| 1 | #---------------------------------------------------------------------------- |
| 2 | # Name: ExtensionService.py |
| 3 | # Purpose: Extension Service for IDE |
| 4 | # |
| 5 | # Author: Peter Yared |
| 6 | # |
| 7 | # Created: 5/23/05 |
| 8 | # CVS-ID: $ID:$ |
| 9 | # Copyright: (c) 2005-2006 ActiveGrid, Inc. |
| 10 | # License: wxWindows License |
| 11 | #---------------------------------------------------------------------------- |
| 12 | |
| 13 | import wx |
| 14 | import wx.lib.pydocview |
| 15 | import MessageService |
| 16 | import ProjectEditor |
| 17 | import os |
| 18 | import os.path |
| 19 | import activegrid.util.xmlutils as xmlutils |
| 20 | _ = wx.GetTranslation |
| 21 | |
| 22 | |
| 23 | #---------------------------------------------------------------------------- |
| 24 | # Constants |
| 25 | #---------------------------------------------------------------------------- |
| 26 | SPACE = 10 |
| 27 | HALF_SPACE = 5 |
| 28 | |
| 29 | |
| 30 | #---------------------------------------------------------------------------- |
| 31 | # Classes |
| 32 | #---------------------------------------------------------------------------- |
| 33 | |
| 34 | class Extension: |
| 35 | |
| 36 | |
| 37 | def __init__(self, menuItemName=None): |
| 38 | self.menuItemName = menuItemName |
| 39 | self.id = 0 |
| 40 | self.menuItemDesc = '' |
| 41 | self.command = '' |
| 42 | self.commandPreArgs = '' |
| 43 | self.commandPostArgs = '' |
| 44 | self.fileExt = None |
| 45 | self.opOnSelectedFile = True |
| 46 | |
| 47 | |
| 48 | class ExtensionService(wx.lib.pydocview.DocService): |
| 49 | |
| 50 | EXTENSIONS_KEY = "/AG_Extensions" |
| 51 | |
| 52 | def __init__(self): |
| 53 | self.LoadExtensions() |
| 54 | |
| 55 | |
| 56 | def __getExtensionKeyName(extensionName): |
| 57 | return "%s/%s" % (ExtensionService.EXTENSIONS_KEY, extensionName) |
| 58 | |
| 59 | |
| 60 | __getExtensionKeyName = staticmethod(__getExtensionKeyName) |
| 61 | |
| 62 | |
| 63 | def LoadExtensions(self): |
| 64 | self._extensions = [] |
| 65 | |
| 66 | extensionNames = [] |
| 67 | config = wx.ConfigBase_Get() |
| 68 | path = config.GetPath() |
| 69 | try: |
| 70 | config.SetPath(ExtensionService.EXTENSIONS_KEY) |
| 71 | cont, value, index = config.GetFirstEntry() |
| 72 | while cont: |
| 73 | extensionNames.append(value) |
| 74 | cont, value, index = config.GetNextEntry(index) |
| 75 | finally: |
| 76 | config.SetPath(path) |
| 77 | |
| 78 | for extensionName in extensionNames: |
| 79 | extensionData = config.Read(self.__getExtensionKeyName(extensionName)) |
| 80 | if extensionData: |
| 81 | extension = xmlutils.unmarshal(extensionData.encode('utf-8')) |
| 82 | self._extensions.append(extension) |
| 83 | |
| 84 | |
| 85 | def SaveExtensions(self): |
| 86 | config = wx.ConfigBase_Get() |
| 87 | config.DeleteGroup(ExtensionService.EXTENSIONS_KEY) |
| 88 | for extension in self._extensions: |
| 89 | config.Write(self.__getExtensionKeyName(extension.menuItemName), xmlutils.marshal(extension)) |
| 90 | |
| 91 | |
| 92 | def GetExtensions(self): |
| 93 | return self._extensions |
| 94 | |
| 95 | |
| 96 | def SetExtensions(self, extensions): |
| 97 | self._extensions = extensions |
| 98 | |
| 99 | |
| 100 | def CheckSumExtensions(self): |
| 101 | return xmlutils.marshal(self._extensions) |
| 102 | |
| 103 | |
| 104 | def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None): |
| 105 | toolsMenuIndex = menuBar.FindMenu(_("&Tools")) |
| 106 | if toolsMenuIndex > -1: |
| 107 | toolsMenu = menuBar.GetMenu(toolsMenuIndex) |
| 108 | else: |
| 109 | toolsMenu = wx.Menu() |
| 110 | |
| 111 | if self._extensions: |
| 112 | if toolsMenu.GetMenuItems(): |
| 113 | toolsMenu.AppendSeparator() |
| 114 | for ext in self._extensions: |
| 115 | # Append a tool menu item for each extension |
| 116 | ext.id = wx.NewId() |
| 117 | toolsMenu.Append(ext.id, ext.menuItemName) |
| 118 | wx.EVT_MENU(frame, ext.id, frame.ProcessEvent) |
| 119 | wx.EVT_UPDATE_UI(frame, ext.id, frame.ProcessUpdateUIEvent) |
| 120 | |
| 121 | if toolsMenuIndex == -1: |
| 122 | index = menuBar.FindMenu(_("&Run")) |
| 123 | if index == -1: |
| 124 | index = menuBar.FindMenu(_("&Project")) |
| 125 | if index == -1: |
| 126 | index = menuBar.FindMenu(_("&Format")) |
| 127 | if index == -1: |
| 128 | index = menuBar.FindMenu(_("&View")) |
| 129 | menuBar.Insert(index + 1, toolsMenu, _("&Tools")) |
| 130 | |
| 131 | |
| 132 | def ProcessEvent(self, event): |
| 133 | id = event.GetId() |
| 134 | for extension in self._extensions: |
| 135 | if id == extension.id: |
| 136 | self.OnExecuteExtension(extension) |
| 137 | return True |
| 138 | return False |
| 139 | |
| 140 | |
| 141 | def ProcessUpdateUIEvent(self, event): |
| 142 | id = event.GetId() |
| 143 | for extension in self._extensions: |
| 144 | if id == extension.id: |
| 145 | if extension.fileExt: |
| 146 | doc = wx.GetApp().GetDocumentManager().GetCurrentDocument() |
| 147 | if doc and '*' in extension.fileExt: |
| 148 | event.Enable(True) |
| 149 | return True |
| 150 | if doc: |
| 151 | for fileExt in extension.fileExt: |
| 152 | if fileExt in doc.GetDocumentTemplate().GetFileFilter(): |
| 153 | event.Enable(True) |
| 154 | return True |
| 155 | if extension.opOnSelectedFile and isinstance(doc, ProjectEditor.ProjectDocument): |
| 156 | filename = doc.GetFirstView().GetSelectedFile() |
| 157 | if filename: |
| 158 | template = wx.GetApp().GetDocumentManager().FindTemplateForPath(filename) |
| 159 | for fileExt in extension.fileExt: |
| 160 | if fileExt in template.GetFileFilter(): |
| 161 | event.Enable(True) |
| 162 | return True |
| 163 | event.Enable(False) |
| 164 | return False |
| 165 | return False |
| 166 | |
| 167 | |
| 168 | def OnExecuteExtension(self, extension): |
| 169 | if extension.fileExt: |
| 170 | doc = wx.GetApp().GetDocumentManager().GetCurrentDocument() |
| 171 | if not doc: |
| 172 | return |
| 173 | if extension.opOnSelectedFile and isinstance(doc, ProjectEditor.ProjectDocument): |
| 174 | filename = doc.GetFirstView().GetSelectedFile() |
| 175 | if not filename: |
| 176 | filename = doc.GetFilename() |
| 177 | else: |
| 178 | filename = doc.GetFilename() |
| 179 | ext = os.path.splitext(filename)[1] |
| 180 | if not '*' in extension.fileExt: |
| 181 | if not ext or ext[1:] not in extension.fileExt: |
| 182 | return |
| 183 | cmds = [extension.command] |
| 184 | if extension.commandPreArgs: |
| 185 | cmds.append(extension.commandPreArgs) |
| 186 | cmds.append(filename) |
| 187 | if extension.commandPostArgs: |
| 188 | cmds.append(extension.commandPostArgs) |
| 189 | os.spawnv(os.P_NOWAIT, extension.command, cmds) |
| 190 | |
| 191 | else: |
| 192 | cmd = extension.command |
| 193 | if extension.commandPreArgs: |
| 194 | cmd = cmd + ' ' + extension.commandPreArgs |
| 195 | if extension.commandPostArgs: |
| 196 | cmd = cmd + ' ' + extension.commandPostArgs |
| 197 | f = os.popen(cmd) |
| 198 | messageService = wx.GetApp().GetService(MessageService.MessageService) |
| 199 | messageService.ShowWindow() |
| 200 | view = messageService.GetView() |
| 201 | for line in f.readlines(): |
| 202 | view.AddLines(line) |
| 203 | view.GetControl().EnsureCaretVisible() |
| 204 | f.close() |
| 205 | |
| 206 | |
| 207 | class ExtensionOptionsPanel(wx.Panel): |
| 208 | |
| 209 | |
| 210 | def __init__(self, parent, id): |
| 211 | wx.Panel.__init__(self, parent, id) |
| 212 | |
| 213 | extOptionsPanelBorderSizer = wx.BoxSizer(wx.VERTICAL) |
| 214 | |
| 215 | extOptionsPanelSizer = wx.BoxSizer(wx.HORIZONTAL) |
| 216 | |
| 217 | extCtrlSizer = wx.BoxSizer(wx.VERTICAL) |
| 218 | extCtrlSizer.Add(wx.StaticText(self, -1, _("External Tools:")), 0, wx.BOTTOM, HALF_SPACE) |
| 219 | self._extListBox = wx.ListBox(self, -1, style=wx.LB_SINGLE) |
| 220 | self.Bind(wx.EVT_LISTBOX, self.OnListBoxSelect, self._extListBox) |
| 221 | extCtrlSizer.Add(self._extListBox, 1, wx.BOTTOM | wx.EXPAND, SPACE) |
| 222 | buttonSizer = wx.GridSizer(cols=2, vgap=HALF_SPACE, hgap=HALF_SPACE) |
| 223 | self._moveUpButton = wx.Button(self, -1, _("Move Up")) |
| 224 | self.Bind(wx.EVT_BUTTON, self.OnMoveUp, self._moveUpButton) |
| 225 | buttonSizer.Add(self._moveUpButton, 1, wx.EXPAND) |
| 226 | self._moveDownButton = wx.Button(self, -1, _("Move Down")) |
| 227 | self.Bind(wx.EVT_BUTTON, self.OnMoveDown, self._moveDownButton) |
| 228 | buttonSizer.Add(self._moveDownButton, 1, wx.EXPAND) |
| 229 | self._addButton = wx.Button(self, wx.ID_ADD) |
| 230 | self.Bind(wx.EVT_BUTTON, self.OnAdd, self._addButton) |
| 231 | buttonSizer.Add(self._addButton, 1, wx.EXPAND) |
| 232 | self._deleteButton = wx.Button(self, wx.ID_DELETE, label=_("Delete")) # get rid of accelerator for letter d in "&Delete" |
| 233 | self.Bind(wx.EVT_BUTTON, self.OnDelete, self._deleteButton) |
| 234 | buttonSizer.Add(self._deleteButton, 1, wx.EXPAND) |
| 235 | extCtrlSizer.Add(buttonSizer, 0, wx.ALIGN_CENTER) |
| 236 | extOptionsPanelSizer.Add(extCtrlSizer, 0, wx.EXPAND) |
| 237 | |
| 238 | self._extDetailPanel = wx.Panel(self) |
| 239 | staticBox = wx.StaticBox(self, label=_("Selected External Tool")) |
| 240 | staticBoxSizer = wx.StaticBoxSizer(staticBox, wx.VERTICAL) |
| 241 | |
| 242 | extDetailSizer = wx.FlexGridSizer(cols=2, vgap=5, hgap=5) |
| 243 | extDetailSizer.AddGrowableCol(1,1) |
| 244 | |
| 245 | extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Name:")), flag=wx.ALIGN_CENTER_VERTICAL) |
| 246 | self._menuItemNameTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) |
| 247 | extDetailSizer.Add(self._menuItemNameTextCtrl, 0, wx.EXPAND) |
| 248 | self.Bind(wx.EVT_TEXT, self.SaveCurrentItem, self._menuItemNameTextCtrl) |
| 249 | |
| 250 | extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Description:")), flag=wx.ALIGN_CENTER_VERTICAL) |
| 251 | self._menuItemDescTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) |
| 252 | extDetailSizer.Add(self._menuItemDescTextCtrl, 0, wx.EXPAND) |
| 253 | |
| 254 | extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Path:")), flag=wx.ALIGN_CENTER_VERTICAL) |
| 255 | self._commandTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) |
| 256 | findFileButton = wx.Button(self._extDetailPanel, -1, _("Browse...")) |
| 257 | def OnBrowseButton(event): |
| 258 | fileDlg = wx.FileDialog(self, _("Choose an Executable:"), style=wx.OPEN|wx.FILE_MUST_EXIST|wx.HIDE_READONLY|wx.CHANGE_DIR) |
| 259 | path = self._commandTextCtrl.GetValue() |
| 260 | if path: |
| 261 | fileDlg.SetPath(path) |
| 262 | # fileDlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog |
| 263 | if fileDlg.ShowModal() == wx.ID_OK: |
| 264 | self._commandTextCtrl.SetValue(fileDlg.GetPath()) |
| 265 | self._commandTextCtrl.SetInsertionPointEnd() |
| 266 | self._commandTextCtrl.SetToolTipString(fileDlg.GetPath()) |
| 267 | fileDlg.Destroy() |
| 268 | wx.EVT_BUTTON(findFileButton, -1, OnBrowseButton) |
| 269 | hsizer = wx.BoxSizer(wx.HORIZONTAL) |
| 270 | hsizer.Add(self._commandTextCtrl, 1, wx.EXPAND) |
| 271 | hsizer.Add(findFileButton, 0, wx.LEFT, HALF_SPACE) |
| 272 | extDetailSizer.Add(hsizer, 0, wx.EXPAND) |
| 273 | |
| 274 | extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Pre Args:")), flag=wx.ALIGN_CENTER_VERTICAL) |
| 275 | self._commandPreArgsTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) |
| 276 | extDetailSizer.Add(self._commandPreArgsTextCtrl, 0, wx.EXPAND) |
| 277 | |
| 278 | extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Post Args:")), flag=wx.ALIGN_CENTER_VERTICAL) |
| 279 | self._commandPostArgsTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) |
| 280 | extDetailSizer.Add(self._commandPostArgsTextCtrl, 0, wx.EXPAND) |
| 281 | |
| 282 | extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("File Extensions:")), flag=wx.ALIGN_CENTER_VERTICAL) |
| 283 | self._fileExtTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) |
| 284 | self._fileExtTextCtrl.SetToolTipString(_("""For example: "txt, text" (comma separated) or "*" for all files""")) |
| 285 | extDetailSizer.Add(self._fileExtTextCtrl, 0, wx.EXPAND) |
| 286 | |
| 287 | self._selFileCtrl = wx.CheckBox(self._extDetailPanel, -1, _("Operate on Selected File")) |
| 288 | extDetailSizer.Add(self._selFileCtrl, 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP, SPACE) |
| 289 | self._selFileCtrl.SetToolTipString(_("If focus is in the project, instead of operating on the project file, operate on the selected file.")) |
| 290 | |
| 291 | self._extDetailPanel.SetSizer(extDetailSizer) |
| 292 | staticBoxSizer.Add(self._extDetailPanel, 1, wx.ALL|wx.EXPAND, SPACE) |
| 293 | |
| 294 | extOptionsPanelSizer.Add(staticBoxSizer, 1, wx.LEFT|wx.EXPAND, SPACE) |
| 295 | |
| 296 | extOptionsPanelBorderSizer.Add(extOptionsPanelSizer, 1, wx.ALL|wx.EXPAND, SPACE) |
| 297 | self.SetSizer(extOptionsPanelBorderSizer) |
| 298 | |
| 299 | if self.PopulateItems(): |
| 300 | self._extListBox.SetSelection(0) |
| 301 | self.OnListBoxSelect() |
| 302 | |
| 303 | self.Layout() |
| 304 | |
| 305 | parent.AddPage(self, _("External Tools")) |
| 306 | |
| 307 | |
| 308 | def OnOK(self, optionsDialog): |
| 309 | self.SaveCurrentItem() |
| 310 | extensionsService = wx.GetApp().GetService(ExtensionService) |
| 311 | extensionsService.SetExtensions(self._extensions) |
| 312 | extensionsService.SaveExtensions() |
| 313 | if extensionsService.CheckSumExtensions() != self._oldExtensions: # see PopulateItems() note about self._oldExtensions |
| 314 | msgTitle = wx.GetApp().GetAppName() |
| 315 | if not msgTitle: |
| 316 | msgTitle = _("Document Options") |
| 317 | wx.MessageBox(_("Extension changes will not appear until the application is restarted."), |
| 318 | msgTitle, |
| 319 | wx.OK | wx.ICON_INFORMATION, |
| 320 | self.GetParent()) |
| 321 | |
| 322 | |
| 323 | def PopulateItems(self): |
| 324 | extensionsService = wx.GetApp().GetService(ExtensionService) |
| 325 | import copy |
| 326 | self._extensions = copy.deepcopy(extensionsService.GetExtensions()) |
| 327 | self._oldExtensions = extensionsService.CheckSumExtensions() # wxBug: need to make a copy now since the deepcopy reorders fields, so we must compare the prestine copy with the modified copy |
| 328 | for extension in self._extensions: |
| 329 | self._extListBox.Append(extension.menuItemName, extension) |
| 330 | self._currentItem = None |
| 331 | self._currentItemIndex = -1 |
| 332 | return len(self._extensions) |
| 333 | |
| 334 | |
| 335 | def OnListBoxSelect(self, event=None): |
| 336 | self.SaveCurrentItem() |
| 337 | if self._extListBox.GetSelection() == wx.NOT_FOUND: |
| 338 | self._currentItemIndex = -1 |
| 339 | self._currentItem = None |
| 340 | self._deleteButton.Enable(False) |
| 341 | self._moveUpButton.Enable(False) |
| 342 | self._moveDownButton.Enable(False) |
| 343 | else: |
| 344 | self._currentItemIndex = self._extListBox.GetSelection() |
| 345 | self._currentItem = self._extListBox.GetClientData(self._currentItemIndex) |
| 346 | self._deleteButton.Enable() |
| 347 | self._moveUpButton.Enable(self._extListBox.GetCount() > 1 and self._currentItemIndex > 0) |
| 348 | self._moveDownButton.Enable(self._extListBox.GetCount() > 1 and self._currentItemIndex < self._extListBox.GetCount() - 1) |
| 349 | self.LoadItem(self._currentItem) |
| 350 | |
| 351 | |
| 352 | def SaveCurrentItem(self, event=None): |
| 353 | extension = self._currentItem |
| 354 | if extension: |
| 355 | if extension.menuItemName != self._menuItemNameTextCtrl.GetValue(): |
| 356 | extension.menuItemName = self._menuItemNameTextCtrl.GetValue() |
| 357 | self._extListBox.SetString(self._currentItemIndex, extension.menuItemName) |
| 358 | extension.menuItemDesc = self._menuItemDescTextCtrl.GetValue() |
| 359 | extension.command = self._commandTextCtrl.GetValue() |
| 360 | extension.commandPreArgs = self._commandPreArgsTextCtrl.GetValue() |
| 361 | extension.commandPostArgs = self._commandPostArgsTextCtrl.GetValue() |
| 362 | fileExt = self._fileExtTextCtrl.GetValue().replace(' ','') |
| 363 | if not fileExt: |
| 364 | extension.fileExt = None |
| 365 | else: |
| 366 | extension.fileExt = fileExt.split(',') |
| 367 | extension.opOnSelectedFile = self._selFileCtrl.GetValue() |
| 368 | |
| 369 | |
| 370 | def LoadItem(self, extension): |
| 371 | if extension: |
| 372 | self._menuItemDescTextCtrl.SetValue(extension.menuItemDesc or '') |
| 373 | self._commandTextCtrl.SetValue(extension.command or '') |
| 374 | self._commandTextCtrl.SetToolTipString(extension.command or '') |
| 375 | self._commandPreArgsTextCtrl.SetValue(extension.commandPreArgs or '') |
| 376 | self._commandPostArgsTextCtrl.SetValue(extension.commandPostArgs or '') |
| 377 | if extension.fileExt: |
| 378 | list = "" |
| 379 | for ext in extension.fileExt: |
| 380 | if list: |
| 381 | list = list + ", " |
| 382 | list = list + ext |
| 383 | self._fileExtTextCtrl.SetValue(list) |
| 384 | else: |
| 385 | self._fileExtTextCtrl.SetValue('') |
| 386 | self._selFileCtrl.SetValue(extension.opOnSelectedFile) |
| 387 | self._menuItemNameTextCtrl.SetValue(extension.menuItemName or '') # Do the name last since it triggers the write event that updates the entire item |
| 388 | self._extDetailPanel.Enable() |
| 389 | else: |
| 390 | self._menuItemNameTextCtrl.SetValue('') |
| 391 | self._menuItemDescTextCtrl.SetValue('') |
| 392 | self._commandTextCtrl.SetValue('') |
| 393 | self._commandTextCtrl.SetToolTipString(_("Path to executable")) |
| 394 | self._commandPreArgsTextCtrl.SetValue('') |
| 395 | self._commandPostArgsTextCtrl.SetValue('') |
| 396 | self._fileExtTextCtrl.SetValue('') |
| 397 | self._selFileCtrl.SetValue(True) |
| 398 | self._extDetailPanel.Enable(False) |
| 399 | |
| 400 | |
| 401 | def OnAdd(self, event): |
| 402 | self.SaveCurrentItem() |
| 403 | name = _("Untitled") |
| 404 | count = 1 |
| 405 | while self._extListBox.FindString(name) != wx.NOT_FOUND: |
| 406 | count = count + 1 |
| 407 | name = _("Untitled%s") % count |
| 408 | extension = Extension(name) |
| 409 | self._extensions.append(extension) |
| 410 | self._extListBox.Append(extension.menuItemName, extension) |
| 411 | self._extListBox.SetStringSelection(extension.menuItemName) |
| 412 | self.OnListBoxSelect() |
| 413 | self._menuItemNameTextCtrl.SetFocus() |
| 414 | self._menuItemNameTextCtrl.SetSelection(-1, -1) |
| 415 | |
| 416 | |
| 417 | def OnDelete(self, event): |
| 418 | self._extListBox.Delete(self._currentItemIndex) |
| 419 | self._extensions.remove(self._currentItem) |
| 420 | self._currentItemIndex = min(self._currentItemIndex, self._extListBox.GetCount() - 1) |
| 421 | if self._currentItemIndex > -1: |
| 422 | self._extListBox.SetSelection(self._currentItemIndex) |
| 423 | self._currentItem = None # Don't update it since it no longer exists |
| 424 | self.OnListBoxSelect() |
| 425 | |
| 426 | |
| 427 | def OnMoveUp(self, event): |
| 428 | itemAboveString = self._extListBox.GetString(self._currentItemIndex - 1) |
| 429 | itemAboveData = self._extListBox.GetClientData(self._currentItemIndex - 1) |
| 430 | self._extListBox.Delete(self._currentItemIndex - 1) |
| 431 | self._extListBox.Insert(itemAboveString, self._currentItemIndex) |
| 432 | self._extListBox.SetClientData(self._currentItemIndex, itemAboveData) |
| 433 | self._currentItemIndex = self._currentItemIndex - 1 |
| 434 | self.OnListBoxSelect() # Reset buttons |
| 435 | |
| 436 | |
| 437 | def OnMoveDown(self, event): |
| 438 | itemBelowString = self._extListBox.GetString(self._currentItemIndex + 1) |
| 439 | itemBelowData = self._extListBox.GetClientData(self._currentItemIndex + 1) |
| 440 | self._extListBox.Delete(self._currentItemIndex + 1) |
| 441 | self._extListBox.Insert(itemBelowString, self._currentItemIndex) |
| 442 | self._extListBox.SetClientData(self._currentItemIndex, itemBelowData) |
| 443 | self._currentItemIndex = self._currentItemIndex + 1 |
| 444 | self.OnListBoxSelect() # Reset buttons |