Changeset 4079

Show
Ignore:
Timestamp:
05/12/08 06:39:42 (3 months ago)
Author:
ed
Message:

Began implementing toolbar support for dDockForm, but for the life of me I can't see a difference between toolbars and any other panes. Added the 'Toolbar' property that returns True if the pane is a toolbar.

Added the '_Manager' property to _dDockPanel. Previously the only reference to the AUI manager available was through the form.

Fixed several naming conflict issues. Besides the wxPython requirement of siblings having unique names, the AUI stuff requires that each managed pane be uniquely named (they are actually children of the floating pane window).

Fixed some issues with some properties not being set; adding them to the delayed properties resolved that.

Added support for saving and restoring the layout of a dDockForm when SaveRestorePosition? is True. This is still not working as smoothly as possible; if you change the properties passed to a _dDockPanel, restoring the layout also restores the old property settings.

Tried to implement DynamicCaption? as a proof of concept for Dynamic* props, but there is no way to tie into the AUI events such as docking and undocking, so this is marginal at best right now.

Added the 'ShowActivePanel?' and 'TransparentDrag?' properties to dDockForm. When the former is True, the 'active' panel's title bar will be hilited. When TransparentDrag? is True, the panel being dragged assumes a semi-transparent appearance.

Fixed the form's update(), as it wasn't propagating to the panels.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dabo/ui/uiwx/dDockForm.py

    r3303 r4079  
    1010from dabo.ui import makeDynamicProperty 
    1111 
     12flag_allow_float = aui.AUI_MGR_ALLOW_FLOATING 
     13flag_show_active = aui.AUI_MGR_ALLOW_ACTIVE_PANE 
     14flag_transparent_drag = aui.AUI_MGR_TRANSPARENT_DRAG 
     15flag_rectangle_hint = aui.AUI_MGR_RECTANGLE_HINT 
     16flag_transparent_hint = aui.AUI_MGR_TRANSPARENT_HINT 
     17flag_venetian_blinds_hint = aui.AUI_MGR_VENETIAN_BLINDS_HINT 
     18flag_no_venetian_blinds_fade = aui.AUI_MGR_NO_VENETIAN_BLINDS_FADE 
     19flag_hint_fade = aui.AUI_MGR_HINT_FADE 
     20 
    1221 
    1322class _dDockManager(aui.AuiManager): 
    1423    def __init__(self, win): 
    15         super(_dDockManager, self).__init__(win) 
    16      
    17      
    18     def addPane(self, win, name=None, typ=None, caption=None): 
     24        self._managedWindow = win 
     25        flags = flag_allow_float | flag_transparent_drag | flag_rectangle_hint | flag_transparent_hint 
     26        super(_dDockManager, self).__init__(win, flags=flags) 
     27        self.Bind(aui.EVT_AUI_RENDER, self.aui_render) 
     28 
     29 
     30    def aui_render(self, evt): 
     31        evt.Skip() 
     32        dabo.ui.callAfterInterval(100, self._managedWindow.update) 
     33     
     34     
     35    def addPane(self, win, name=None, typ=None, caption=None, toolbar=None): 
    1936        pi = PaneInfo() 
     37        if toolbar: 
     38            pi.ToolbarPane() 
    2039        if name is not None: 
    2140            pi = pi.Name(name) 
     
    4665class _dDockPanel(dabo.ui.dPanel): 
    4766    def __init__(self, parent, properties=None, attProperties=None, *args, **kwargs): 
    48         pname = self._extractKey(kwargs, "name", "") 
     67        nmU = self._extractKey((properties, kwargs), "Name", "") 
     68        nb = self._extractKey((properties, kwargs), "NameBase", "") 
     69        nmL = self._extractKey((properties, kwargs), "name", "") 
     70        kwargs["NameBase"] = [txt for txt in (nmU, nb, nmL, "_dDockPanel") if txt][0] 
    4971        pcapUp = self._extractKey(kwargs, "Caption", "") 
    5072        pcap = self._extractKey(kwargs, "caption", "") 
    5173        ptype = self._extractKey(kwargs, "typ", "") 
    52         kwargs["NameBase"] = pname 
    5374        if pcapUp: 
    5475            kwargs["Caption"] = pcapUp 
     
    5677            kwargs["Caption"] = pcap 
    5778        self._paramType = ptype 
     79        self._toolbar = self._extractKey(kwargs, "Toolbar", False) 
    5880         
    5981        # Initialize attributes that underly properties 
     
    80102            self._floatingSize = self.GetParent().GetSize().Get() 
    81103     
    82      
     104 
     105    def _uniqueNameForParent(self, name, parent=None): 
     106        """We need to check the AUI manager's PaneInfo name value, too, as that has to be unique  
     107        there as well as the form. 
     108        """ 
     109        changed = True 
     110        while changed: 
     111            i = 0 
     112            auiOK = False 
     113            while not auiOK: 
     114                auiOK = True 
     115                candidate = name 
     116                if i: 
     117                    candidate = "%s%s" % (name, i) 
     118                mtch = [pi.name for pi in self._Manager.GetAllPanes() 
     119                        if pi.name == candidate] 
     120                if mtch: 
     121                    auiOK = False 
     122                    i += 1 
     123            changed = changed and (candidate != name) 
     124            name = candidate 
     125 
     126            candidate = super(_dDockPanel, self)._uniqueNameForParent(name, parent) 
     127            changed = changed and (candidate != name) 
     128            name = candidate 
     129 
     130 
    83131    def float(self): 
    84132        """Float the panel if it isn't already floating.""" 
     
    86134            return 
    87135        self.__pi.Float() 
    88         self.Form._refreshState() 
     136        self._updateAUI() 
    89137         
    90138         
     
    104152                dabo.errorLog.write(_("Invalid dock position: '%s'.") % side) 
    105153        inf.Dock() 
    106         self.Form._refreshState() 
     154        self._updateAUI() 
    107155             
    108156         
     
    114162        """ 
    115163        self._propDelayDict = {} 
    116         for delayed in ("Left", "Right", "Top", "Bottom", "Width", "Height"): 
    117             val = self._extractKey(props, delayed) 
    118             if val: 
     164        props2Delay = ("Bottom", "BottomDockable", "Caption", "DestroyOnClose", "Dockable", "Docked",  
     165                "DockSide", "Floatable", "Floating", "FloatingBottom", "FloatingHeight", "FloatingLeft",  
     166                "FloatingPosition", "FloatingRight", "FloatingSize", "FloatingTop", "FloatingWidth", "Height",  
     167                "Left", "LeftDockable", "Movable", "Resizable", "Right", "RightDockable", "ShowBorder",  
     168                "ShowCaption", "ShowCloseButton", "ShowGripper", "ShowMaximizeButton",  
     169                "ShowMinimizeButton", "ShowPinButton", "Top", "TopDockable", "Visible", "Width") 
     170        for delayed in props2Delay: 
     171            val = self._extractKey(props, delayed, None) 
     172            if val is not None: 
    119173                self._propDelayDict[delayed] = val 
    120174        return super(_dDockPanel, self)._beforeSetProperties(props) 
    121175         
    122176         
    123     def _setProperties(self, props): 
     177    def _afterSetProperties(self): 
     178        nm = self.Name 
    124179        frm = self.Form 
    125         self.__pi = frm._mgr.addPane(self, name=props["NameBase"]
    126                 typ=self._paramType, caption=props["Caption"]
     180        self.__pi = self._Manager.addPane(self, name=nm
     181                typ=self._paramType, caption=self._propDelayDict.get("Caption", "_dDockPanel")
    127182        del self._paramType 
    128183        self.__pi.MinSize((50,50)) 
    129         super(_dDockPanel, self)._setProperties(props) 
    130  
    131  
    132     def _afterSetProperties(self): 
    133184        if self._propDelayDict: 
    134185            self.setProperties(self._propDelayDict) 
    135186        del self._propDelayDict 
    136          
    137          
     187 
     188 
     189    def getState(self): 
     190        """Returns the local name and a string that can be used to restore the state of this pane.""" 
     191        inf = self._Manager.SavePaneInfo(self.__pi) 
     192        try: 
     193            infPairs = (qq.split("=") for qq in inf.split(";")) 
     194            nm = dict(infPairs)["name"] 
     195        except KeyError: 
     196            # For some reason a name was not returned 
     197            return "" 
     198        return (nm, inf.replace("name=%s;" % nm, "")) 
     199 
     200 
     201    def _updateAUI(self): 
     202        frm = self.Form 
     203        if frm is not None: 
     204            frm._refreshState() 
     205        else: 
     206            try: 
     207                self._Manager.runUpdate() 
     208            except AttributeError: 
     209                pass 
     210 
     211 
    138212    def __getPosition(self): 
    139213        if self.Floating: 
     
    173247        if self._constructed(): 
    174248            self.__pi.BottomDockable(val) 
    175             self.Form._refreshState() 
     249            self._updateAUI() 
    176250        else: 
    177251            self._properties["BottomDockable"] = val 
    178  
    179252 
    180253    def _getCaption(self): 
     
    189262            self._caption = val 
    190263            self.__pi.Caption(val) 
    191             self.Form._refreshState() 
     264            self._updateAUI() 
    192265        else: 
    193266            self._properties["Caption"] = val 
     
    201274            self._destroyOnClose = val 
    202275            self.__pi.DestroyOnClose(val) 
    203             self.Form._refreshState() 
     276            self._updateAUI() 
    204277        else: 
    205278            self._properties["DestroyOnClose"] = val 
     
    213286            self._dockable = val 
    214287            self.__pi.Dockable(val) 
    215             self.Form._refreshState() 
     288            if self.Docked: 
     289                self.Docked = val 
     290            self._updateAUI() 
    216291        else: 
    217292            self._properties["Dockable"] = val 
     
    232307                chg = True 
    233308            if chg: 
    234                 self.Form._refreshState() 
     309                self._updateAUI() 
    235310        else: 
    236311            self._properties["Docked"] = val 
     
    244319            vUp = val[0].upper() 
    245320            self.__pi.dock_direction = {"T": 1, "R": 2, "B": 3, "L": 4}[vUp] 
    246             self.Form._refreshState() 
     321            self._updateAUI() 
    247322        else: 
    248323            self._properties["DockSide"] = val 
     
    256331            self._floatable = val 
    257332            self.__pi.Floatable(val) 
    258             self.Form._refreshState() 
     333            self._updateAUI() 
    259334        else: 
    260335            self._properties["Floatable"] = val 
     
    275350                chg = True 
    276351            if chg: 
    277                 self.Form._refreshState() 
    278         else: 
    279             print dir(self) 
     352                self._updateAUI() 
     353        else: 
    280354            self._properties["Floating"] = val 
    281355 
     
    415489        if self._constructed(): 
    416490            self.__pi.LeftDockable(val) 
    417             self.Form._refreshState() 
     491            self._updateAUI() 
    418492        else: 
    419493            self._properties["LeftDockable"] = val 
     494 
     495 
     496    def _getManager(self): 
     497        try: 
     498            mgr = self._mgr 
     499        except AttributeError: 
     500            mgr = self._mgr = self.Form._mgr 
     501        return mgr 
    420502 
    421503 
     
    427509            self._movable = val 
    428510            self.__pi.Movable(val) 
    429             self.Form._refreshState() 
     511            self._updateAUI() 
    430512        else: 
    431513            self._properties["Movable"] = val 
     
    439521            self._resizable = val 
    440522            self.__pi.Resizable(val) 
    441             self.Form._refreshState() 
     523            self._updateAUI() 
    442524        else: 
    443525            self._properties["Resizable"] = val 
     
    463545        if self._constructed(): 
    464546            self.__pi.RightDockable(val) 
    465             self.Form._refreshState() 
     547            self._updateAUI() 
    466548        else: 
    467549            self._properties["RightDockable"] = val 
     
    475557            self._showBorder = val 
    476558            self.__pi.PaneBorder(val) 
    477             self.Form._refreshState() 
     559            self._updateAUI() 
    478560        else: 
    479561            self._properties["ShowBorder"] = val 
     
    487569            self._showCaption = val 
    488570            self.__pi.CaptionVisible(val) 
    489             self.Form._refreshState() 
     571            self._updateAUI() 
    490572        else: 
    491573            self._properties["ShowCaption"] = val 
     
    515597            self._showGripper = val 
    516598            self.__pi.Gripper(val) 
    517             self.Form._refreshState() 
     599            self._updateAUI() 
    518600        else: 
    519601            self._properties["ShowGripper"] = val 
     
    527609            self._showMaximizeButton = val 
    528610            self.__pi.MaximizeButton(val) 
    529             self.Form._refreshState() 
     611            self._updateAUI() 
    530612        else: 
    531613            self._properties["ShowMaximizeButton"] = val 
     
    539621            self._showMinimizeButton = val 
    540622            self.__pi.MinimizeButton(val) 
    541             self.Form._refreshState() 
     623            self._updateAUI() 
    542624        else: 
    543625            self._properties["ShowMinimizeButton"] = val 
     
    551633            self._showPinButton = val 
    552634            self.__pi.PinButton(val) 
    553             self.Form._refreshState() 
     635            self._updateAUI() 
    554636        else: 
    555637            self._properties["ShowPinButton"] = val 
     638 
     639 
     640 
     641    def _getToolbar(self): 
     642        return self._toolbar 
    556643 
    557644 
     
    575662        if self._constructed(): 
    576663            self.__pi.TopDockable(val) 
    577             self.Form._refreshState() 
     664            self._updateAUI() 
    578665        else: 
    579666            self._properties["TopDockable"] = val 
     
    586673        if self._constructed(): 
    587674            self.__pi.Show(val) 
    588             self.Form._refreshState() 
     675            self._updateAUI() 
    589676        else: 
    590677            self._properties["Visible"] = val 
     
    666753            _("Can the panel be docked to the left edge of the form? Default=True  (bool)")) 
    667754 
     755    _Manager = property(_getManager, None, None, 
     756            _("Reference to the AUI manager (for internal use only).  (_dDockManager)")) 
     757 
    668758    Movable = property(_getMovable, _setMovable, None, 
    669759            _("Can the panel be moved (True, default), or is it in a fixed position (False).  (bool)")) 
     
    699789            _("Does the panel display a pin button when floating? Default=False  (bool)")) 
    700790 
     791    Toolbar = property(_getToolbar, None, None, 
     792            _("Returns True if this is a Toolbar pane. Default=False  (bool)")) 
     793 
    701794    Top = property(_getTop, _setTop, None, 
    702795            _("Position in pixels of the top side of the panel. Read-only when docked; read-write when floating  (int)")) 
     
    711804            _("Position in pixels of the width of the panel. Read-only when docked; read-write when floating  (int)")) 
    712805 
     806 
     807    DynamicCaption = makeDynamicProperty(Caption) 
    713808     
    714809         
     
    716811class dDockForm(dabo.ui.dForm): 
    717812    def _afterInit(self): 
     813        self._inUpdate = False 
    718814        self._mgr = mgr = _dDockManager(self) 
    719815        pc = self.getBasePanelClass() 
    720816        self._centerPanel = pc(self, name="CenterPanel", typ="center") 
    721817        self._centerPanel.Sizer = dabo.ui.dSizer("v") 
     818        self._panels = {} 
    722819        super(dDockForm, self)._afterInit() 
    723820        self.bindEvent(dEvents.Destroy, self.__onDestroy) 
     
    726823    def __onDestroy(self, evt): 
    727824        if self._finito: 
     825            # Need to save this here, since we can't respond to all layout changes. 
     826            self.saveSizeAndPosition() 
    728827            self._mgr.UnInit() 
     828 
    729829     
    730830    def getBasePanelClass(cls): 
     
    736836        ok = isinstance(evt.child, (_dDockPanel, dabo.ui.dStatusBar, dabo.ui.dShell.dShell)) 
    737837        if not ok: 
    738             print "BORN:", evt.child 
     838            # This should never happen; if so, log the error 
     839            dabo.errorLog.write(_("Unmanaged object added to a Dock Form: %s") %evt.child) 
    739840         
    740841         
    741842    def addObject(self, classRef, Name=None, *args, **kwargs): 
     843        """To support the old addObject() syntax, we need to re-direct the request 
     844        to the center panel. 
     845        """ 
    742846        self._centerPanel.addObject(classRef, Name=Name, *args, **kwargs) 
    743847         
    744848     
    745849    def addPanel(self, *args, **kwargs): 
     850        """Adds a dockable panel to the form.""" 
    746851        pnl = _dDockPanel(self, *args, **kwargs) 
    747852        self._refreshState() 
     853        # Store the pane info 
     854        nm = pnl.getState()[0] 
     855        self._panels[pnl] = nm 
    748856        return pnl 
    749      
    750      
     857 
     858 
    751859    def _refreshState(self, interval=None): 
    752860        if self._finito: 
     
    757865            self._mgr.Update() 
    758866        else: 
    759             dabo.ui.callAfterInterval(interval, self._mgr.runUpdate)         
     867            dabo.ui.callAfterInterval(interval, self._mgr.runUpdate) 
     868        if not self._inUpdate: 
     869            dabo.ui.callAfter(self.update) 
     870     
     871     
     872    def update(self): 
     873        if not self._inUpdate: 
     874            self._inUpdate = True 
     875            super(dDockForm, self).update() 
     876            # Update the panels 
     877            for pnl in self._panels.keys(): 
     878                pnl.update() 
     879            dabo.ui.callAfterInterval(500, self._clearInUpdate) 
     880 
     881 
     882    def _clearInUpdate(self): 
     883        self._inUpdate = False 
     884 
     885 
     886    def saveSizeAndPosition(self): 
     887        """ Save the panel layout info, then call the default behavior.""" 
     888        if self.Application: 
     889            if self.SaveRestorePosition and not self.TempForm: 
     890                self.Application.setUserSetting("perspective", self._mgr.SavePerspective()) 
     891                if not self._finito: 
     892                    super(dDockForm, self).saveSizeAndPosition() 
     893 
     894 
     895    def restoreSizeAndPosition(self): 
     896        """Restore the panel layout, if possible, then call the default behavior.""" 
     897        if self.Application and self.SaveRestorePosition: 
     898            super(dDockForm, self).restoreSizeAndPosition() 
     899            ps = self.Application.getUserSetting("perspective", "") 
     900            if ps: 
     901                self._mgr.LoadPerspective(ps) 
    760902 
    761903 
     
    766908 
    767909 
     910    def _getShowActivePanel(self): 
     911        return bool(self._mgr.GetFlags() & flag_show_active) 
     912 
     913    def _setShowActivePanel(self, val): 
     914        if self._constructed(): 
     915            self._transparentDrag = val 
     916            flags = self._mgr.GetFlags() 
     917            if val: 
     918                newFlags = flags | flag_show_active 
     919            else: 
     920                newFlags = flags & ~flag_show_active 
     921            self._mgr.SetFlags(newFlags) 
     922        else: 
     923            self._properties["ShowActivePanel"] = val 
     924 
     925 
     926    def _getTransparentDrag(self): 
     927        return bool(self._mgr.GetFlags() & flag_transparent_drag) 
     928 
     929    def _setTransparentDrag(self, val): 
     930        if self._constructed(): 
     931            self._transparentDrag = val 
     932            flags = self._mgr.GetFlags() 
     933            if val: 
     934                newFlags = flags | flag_transparent_drag 
     935            else: 
     936                newFlags = flags & ~flag_transparent_drag 
     937            self._mgr.SetFlags(newFlags) 
     938        else: 
     939            self._properties["TransparentDrag"] = val 
     940 
     941 
    768942    CenterPanel = property(_getCenterPanel, None, None, 
    769943            _("Reference to the center (i.e., non-docking) panel. (read-only) (dPanel)")) 
    770      
    771      
     944 
     945    ShowActivePanel = property(_getShowActivePanel, _setShowActivePanel, None, 
     946            _("When True, the title bar of the active pane is highlighted. Default=False  (bool)")) 
     947     
     948    TransparentDrag = property(_getTransparentDrag, _setTransparentDrag, None, 
     949            _("When dragging panes, do they appear transparent? Default=True  (bool)")) 
    772950 
    773951 
    774952 
    775953class _dDockForm_test(dDockForm): 
     954    def initProperties(self): 
     955        self.SaveRestorePosition = False 
     956        self.Size = (700, 500) 
     957 
    776958    def afterInit(self): 
    777         self.fp = _dDockPanel(self, Floating=True, BackColor="orange", 
    778                 Caption="I'm Floating!", Top=70, Left=100) 
    779         self.dp = _dDockPanel(self, Floating=False, BackColor="slateblue",  
     959        self.fp = self.addPanel(Floating=True, BackColor="orange", 
     960                Caption="Initially Floating", Top=70, Left=200) 
     961        self.dp = self.addPanel(Floating=False, Caption="Initially Docked", BackColor="slateblue",  
    780962                ShowCaption=False, ShowPinButton=True, ShowCloseButton=False, 
    781963                ShowGripper=True) 
    782         btn = dabo.ui.dButton(self._centerPanel, Caption="Test Orange", OnHit=self.onTestFP) 
    783         self._centerPanel.Sizer.append(btn) 
    784         btn = dabo.ui.dButton(self._centerPanel, Caption="Test Blue", OnHit=self.onTestDP) 
    785         self._centerPanel.Sizer.append(btn) 
     964        btn = dabo.ui.dButton(self.CenterPanel, Caption="Test Orange", OnHit=self.onTestFP) 
     965        self.CenterPanel.Sizer.append(btn) 
     966        btn = dabo.ui.dButton(self.CenterPanel, Caption="Test Blue", OnHit=self.onTestDP) 
     967        self.CenterPanel.Sizer.append(btn) 
     968        chk = dabo.ui.dCheckBox(self.CenterPanel, Caption="Orange Dockable", DataSource=self.fp, 
     969                DataField="Dockable") 
     970        self.CenterPanel.Sizer.append(chk) 
    786971        self.fp.DynamicCaption = self.capForOrange 
    787972 
    788  
    789973    def capForOrange(self): 
     974        print "CAPFOR", self.fp.Docked 
    790975        state = "Floating" 
    791976        if self.fp.Docked: 
    792977            state = "Docked" 
     978        print "STATE", state 
    793979        return "I'm %s!" % state 
    794980         
    795      
    796981    def onTestFP(self, evt): 
    797982        self.printTest(self.fp)