dabo Commit
Revision 4079
Date: 2008-05-12 06:39:42 -0700 (Mon, 12 May 2008)
Author: Ed
Trac: http://svn.dabodev.com/trac/dabo/changeset/4079
Changed:
U trunk/dabo/ui/uiwx/dDockForm.py
Log:
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.
Diff:
Modified: trunk/dabo/ui/uiwx/dDockForm.py
===================================================================
--- trunk/dabo/ui/uiwx/dDockForm.py 2008-05-11 16:35:02 UTC (rev 4078)
+++ trunk/dabo/ui/uiwx/dDockForm.py 2008-05-12 13:39:42 UTC (rev 4079)
@@ -9,14 +9,33 @@
import dabo.dEvents as dEvents
from dabo.ui import makeDynamicProperty
+flag_allow_float = aui.AUI_MGR_ALLOW_FLOATING
+flag_show_active = aui.AUI_MGR_ALLOW_ACTIVE_PANE
+flag_transparent_drag = aui.AUI_MGR_TRANSPARENT_DRAG
+flag_rectangle_hint = aui.AUI_MGR_RECTANGLE_HINT
+flag_transparent_hint = aui.AUI_MGR_TRANSPARENT_HINT
+flag_venetian_blinds_hint = aui.AUI_MGR_VENETIAN_BLINDS_HINT
+flag_no_venetian_blinds_fade = aui.AUI_MGR_NO_VENETIAN_BLINDS_FADE
+flag_hint_fade = aui.AUI_MGR_HINT_FADE
+
class _dDockManager(aui.AuiManager):
def __init__(self, win):
- super(_dDockManager, self).__init__(win)
+ self._managedWindow = win
+ flags = flag_allow_float | flag_transparent_drag |
flag_rectangle_hint | flag_transparent_hint
+ super(_dDockManager, self).__init__(win, flags=flags)
+ self.Bind(aui.EVT_AUI_RENDER, self.aui_render)
+
+
+ def aui_render(self, evt):
+ evt.Skip()
+ dabo.ui.callAfterInterval(100, self._managedWindow.update)
- def addPane(self, win, name=None, typ=None, caption=None):
+ def addPane(self, win, name=None, typ=None, caption=None, toolbar=None):
pi = PaneInfo()
+ if toolbar:
+ pi.ToolbarPane()
if name is not None:
pi = pi.Name(name)
if caption is not None:
@@ -45,16 +64,19 @@
class _dDockPanel(dabo.ui.dPanel):
def __init__(self, parent, properties=None, attProperties=None, *args,
**kwargs):
- pname = self._extractKey(kwargs, "name", "")
+ nmU = self._extractKey((properties, kwargs), "Name", "")
+ nb = self._extractKey((properties, kwargs), "NameBase", "")
+ nmL = self._extractKey((properties, kwargs), "name", "")
+ kwargs["NameBase"] = [txt for txt in (nmU, nb, nmL,
"_dDockPanel") if txt][0]
pcapUp = self._extractKey(kwargs, "Caption", "")
pcap = self._extractKey(kwargs, "caption", "")
ptype = self._extractKey(kwargs, "typ", "")
- kwargs["NameBase"] = pname
if pcapUp:
kwargs["Caption"] = pcapUp
else:
kwargs["Caption"] = pcap
self._paramType = ptype
+ self._toolbar = self._extractKey(kwargs, "Toolbar", False)
# Initialize attributes that underly properties
self._bottomDockable = True
@@ -79,13 +101,39 @@
self._floatingPosition =
self.GetParent().GetPosition().Get()
self._floatingSize = self.GetParent().GetSize().Get()
-
+
+ def _uniqueNameForParent(self, name, parent=None):
+ """We need to check the AUI manager's PaneInfo name value, too,
as that has to be unique
+ there as well as the form.
+ """
+ changed = True
+ while changed:
+ i = 0
+ auiOK = False
+ while not auiOK:
+ auiOK = True
+ candidate = name
+ if i:
+ candidate = "%s%s" % (name, i)
+ mtch = [pi.name for pi in
self._Manager.GetAllPanes()
+ if pi.name == candidate]
+ if mtch:
+ auiOK = False
+ i += 1
+ changed = changed and (candidate != name)
+ name = candidate
+
+ candidate = super(_dDockPanel,
self)._uniqueNameForParent(name, parent)
+ changed = changed and (candidate != name)
+ name = candidate
+
+
def float(self):
"""Float the panel if it isn't already floating."""
if self.Floating or not self.Floatable:
return
self.__pi.Float()
- self.Form._refreshState()
+ self._updateAUI()
def dock(self, side=None):
@@ -103,7 +151,7 @@
else:
dabo.errorLog.write(_("Invalid dock position:
'%s'.") % side)
inf.Dock()
- self.Form._refreshState()
+ self._updateAUI()
def _beforeSetProperties(self, props):
@@ -113,28 +161,54 @@
them now, and then set them afterwards.
"""
self._propDelayDict = {}
- for delayed in ("Left", "Right", "Top", "Bottom", "Width",
"Height"):
- val = self._extractKey(props, delayed)
- if val:
+ props2Delay = ("Bottom", "BottomDockable", "Caption",
"DestroyOnClose", "Dockable", "Docked",
+ "DockSide", "Floatable", "Floating",
"FloatingBottom", "FloatingHeight", "FloatingLeft",
+ "FloatingPosition", "FloatingRight",
"FloatingSize", "FloatingTop", "FloatingWidth", "Height",
+ "Left", "LeftDockable", "Movable", "Resizable",
"Right", "RightDockable", "ShowBorder",
+ "ShowCaption", "ShowCloseButton",
"ShowGripper", "ShowMaximizeButton",
+ "ShowMinimizeButton", "ShowPinButton", "Top",
"TopDockable", "Visible", "Width")
+ for delayed in props2Delay:
+ val = self._extractKey(props, delayed, None)
+ if val is not None:
self._propDelayDict[delayed] = val
return super(_dDockPanel, self)._beforeSetProperties(props)
- def _setProperties(self, props):
+ def _afterSetProperties(self):
+ nm = self.Name
frm = self.Form
- self.__pi = frm._mgr.addPane(self, name=props["NameBase"],
- typ=self._paramType, caption=props["Caption"])
+ self.__pi = self._Manager.addPane(self, name=nm,
+ typ=self._paramType,
caption=self._propDelayDict.get("Caption", "_dDockPanel"))
del self._paramType
self.__pi.MinSize((50,50))
- super(_dDockPanel, self)._setProperties(props)
-
-
- def _afterSetProperties(self):
if self._propDelayDict:
self.setProperties(self._propDelayDict)
del self._propDelayDict
-
-
+
+
+ def getState(self):
+ """Returns the local name and a string that can be used to
restore the state of this pane."""
+ inf = self._Manager.SavePaneInfo(self.__pi)
+ try:
+ infPairs = (qq.split("=") for qq in inf.split(";"))
+ nm = dict(infPairs)["name"]
+ except KeyError:
+ # For some reason a name was not returned
+ return ""
+ return (nm, inf.replace("name=%s;" % nm, ""))
+
+
+ def _updateAUI(self):
+ frm = self.Form
+ if frm is not None:
+ frm._refreshState()
+ else:
+ try:
+ self._Manager.runUpdate()
+ except AttributeError:
+ pass
+
+
def __getPosition(self):
if self.Floating:
obj = self.GetParent()
@@ -172,11 +246,10 @@
def _setBottomDockable(self, val):
if self._constructed():
self.__pi.BottomDockable(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["BottomDockable"] = val
-
def _getCaption(self):
try:
return self._caption
@@ -188,7 +261,7 @@
if self._constructed():
self._caption = val
self.__pi.Caption(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["Caption"] = val
@@ -200,7 +273,7 @@
if self._constructed():
self._destroyOnClose = val
self.__pi.DestroyOnClose(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["DestroyOnClose"] = val
@@ -212,7 +285,9 @@
if self._constructed():
self._dockable = val
self.__pi.Dockable(val)
- self.Form._refreshState()
+ if self.Docked:
+ self.Docked = val
+ self._updateAUI()
else:
self._properties["Dockable"] = val
@@ -231,7 +306,7 @@
self.__pi.Float()
chg = True
if chg:
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["Docked"] = val
@@ -243,7 +318,7 @@
if self._constructed():
vUp = val[0].upper()
self.__pi.dock_direction = {"T": 1, "R": 2, "B": 3,
"L": 4}[vUp]
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["DockSide"] = val
@@ -255,7 +330,7 @@
if self._constructed():
self._floatable = val
self.__pi.Floatable(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["Floatable"] = val
@@ -274,9 +349,8 @@
self.__pi.Dock()
chg = True
if chg:
- self.Form._refreshState()
+ self._updateAUI()
else:
- print dir(self)
self._properties["Floating"] = val
@@ -414,11 +488,19 @@
def _setLeftDockable(self, val):
if self._constructed():
self.__pi.LeftDockable(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["LeftDockable"] = val
+ def _getManager(self):
+ try:
+ mgr = self._mgr
+ except AttributeError:
+ mgr = self._mgr = self.Form._mgr
+ return mgr
+
+
def _getMovable(self):
return self._movable
@@ -426,7 +508,7 @@
if self._constructed():
self._movable = val
self.__pi.Movable(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["Movable"] = val
@@ -438,7 +520,7 @@
if self._constructed():
self._resizable = val
self.__pi.Resizable(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["Resizable"] = val
@@ -462,7 +544,7 @@
def _setRightDockable(self, val):
if self._constructed():
self.__pi.RightDockable(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["RightDockable"] = val
@@ -474,7 +556,7 @@
if self._constructed():
self._showBorder = val
self.__pi.PaneBorder(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["ShowBorder"] = val
@@ -486,7 +568,7 @@
if self._constructed():
self._showCaption = val
self.__pi.CaptionVisible(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["ShowCaption"] = val
@@ -514,7 +596,7 @@
if self._constructed():
self._showGripper = val
self.__pi.Gripper(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["ShowGripper"] = val
@@ -526,7 +608,7 @@
if self._constructed():
self._showMaximizeButton = val
self.__pi.MaximizeButton(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["ShowMaximizeButton"] = val
@@ -538,7 +620,7 @@
if self._constructed():
self._showMinimizeButton = val
self.__pi.MinimizeButton(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["ShowMinimizeButton"] = val
@@ -550,11 +632,16 @@
if self._constructed():
self._showPinButton = val
self.__pi.PinButton(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["ShowPinButton"] = val
+
+ def _getToolbar(self):
+ return self._toolbar
+
+
def _getTop(self):
return self.__getPosition()[1]
@@ -574,7 +661,7 @@
def _setTopDockable(self, val):
if self._constructed():
self.__pi.TopDockable(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["TopDockable"] = val
@@ -585,7 +672,7 @@
def _setVisible(self, val):
if self._constructed():
self.__pi.Show(val)
- self.Form._refreshState()
+ self._updateAUI()
else:
self._properties["Visible"] = val
@@ -665,6 +752,9 @@
LeftDockable = property(_getLeftDockable, _setLeftDockable, None,
_("Can the panel be docked to the left edge of the
form? Default=True (bool)"))
+ _Manager = property(_getManager, None, None,
+ _("Reference to the AUI manager (for internal use
only). (_dDockManager)"))
+
Movable = property(_getMovable, _setMovable, None,
_("Can the panel be moved (True, default), or is it in
a fixed position (False). (bool)"))
@@ -698,6 +788,9 @@
ShowPinButton = property(_getShowPinButton, _setShowPinButton, None,
_("Does the panel display a pin button when floating?
Default=False (bool)"))
+ Toolbar = property(_getToolbar, None, None,
+ _("Returns True if this is a Toolbar pane.
Default=False (bool)"))
+
Top = property(_getTop, _setTop, None,
_("Position in pixels of the top side of the panel.
Read-only when docked; read-write when floating (int)"))
@@ -710,22 +803,29 @@
Width = property(_getWidth, _setWidth, None,
_("Position in pixels of the width of the panel.
Read-only when docked; read-write when floating (int)"))
+
+ DynamicCaption = makeDynamicProperty(Caption)
class dDockForm(dabo.ui.dForm):
def _afterInit(self):
+ self._inUpdate = False
self._mgr = mgr = _dDockManager(self)
pc = self.getBasePanelClass()
self._centerPanel = pc(self, name="CenterPanel", typ="center")
self._centerPanel.Sizer = dabo.ui.dSizer("v")
+ self._panels = {}
super(dDockForm, self)._afterInit()
self.bindEvent(dEvents.Destroy, self.__onDestroy)
def __onDestroy(self, evt):
if self._finito:
+ # Need to save this here, since we can't respond to all
layout changes.
+ self.saveSizeAndPosition()
self._mgr.UnInit()
+
def getBasePanelClass(cls):
return _dDockPanel
@@ -735,19 +835,27 @@
def onChildBorn(self, evt):
ok = isinstance(evt.child, (_dDockPanel, dabo.ui.dStatusBar,
dabo.ui.dShell.dShell))
if not ok:
- print "BORN:", evt.child
+ # This should never happen; if so, log the error
+ dabo.errorLog.write(_("Unmanaged object added to a Dock
Form: %s") %evt.child)
def addObject(self, classRef, Name=None, *args, **kwargs):
+ """To support the old addObject() syntax, we need to re-direct
the request
+ to the center panel.
+ """
self._centerPanel.addObject(classRef, Name=Name, *args,
**kwargs)
def addPanel(self, *args, **kwargs):
+ """Adds a dockable panel to the form."""
pnl = _dDockPanel(self, *args, **kwargs)
self._refreshState()
+ # Store the pane info
+ nm = pnl.getState()[0]
+ self._panels[pnl] = nm
return pnl
-
-
+
+
def _refreshState(self, interval=None):
if self._finito:
return
@@ -756,43 +864,120 @@
if interval == 0:
self._mgr.Update()
else:
- dabo.ui.callAfterInterval(interval,
self._mgr.runUpdate)
+ dabo.ui.callAfterInterval(interval, self._mgr.runUpdate)
+ if not self._inUpdate:
+ dabo.ui.callAfter(self.update)
+
+
+ def update(self):
+ if not self._inUpdate:
+ self._inUpdate = True
+ super(dDockForm, self).update()
+ # Update the panels
+ for pnl in self._panels.keys():
+ pnl.update()
+ dabo.ui.callAfterInterval(500, self._clearInUpdate)
+ def _clearInUpdate(self):
+ self._inUpdate = False
+
+
+ def saveSizeAndPosition(self):
+ """ Save the panel layout info, then call the default
behavior."""
+ if self.Application:
+ if self.SaveRestorePosition and not self.TempForm:
+ self.Application.setUserSetting("perspective",
self._mgr.SavePerspective())
+ if not self._finito:
+ super(dDockForm,
self).saveSizeAndPosition()
+
+
+ def restoreSizeAndPosition(self):
+ """Restore the panel layout, if possible, then call the default
behavior."""
+ if self.Application and self.SaveRestorePosition:
+ super(dDockForm, self).restoreSizeAndPosition()
+ ps = self.Application.getUserSetting("perspective", "")
+ if ps:
+ self._mgr.LoadPerspective(ps)
+
+
# Property get/set/del methods follow. Scroll to bottom to see the
property
# definitions themselves.
def _getCenterPanel(self):
return self._centerPanel
+ def _getShowActivePanel(self):
+ return bool(self._mgr.GetFlags() & flag_show_active)
+
+ def _setShowActivePanel(self, val):
+ if self._constructed():
+ self._transparentDrag = val
+ flags = self._mgr.GetFlags()
+ if val:
+ newFlags = flags | flag_show_active
+ else:
+ newFlags = flags & ~flag_show_active
+ self._mgr.SetFlags(newFlags)
+ else:
+ self._properties["ShowActivePanel"] = val
+
+
+ def _getTransparentDrag(self):
+ return bool(self._mgr.GetFlags() & flag_transparent_drag)
+
+ def _setTransparentDrag(self, val):
+ if self._constructed():
+ self._transparentDrag = val
+ flags = self._mgr.GetFlags()
+ if val:
+ newFlags = flags | flag_transparent_drag
+ else:
+ newFlags = flags & ~flag_transparent_drag
+ self._mgr.SetFlags(newFlags)
+ else:
+ self._properties["TransparentDrag"] = val
+
+
CenterPanel = property(_getCenterPanel, None, None,
_("Reference to the center (i.e., non-docking) panel.
(read-only) (dPanel)"))
+
+ ShowActivePanel = property(_getShowActivePanel, _setShowActivePanel,
None,
+ _("When True, the title bar of the active pane is
highlighted. Default=False (bool)"))
-
+ TransparentDrag = property(_getTransparentDrag, _setTransparentDrag,
None,
+ _("When dragging panes, do they appear transparent?
Default=True (bool)"))
class _dDockForm_test(dDockForm):
+ def initProperties(self):
+ self.SaveRestorePosition = False
+ self.Size = (700, 500)
+
def afterInit(self):
- self.fp = _dDockPanel(self, Floating=True, BackColor="orange",
- Caption="I'm Floating!", Top=70, Left=100)
- self.dp = _dDockPanel(self, Floating=False,
BackColor="slateblue",
+ self.fp = self.addPanel(Floating=True, BackColor="orange",
+ Caption="Initially Floating", Top=70, Left=200)
+ self.dp = self.addPanel(Floating=False, Caption="Initially
Docked", BackColor="slateblue",
ShowCaption=False, ShowPinButton=True,
ShowCloseButton=False,
ShowGripper=True)
- btn = dabo.ui.dButton(self._centerPanel, Caption="Test Orange",
OnHit=self.onTestFP)
- self._centerPanel.Sizer.append(btn)
- btn = dabo.ui.dButton(self._centerPanel, Caption="Test Blue",
OnHit=self.onTestDP)
- self._centerPanel.Sizer.append(btn)
+ btn = dabo.ui.dButton(self.CenterPanel, Caption="Test Orange",
OnHit=self.onTestFP)
+ self.CenterPanel.Sizer.append(btn)
+ btn = dabo.ui.dButton(self.CenterPanel, Caption="Test Blue",
OnHit=self.onTestDP)
+ self.CenterPanel.Sizer.append(btn)
+ chk = dabo.ui.dCheckBox(self.CenterPanel, Caption="Orange
Dockable", DataSource=self.fp,
+ DataField="Dockable")
+ self.CenterPanel.Sizer.append(chk)
self.fp.DynamicCaption = self.capForOrange
-
def capForOrange(self):
+ print "CAPFOR", self.fp.Docked
state = "Floating"
if self.fp.Docked:
state = "Docked"
+ print "STATE", state
return "I'm %s!" % state
-
def onTestFP(self, evt):
self.printTest(self.fp)
def onTestDP(self, evt):
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev
Searchable Archives: http://leafe.com/archives/search/dabo-dev
This message: http://leafe.com/archives/byMID/[EMAIL PROTECTED]