daboide Commit
Revision 644
Date: 2006-10-08 17:03:21 -0700 (Sun, 08 Oct 2006)
Author: ed

Changed:
U   trunk/ClassDesigner.py
U   trunk/ClassDesignerComponents.py
U   trunk/ClassDesignerControlMixin.py

Log:
Fixed the saving of embedded custom classes so that they use relative paths.

Refactored out the code for opening a class and its associated code file so 
that it can be called from different parts of the ClassDesigner.

Fixed a bug that would throw an error if the Designer's Selection contained 
None values.

Got pageframe-type controls to work in the ClassDesigner on sizer-less forms.

Moved the checking for minimum sizes after the instantiation, since many 
objects had not yet had their 'drawn' sizes applied.

Removed several event bindings from the control mixin that were redundant. 
Removed duplicate key events when received by controls within containers such 
as pageframes, grids, etc.

Added a convenience prop 'UsingSizers' to the controls to replace the repeated 
reference to 'self.Form.UseSizers'.


Diff:
Modified: trunk/ClassDesigner.py
===================================================================
--- trunk/ClassDesigner.py      2006-10-07 13:49:39 UTC (rev 643)
+++ trunk/ClassDesigner.py      2006-10-09 00:03:21 UTC (rev 644)
@@ -419,15 +419,13 @@
                return ret
        
        
-       def openClass(self, pth):
-               """Called when the user selects the 'Open' menu and selects 
-               a saved XML file. We need to open the file, and confirm that it 
is 
-               indeed a valid class file. If so, we then re-construct the 
class in
-               a new ClassDesigner window.
+       def _importClassXML(self, pth):
+               """Read in the XML and associated code file (if any), and
+               return a dict that can be used to re-create the object.
                """
                xml = open(pth).read()
                try:
-                       clsd = xtd.xmltodict(xml)
+                       dct = xtd.xmltodict(xml)
                except:
                        raise IOError, _("This does not appear to be a valid 
class file.")
                # Get the associated code file, if any
@@ -435,10 +433,19 @@
                if os.path.exists(codePth):
                        try:
                                codeDict = 
desUtil.parseCodeFile(open(codePth).read())
-                               desUtil.addCodeToClassDict(clsd, codeDict)
+                               desUtil.addCodeToClassDict(dct, codeDict)
                        except StandardError, e:
                                print "Failed to parse code file:", e
-
+               return dct
+               
+       
+       def openClass(self, pth):
+               """Called when the user selects the 'Open' menu and selects 
+               a saved XML file. We need to open the file, and confirm that it 
is 
+               indeed a valid class file. If so, we then re-construct the 
class in
+               a new ClassDesigner window.
+               """
+               clsd = self._importClassXML(pth)
                # See if it is a full form-based class, or an individual 
component.
                isFormClass = (clsd["name"] == "dForm")
                if isFormClass:
@@ -1686,11 +1693,13 @@
                                        obj.Selected = newsel
                        else:
                                for oldSel in self._selection:
-                                       oldSel.Selected = False
+                                       if oldSel is not None:
+                                               oldSel.Selected = False
                                self._selection = []
                                for obj in objs:
-                                       self._selection.append(obj)
-                                       obj.Selected = True
+                                       if obj is not None:
+                                               self._selection.append(obj)
+                                               obj.Selected = True
                if len(self._selection) > 0:
                        self._srcObj = self._selection[0]
                else:
@@ -1748,7 +1757,7 @@
                        pnl = self._selection[0]
                # Handle the odd behavior of pages and when adding 
                # controls programmatically.
-               if isinstance(pnl, (dui.dPage, dui.dForm)):
+               if self.UseSizers and isinstance(pnl, (dui.dPage, dui.dForm)):
                        pnl = self.getMainLayoutPanel(pnl)
                return pnl
                
@@ -1924,38 +1933,40 @@
                if isPageControl:
                        noTabs = issubclass(cls, dui.dPageFrameNoTabs)
                        props["PageClass"] = self.getControlClass(dui.dPage)
-                       
-                       class PageInfoDialog(dui.dOkCancelDialog):
-                               def __init__(self, *args, **kwargs):
-                                       self.noTabs = self._extractKey(kwargs, 
"NoTabs", False)
-                                       self.pageCount = 3
-                                       self.tabPositions = ("Top", "Bottom", 
"Left", "Right")
-                                       self.tabPosSelection = 0
-                                       super(PageInfoDialog, 
self).__init__(*args, **kwargs)
-                                       
-                               def addControls(self):
-                                       self.Caption = _("Paged Control 
Settings")
-                                       gsz = dui.dGridSizer(maxCols=2, hgap=5, 
vgap=12)
-                                       lbl = dui.dLabel(self, 
Caption=_("Number of pages:"))
-                                       spn = dui.dSpinner(self, 
DataSource="form", 
-                                                       DataField="pageCount", 
Min=1, Max=20, Value=3)
-                                       gsz.append(lbl, halign="right")
-                                       gsz.append(spn)
-                                       
-                                       if not self.noTabs:
-                                               lbl = dui.dLabel(self, 
Caption=_("Tab Position:"))
-                                               dd = dui.dDropdownList(self, 
Choices=(_("Top"), 
-                                                               _("Bottom"), 
_("Left"), _("Right")), ValueMode="Position",
-                                                               Value=0, 
DataSource="form", DataField="tabPosSelection")
+                       if not useSizers:
+                               props["PageSizerClass"] = None
+
+                       if not props.get("PageCount", 0):
+                               class PageInfoDialog(dui.dOkCancelDialog):
+                                       def __init__(self, *args, **kwargs):
+                                               self.noTabs = 
self._extractKey(kwargs, "NoTabs", False)
+                                               self.pageCount = 3
+                                               self.tabPositions = ("Top", 
"Bottom", "Left", "Right")
+                                               self.tabPosSelection = 0
+                                               super(PageInfoDialog, 
self).__init__(*args, **kwargs)
+                                               
+                                       def addControls(self):
+                                               self.Caption = _("Paged Control 
Settings")
+                                               gsz = dui.dGridSizer(maxCols=2, 
hgap=5, vgap=12)
+                                               lbl = dui.dLabel(self, 
Caption=_("Number of pages:"))
+                                               spn = dui.dSpinner(self, 
DataSource="form", 
+                                                               
DataField="pageCount", Min=1, Max=20, Value=3)
                                                gsz.append(lbl, halign="right")
-                                               gsz.append(dd)
-                                       gsz.setColExpand("all", True)
-                                       
-                                       self.Sizer.append1x(gsz, border=30, 
halign="Center", valign="Middle")
-                                       self.refresh()
-                                       self.layout()
-                       
-                       if not props.get("PageCount", 0):
+                                               gsz.append(spn)
+                                               
+                                               if not self.noTabs:
+                                                       lbl = dui.dLabel(self, 
Caption=_("Tab Position:"))
+                                                       dd = 
dui.dDropdownList(self, Choices=(_("Top"), 
+                                                                       
_("Bottom"), _("Left"), _("Right")), ValueMode="Position",
+                                                                       
Value=0, DataSource="form", DataField="tabPosSelection")
+                                                       gsz.append(lbl, 
halign="right")
+                                                       gsz.append(dd)
+                                               gsz.setColExpand("all", True)
+                                               
+                                               self.Sizer.append1x(gsz, 
border=30, halign="Center", valign="Middle")
+                                               self.refresh()
+                                               self.layout()
+                               
                                dlg = PageInfoDialog(self.currentForm, 
NoTabs=noTabs, 
                                                
BasePrefKey=self.BasePrefKey+".PageInfoDialog")
                                dlg.AutoSize = False
@@ -2025,7 +2036,6 @@
                        else:
                                sz.insert(pos, obj)
                else:
-                       self._srcPos = self._srcPos
                        if self._srcPos is not None:
                                parentPos = 
obj.Parent.formCoordinates(obj.Parent.Position)
                                obj.Position = (self._srcPos[0] - parentPos[0], 
self._srcPos[1] - parentPos[1])
@@ -2048,19 +2058,17 @@
                                
                if isPageControl:
                        pg0panel = None
-                       for pg in obj.Pages[::-1]:
-                               pg.Sizer = LayoutSizer("v")
-                               pg0panel = LayoutPanel(pg)
-#                              pg0panel.BackColor = pg.BackColor
+                       if useSizers:
+                               for pg in obj.Pages[::-1]:
+                                       pg.Sizer = LayoutSizer("v")
+                                       pg0panel = LayoutPanel(pg)
 
                if useSizers:
                        newitem = obj.ControllingSizerItem
                        sz.setItemProps(newitem, itmProps)
                else:
-                       if obj.Width < obj.defaultWd:
-                               dabo.ui.setAfter(obj, "Width", obj.defaultWd)
-                       if obj.Height < obj.defaultHt:
-                               dabo.ui.setAfter(obj, "Height", obj.defaultHt)
+                       dabo.ui.callAfter(self.checkMinSize, obj)
+       
                try:
                        dui.callAfterInterval(500, obj.Form.layout)
                except:
@@ -2079,7 +2087,7 @@
                                obj.fillGrid()
 
                if not skipUpdate:
-                       if isPageControl:
+                       if useSizers and isPageControl:
                                dui.callAfter(self.select, pg0panel)
                        else:
                                dui.callAfter(self.select, obj)
@@ -2107,6 +2115,13 @@
                return ret
 
 
+       def checkMinSize(self, obj):
+               if obj.Height < obj.defaultHt:
+                       obj.Height = obj.defaultHt
+               if obj.Width < obj.defaultWd:
+                       obj.Width = obj.defaultWd
+
+
        def addSlotOptions(self, obj, pop, sepBefore=False, sepAfter=False):
                """Takes an object and a context menu, and adds the appropriate 
options
                depending on its position in the design surface.
@@ -2221,9 +2236,7 @@
                """Creates the popup menu for selecting child objects"""
                # Store the source object
                self._srcObj = srcObj
-               mpX, mpY = dui.getFormMousePosition()
-               objX, objY = srcObj.objectCoordinates((mpX, mpY))
-               self._srcPos = (mpX - objX, mpY - objY)
+               self._srcPos = dui.getFormMousePosition()
                
                mainpop = dui.dMenu()
                if self.UseSizers:
@@ -2309,11 +2322,7 @@
                                # Strip out the ordering information
                                pth = pth[1:]
                self.addToMRU(self._customClassCaption, pth, 
self.addCustomClass)
-               xml = open(pth).read()
-               try:
-                       clsd = xtd.xmltodict(xml)
-               except:
-                       raise IOError, _("This does not appear to be a valid 
class file.")
+               clsd = self._importClassXML(pth)
                # We need to replace the 'designerClass' attribute so that 
                # recreateChildren() knows what to add.
                nm = clsd["name"]
@@ -2334,7 +2343,9 @@
                        szr = None
                        fromSzr = False
                # OK, add it in...
+               self._basePath = self._srcObj.Form._classFile 
                mainObj = self.recreateChildren(self._srcObj, clsd, szr, 
fromSzr)
+               self._basePath = None
                # This is the key that marks it as a class, and not a base 
object.
                prop = LayoutSaverMixin.classFlagProp
                mainObj.__setattr__(prop, pth)
@@ -2373,7 +2384,7 @@
                        self._codeDict[obj] = cd
                        
                for att, val in atts.items():
-                       if att in ("children", "classID", "designerClass", 
"SlotCount"):
+                       if att in ("children", "classID", "code-ID", 
"designerClass", "SlotCount"):
                                continue
                        elif att == "savedClass":
                                obj.savedClass = True

Modified: trunk/ClassDesignerComponents.py
===================================================================
--- trunk/ClassDesignerComponents.py    2006-10-07 13:49:39 UTC (rev 643)
+++ trunk/ClassDesignerComponents.py    2006-10-09 00:03:21 UTC (rev 644)
@@ -79,7 +79,13 @@
                        if classDict:
                                defVals.update(classDict.get("attributes", {}))
                if isClass:
-                       ra["designerClass"] = clsPath
+                       clsRef = os.path.abspath(clsPath)
+                       if isinstance(self, dabo.ui.dForm):
+                               relPath = self._classFile
+                       else:
+                               relPath = self.Form._classFile
+                       ra["designerClass"] = 
dabo.lib.utils.getPathAttributePrefix() + \
+                                       dabo.lib.utils.relativePath(clsRef, 
relPath)
                        ra["savedClass"] = True
                else:
                        ra["designerClass"] = self.getClassName()
@@ -1645,7 +1651,7 @@
        """
        def afterInit(self):
                self.IsContainer = True
-               self.bindEvent(dEvents.KeyChar, self.Form.onKeyChar)
+#              self.bindEvent(dEvents.KeyChar, self.Form.onKeyChar)
                
                
        def onMouseMove(self, evt):

Modified: trunk/ClassDesignerControlMixin.py
===================================================================
--- trunk/ClassDesignerControlMixin.py  2006-10-07 13:49:39 UTC (rev 643)
+++ trunk/ClassDesignerControlMixin.py  2006-10-09 00:03:21 UTC (rev 644)
@@ -37,6 +37,8 @@
                self._hiliteBorderWidth = 0
                # Create the actual hilite border object
                self._hiliteBorder = None
+               # Caches the form's setting for 'useSizers'
+               self._usingSizers = None
                # References for resizing interactively
                self._startX = self._startY = self._startWd = self._startHt = 0
                # Reference for dragging interactively
@@ -97,8 +99,8 @@
                        self.setRootNode("Tree")
                elif isinstance(self, (dabo.ui.dPageFrame, dabo.ui.dPageList, 
                                dabo.ui.dPageSelect, dabo.ui.dPageFrameNoTabs)):
-                       self.defaultWd = 200
-                       self.defaultHt = 200
+                       self.defaultWd = 400
+                       self.defaultHt = 300
                        # Bind the active page to the current selection
                        self.bindEvent(dEvents.PageChanged, self.desSelectPage)
                elif isinstance(self, (dabo.ui.dPanel, dabo.ui.dImage, 
dabo.ui.dBitmap,
@@ -114,11 +116,11 @@
                self.HiliteBorderLineStyle = "dot"
                self.HiliteBorderWidth = 0
                
-               self.bindEvent(dEvents.KeyChar, self.onKeyChar)
-               self.bindEvent(dEvents.MouseLeftDown, self.onMouseLeftDown)
-               self.bindEvent(dEvents.MouseLeftUp, self.onMouseLeftUp)
-               self.bindEvent(dEvents.MouseMove, self.onMouseMove)
-               self.bindEvent(dEvents.ContextMenu, self.onContextMenu)
+#              self.bindEvent(dEvents.KeyChar, self.onKeyChar)
+#              self.bindEvent(dEvents.MouseLeftDown, self.onMouseLeftDown)
+#              self.bindEvent(dEvents.MouseLeftUp, self.onMouseLeftUp)
+#              self.bindEvent(dEvents.MouseMove, self.onMouseMove)
+#              self.bindEvent(dEvents.ContextMenu, self.onContextMenu)
                
 #              self.bindKey("left", self.Form.keyMoveLeft)
                
@@ -128,7 +130,9 @@
                
                
        def onKeyChar(self, evt):
-               print "KEY/Control", self.Name, evt.keyCode, evt.keyChar, 
dKeys.key_Left
+               if isinstance(self, (dabo.ui.dPage, dabo.ui.dColumn)):
+                       # The key will get processed by the container
+                       return
                self.Form.onKeyChar(evt)
 
                
@@ -147,7 +151,7 @@
                        pass
                else:
                        evt.stop()
-                       if not self.Form.UseSizers:
+                       if not self.UsingSizers:
                                self.Form.onControlLeftDown(evt)
 
 
@@ -171,40 +175,39 @@
                # If it is a LayoutPanel or page, return - the event 
                # is handled elsewhere
                evt.stop()
-               if isinstance(self, (dabo.ui.dPage, LayoutPanel)):
+               if self.UsingSizers and isinstance(self, (dabo.ui.dPage, 
LayoutPanel)):
                        return
                pop = self.createContextMenu()
                self.showContextMenu(pop)
 
 
        def createContextMenu(self):
-               if isinstance(self, (dabo.ui.dPanel,)):
-                       # If the control can contain child objects, get that 
menu.
-                       # If it already has child objects, though, do not get 
the menu.
+               canAddObjects = False
+               if not self.UsingSizers:
+                       if self is self.Form.ActiveContainer:
+                               # If the control can contain child objects, get 
that menu.
+                               canAddObjects = True
+               if canAddObjects:
                        pop = self.Form.app.getControlMenu(self, False)
-#                      if len(self.Children) == 0:
-#                              pop = self.Form.app.getControlMenu(self, True)
-#                      else:
-#                              return None
                else:
                        pop = dabo.ui.dMenu()
                if len(pop.Children):
                        pop.prependSeparator()
-               if not self.Form.UseSizers and self.IsContainer \
+               if not self.UsingSizers and self.IsContainer \
                                and not self is self.Form.ActiveContainer:
                        pop.prepend(_("Edit Contents"), 
bindfunc=self.onEditContainer)                  
                if len(pop.Children):
                        pop.prependSeparator()
                pop.prepend(_("Edit Code"), bindfunc=self.onEditCode)
                pop.prependSeparator()
-               if not self.Form.UseSizers and self is 
self.Form.ActiveContainer:
+               if not self.UsingSizers and self is self.Form.ActiveContainer:
                        if self.Form.app.Clipboard:
                                pop.prepend(_("Paste"), bindfunc=self.onPaste)
                else:
                        pop.prepend(_("Delete"), bindfunc=self.onDelete)
                        pop.prepend(_("Copy"), bindfunc=self.onCopy)
                        pop.prepend(_("Cut"), bindfunc=self.onCut)
-               if self.Form.UseSizers:
+               if self.UsingSizers:
                        self.Application.addSlotOptions(self, pop, 
sepBefore=True)
                        # Add the Sizer editing option
                        pop.appendSeparator()
@@ -247,7 +250,7 @@
                if isinstance(self, dabo.ui.dPage):
                        dabo.ui.callAfter(self.Parent.onDelete, evt)
                        return
-               if self.Form.UseSizers:
+               if self.UsingSizers:
                        self.ControllingSizer.delete(self)
                else:
                        self.Form.select(self.Parent)
@@ -270,6 +273,7 @@
        
        def desSelectPage(self, evt):
                """Called when a page is selected"""
+               if not self.UsingSizers: return
                try:
                        obj = self.Application.Selection[0]
                        if obj.isContainedBy(self.SelectedPage):
@@ -781,7 +785,8 @@
                
                
        def _getContainerState(self):
-               return isinstance(self, (dabo.ui.dPanel, dabo.ui.dForm, 
dabo.ui.dDialog) )
+               return isinstance(self, (dabo.ui.dPanel, dabo.ui.dPage, 
dabo.ui.dForm, 
+                               dabo.ui.dDialog) )
        
        
        def _getRegID(self):
@@ -804,12 +809,15 @@
        def _setSelected(self, val):
                oldval = self._selected
                self._selected = val
-               if self.Form.UseSizers:
+               if self.UsingSizers:
                        self.HiliteBorderWidth = (0, 2)[val]
                else:
                        self.HiliteBorderWidth = (0, 2)[self is 
self.Form.ActiveContainer]
                if not val:
                        self.Form.hideHandles(self)
+               else:
+                       if isinstance(self, dabo.ui.dPage):
+                               self.Parent.SelectedPage = self
                if hasattr(self, "_redraw"):
                        autoclear = self._autoClearDrawings
                        needRefresh = False
@@ -948,6 +956,12 @@
                return ret
 
        
+       def _getUsingSizers(self):
+               if self._usingSizers is None:
+                       self._usingSizers = self.Form.UseSizers
+               return self._usingSizers
+
+
        DesignerEvents = property(_getDesEvents, None, None,
                        _("""Returns a list of the most common events for the 
control.
                        This will determine which events are displayed in the 
PropSheet
@@ -1015,6 +1029,9 @@
        TreeDisplayCaption = property(_getTreeDisp, None, None,
                        _("Displayed text in the Designer Tree.  (tuple)") )
 
+       UsingSizers = property(_getUsingSizers, None, None,
+                       _("Convenience property. Reflects the form's UseSizers 
value  (bool)"))
+       
 
 
 if __name__ == "__main__":




_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev

Reply via email to