def OnViewAllTags(self, event): if self._view_all_tags_dialog is None: self._view_all_tags_dialog = ViewAllTagsDialog(self._controller, self) self._view_all_tags_dialog.show_dialog()
class RideFrame(wx.Frame, RideEventHandler): def __init__(self, application, controller): wx.Frame.__init__(self, parent=None, title='RIDE', pos=application.settings['mainframe position'], size=application.settings['mainframe size']) self.ensure_on_screen() if application.settings['mainframe maximized']: self.Maximize() self._application = application self._controller = controller self._init_ui() self._plugin_manager = PluginManager(self.notebook) self._review_dialog = None self._view_all_tags_dialog = None self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_MOVE, self.OnMove) self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize) self._subscribe_messages() self.Show() wx.CallLater(100, self.actions.register_tools) def _subscribe_messages(self): for listener, topic in [ (lambda msg: self.SetStatusText('Saved %s' % msg.path), RideSaved), (lambda msg: self.SetStatusText('Saved all files'), RideSaveAll), (self._set_label, RideTreeSelection), (self._show_validation_error, RideInputValidationError), (self._show_modification_prevented_error, RideModificationPrevented) ]: PUBLISHER.subscribe(listener, topic) def _set_label(self, message): self.SetTitle(self._create_title(message)) def _create_title(self, message): title = 'RIDE' if message: item = message.item title += ' - ' + item.datafile.name if not item.is_modifiable(): title += ' (READ ONLY)' return title def _show_validation_error(self, message): wx.MessageBox(message.message, 'Validation Error', style=wx.ICON_ERROR) def _show_modification_prevented_error(self, message): wx.MessageBox('"%s" is read only' % message.controller.datafile_controller.filename, 'Modification prevented', style=wx.ICON_ERROR) def _init_ui(self): splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) self.notebook = NoteBook(splitter, self._application) mb = MenuBar(self) self.toolbar = ToolBar(self) self.actions = ActionRegisterer(mb, self.toolbar, ShortcutRegistry(self)) self.tree = Tree(splitter, self.actions, self._application.settings) self.actions.register_actions( ActionInfoCollection(_menudata, self, self.tree)) mb.take_menu_bar_into_use() splitter.SetMinimumPaneSize(100) splitter.SplitVertically(self.tree, self.notebook, 300) self.CreateStatusBar() self.SetIcons(ImageProvider().PROGICONS) def get_selected_datafile(self): return self.tree.get_selected_datafile() def get_selected_datafile_controller(self): return self.tree.get_selected_datafile_controller() def OnClose(self, event): if self._allowed_to_exit(): PUBLISHER.unsubscribe(self._set_label, RideTreeSelection) RideClosing().publish() self.Destroy() else: wx.CloseEvent.Veto(event) def OnSize(self, event): if not self.IsMaximized(): self._application.settings['mainframe maximized'] = False self._application.settings['mainframe size'] = self.GetSizeTuple() event.Skip() def OnMove(self, event): # When the window is Iconized, a move event is also raised, but we # don't want to update the position in the settings file if not self.IsIconized() and not self.IsMaximized(): self._application.settings['mainframe position'] = self.GetPositionTuple() event.Skip() def OnMaximize(self, event): self._application.settings['mainframe maximized'] = True event.Skip() def OnReleasenotes(self, event): pass def _allowed_to_exit(self): if self.has_unsaved_changes(): ret = wx.MessageBox('There are unsaved modifications.\n' 'Do you want to save your changes before exiting?', 'Warning', wx.ICON_WARNING|wx.CANCEL|wx.YES_NO) if ret == wx.CANCEL: return False if ret == wx.YES: self.save() return True def has_unsaved_changes(self): return self._controller.is_dirty() def OnNewProject(self, event): if not self.check_unsaved_modifications(): return NewProjectDialog(self._controller).execute() self._populate_tree() def _populate_tree(self): self.tree.populate(self._controller) def OnOpenTestSuite(self, event): if not self.check_unsaved_modifications(): return path = RobotFilePathDialog( self, self._controller, self._application.settings).execute() if path: self.open_suite(path) def check_unsaved_modifications(self): if self.has_unsaved_changes(): ret = wx.MessageBox('There are unsaved modifications.\n' 'Do you want to proceed without saving?', 'Warning', wx.ICON_WARNING|wx.YES_NO) return ret == wx.YES return True def open_suite(self, path): self._controller.update_default_dir(path) self._controller.load_datafile(path, LoadProgressObserver(self)) self._populate_tree() def refresh_datafile(self, item, event): self.tree.refresh_datafile(item, event) def OnOpenDirectory(self, event): if self.check_unsaved_modifications(): path = wx.DirSelector(message='Choose a directory containing Robot files', defaultPath=self._controller.default_dir) if path: self.open_suite(path) def OnReload(self, event): # path = wx.DirSelector(message='Choose a directory containing Robot files', # defaultPath=self._controller.default_dir) python_home = get_python_lib() script_and_parameter ='python ' + python_home + '\PublicLibrary\RF_tool_box.py ' + self._controller.default_dir os.system(script_and_parameter) self.open_suite(self._controller.default_dir) def OnSave(self, event): self.save() def OnSaveAll(self, event): self.save_all() def save_all(self): self._show_dialog_for_files_without_format() self._controller.execute(SaveAll()) def save(self, controller=None): if controller is None : controller = self.get_selected_datafile_controller() if controller is not None: if not controller.has_format(): self._show_dialog_for_files_without_format(controller) else: controller.execute(SaveFile()) def _show_dialog_for_files_without_format(self, controller=None): files_without_format = self._controller.get_files_without_format(controller) for f in files_without_format: self._show_format_dialog_for(f) def _show_format_dialog_for(self, file_controller_without_format): InitFileFormatDialog(file_controller_without_format).execute() def OnExit(self, event): self.Close() def OnManagePlugins(self, event): self._plugin_manager.show(self._application.get_plugins()) def OnViewAllTags(self, event): if self._view_all_tags_dialog is None: self._view_all_tags_dialog = ViewAllTagsDialog(self._controller, self) self._view_all_tags_dialog.show_dialog() def OnSearchUnusedKeywords(self, event): if self._review_dialog is None: self._review_dialog = ReviewDialog(self._controller, self) self._review_dialog.show_dialog() def OnPreferences(self, event): dlg = PreferenceEditor(self, "RIDE - Preferences", self._application.preferences, style='tree') # I would prefer that this not be modal, but making it non- # modal opens up a can of worms. We don't want to have to deal # with settings getting changed out from under us while the # dialog is open. dlg.ShowModal() dlg.Destroy() def OnAbout(self, event): dlg = AboutDialog() dlg.ShowModal() dlg.Destroy() def OnShortcutkeys(self, event): dialog = ShortcutKeysDialog() dialog.Show() def OnReportaProblem(self, event): wx.LaunchDefaultBrowser('http://github.com/robotframework/RIDE/issues') def OnUserGuide(self, event): wx.LaunchDefaultBrowser('http://robotframework.org/robotframework/#user-guide') def _has_data(self): return self._controller.data is not None def _refresh(self): self._controller.update_namespace() # This code is copied from http://wiki.wxpython.org/EnsureFrameIsOnScreen, # and adapted to fit our code style. def ensure_on_screen(self): try: display_id = wx.Display.GetFromWindow(self) except NotImplementedError: display_id = 0 if display_id == -1: display_id = 0 geometry = wx.Display(display_id).GetGeometry() position = self.GetPosition() if position.x < geometry.x: position.x = geometry.x if position.y < geometry.y: position.y = geometry.y size = self.GetSize() if size.width > geometry.width: size.width = geometry.width position.x = geometry.x elif position.x + size.width > geometry.x + geometry.width: position.x = geometry.x + geometry.width - size.width if size.height > geometry.height: size.height = geometry.height position.y = geometry.y elif position.y + size.height > geometry.y + geometry.height: position.y = geometry.y + geometry.height - size.height self.SetPosition(position) self.SetSize(size)
class RideFrame(wx.Frame, RideEventHandler): def __init__(self, application, controller): wx.Frame.__init__(self, parent=None, title='RIDE', pos=application.settings['mainframe position'], size=application.settings['mainframe size']) self.ensure_on_screen() if application.settings['mainframe maximized']: self.Maximize() self._application = application self._controller = controller self._init_ui() self._plugin_manager = PluginManager(self.notebook) self._review_dialog = None self._view_all_tags_dialog = None self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_MOVE, self.OnMove) self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize) self._subscribe_messages() self.Show() wx.CallLater(100, self.actions.register_tools) def _subscribe_messages(self): for listener, topic in [ (lambda msg: self.SetStatusText('Saved %s' % msg.path), RideSaved), (lambda msg: self.SetStatusText('Saved all files'), RideSaveAll), (self._set_label, RideTreeSelection), (self._show_validation_error, RideInputValidationError), (self._show_modification_prevented_error, RideModificationPrevented) ]: PUBLISHER.subscribe(listener, topic) def _set_label(self, message): self.SetTitle(self._create_title(message)) def _create_title(self, message): title = 'RIDE' if message: item = message.item title += ' - ' + item.datafile.name if not item.is_modifiable(): title += ' (READ ONLY)' return title def _show_validation_error(self, message): wx.MessageBox(message.message, 'Validation Error', style=wx.ICON_ERROR) def _show_modification_prevented_error(self, message): wx.MessageBox('"%s" is read only' % message.controller.datafile_controller.filename, 'Modification prevented', style=wx.ICON_ERROR) def _init_ui(self): splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) self.notebook = NoteBook(splitter, self._application) mb = MenuBar(self) self.toolbar = ToolBar(self) self.actions = ActionRegisterer(mb, self.toolbar, ShortcutRegistry(self)) self.tree = Tree(splitter, self.actions, self._application.settings) self.actions.register_actions( ActionInfoCollection(_menudata, self, self.tree)) mb.take_menu_bar_into_use() splitter.SetMinimumPaneSize(100) splitter.SplitVertically(self.tree, self.notebook, 300) self.CreateStatusBar() self.SetIcons(ImageProvider().PROGICONS) def get_selected_datafile(self): return self.tree.get_selected_datafile() def get_selected_datafile_controller(self): return self.tree.get_selected_datafile_controller() def OnClose(self, event): if self._allowed_to_exit(): PUBLISHER.unsubscribe(self._set_label, RideTreeSelection) RideClosing().publish() self.Destroy() else: wx.CloseEvent.Veto(event) def OnSize(self, event): if not self.IsMaximized(): self._application.settings['mainframe maximized'] = False self._application.settings['mainframe size'] = self.GetSizeTuple() event.Skip() def OnMove(self, event): # When the window is Iconized, a move event is also raised, but we # don't want to update the position in the settings file if not self.IsIconized() and not self.IsMaximized(): self._application.settings['mainframe position'] = self.GetPositionTuple() event.Skip() def OnMaximize(self, event): self._application.settings['mainframe maximized'] = True event.Skip() def OnReleasenotes(self, event): pass def _allowed_to_exit(self): if self.has_unsaved_changes(): ret = wx.MessageBox('There are unsaved modifications.\n' 'Do you want to save your changes before exiting?', 'Warning', wx.ICON_WARNING|wx.CANCEL|wx.YES_NO) if ret == wx.CANCEL: return False if ret == wx.YES: self.save() return True def has_unsaved_changes(self): return self._controller.is_dirty() def OnNewProject(self, event): if not self.check_unsaved_modifications(): return NewProjectDialog(self._controller).execute() self._populate_tree() def _populate_tree(self): self.tree.populate(self._controller) def OnOpenTestSuite(self, event): if not self.check_unsaved_modifications(): return path = self._get_path() if path: self.open_suite(path) def check_unsaved_modifications(self): if self.has_unsaved_changes(): ret = wx.MessageBox('There are unsaved modifications.\n' 'Do you want to proceed without saving?', 'Warning', wx.ICON_WARNING|wx.YES_NO) return ret == wx.YES return True def _get_path(self): wildcard = 'Robot data (*robot)|*.robot|Robot data (*txt)|*.txt|All files|*.*' dlg = wx.FileDialog( self, message='Open', wildcard=wildcard, defaultDir=self._controller.default_dir, style=wx.OPEN) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self._controller.update_default_dir(path) else: path = None dlg.Destroy() return path def open_suite(self, path): self._controller.update_default_dir(path) self._controller.load_datafile(path, LoadProgressObserver(self)) self._populate_tree() def refresh_datafile(self, item, event): self.tree.refresh_datafile(item, event) def OnOpenDirectory(self, event): if self.check_unsaved_modifications(): path = wx.DirSelector(message='Choose a directory containing Robot files', defaultPath=self._controller.default_dir) if path: self.open_suite(path) def OnSave(self, event): self.save() def OnSaveAll(self, event): self.save_all() def save_all(self): self._show_dialog_for_files_without_format() self._controller.execute(SaveAll()) def save(self, controller=None): if controller is None : controller = self.get_selected_datafile_controller() if controller is not None: if not controller.has_format(): self._show_dialog_for_files_without_format(controller) else: controller.execute(SaveFile()) def _show_dialog_for_files_without_format(self, controller=None): files_without_format = self._controller.get_files_without_format(controller) for f in files_without_format: self._show_format_dialog_for(f) def _show_format_dialog_for(self, file_controller_without_format): InitFileFormatDialog(file_controller_without_format).execute() def OnExit(self, event): self.Close() def OnManagePlugins(self, event): self._plugin_manager.show(self._application.get_plugins()) def OnViewAllTags(self, event): if self._view_all_tags_dialog is None: self._view_all_tags_dialog = ViewAllTagsDialog(self._controller, self) self._view_all_tags_dialog.show_dialog() def OnSearchUnusedKeywords(self, event): if self._review_dialog is None: self._review_dialog = ReviewDialog(self._controller, self) self._review_dialog.show_dialog() def OnPreferences(self, event): dlg = PreferenceEditor(self, "RIDE - Preferences", self._application.preferences, style='tree') # I would prefer that this not be modal, but making it non- # modal opens up a can of worms. We don't want to have to deal # with settings getting changed out from under us while the # dialog is open. dlg.ShowModal() dlg.Destroy() def OnAbout(self, event): dlg = AboutDialog() dlg.ShowModal() dlg.Destroy() def OnShortcutkeys(self, event): dialog = ShortcutKeysDialog() dialog.Show() def OnReportaProblem(self, event): wx.LaunchDefaultBrowser('http://github.com/robotframework/RIDE/issues') def OnUserGuide(self, event): wx.LaunchDefaultBrowser('http://robotframework.org/robotframework/#user-guide') def _has_data(self): return self._controller.data is not None def _refresh(self): self._controller.update_namespace() # This code is copied from http://wiki.wxpython.org/EnsureFrameIsOnScreen, # and adapted to fit our code style. def ensure_on_screen(self): try: display_id = wx.Display.GetFromWindow(self) except NotImplementedError: display_id = 0 if display_id == -1: display_id = 0 geometry = wx.Display(display_id).GetGeometry() position = self.GetPosition() if position.x < geometry.x: position.x = geometry.x if position.y < geometry.y: position.y = geometry.y size = self.GetSize() if size.width > geometry.width: size.width = geometry.width position.x = geometry.x elif position.x + size.width > geometry.x + geometry.width: position.x = geometry.x + geometry.width - size.width if size.height > geometry.height: size.height = geometry.height position.y = geometry.y elif position.y + size.height > geometry.y + geometry.height: position.y = geometry.y + geometry.height - size.height self.SetPosition(position) self.SetSize(size)
def OnViewAllTags(self, event): if self._view_all_tags_dialog is None: self._view_all_tags_dialog = ViewAllTagsDialog(self._controller, self) self._view_all_tags_dialog.show_dialog()
class RideFrame(wx.Frame): def __init__(self, application, controller): size = application.settings.get('mainframe size', (1100, 700)) wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title='RIDE', pos=application.settings.get('mainframe position', (50, 30)), size=size, style=wx.DEFAULT_FRAME_STYLE | wx.SUNKEN_BORDER) # set Left to Right direction (while we don't have localization) self.SetLayoutDirection(wx.Layout_LeftToRight) # self.SetLayoutDirection(wx.Layout_RightToLeft) self._mgr = aui.AuiManager() # tell AuiManager to manage this frame self._mgr.SetManagedWindow(self) # set frame icon # self.SetIcon(Icon('widgets/robot.ico')) # Maybe is not needed # self.SetMinSize(size) self.SetMinSize(wx.Size(400, 300)) self.ensure_on_screen() if application.settings.get('mainframe maximized', False): self.Maximize() self._application = application self._controller = controller self.favicon = Icon( os.path.join(os.path.dirname(__file__), "..", "widgets", "robot.ico"), wx.BITMAP_TYPE_ICO, 256, 256) self.SetIcon(self.favicon) #TODO use SetIcons for all sizes self._init_ui() self._plugin_manager = PluginManager(self.notebook) self._review_dialog = None self._view_all_tags_dialog = None #, self, self.actions, # self._application.settings) self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_MOVE, self.OnMove) self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize) self.Bind(wx.EVT_DIRCTRL_FILEACTIVATED, self.OnOpenFile) self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnMenuOpenFile) self._subscribe_messages() wx.CallAfter(self.actions.register_tools) # DEBUG def _subscribe_messages(self): for listener, topic in [ (lambda msg: self.SetStatusText('Saved %s' % msg.path), RideSaved), (lambda msg: self.SetStatusText('Saved all files'), RideSaveAll), (self._set_label, RideTreeSelection), (self._show_validation_error, RideInputValidationError), (self._show_modification_prevented_error, RideModificationPrevented) ]: PUBLISHER.subscribe(listener, topic) def _set_label(self, message): self.SetTitle(self._create_title(message)) def _create_title(self, message): title = 'RIDE' if message: item = message.item title += ' - ' + item.datafile.name if not item.is_modifiable(): title += ' (READ ONLY)' return title def _show_validation_error(self, message): wx.MessageBox(message.message, 'Validation Error', style=wx.ICON_ERROR) def _show_modification_prevented_error(self, message): wx.MessageBox("\"%s\" is read only" % message.controller.datafile_controller.filename, "Modification prevented", style=wx.ICON_ERROR) def _init_ui(self): # self._mgr.AddPane(wx.Panel(self), aui.AuiPaneInfo().CenterPane()) ##### self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) # self._mgr.AddPane(wx.Panel(self), aui.AuiPaneInfo().CenterPane()) # set up default notebook style self._notebook_style = aui.AUI_NB_DEFAULT_STYLE | \ aui.AUI_NB_TAB_EXTERNAL_MOVE | wx.NO_BORDER # TODO self._notebook_theme = 0 (allow to select themes for notebooks) # self.notebook = NoteBook(self.splitter, self._application, # self._notebook_style) self.notebook = NoteBook(self, self._application, self._notebook_style) self._mgr.AddPane( self.notebook, aui.AuiPaneInfo().Name("notebook_editors").CenterPane().PaneBorder( False)) ################ Test # self._mgr.AddPane(self.CreateTextCtrl(), # aui.AuiPaneInfo().Name("text_content"). # CenterPane().Hide().MinimizeButton(True)) # # self._mgr.AddPane(self.CreateHTMLCtrl(), # aui.AuiPaneInfo().Name("html_content"). # CenterPane().Hide().MinimizeButton(True)) # # self._mgr.AddPane(self.CreateNotebook(), # aui.AuiPaneInfo().Name("notebook_content"). # CenterPane().PaneBorder(False)) #################### # self._mgr.AddPane(self.CreateSizeReportCtrl(), aui.AuiPaneInfo(). # Name("test1").Caption( # "Pane Caption").Top().MinimizeButton(True)) mb = MenuBar(self) self.toolbar = ToolBar(self) self.toolbar.SetMinSize(wx.Size(100, 60)) # self.SetToolBar(self.toolbar.GetToolBar()) self._mgr.AddPane( self.toolbar, aui.AuiPaneInfo().Name("maintoolbar").ToolbarPane().Top()) self.actions = ActionRegisterer(self._mgr, mb, self.toolbar, ShortcutRegistry(self)) """ ##### Test tb3 = self.testToolbar() self._mgr.AddPane(tb3, aui.AuiPaneInfo().Name("tb3").Caption("Toolbar 3"). ToolbarPane().Top().Row(1).Position(1)) ##### End Test """ # Tree is always created here self.tree = Tree(self, self.actions, self._application.settings) self.tree.SetMinSize(wx.Size(120, 200)) # TreePlugin will manage showing the Tree self.actions.register_actions( ActionInfoCollection(_menudata, self, self.tree)) ###### File explorer panel is always created here self.filemgr = FileExplorer(self, self._controller) self.filemgr.SetMinSize(wx.Size(120, 200)) mb.take_menu_bar_into_use() self.CreateStatusBar() self.SetIcons(ImageProvider().PROGICONS) # tell the manager to "commit" all the changes just made self._mgr.Update() def testToolbar(self): #### More testing prepend_items, append_items = [], [] item = aui.AuiToolBarItem() item.SetKind(wx.ITEM_SEPARATOR) append_items.append(item) item = aui.AuiToolBarItem() item.SetKind(wx.ITEM_NORMAL) item.SetId(ID_CustomizeToolbar) item.SetLabel("Customize...") append_items.append(item) tb3 = aui.AuiToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, agwStyle=aui.AUI_TB_DEFAULT_STYLE | aui.AUI_TB_OVERFLOW) tb3.SetToolBitmapSize(wx.Size(16, 16)) tb3_bmp1 = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, wx.Size(16, 16)) tb3.AddSimpleTool(ID_SampleItem + 16, "Check 1", tb3_bmp1, "Check 1", aui.ITEM_CHECK) tb3.AddSimpleTool(ID_SampleItem + 17, "Check 2", tb3_bmp1, "Check 2", aui.ITEM_CHECK) tb3.AddSimpleTool(ID_SampleItem + 18, "Check 3", tb3_bmp1, "Check 3", aui.ITEM_CHECK) tb3.AddSimpleTool(ID_SampleItem + 19, "Check 4", tb3_bmp1, "Check 4", aui.ITEM_CHECK) tb3.AddSeparator() tb3.AddSimpleTool(ID_SampleItem + 20, "Radio 1", tb3_bmp1, "Radio 1", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 21, "Radio 2", tb3_bmp1, "Radio 2", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 22, "Radio 3", tb3_bmp1, "Radio 3", aui.ITEM_RADIO) tb3.AddSeparator() tb3.AddSimpleTool(ID_SampleItem + 23, "Radio 1 (Group 2)", tb3_bmp1, "Radio 1 (Group 2)", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 24, "Radio 2 (Group 2)", tb3_bmp1, "Radio 2 (Group 2)", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 25, "Radio 3 (Group 2)", tb3_bmp1, "Radio 3 (Group 2)", aui.ITEM_RADIO) tb3.SetCustomOverflowItems(prepend_items, append_items) tb3.Realize() return tb3 def get_selected_datafile(self): return self.tree.get_selected_datafile() def get_selected_datafile_controller(self): return self.tree.get_selected_datafile_controller() def OnClose(self, event): if self._allowed_to_exit(): perspective = self._mgr.SavePerspective() self._application.settings.set('AUI Perspective', perspective) PUBLISHER.unsubscribe(self._set_label, RideTreeSelection) RideClosing().publish() # deinitialize the frame manager self._mgr.UnInit() self.Destroy() else: wx.CloseEvent.Veto(event) def OnSize(self, event): if not self.IsMaximized(): self._application.settings['mainframe maximized'] = False self._application.settings['mainframe size'] = self.DoGetSize() event.Skip() def OnMove(self, event): # When the window is Iconized, a move event is also raised, but we # don't want to update the position in the settings file if not self.IsIconized() and not self.IsMaximized(): self._application.settings['mainframe position'] =\ self.DoGetPosition() event.Skip() def OnMaximize(self, event): self._application.settings['mainframe maximized'] = True event.Skip() def OnReleasenotes(self, event): pass def _allowed_to_exit(self): if self.has_unsaved_changes(): ret = wx.MessageBox( "There are unsaved modifications.\n" "Do you want to save your changes before " "exiting?", "Warning", wx.ICON_WARNING | wx.CANCEL | wx.YES_NO) if ret == wx.CANCEL: return False if ret == wx.YES: self.save() return True def has_unsaved_changes(self): return self._controller.is_dirty() def OnNewProject(self, event): if not self.check_unsaved_modifications(): return NewProjectDialog(self._controller).execute() self._populate_tree() def _populate_tree(self): self.tree.populate(self._controller) self.filemgr.update_tree() def OnOpenFile(self, event): if not self.filemgr: return # EVT_DIRCTRL_FILEACTIVATED from os.path import splitext robottypes = self._application.settings.get( 'robot types', ['robot', 'resource' 'txt', 'tsv', 'html']) path = self.filemgr.GetFilePath() ext = '' if len(path) > 0: ext = splitext(path) ext = ext[1].replace('.', '') # print("DEBUG: path %s ext %s" % (path, ext)) if len(ext) > 0 and ext in robottypes: if not self.check_unsaved_modifications(): return if self.open_suite(path): return from robotide.editor import customsourceeditor customsourceeditor.main(path) def OnMenuOpenFile(self, event): if not self.filemgr: return # TODO: Use widgets/popupmenu tools path = self.filemgr.GetFilePath() if len(path) > 0: self.OnOpenFile(event) else: path = self.filemgr.GetPath() if not self.check_unsaved_modifications(): return self.open_suite(path) # It is a directory, do not edit event.Skip() def OnOpenTestSuite(self, event): if not self.check_unsaved_modifications(): return path = RobotFilePathDialog(self, self._controller, self._application.settings).execute() if path: if self.open_suite(path): return from robotide.editor import customsourceeditor customsourceeditor.main(path) def check_unsaved_modifications(self): if self.has_unsaved_changes(): ret = wx.MessageBox( "There are unsaved modifications.\n" "Do you want to proceed without saving?", "Warning", wx.ICON_WARNING | wx.YES_NO) return ret == wx.YES return True def open_suite(self, path): self._controller.update_default_dir(path) # self._controller.default_dir will only save dir path # need to save path to self._application.workspace_path too self._application.workspace_path = path try: err = self._controller.load_datafile(path, LoadProgressObserver(self)) finally: if isinstance(err, UserWarning): # raise err # Just leave message in Parser Log return False self._populate_tree() return True def refresh_datafile(self, item, event): self.tree.refresh_datafile(item, event) if self.filemgr: self.filemgr.ReCreateTree() def OnOpenDirectory(self, event): if self.check_unsaved_modifications(): path = wx.DirSelector(message="Choose a directory containing Robot" " files", default_path=self._controller.default_dir) if path: self.open_suite(path) def OnSave(self, event): RideBeforeSaving().publish() self.save() def OnSaveAll(self, event): RideBeforeSaving().publish() self.save_all() def save_all(self): self._show_dialog_for_files_without_format() self._controller.execute(SaveAll()) def save(self, controller=None): if controller is None: controller = self.get_selected_datafile_controller() if controller is not None: if not controller.has_format(): self._show_dialog_for_files_without_format(controller) else: controller.execute(SaveFile()) def _show_dialog_for_files_without_format(self, controller=None): files_without_format = self._controller.get_files_without_format( controller) for f in files_without_format: self._show_format_dialog_for(f) def _show_format_dialog_for(self, file_controller_without_format): InitFileFormatDialog(file_controller_without_format).execute() def OnExit(self, event): self.Close() def OnManagePlugins(self, event): self._plugin_manager.show(self._application.get_plugins()) def OnViewAllTags(self, event): if self._view_all_tags_dialog is None: self._view_all_tags_dialog = ViewAllTagsDialog( self._controller, self) self._view_all_tags_dialog.show_dialog() def OnSearchUnusedKeywords(self, event): if self._review_dialog is None: self._review_dialog = ReviewDialog(self._controller, self) self._review_dialog.show_dialog() def OnPreferences(self, event): dlg = PreferenceEditor(self, "RIDE - Preferences", self._application.preferences, style='tree') # I would prefer that this not be modal, but making it non- # modal opens up a can of worms. We don't want to have to deal # with settings getting changed out from under us while the # dialog is open. dlg.ShowModal() dlg.Destroy() def OnAbout(self, event): dlg = AboutDialog() dlg.ShowModal() dlg.Destroy() def OnShortcutkeys(self, event): dialog = ShortcutKeysDialog() dialog.Show() def OnReportaProblem(self, event): wx.LaunchDefaultBrowser("https://github.com/robotframework/RIDE/issues" "?utf8=%E2%9C%93&q=is%3Aissue+%22search" "%20your%20problem%22") def OnUserGuide(self, event): wx.LaunchDefaultBrowser("http://robotframework.org/robotframework/" "#user-guide") def OnWiki(self, event): wx.LaunchDefaultBrowser("https://github.com/robotframework/RIDE/wiki") def _has_data(self): return self._controller.data is not None def _refresh(self): self._controller.update_namespace() # This code is copied from http://wiki.wxpython.org/EnsureFrameIsOnScreen, # and adapted to fit our code style. def ensure_on_screen(self): try: display_id = wx.Display.GetFromWindow(self) except NotImplementedError: display_id = 0 if display_id == -1: display_id = 0 geometry = wx.Display(display_id).GetGeometry() position = self.GetPosition() if position.x < geometry.x: position.x = geometry.x if position.y < geometry.y: position.y = geometry.y size = self.GetSize() if size.width > geometry.width: size.width = geometry.width position.x = geometry.x elif position.x + size.width > geometry.x + geometry.width: position.x = geometry.x + geometry.width - size.width if size.height > geometry.height: size.height = geometry.height position.y = geometry.y elif position.y + size.height > geometry.y + geometry.height: position.y = geometry.y + geometry.height - size.height self.SetPosition(position) self.SetSize(size) # DEBUG just some testing def CreateSizeReportCtrl(self, width=80, height=80): ctrl = SizeReportCtrl(self, -1, wx.DefaultPosition, wx.Size(width, height), self._mgr) return ctrl def show_confirm_reload_dlg(self, event): msg = [ 'Workspace modifications detected on the file system.', 'Do you want to reload the workspace?', 'Answering <No> will overwrite the changes on disk.' ] if self._controller.is_dirty(): msg.insert(2, 'Answering <Yes> will discard unsaved changes.') ret = wx.MessageBox('\n'.join(msg), 'Files Changed On Disk', style=wx.YES_NO | wx.ICON_WARNING) confirmed = ret == wx.YES if confirmed: # workspace_path should update after open directory/suite # There're two scenarios: # 1. path is a directory # 2. path is a suite file new_path = RideFSWatcherHandler.get_workspace_new_path() if new_path and os.path.exists(new_path): wx.CallAfter(self.open_suite, new_path) else: # in case workspace is totally removed # ask user to open new directory # TODO add some notification msg to users wx.CallAfter(self.OnOpenDirectory, event) else: for _ in self._controller.datafiles: if _.has_been_modified_on_disk( ) or _.has_been_removed_from_disk(): if not os.path.exists(_.directory): # sub folder is removed, create new one before saving os.makedirs(_.directory) _.mark_dirty() self.save_all()
class RideFrame(with_metaclass(classmaker(), wx.Frame, RideEventHandler)): def __init__(self, application, controller): size = application.settings.get('mainframe size', (1100, 700)) wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title='RIDE', pos=application.settings.get('mainframe position', (50, 30)), size=size, style=wx.DEFAULT_FRAME_STYLE | wx.SUNKEN_BORDER) self._mgr = aui.AuiManager() # tell AuiManager to manage this frame self._mgr.SetManagedWindow(self) # set frame icon # self.SetIcon(Icon('widgets/robot.ico')) # Maybe is not needed # self.SetMinSize(size) self.SetMinSize(wx.Size(400, 300)) self.ensure_on_screen() if application.settings.get('mainframe maximized', False): self.Maximize() self._application = application self._controller = controller self._init_ui() self._plugin_manager = PluginManager(self.notebook) self._review_dialog = None self._view_all_tags_dialog = None self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_MOVE, self.OnMove) self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize) self.Bind(wx.EVT_DIRCTRL_FILEACTIVATED, self.OnOpenFile) self._subscribe_messages() #print("DEBUG: Call register_tools, actions: %s" % self.actions.__repr__()) if PY2: wx.CallLater(100, self.actions.register_tools) # DEBUG else: wx.CallAfter(self.actions.register_tools) # DEBUG def _subscribe_messages(self): for listener, topic in [ (lambda msg: self.SetStatusText('Saved %s' % msg.path), RideSaved), (lambda msg: self.SetStatusText('Saved all files'), RideSaveAll), (self._set_label, RideTreeSelection), (self._show_validation_error, RideInputValidationError), (self._show_modification_prevented_error, RideModificationPrevented) ]: PUBLISHER.subscribe(listener, topic) def _set_label(self, message): self.SetTitle(self._create_title(message)) def _create_title(self, message): title = 'RIDE' if message: item = message.item title += ' - ' + item.datafile.name if not item.is_modifiable(): title += ' (READ ONLY)' return title def _show_validation_error(self, message): wx.MessageBox(message.message, 'Validation Error', style=wx.ICON_ERROR) def _show_modification_prevented_error(self, message): wx.MessageBox("\"%s\" is read only" % message.controller.datafile_controller.filename, "Modification prevented", style=wx.ICON_ERROR) def _init_ui(self): # self._mgr.AddPane(wx.Panel(self), aui.AuiPaneInfo().CenterPane()) ##### self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) # self._mgr.AddPane(wx.Panel(self), aui.AuiPaneInfo().CenterPane()) # set up default notebook style self._notebook_style = aui.AUI_NB_DEFAULT_STYLE |\ aui.AUI_NB_TAB_EXTERNAL_MOVE | wx.NO_BORDER # TODO self._notebook_theme = 0 (allow to select themes for notebooks) # self.notebook = NoteBook(self.splitter, self._application, # self._notebook_style) self.notebook = NoteBook(self, self._application, self._notebook_style) self._mgr.AddPane( self.notebook, aui.AuiPaneInfo().Name("notebook_editors").CenterPane().PaneBorder( False)) ################ Test # self._mgr.AddPane(self.CreateTextCtrl(), # aui.AuiPaneInfo().Name("text_content"). # CenterPane().Hide().MinimizeButton(True)) # # self._mgr.AddPane(self.CreateHTMLCtrl(), # aui.AuiPaneInfo().Name("html_content"). # CenterPane().Hide().MinimizeButton(True)) # # self._mgr.AddPane(self.CreateNotebook(), # aui.AuiPaneInfo().Name("notebook_content"). # CenterPane().PaneBorder(False)) #################### # self._mgr.AddPane(self.CreateSizeReportCtrl(), aui.AuiPaneInfo(). # Name("test1").Caption( # "Pane Caption").Top().MinimizeButton(True)) mb = MenuBar(self) self.toolbar = ToolBar(self) self.toolbar.SetMinSize(wx.Size(100, 60)) # self.SetToolBar(self.toolbar.GetToolBar()) self._mgr.AddPane( self.toolbar, aui.AuiPaneInfo().Name("maintoolbar").ToolbarPane().Top()) self.actions = ActionRegisterer(self._mgr, mb, self.toolbar, ShortcutRegistry(self)) """ ##### Test tb3 = self.testToolbar() self._mgr.AddPane(tb3, aui.AuiPaneInfo().Name("tb3").Caption("Toolbar 3"). ToolbarPane().Top().Row(1).Position(1)) ##### End Test """ # self._mgr.AddPane(self.CreateTreeControl(), # aui.AuiPaneInfo().Name("tree_content"). # CenterPane().Hide().MinimizeButton(True)) ###### self.tree = Tree(self.splitter, self.actions, self._application.settings) self.tree = Tree(self, self.actions, self._application.settings) #self.tree.SetMinSize(wx.Size(100, 200)) self.tree.SetMinSize(wx.Size(120, 200)) self._mgr.AddPane( self.tree, aui.AuiPaneInfo().Name("tree_content").Caption( "Test Suites").LeftDockable(True).CloseButton(False)) # MaximizeButton(True).MinimizeButton(True)) self.actions.register_actions( ActionInfoCollection(_menudata, self, self.tree)) ###### File explorer pane self.filemgr = wx.GenericDirCtrl(self, -1, size=(200, 225), style=wx.DIRCTRL_3D_INTERNAL) self.filemgr.SetMinSize(wx.Size(120, 200)) self._mgr.AddPane( self.filemgr, aui.AuiPaneInfo().Name("file_manager").Caption( "Files").LeftDockable(True).CloseButton(True)) mb.take_menu_bar_into_use() #### self.splitter.SetMinimumPaneSize(100) #### self.splitter.SplitVertically(self.tree, self.notebook, 300) self.CreateStatusBar() self.SetIcons(ImageProvider().PROGICONS) # tell the manager to "commit" all the changes just made self._mgr.Update() def testToolbar(self): #### More testing prepend_items, append_items = [], [] item = aui.AuiToolBarItem() item.SetKind(wx.ITEM_SEPARATOR) append_items.append(item) item = aui.AuiToolBarItem() item.SetKind(wx.ITEM_NORMAL) item.SetId(ID_CustomizeToolbar) item.SetLabel("Customize...") append_items.append(item) tb3 = aui.AuiToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, agwStyle=aui.AUI_TB_DEFAULT_STYLE | aui.AUI_TB_OVERFLOW) tb3.SetToolBitmapSize(wx.Size(16, 16)) tb3_bmp1 = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, wx.Size(16, 16)) tb3.AddSimpleTool(ID_SampleItem + 16, "Check 1", tb3_bmp1, "Check 1", aui.ITEM_CHECK) tb3.AddSimpleTool(ID_SampleItem + 17, "Check 2", tb3_bmp1, "Check 2", aui.ITEM_CHECK) tb3.AddSimpleTool(ID_SampleItem + 18, "Check 3", tb3_bmp1, "Check 3", aui.ITEM_CHECK) tb3.AddSimpleTool(ID_SampleItem + 19, "Check 4", tb3_bmp1, "Check 4", aui.ITEM_CHECK) tb3.AddSeparator() tb3.AddSimpleTool(ID_SampleItem + 20, "Radio 1", tb3_bmp1, "Radio 1", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 21, "Radio 2", tb3_bmp1, "Radio 2", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 22, "Radio 3", tb3_bmp1, "Radio 3", aui.ITEM_RADIO) tb3.AddSeparator() tb3.AddSimpleTool(ID_SampleItem + 23, "Radio 1 (Group 2)", tb3_bmp1, "Radio 1 (Group 2)", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 24, "Radio 2 (Group 2)", tb3_bmp1, "Radio 2 (Group 2)", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 25, "Radio 3 (Group 2)", tb3_bmp1, "Radio 3 (Group 2)", aui.ITEM_RADIO) tb3.SetCustomOverflowItems(prepend_items, append_items) tb3.Realize() return tb3 def get_selected_datafile(self): return self.tree.get_selected_datafile() def get_selected_datafile_controller(self): return self.tree.get_selected_datafile_controller() def OnClose(self, event): if self._allowed_to_exit(): PUBLISHER.unsubscribe(self._set_label, RideTreeSelection) RideClosing().publish() # deinitialize the frame manager self._mgr.UnInit() self.Destroy() else: wx.CloseEvent.Veto(event) def OnSize(self, event): if not self.IsMaximized(): self._application.settings['mainframe maximized'] = False self._application.settings['mainframe size'] = self.MyGetSize() # DEBUG wxPhoenix .GetSizeTuple() event.Skip() def OnMove(self, event): # When the window is Iconized, a move event is also raised, but we # don't want to update the position in the settings file if not self.IsIconized() and not self.IsMaximized(): # DEBUG wxPhoenix writes wx.Point(50, 30) instead of just (50, 30) self._application.settings['mainframe position'] = \ self.MyGetPosition() # DEBUG wxPhoenix self.GetPositionTuple() event.Skip() def OnMaximize(self, event): self._application.settings['mainframe maximized'] = True event.Skip() def OnReleasenotes(self, event): pass def MyGetSize(self): if wx.VERSION >= (3, 0, 3, ''): # DEBUG wxPhoenix return self.DoGetSize() else: return self.GetSizeTuple() def MyGetPosition(self): if wx.VERSION >= (3, 0, 3, ''): # DEBUG wxPhoenix return self.DoGetPosition() else: return self.GetPositionTuple() def _allowed_to_exit(self): if self.has_unsaved_changes(): ret = wx.MessageBox( "There are unsaved modifications.\n" "Do you want to save your changes before " "exiting?", "Warning", wx.ICON_WARNING | wx.CANCEL | wx.YES_NO) if ret == wx.CANCEL: return False if ret == wx.YES: self.save() return True def has_unsaved_changes(self): return self._controller.is_dirty() def OnNewProject(self, event): if not self.check_unsaved_modifications(): return NewProjectDialog(self._controller).execute() self._populate_tree() def _populate_tree(self): self.tree.populate(self._controller) if len(self._controller.data.directory) > 1: self.filemgr.SelectPath(self._controller.data.source) try: self.filemgr.ExpandPath(self._controller.data.source) except Exception: pass self.filemgr.Update() def OnOpenFile(self, event): # EVT_DIRCTRL_FILEACTIVATED from os.path import splitext robottypes = self._application.settings.get( 'robot types', ['robot', 'resource' 'txt', 'tsv', 'html']) path = self.filemgr.GetFilePath() ext = splitext(path) ext = ext[1].replace('.', '') # print("DEBUG: path %s ext %s" % (path, ext)) if ext in robottypes: if not self.check_unsaved_modifications(): return try: self.open_suite(path) return except UserWarning as e: pass from robotide.editor import customsourceeditor customsourceeditor.main(path) def OnOpenTestSuite(self, event): if not self.check_unsaved_modifications(): return path = RobotFilePathDialog(self, self._controller, self._application.settings).execute() if path: try: self.open_suite(path) return except UserWarning as e: pass from robotide.editor import customsourceeditor customsourceeditor.main(path) def check_unsaved_modifications(self): if self.has_unsaved_changes(): ret = wx.MessageBox( "There are unsaved modifications.\n" "Do you want to proceed without saving?", "Warning", wx.ICON_WARNING | wx.YES_NO) return ret == wx.YES return True def open_suite(self, path): self._controller.update_default_dir(path) err = self._controller.load_datafile(path, LoadProgressObserver(self)) if isinstance(err, UserWarning): raise err self._populate_tree() def refresh_datafile(self, item, event): self.tree.refresh_datafile(item, event) def OnOpenDirectory(self, event): if self.check_unsaved_modifications(): if wx.VERSION >= (3, 0, 3, ''): # DEBUG wxPhoenix path = wx.DirSelector( message="Choose a directory containing " "Robot files", default_path=self._controller.default_dir) else: path = wx.DirSelector(message="Choose a directory containing " "Robot files", defaultPath=self._controller.default_dir) if path: self.open_suite(path) def OnSave(self, event): self.save() def OnSaveAll(self, event): self.save_all() def save_all(self): self._show_dialog_for_files_without_format() self._controller.execute(SaveAll()) def save(self, controller=None): if controller is None: controller = self.get_selected_datafile_controller() if controller is not None: if not controller.has_format(): self._show_dialog_for_files_without_format(controller) else: controller.execute(SaveFile()) def _show_dialog_for_files_without_format(self, controller=None): files_without_format = self._controller.get_files_without_format( controller) for f in files_without_format: self._show_format_dialog_for(f) def _show_format_dialog_for(self, file_controller_without_format): InitFileFormatDialog(file_controller_without_format).execute() def OnExit(self, event): self.Close() def OnManagePlugins(self, event): self._plugin_manager.show(self._application.get_plugins()) def OnViewAllTags(self, event): if self._view_all_tags_dialog is None: self._view_all_tags_dialog = ViewAllTagsDialog( self._controller, self) self._view_all_tags_dialog.show_dialog() def OnSearchUnusedKeywords(self, event): if self._review_dialog is None: self._review_dialog = ReviewDialog(self._controller, self) self._review_dialog.show_dialog() def OnPreferences(self, event): dlg = PreferenceEditor(self, "RIDE - Preferences", self._application.preferences, style='tree') # I would prefer that this not be modal, but making it non- # modal opens up a can of worms. We don't want to have to deal # with settings getting changed out from under us while the # dialog is open. dlg.ShowModal() dlg.Destroy() def OnAbout(self, event): dlg = AboutDialog() dlg.ShowModal() dlg.Destroy() def OnShortcutkeys(self, event): dialog = ShortcutKeysDialog() dialog.Show() def OnReportaProblem(self, event): wx.LaunchDefaultBrowser( "https://github.com/robotframework/RIDE/issues") def OnUserGuide(self, event): wx.LaunchDefaultBrowser("http://robotframework.org/robotframework/" "#user-guide") def _has_data(self): return self._controller.data is not None def _refresh(self): self._controller.update_namespace() # This code is copied from http://wiki.wxpython.org/EnsureFrameIsOnScreen, # and adapted to fit our code style. def ensure_on_screen(self): try: display_id = wx.Display.GetFromWindow(self) except NotImplementedError: display_id = 0 if display_id == -1: display_id = 0 geometry = wx.Display(display_id).GetGeometry() position = self.GetPosition() if position.x < geometry.x: position.x = geometry.x if position.y < geometry.y: position.y = geometry.y size = self.GetSize() if size.width > geometry.width: size.width = geometry.width position.x = geometry.x elif position.x + size.width > geometry.x + geometry.width: position.x = geometry.x + geometry.width - size.width if size.height > geometry.height: size.height = geometry.height position.y = geometry.y elif position.y + size.height > geometry.y + geometry.height: position.y = geometry.y + geometry.height - size.height self.SetPosition(position) self.SetSize(size) # DEBUG just some testing def CreateSizeReportCtrl(self, width=80, height=80): ctrl = SizeReportCtrl(self, -1, wx.DefaultPosition, wx.Size(width, height), self._mgr) return ctrl
class RideFrame(wx.Frame, RideEventHandler): __metaclass__ = classmaker() def __init__(self, application, controller): size = application.settings.get('mainframe size', (1100, 700)) wx.Frame.__init__(self, parent=None, id = wx.ID_ANY, title='RIDE', pos=application.settings.get('mainframe position', (50, 30)), size=size, style=wx.DEFAULT_FRAME_STYLE | wx.SUNKEN_BORDER) self._mgr = aui.AuiManager() # tell AuiManager to manage this frame self._mgr.SetManagedWindow(self) # set frame icon # self.SetIcon(Icon('widgets/robot.ico')) # Maybe is not needed # self.SetMinSize(size) self.SetMinSize(wx.Size(400, 300)) self.ensure_on_screen() if application.settings.get('mainframe maximized', False): self.Maximize() self._application = application self._controller = controller self._init_ui() self._plugin_manager = PluginManager(self.notebook) self._review_dialog = None self._view_all_tags_dialog = None self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_MOVE, self.OnMove) self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize) self.Bind(wx.EVT_DIRCTRL_FILEACTIVATED, self.OnOpenFile) self._subscribe_messages() #print("DEBUG: Call register_tools, actions: %s" % self.actions.__repr__()) if PY2: wx.CallLater(100, self.actions.register_tools) # DEBUG else: wx.CallAfter(self.actions.register_tools) # DEBUG def _subscribe_messages(self): for listener, topic in [ (lambda msg: self.SetStatusText('Saved %s' % msg.path), RideSaved), (lambda msg: self.SetStatusText('Saved all files'), RideSaveAll), (self._set_label, RideTreeSelection), (self._show_validation_error, RideInputValidationError), (self._show_modification_prevented_error, RideModificationPrevented) ]: PUBLISHER.subscribe(listener, topic) def _set_label(self, message): self.SetTitle(self._create_title(message)) def _create_title(self, message): title = 'RIDE' if message: item = message.item title += ' - ' + item.datafile.name if not item.is_modifiable(): title += ' (READ ONLY)' return title def _show_validation_error(self, message): wx.MessageBox(message.message, 'Validation Error', style=wx.ICON_ERROR) def _show_modification_prevented_error(self, message): wx.MessageBox("\"%s\" is read only" % message.controller.datafile_controller.filename, "Modification prevented", style=wx.ICON_ERROR) def _init_ui(self): # self._mgr.AddPane(wx.Panel(self), aui.AuiPaneInfo().CenterPane()) ##### self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) # self._mgr.AddPane(wx.Panel(self), aui.AuiPaneInfo().CenterPane()) # set up default notebook style self._notebook_style = aui.AUI_NB_DEFAULT_STYLE |\ aui.AUI_NB_TAB_EXTERNAL_MOVE | wx.NO_BORDER # TODO self._notebook_theme = 0 (allow to select themes for notebooks) # self.notebook = NoteBook(self.splitter, self._application, # self._notebook_style) self.notebook = NoteBook(self, self._application, self._notebook_style) self._mgr.AddPane(self.notebook, aui.AuiPaneInfo().Name("notebook_editors"). CenterPane().PaneBorder(False)) ################ Test # self._mgr.AddPane(self.CreateTextCtrl(), # aui.AuiPaneInfo().Name("text_content"). # CenterPane().Hide().MinimizeButton(True)) # # self._mgr.AddPane(self.CreateHTMLCtrl(), # aui.AuiPaneInfo().Name("html_content"). # CenterPane().Hide().MinimizeButton(True)) # # self._mgr.AddPane(self.CreateNotebook(), # aui.AuiPaneInfo().Name("notebook_content"). # CenterPane().PaneBorder(False)) #################### # self._mgr.AddPane(self.CreateSizeReportCtrl(), aui.AuiPaneInfo(). # Name("test1").Caption( # "Pane Caption").Top().MinimizeButton(True)) mb = MenuBar(self) self.toolbar = ToolBar(self) self.toolbar.SetMinSize(wx.Size(100, 60)) # self.SetToolBar(self.toolbar.GetToolBar()) self._mgr.AddPane(self.toolbar, aui.AuiPaneInfo().Name("maintoolbar"). ToolbarPane().Top()) self.actions = ActionRegisterer(self._mgr, mb, self.toolbar, ShortcutRegistry(self)) """ ##### Test tb3 = self.testToolbar() self._mgr.AddPane(tb3, aui.AuiPaneInfo().Name("tb3").Caption("Toolbar 3"). ToolbarPane().Top().Row(1).Position(1)) ##### End Test """ # self._mgr.AddPane(self.CreateTreeControl(), # aui.AuiPaneInfo().Name("tree_content"). # CenterPane().Hide().MinimizeButton(True)) ###### self.tree = Tree(self.splitter, self.actions, self._application.settings) self.tree = Tree(self, self.actions, self._application.settings) #self.tree.SetMinSize(wx.Size(100, 200)) self.tree.SetMinSize(wx.Size(120, 200)) self._mgr.AddPane(self.tree, aui.AuiPaneInfo().Name("tree_content"). Caption("Test Suites").LeftDockable(True). CloseButton(False)) # MaximizeButton(True).MinimizeButton(True)) self.actions.register_actions( ActionInfoCollection(_menudata, self, self.tree)) ###### File explorer pane self.filemgr = wx.GenericDirCtrl(self, -1, size=(200, 225), style=wx.DIRCTRL_3D_INTERNAL) self.filemgr.SetMinSize(wx.Size(120, 200)) self._mgr.AddPane(self.filemgr, aui.AuiPaneInfo().Name("file_manager"). Caption("Files").LeftDockable(True). CloseButton(True)) mb.take_menu_bar_into_use() #### self.splitter.SetMinimumPaneSize(100) #### self.splitter.SplitVertically(self.tree, self.notebook, 300) self.CreateStatusBar() self.SetIcons(ImageProvider().PROGICONS) # tell the manager to "commit" all the changes just made self._mgr.Update() def testToolbar(self): #### More testing prepend_items, append_items = [], [] item = aui.AuiToolBarItem() item.SetKind(wx.ITEM_SEPARATOR) append_items.append(item) item = aui.AuiToolBarItem() item.SetKind(wx.ITEM_NORMAL) item.SetId(ID_CustomizeToolbar) item.SetLabel("Customize...") append_items.append(item) tb3 = aui.AuiToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, agwStyle=aui.AUI_TB_DEFAULT_STYLE | aui.AUI_TB_OVERFLOW) tb3.SetToolBitmapSize(wx.Size(16, 16)) tb3_bmp1 = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, wx.Size(16, 16)) tb3.AddSimpleTool(ID_SampleItem + 16, "Check 1", tb3_bmp1, "Check 1", aui.ITEM_CHECK) tb3.AddSimpleTool(ID_SampleItem + 17, "Check 2", tb3_bmp1, "Check 2", aui.ITEM_CHECK) tb3.AddSimpleTool(ID_SampleItem + 18, "Check 3", tb3_bmp1, "Check 3", aui.ITEM_CHECK) tb3.AddSimpleTool(ID_SampleItem + 19, "Check 4", tb3_bmp1, "Check 4", aui.ITEM_CHECK) tb3.AddSeparator() tb3.AddSimpleTool(ID_SampleItem + 20, "Radio 1", tb3_bmp1, "Radio 1", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 21, "Radio 2", tb3_bmp1, "Radio 2", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 22, "Radio 3", tb3_bmp1, "Radio 3", aui.ITEM_RADIO) tb3.AddSeparator() tb3.AddSimpleTool(ID_SampleItem + 23, "Radio 1 (Group 2)", tb3_bmp1, "Radio 1 (Group 2)", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 24, "Radio 2 (Group 2)", tb3_bmp1, "Radio 2 (Group 2)", aui.ITEM_RADIO) tb3.AddSimpleTool(ID_SampleItem + 25, "Radio 3 (Group 2)", tb3_bmp1, "Radio 3 (Group 2)", aui.ITEM_RADIO) tb3.SetCustomOverflowItems(prepend_items, append_items) tb3.Realize() return tb3 def get_selected_datafile(self): return self.tree.get_selected_datafile() def get_selected_datafile_controller(self): return self.tree.get_selected_datafile_controller() def OnClose(self, event): if self._allowed_to_exit(): PUBLISHER.unsubscribe(self._set_label, RideTreeSelection) RideClosing().publish() # deinitialize the frame manager self._mgr.UnInit() self.Destroy() else: wx.CloseEvent.Veto(event) def OnSize(self, event): if not self.IsMaximized(): self._application.settings['mainframe maximized'] = False self._application.settings['mainframe size'] = self.MyGetSize() # DEBUG wxPhoenix .GetSizeTuple() event.Skip() def OnMove(self, event): # When the window is Iconized, a move event is also raised, but we # don't want to update the position in the settings file if not self.IsIconized() and not self.IsMaximized(): # DEBUG wxPhoenix writes wx.Point(50, 30) instead of just (50, 30) self._application.settings['mainframe position'] = \ self.MyGetPosition() # DEBUG wxPhoenix self.GetPositionTuple() event.Skip() def OnMaximize(self, event): self._application.settings['mainframe maximized'] = True event.Skip() def OnReleasenotes(self, event): pass def MyGetSize(self): if wx.VERSION >= (3, 0, 3, ''): # DEBUG wxPhoenix return self.DoGetSize() else: return self.GetSizeTuple() def MyGetPosition(self): if wx.VERSION >= (3, 0, 3, ''): # DEBUG wxPhoenix return self.DoGetPosition() else: return self.GetPositionTuple() def _allowed_to_exit(self): if self.has_unsaved_changes(): ret = wx.MessageBox("There are unsaved modifications.\n" "Do you want to save your changes before " "exiting?", "Warning", wx.ICON_WARNING | wx.CANCEL | wx.YES_NO) if ret == wx.CANCEL: return False if ret == wx.YES: self.save() return True def has_unsaved_changes(self): return self._controller.is_dirty() def OnNewProject(self, event): if not self.check_unsaved_modifications(): return NewProjectDialog(self._controller).execute() self._populate_tree() def _populate_tree(self): self.tree.populate(self._controller) if len(self._controller.data.directory) > 1: self.filemgr.SelectPath(self._controller.data.source) try: self.filemgr.ExpandPath(self._controller.data.source) except Exception: pass self.filemgr.Update() def OnOpenFile(self, event): # EVT_DIRCTRL_FILEACTIVATED from os.path import splitext robottypes = self._application.settings.get('robot types', ['robot', 'txt', 'tsv', 'html']) path = self.filemgr.GetFilePath() ext = splitext(path) ext = ext[1].replace('.', '') # print("DEBUG: path %s ext %s" % (path, ext)) if ext in robottypes: if not self.check_unsaved_modifications(): return try: self.open_suite(path) return except UserWarning as e: pass from robotide.editor import customsourceeditor customsourceeditor.main(path) def OnOpenTestSuite(self, event): if not self.check_unsaved_modifications(): return path = RobotFilePathDialog( self, self._controller, self._application.settings).execute() if path: try: self.open_suite(path) return except UserWarning as e: pass from robotide.editor import customsourceeditor customsourceeditor.main(path) def check_unsaved_modifications(self): if self.has_unsaved_changes(): ret = wx.MessageBox("There are unsaved modifications.\n" "Do you want to proceed without saving?", "Warning", wx.ICON_WARNING | wx.YES_NO) return ret == wx.YES return True def open_suite(self, path): self._controller.update_default_dir(path) err = self._controller.load_datafile(path, LoadProgressObserver(self)) if isinstance(err, UserWarning): raise err self._populate_tree() def refresh_datafile(self, item, event): self.tree.refresh_datafile(item, event) def OnOpenDirectory(self, event): if self.check_unsaved_modifications(): if wx.VERSION >= (3, 0, 3, ''): # DEBUG wxPhoenix path = wx.DirSelector(message="Choose a directory containing " "Robot files", default_path=self._controller.default_dir ) else: path = wx.DirSelector(message="Choose a directory containing " "Robot files", defaultPath=self._controller.default_dir) if path: self.open_suite(path) def OnSave(self, event): self.save() def OnSaveAll(self, event): self.save_all() def save_all(self): self._show_dialog_for_files_without_format() self._controller.execute(SaveAll()) def save(self, controller=None): if controller is None: controller = self.get_selected_datafile_controller() if controller is not None: if not controller.has_format(): self._show_dialog_for_files_without_format(controller) else: controller.execute(SaveFile()) def _show_dialog_for_files_without_format(self, controller=None): files_without_format = self._controller.get_files_without_format( controller) for f in files_without_format: self._show_format_dialog_for(f) def _show_format_dialog_for(self, file_controller_without_format): InitFileFormatDialog(file_controller_without_format).execute() def OnExit(self, event): self.Close() def OnManagePlugins(self, event): self._plugin_manager.show(self._application.get_plugins()) def OnViewAllTags(self, event): if self._view_all_tags_dialog is None: self._view_all_tags_dialog = ViewAllTagsDialog(self._controller, self) self._view_all_tags_dialog.show_dialog() def OnSearchUnusedKeywords(self, event): if self._review_dialog is None: self._review_dialog = ReviewDialog(self._controller, self) self._review_dialog.show_dialog() def OnPreferences(self, event): dlg = PreferenceEditor(self, "RIDE - Preferences", self._application.preferences, style='tree') # I would prefer that this not be modal, but making it non- # modal opens up a can of worms. We don't want to have to deal # with settings getting changed out from under us while the # dialog is open. dlg.ShowModal() dlg.Destroy() def OnAbout(self, event): dlg = AboutDialog() dlg.ShowModal() dlg.Destroy() def OnShortcutkeys(self, event): dialog = ShortcutKeysDialog() dialog.Show() def OnReportaProblem(self, event): wx.LaunchDefaultBrowser("https://github.com/robotframework/RIDE/issues" ) def OnUserGuide(self, event): wx.LaunchDefaultBrowser("http://robotframework.org/robotframework/" "#user-guide") def _has_data(self): return self._controller.data is not None def _refresh(self): self._controller.update_namespace() # This code is copied from http://wiki.wxpython.org/EnsureFrameIsOnScreen, # and adapted to fit our code style. def ensure_on_screen(self): try: display_id = wx.Display.GetFromWindow(self) except NotImplementedError: display_id = 0 if display_id == -1: display_id = 0 geometry = wx.Display(display_id).GetGeometry() position = self.GetPosition() if position.x < geometry.x: position.x = geometry.x if position.y < geometry.y: position.y = geometry.y size = self.GetSize() if size.width > geometry.width: size.width = geometry.width position.x = geometry.x elif position.x + size.width > geometry.x + geometry.width: position.x = geometry.x + geometry.width - size.width if size.height > geometry.height: size.height = geometry.height position.y = geometry.y elif position.y + size.height > geometry.y + geometry.height: position.y = geometry.y + geometry.height - size.height self.SetPosition(position) self.SetSize(size) # DEBUG just some testing def CreateSizeReportCtrl(self, width=80, height=80): ctrl = SizeReportCtrl(self, -1, wx.DefaultPosition, wx.Size(width, height), self._mgr) return ctrl