diff --git a/MAVProxy/modules/mavproxy_misseditor/missionEditorFrame.py b/MAVProxy/modules/mavproxy_misseditor/missionEditorFrame.py index 03fa462ef1..d6f3c3f972 100755 --- a/MAVProxy/modules/mavproxy_misseditor/missionEditorFrame.py +++ b/MAVProxy/modules/mavproxy_misseditor/missionEditorFrame.py @@ -39,6 +39,140 @@ ME_DIST_COL = 12 ME_ANGLE_COL = 13 + +class ListCtrlComboPopup(wx.ComboPopup): + + def __init__(self): + wx.ComboPopup.__init__(self) + self.lc = None + + def AddItem(self, txt): + self.lc.InsertItem(self.lc.GetItemCount(), txt) + + def OnMotion(self, evt): + item, flags = self.lc.HitTest(evt.GetPosition()) + if item >= 0: + self.lc.Select(item) + self.curitem = item + + def OnLeftDown(self, evt): + self.value = self.curitem + self.Dismiss() + + # This is called immediately after construction finishes. You can + # use self.GetCombo if needed to get to the ComboCtrl instance. + def Init(self): + self.value = -1 + self.curitem = -1 + + # Create the popup child control. Return true for success. + def Create(self, parent): + self.lc = wx.ListCtrl(parent, style=wx.LC_SINGLE_SEL | wx.SIMPLE_BORDER | wx.LC_REPORT | wx.LC_NO_HEADER) + self.lc.InsertColumn(0, '') + self.lc.Bind(wx.EVT_MOTION, self.OnMotion) + self.lc.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) + return True + + # Return the widget that is to be used for the popup + def GetControl(self): + return self.lc + + # Called just prior to displaying the popup, you can use it to + # 'select' the current item. + def SetStringValue(self, val): + idx = self.lc.FindItem(-1, val) + if idx != wx.NOT_FOUND: + self.lc.Select(idx) + + def FindString(self, val): + idx = self.lc.FindItem(-1, val) + if idx == wx.NOT_FOUND: + idx = 0 + return idx + + # Return a string representation of the current item. + def GetStringValue(self): + if self.value >= 0: + return self.lc.GetItemText(self.value) + return "" + + # Called immediately after the popup is shown + def OnPopup(self): + self.lc.SetColumnWidth(0, wx.LIST_AUTOSIZE) + wx.ComboPopup.OnPopup(self) + + # Called when popup is dismissed + def OnDismiss(self): + wx.ComboPopup.OnDismiss(self) + + # This is called to custom paint in the combo control itself + # (ie. not the popup). Default implementation draws value as + # string. + def PaintComboControl(self, dc, rect): + wx.ComboPopup.PaintComboControl(self, dc, rect) + + # Receives key events from the parent ComboCtrl. Events not + # handled should be skipped, as usual. + def OnComboKeyEvent(self, event): + wx.ComboPopup.OnComboKeyEvent(self, event) + + # Implement if you need to support special action when user + # double-clicks on the parent wxComboCtrl. + def OnComboDoubleClick(self): + wx.ComboPopup.OnComboDoubleClick(self) + + # Return final size of popup. Called on every popup, just prior to OnPopup. + # minWidth = preferred minimum width for window + # prefHeight = preferred height. Only applies if > 0, + # maxHeight = max height for window, as limited by screen size + # and should only be rounded down, if necessary. + def GetAdjustedSize(self, minWidth, prefHeight, maxHeight): + return wx.ComboPopup.GetAdjustedSize(self, minWidth, prefHeight, maxHeight) + + # Return true if you want delay the call to Create until the popup + # is shown for the first time. It is more efficient, but note that + # it is often more convenient to have the control created + # immediately. + # Default returns false. + def LazyCreate(self): + return wx.ComboPopup.LazyCreate(self) + + +class DropdownCellEditor(grid.GridCellEditor): + def __init__(self, choices): + super().__init__() + self.choices = choices + + def Create(self, parent, id, evtHandler): + self.control = wx.ComboCtrl(parent, id, "", style=wx.CB_READONLY) + self.popupCtrl = ListCtrlComboPopup() + self.control.SetPopupControl(self.popupCtrl) + for choice in self.choices: + self.popupCtrl.AddItem(choice) + self.SetControl(self.control) + + def Clone(self): + return DropdownCellEditor(self.choices) + + def BeginEdit(self, row, col, grid): + self.startValue = grid.GetTable().GetValue(row, col) + self.control.SetValue(self.startValue) + + def EndEdit(self, row, col, grid, oldval): + self.endValue = self.popupCtrl.GetStringValue() + if self.endValue != oldval and self.endValue != "": + return self.endValue + else: + return None + + def ApplyEdit(self, row, col, grid): + self.control.SetValue(self.endValue) + grid.GetTable().SetValue(row, col, self.endValue) + + def Reset(self): + self.control.SetValue(self.startValue) + + class MissionEditorFrame(wx.Frame): def __init__(self, state, elemodel='SRTM3', *args, **kwds): # begin wxGlade: MissionEditorFrame.__init__ @@ -354,8 +488,9 @@ def process_gui_event(self, event): def prep_new_row(self, row_num): command_choices = sorted(list(me_defines.miss_cmds.values())) - cell_ed = wx.grid.GridCellChoiceEditor(command_choices) + cell_ed = DropdownCellEditor(command_choices) self.grid_mission.SetCellEditor(row_num, ME_COMMAND_COL, cell_ed) + cell_ed.IncRef() self.grid_mission.SetCellValue(row_num, ME_COMMAND_COL, "NAV_WAYPOINT") for i in range(1, 7):