diff --git a/wx/lib/agw/aui/auibar.py b/wx/lib/agw/aui/auibar.py index ac2ac916..27eecde4 100644 --- a/wx/lib/agw/aui/auibar.py +++ b/wx/lib/agw/aui/auibar.py @@ -271,8 +271,9 @@ class AuiToolBarItem(object): """ AuiToolBarItem is a toolbar element. - It has a unique id (except for the separators which always have id = -1), the - style (telling whether it is a normal button, separator or a control), the + It has a unique id (except for the separators which always have id = -1 and the + automatically added restore-from-minimize which always have id = ID_RESTORE_FRAME), + the style (telling whether it is a normal button, separator or a control), the state (toggled or not, enabled or not) and short and long help strings. The default implementations use the short help string for the tooltip text which is popped up when the mouse pointer enters the tool and the long help string @@ -2035,26 +2036,26 @@ class AuiToolBar(wx.Control): self.Clear() - def DeleteTool(self, tool_id): + def DeleteTool(self, tool): """ Removes the specified tool from the toolbar and deletes it. - :param integer `tool_id`: the :class:`AuiToolBarItem` identifier. + :param `tool`: the :class:`AuiToolBarItem` or its integer identifier. :returns: ``True`` if the tool was deleted, ``False`` otherwise. :note: Note that it is unnecessary to call :meth:`Realize` for the change to take place, it will happen immediately. """ - - idx = self.GetToolIndex(tool_id) - - if idx >= 0 and idx < len(self._items): - self._items.pop(idx) - self.Realize() - return True - - return False + if isinstance(tool, AuiToolBarItem): + try: + self._items.remove(tool) + self.Realize() + return True + except ValueError: + return False + # Assume tool is the id of the tool to be removed + return self.DeleteToolByPos(self.GetToolIndex(tool)) def DeleteToolByPos(self, pos): @@ -2114,6 +2115,19 @@ class AuiToolBar(wx.Control): return None + def FindToolByUserData(self, userData): + """ + Finds a tool for the given client id. + + :param PyObject `userData`: the user data object. + """ + + for item in self._items: + if item.user_data == userData: + return item + + return None + def FindToolForPosition(self, x, y): """ Finds a tool for the given mouse position. diff --git a/wx/lib/agw/aui/framemanager.py b/wx/lib/agw/aui/framemanager.py index 7cd5846e..8788f8d8 100644 --- a/wx/lib/agw/aui/framemanager.py +++ b/wx/lib/agw/aui/framemanager.py @@ -4778,6 +4778,11 @@ class AuiManager(wx.EvtHandler): id = notebook.GetPageIndex(p.window) notebook.RemovePage(id) p.window.Reparent(self._frame) + + elif p.IsMinimized(): + # if we were minimized, restore so any restore icons in toolbars are removed + self.RestoreMinimizedPane(p) + # make sure there are no references to this pane in our uiparts, # just in case the caller doesn't call Update() immediately after @@ -4807,6 +4812,11 @@ class AuiManager(wx.EvtHandler): # if we were maximized, restore if pane_info.IsMaximized(): self.RestorePane(pane_info) + + # if we were minimized, restore so any restore icons in toolbars are removed + if pane_info.IsMinimized(): + self.RestoreMinimizedPane(pane_info) + if pane_info.frame: if self._agwFlags & AUI_MGR_ANIMATE_FRAMES: @@ -5072,6 +5082,9 @@ class AuiManager(wx.EvtHandler): result = "name=" + EscapeDelimiters(pane.name) + ";" result += "caption=" + EscapeDelimiters(pane.caption) + ";" + if pane.minimize_target: + result += "minitarget=" + EscapeDelimiters(pane.minimize_target) + ";" + result += "minimode=%u;" % pane.minimize_mode result += "state=%u;" % pane.state result += "dir=%d;" % pane.dock_direction @@ -5119,6 +5132,10 @@ class AuiManager(wx.EvtHandler): pane.name = value elif val_name == "caption": pane.caption = value + elif val_name == "minitarget": + pane.minimize_target = value + elif val_name == "minimode": + pane.minimize_mode = int(value) elif val_name == "state": pane.state = int(value) elif val_name == "dir": @@ -5195,7 +5212,8 @@ class AuiManager(wx.EvtHandler): dock.size) return result - def LoadPerspective(self, layout, update=True, restorecaption=False): + def LoadPerspective(self, layout, update=True, restorecaption=False, + restoreminimize=False): """ Loads a layout which was saved with :meth:`SavePerspective`. @@ -5206,6 +5224,8 @@ class AuiManager(wx.EvtHandler): :param bool `update`: whether to update immediately the window or not; :param bool `restorecaption`: ``False``, restore from persist storage, otherwise use the caption defined in code. + :param bool `restoreminimize`: ``False``, restore from persist storage, + otherwise use the minimize_toolbar and minimize_mode defined in code. """ input = layout @@ -5223,6 +5243,7 @@ class AuiManager(wx.EvtHandler): # mark all panes currently managed as docked and hidden saveCapt = {} # see restorecaption param saveIcon = {} # icons are not preserved by perspectives, so preserve them + saveMinimize = {} # see restoreminimize param for pane in self._panes: # dock the notebook pages @@ -5238,6 +5259,7 @@ class AuiManager(wx.EvtHandler): pane.Dock().Hide() saveCapt[pane.name] = pane.caption saveIcon[pane.name] = pane.icon + saveMinimize[pane.name] = pane.minimize_target, pane.minimize_mode # clear out the dock array; this will be reconstructed self._docks = [] @@ -5298,6 +5320,10 @@ class AuiManager(wx.EvtHandler): # restore icons from code. This is always done. Since icons are not saved in perspectives if pane.name in saveIcon: pane.icon = saveIcon[pane.name] + # restore minimize parameters from code + if restoreminimize: + if pane.name in saveMinimize: + pane.minimize_target, pane.minimize_mode = saveMinimize[pane.name] if not p.IsOk(): if pane.IsNotebookControl(): @@ -5319,10 +5345,29 @@ class AuiManager(wx.EvtHandler): if isinstance(pane.window, auibar.AuiToolBar) and (pane.IsFloatable() or pane.IsDockable()): pane.window.SetGripperVisible(True) - for p in self._panes: - if p.IsMinimized(): - self.MinimizePane(p, False) - + inexistentPaneIndexes = [] + for paneIndex, p in enumerate(self._panes): + if p.window: + if p.IsMinimized(): + self.MinimizePane(p, False) + elif p.minimize_mode & AUI_MINIMIZE_POS_MASK == AUI_MINIMIZE_POS_TOOLBAR: + # If the pane specifies a minimize toolbar, which would be preserved by the loading + # operation rather than using an automatic toolbar which would not be preserved) then + # if pane was minimized before we loaded perspective but the new perspective unminimized + # it then its minimize-from-restore icon is still in the toolbar and must be removed + minimizeToolbar = self.GetPane(p.minimize_target).window + item = minimizeToolbar.FindToolByUserData((ID_RESTORE_FRAME, p.window)) + if item: # Delete the icon if it was there + minimizeToolbar.DeleteTool(item) + else: + # The perspective is referencing a non-existing pane that was added nonetheless. This will + # happen with a notebook that ends up containing no pages + inexistentPaneIndexes.append(paneIndex) + + for paneIndex in reversed(inexistentPaneIndexes): # reverse is required when deleting elements by index + del self._panes[index] + + if update: self.Update() @@ -9863,13 +9908,20 @@ class AuiManager(wx.EvtHandler): restore_bitmap = img.ConvertToBitmap() target = None + restoreToolAlreadyInToolbar = False if posMask == AUI_MINIMIZE_POS_TOOLBAR: target = paneInfo.name + if paneInfo.IsMinimized() and minimize_toolbar.FindToolByUserData((ID_RESTORE_FRAME, paneInfo.window)): + # We are loading a perspective. If the perspective contains the minimize_toolbar, + # then the restore tool for this pane is already in it and we should not add it again + restoreToolAlreadyInToolbar = True - minimize_toolbar.AddSimpleTool(ID_RESTORE_FRAME, paneInfo.caption, restore_bitmap, - _(six.u("Restore %s")) % paneInfo.caption, target=target) - minimize_toolbar.SetAuiManager(self) - minimize_toolbar.Realize() + if not restoreToolAlreadyInToolbar: + tool = minimize_toolbar.AddSimpleTool(ID_RESTORE_FRAME, paneInfo.caption, restore_bitmap, + _(six.u("Restore %s")) % paneInfo.caption, target=target) + tool.SetUserData((ID_RESTORE_FRAME, paneInfo.window)) + minimize_toolbar.SetAuiManager(self) + minimize_toolbar.Realize() toolpanelname = paneInfo.name + "_min" if paneInfo.IsMaximized(): @@ -10031,8 +10083,8 @@ class AuiManager(wx.EvtHandler): targetName = pane.minimize_target toolbarPane = self.GetPane(targetName) toolbar = toolbarPane.window - item = toolbar.FindToolByLabel(pane.caption) - toolbar.DeleteTool(item.id) + item = toolbar.FindToolByUserData((ID_RESTORE_FRAME, pane.window)) + toolbar.DeleteTool(item) else: paneInfo.window.Show(False) self.DetachPane(paneInfo.window)