def create_initial_layout(self, parent): """ Create the initial window layout. """ # The view dock window is where all of the views live. It also contains # a nested dock window where all of the editors live. self._wx_view_dock_window = WorkbenchDockWindow(parent) # The editor dock window (which is nested inside the view dock window) # is where all of the editors live. self._wx_editor_dock_window = WorkbenchDockWindow( self._wx_view_dock_window.control ) editor_dock_window_sizer = DockSizer(contents=DockSection()) self._wx_editor_dock_window.control.SetSizer(editor_dock_window_sizer) # Nest the editor dock window in the view dock window. editor_dock_window_control = DockControl( id = self.editor_area_id, name = 'Editors', control = self._wx_editor_dock_window.control, style = 'fixed', width = self.window.editor_area_size[0], height = self.window.editor_area_size[1], ) view_dock_window_sizer = DockSizer( contents=[editor_dock_window_control] ) self._wx_view_dock_window.control.SetSizer(view_dock_window_sizer) return self._wx_view_dock_window.control
def init(self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ self._uis = [] # Create a DockWindow to hold each separate object's view: theme = self.factory.dock_theme or self.item.container.dock_theme dw = DockWindow(parent, theme=theme) self.control = dw.control self._sizer = DockSizer(DockSection(dock_window=dw)) self.control.SetSizer(self._sizer) # Set up the additional 'list items changed' event handler needed for # a list based trait. Note that we want to fire the update_editor_item # only when the items in the list change and not when intermediate # traits change. Therefore, replace "." by ":" in the extended_name # when setting up the listener. extended_name = self.extended_name.replace('.', ':') self.context_object.on_trait_change( self.update_editor_item, extended_name + '_items?', dispatch='ui') # Set of selection synchronization: self.sync_value(self.factory.selected, 'selected')
def init(self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ self._uis = [] # Create a DockWindow to hold each separate object's view: theme = self.factory.dock_theme or self.item.container.dock_theme dw = DockWindow(parent, theme=theme) self.control = dw.control self._sizer = DockSizer(DockSection(dock_window=dw)) self.control.SetSizer(self._sizer) # Set up the additional 'list items changed' event handler needed for # a list based trait: self.context_object.on_trait_change(self.update_editor_item, self.extended_name + '_items?', dispatch='ui') # Set of selection synchronization: self.sync_value(self.factory.selected, 'selected')
def __init__( self, panel, group, ui, suppress_label, is_dock_window, create_panel ): """ Initializes the object. """ # Get the contents of the group: content = group.get_content() # Create a group editor object if one is needed: self.control = self.sizer = editor = None self.ui = ui self.group = group self.is_horizontal = group.orientation == "horizontal" layout = group.layout is_scrolled_panel = group.scrollable is_splitter = layout == "split" is_tabbed = layout == "tabbed" id = group.id # Assume our contents are not resizable: self.resizable = False if is_dock_window and (is_splitter or is_tabbed): if is_splitter: self.dock_contents = self.add_dock_window_splitter_items( panel, content, group ) else: self.resizable = group.springy self.dock_contents = create_notebook_for_items( content, ui, panel, group, self.add_notebook_item, True ) return if ( is_dock_window or create_panel or is_scrolled_panel or (id != "") or (group.visible_when != "") or (group.enabled_when != "") ): if is_scrolled_panel: new_panel = TraitsUIScrolledPanel(panel) new_panel.SetMinSize(panel.GetMinSize()) self.resizable = True else: new_panel = TraitsUIPanel(panel, -1) sizer = panel.GetSizer() if sizer is None: sizer = wx.BoxSizer(wx.VERTICAL) panel.SetSizer(sizer) self.control = panel = new_panel if is_splitter or is_tabbed: editor = DockWindowGroupEditor(control=panel, ui=ui) else: editor = GroupEditor(control=panel) if id != "": ui.info.bind(group.id, editor) if group.visible_when != "": ui.add_visible(group.visible_when, editor) if group.enabled_when != "": ui.add_enabled(group.enabled_when, editor) self.panel = panel self.dock_contents = None # Determine the horizontal/vertical orientation of the group: if self.is_horizontal: orientation = wx.HORIZONTAL else: orientation = wx.VERTICAL # Set up a group with or without a border around its contents: label = "" if not suppress_label: label = group.label if group.show_border: box = wx.StaticBox(panel, -1, label) self._set_owner(box, group) self.sizer = wx.StaticBoxSizer(box, orientation) else: if layout == "flow": self.sizer = FlowSizer(orientation) else: self.sizer = wx.BoxSizer(orientation) if label != "": self.sizer.Add( heading_text(panel, text=label).control, 0, wx.EXPAND | wx.LEFT | wx.TOP | wx.RIGHT, 4, ) # If no sizer has been specified for the panel yet, make the new sizer # the layout sizer for the panel: if panel.GetSizer() is None: panel.SetSizer(self.sizer) # Set up scrolling now that the sizer has been set: if is_scrolled_panel: if self.is_horizontal: panel.SetupScrolling(scroll_y=False) else: panel.SetupScrolling(scroll_x=False) if is_splitter: dw = DockWindow( panel, handler=ui.handler, handler_args=(ui.info,), id=ui.id, theme=group.dock_theme, ).control if editor is not None: editor.dock_window = dw dw.SetSizer( DockSizer( contents=self.add_dock_window_splitter_items( dw, content, group ) ) ) self.sizer.Add(dw, 1, wx.EXPAND) elif len(content) > 0: if is_tabbed: self.resizable = group.springy dw = create_notebook_for_items( content, ui, panel, group, self.add_notebook_item ) if editor is not None: editor.dock_window = dw self.sizer.Add(dw, self.resizable, wx.EXPAND) # Check if content is all Group objects: elif layout == "fold": self.resizable = True self.sizer.Add( self.create_fold_for_items(panel, content), 1, wx.EXPAND ) elif isinstance(content[0], Group): # If so, add them to the panel and exit: self.add_groups(content, panel) else: self.add_items(content, panel, self.sizer) # If the caller is a DockWindow, we need to define the content we are # adding to it: if is_dock_window: self.dock_contents = DockRegion( contents=[ DockControl( name=group.get_label(self.ui), image=group.image, id=group.get_id(), style=group.dock, dockable=DockableViewElement(ui=ui, element=group), export=group.export, control=panel, ) ] )
def create_notebook_for_items( content, ui, parent, group, item_handler=None, is_dock_window=False ): """ Creates a notebook and adds a list of groups or items to it as separate pages. """ if is_dock_window: nb = parent else: dw = DockWindow( parent, handler=ui.handler, handler_args=(ui.info,), id=ui.id ) if group is not None: dw.theme = group.dock_theme nb = dw.control pages = [] count = 0 # Create a notebook page for each group or item in the content: active = 0 for index, item in enumerate(content): if isinstance(item, Group): # Create the group as a nested DockWindow item: if item.selected: active = index sg_sizer, resizable, contents = fill_panel_for_group( nb, item, ui, suppress_label=True, is_dock_window=True ) # If the result is a region (i.e. notebook) with only one page, # collapse it down into just the contents of the region: if isinstance(contents, DockRegion) and ( len(contents.contents) == 1 ): contents = contents.contents[0] # Add the content to the notebook as a new page: pages.append(contents) else: # Create the new page as a simple DockControl containing the # specified set of controls: page_name = item.get_label(ui) count += 1 if page_name == "": page_name = "Page %d" % count sizer = wx.BoxSizer(wx.VERTICAL) panel = TraitsUIPanel(nb, -1) panel.SetSizer(sizer) pages.append( DockControl( name=page_name, image=item.image, id=item.get_id(), style=item.dock, dockable=DockableViewElement(ui=ui, element=item), export=item.export, control=panel, ) ) item_handler(item, panel, sizer) panel.GetSizer().Fit(panel) region = DockRegion(contents=pages, active=active) # If the caller is a DockWindow, return the region as the result: if is_dock_window: return region nb.SetSizer(DockSizer(contents=DockSection(contents=[region]))) # Return the notebook as the result: return nb
class NotebookEditor(Editor): """ An editor for lists that displays the list as a "notebook" of tabbed pages. """ #--------------------------------------------------------------------------- # Trait definitions: #--------------------------------------------------------------------------- # Is the notebook editor scrollable? This values overrides the default: scrollable = True # The currently selected notebook page object: selected = Any #--------------------------------------------------------------------------- # Finishes initializing the editor by creating the underlying toolkit # widget: #--------------------------------------------------------------------------- def init(self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ self._uis = [] # Create a DockWindow to hold each separate object's view: theme = self.factory.dock_theme or self.item.container.dock_theme dw = DockWindow(parent, theme=theme) self.control = dw.control self._sizer = DockSizer(DockSection(dock_window=dw)) self.control.SetSizer(self._sizer) # Set up the additional 'list items changed' event handler needed for # a list based trait: self.context_object.on_trait_change(self.update_editor_item, self.extended_name + '_items?', dispatch='ui') # Set of selection synchronization: self.sync_value(self.factory.selected, 'selected') #--------------------------------------------------------------------------- # Updates the editor when the object trait changes external to the editor: #--------------------------------------------------------------------------- def update_editor(self): """ Updates the editor when the object trait changes externally to the editor. """ # Make sure the DockWindow is in a correct state: self._sizer.Reset(self.control) # Destroy the views on each current notebook page: self.close_all() # Create a DockControl for each object in the trait's value: uis = self._uis dock_controls = [] for object in self.value: dock_control, view_object, monitoring = self._create_page(object) # Remember the DockControl for later deletion processing: uis.append([dock_control, object, view_object, monitoring]) dock_controls.append(dock_control) # Add the new items to the DockWindow: self.add_controls(dock_controls) if self.ui.info.initialized: self.update_layout() #--------------------------------------------------------------------------- # Handles some subset of the trait's list being updated: #--------------------------------------------------------------------------- def update_editor_item(self, event): """ Handles an update to some subset of the trait's list. """ # Make sure the DockWindow is in a correct state: self._sizer.Reset(self.control) index = event.index # Delete the page corresponding to each removed item: layout = ((len(event.removed) + len(event.added)) <= 1) for i in range(len(event.removed)): dock_control, object, view_object, monitoring = self._uis[index] if monitoring: view_object.on_trait_change(self.update_page_name, self.factory.page_name[1:], remove=True) dock_control.close(layout=layout, force=True) del self._uis[index] # Add a page for each added object: dock_controls = [] for object in event.added: dock_control, view_object, monitoring = self._create_page(object) self._uis[index:index] = [[ dock_control, object, view_object, monitoring ]] dock_controls.append(dock_control) index += 1 # Add the new items to the DockWindow: self.add_controls(dock_controls) self.update_layout() #--------------------------------------------------------------------------- # Closes all currently open notebook pages: #--------------------------------------------------------------------------- def close_all(self): """ Closes all currently open notebook pages. """ page_name = self.factory.page_name[1:] for dock_control, object, view_object, monitoring in self._uis: if monitoring: view_object.on_trait_change(self.update_page_name, page_name, remove=True) dock_control.close(layout=False, force=True) # Reset the list of ui's and dictionary of page name counts: self._uis = [] self._pages = {} #--------------------------------------------------------------------------- # Disposes of the contents of an editor: #--------------------------------------------------------------------------- def dispose(self): """ Disposes of the contents of an editor. """ self.context_object.on_trait_change(self.update_editor_item, self.name + '_items?', remove=True) self.close_all() super(NotebookEditor, self).dispose() #--------------------------------------------------------------------------- # Adds a group of new DockControls to the view: #--------------------------------------------------------------------------- def add_controls(self, controls): """ Adds a group of new DockControls to the view. """ if len(controls) > 0: section = self.control.GetSizer().GetContents() if ((len(section.contents) == 0) or (not isinstance(section.contents[-1], DockRegion))): section.contents.append(DockRegion(contents=controls)) else: for control in controls: section.contents[-1].add(control, activate=False) # Fire this event to activate the dock control corresponding # to the selected object, if any. self._selected_changed(None, self.selected) #--------------------------------------------------------------------------- # Updates the layout of the DockWindow: #--------------------------------------------------------------------------- def update_layout(self): """ Updates the layout of the DockWindow. """ self.control.Layout() self.control.Refresh() #--------------------------------------------------------------------------- # Handles the trait defining a particular page's name being changed: #--------------------------------------------------------------------------- def update_page_name(self): """ Handles the trait defining a particular page's name being changed. """ changed = False for i, value in enumerate(self._uis): dock_control, user_object, view_object, monitoring = value if dock_control.control is not None: name = None handler = getattr( self.ui.handler, '%s_%s_page_name' % (self.object_name, self.name), None) if handler is not None: name = handler(self.ui.info, user_object) if name is None: name = unicode( xgetattr(view_object, self.factory.page_name[1:], u'???')) changed |= (dock_control.name != name) dock_control.name = name if changed: self.update_layout() #--------------------------------------------------------------------------- # Creates a DockControl for a specified object: #--------------------------------------------------------------------------- def _create_page(self, object): """ Creates a DockControl for a specified object. """ # Create the view for the object: view_object = object factory = self.factory if factory.factory is not None: view_object = factory.factory(object) ui = view_object.edit_traits(parent=self.control, view=factory.view, kind=factory.ui_kind).set(parent=self.ui) # Get the name of the page being added to the notebook: name = '' monitoring = False prefix = '%s_%s_page_' % (self.object_name, self.name) page_name = self.factory.page_name if page_name[0:1] == '.': name = xgetattr(view_object, page_name[1:], None) monitoring = (name is not None) if monitoring: handler_name = None method = getattr(self.ui.handler, prefix + 'name', None) if method is not None: handler_name = method(self.ui.info, object) if handler_name is not None: name = handler_name else: name = unicode(name) or u'???' view_object.on_trait_change(self.update_page_name, page_name[1:], dispatch='ui') else: name = '' elif page_name != '': name = page_name if name == '': name = user_name_for(view_object.__class__.__name__) # Make sure the name is not a duplicate: if not monitoring: self._pages[name] = count = self._pages.get(name, 0) + 1 if count > 1: name += (' %d' % count) # Return a new DockControl for the ui, and whether or not its name is # being monitored: image = None method = getattr(self.ui.handler, prefix + 'image', None) if method is not None: image = method(self.ui.info, object) dock_control = DockControl(control=ui.control, id=str(id(ui.control)), name=name, style=factory.dock_style, image=image, export=factory.export, closeable=factory.deletable, dockable=DockableListElement(ui=ui, editor=self)) return (dock_control, view_object, monitoring) #--------------------------------------------------------------------------- # Activates the corresponding dock window when the 'selected' trait of # the editor is changed. #--------------------------------------------------------------------------- def _selected_changed(self, old, new): """ Activates the corresponding dock window when the 'selected' trait of the editor is changed. """ for i, value in enumerate(self._uis): if new == value[1]: value[0].activate() break return