dabo Commit
Revision 4061
Date: 2008-05-04 08:53:57 -0700 (Sun, 04 May 2008)
Author: Ed
Trac: http://svn.dabodev.com/trac/dabo/changeset/4061

Changed:
D   branches/ed-ide/ClassDesigner.py
D   branches/ed-ide/ClassDesignerComponents.py
D   branches/ed-ide/ClassDesignerControlMixin.py
D   branches/ed-ide/ClassDesignerCustomPropertyDialog.py
D   branches/ed-ide/ClassDesignerEditor.py
D   branches/ed-ide/ClassDesignerExceptions.py
D   branches/ed-ide/ClassDesignerFormMixin.py
D   branches/ed-ide/ClassDesignerMenu.py
D   branches/ed-ide/ClassDesignerMethodSheet.py
D   branches/ed-ide/ClassDesignerObjectPropertySheet.py
D   branches/ed-ide/ClassDesignerPemForm.py
D   branches/ed-ide/ClassDesignerPropSheet.py
D   branches/ed-ide/ClassDesignerSizerPalette.py
D   branches/ed-ide/ClassDesignerTreeSheet.py
D   branches/ed-ide/CxnEditor.py
D   branches/ed-ide/DragHandle.py
D   branches/ed-ide/Editor.py
D   branches/ed-ide/MenuBarPanel.py
D   branches/ed-ide/MenuDesigner.py
D   branches/ed-ide/MenuDesignerComponents.py
D   branches/ed-ide/MenuDesignerForm.py
D   branches/ed-ide/MenuDesignerPropForm.py
D   branches/ed-ide/MenuPanel.py
D   branches/ed-ide/PrefEditor.cdxml
D   branches/ed-ide/PrefEditor.py
D   branches/ed-ide/ReportDesigner.py
A   branches/ed-ide/components/
A   branches/ed-ide/components/ClassDesigner/
A   branches/ed-ide/components/ClassDesigner/ClassDesigner.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerComponents.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerControlMixin.py
A   
branches/ed-ide/components/ClassDesigner/ClassDesignerCustomPropertyDialog.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerEditor.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerExceptions.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerFormMixin.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerMenu.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerMethodSheet.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerObjectPropertySheet.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerPemForm.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerPropSheet.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerSizerPalette.py
A   branches/ed-ide/components/ClassDesigner/ClassDesignerTreeSheet.py
A   branches/ed-ide/components/ClassDesigner/DragHandle.py
A   branches/ed-ide/components/ClassDesigner/QLWImageData.py
A   branches/ed-ide/components/ClassDesigner/QuickLayoutWizard.py
A   branches/ed-ide/components/CxnEditor/
A   branches/ed-ide/components/CxnEditor/CxnEditor.py
A   branches/ed-ide/components/CxnEditor/conn.xsd
A   branches/ed-ide/components/MenuDesigner/
A   branches/ed-ide/components/MenuDesigner/MenuBarPanel.py
A   branches/ed-ide/components/MenuDesigner/MenuDesigner.py
A   branches/ed-ide/components/MenuDesigner/MenuDesignerComponents.py
A   branches/ed-ide/components/MenuDesigner/MenuDesignerForm.py
A   branches/ed-ide/components/MenuDesigner/MenuDesignerPropForm.py
A   branches/ed-ide/components/MenuDesigner/MenuPanel.py
A   branches/ed-ide/components/ReportDesigner/
A   branches/ed-ide/components/ReportDesigner/ReportDesigner.py
A   branches/ed-ide/components/ReportDesigner/sample.cnxml
A   branches/ed-ide/components/ReportDesigner/sampleDaboIcon.png
A   branches/ed-ide/components/ReportDesigner/sampleReport.rfxml
A   branches/ed-ide/components/TextEditor/
A   branches/ed-ide/components/TextEditor/TextEditor.py
D   branches/ed-ide/conn.xsd
D   branches/ed-ide/mover.cdxml
D   branches/ed-ide/sample.cnxml
D   branches/ed-ide/sampleDaboIcon.png
D   branches/ed-ide/sampleReport.rfxml
A   branches/ed-ide/samples/
A   branches/ed-ide/samples/classes/
A   branches/ed-ide/samples/classes/mover.cdxml
A   branches/ed-ide/tools/
A   branches/ed-ide/tools/AppWizard/
A   branches/ed-ide/tools/PrefEditor/
A   branches/ed-ide/tools/PrefEditor/PrefEditor.cdxml
A   branches/ed-ide/tools/PrefEditor/PrefEditor.py
D   branches/ed-ide/wizards/

Log:
First pass at reorganizing the IDE stuff

Diff:
Deleted: branches/ed-ide/ClassDesigner.py

Deleted: branches/ed-ide/ClassDesignerComponents.py

Deleted: branches/ed-ide/ClassDesignerControlMixin.py

Deleted: branches/ed-ide/ClassDesignerCustomPropertyDialog.py

Deleted: branches/ed-ide/ClassDesignerEditor.py

Deleted: branches/ed-ide/ClassDesignerExceptions.py

Deleted: branches/ed-ide/ClassDesignerFormMixin.py

Deleted: branches/ed-ide/ClassDesignerMenu.py

Deleted: branches/ed-ide/ClassDesignerMethodSheet.py

Deleted: branches/ed-ide/ClassDesignerObjectPropertySheet.py

Deleted: branches/ed-ide/ClassDesignerPemForm.py

Deleted: branches/ed-ide/ClassDesignerPropSheet.py

Deleted: branches/ed-ide/ClassDesignerSizerPalette.py

Deleted: branches/ed-ide/ClassDesignerTreeSheet.py

Deleted: branches/ed-ide/CxnEditor.py

Deleted: branches/ed-ide/DragHandle.py

Deleted: branches/ed-ide/Editor.py

Deleted: branches/ed-ide/MenuBarPanel.py

Deleted: branches/ed-ide/MenuDesigner.py

Deleted: branches/ed-ide/MenuDesignerComponents.py

Deleted: branches/ed-ide/MenuDesignerForm.py

Deleted: branches/ed-ide/MenuDesignerPropForm.py

Deleted: branches/ed-ide/MenuPanel.py

Deleted: branches/ed-ide/PrefEditor.cdxml

Deleted: branches/ed-ide/PrefEditor.py

Deleted: branches/ed-ide/ReportDesigner.py

Copied: branches/ed-ide/components/ClassDesigner/ClassDesigner.py (from rev 
4060, branches/ed-ide/ClassDesigner.py)
===================================================================
--- branches/ed-ide/components/ClassDesigner/ClassDesigner.py                   
        (rev 0)
+++ branches/ed-ide/components/ClassDesigner/ClassDesigner.py   2008-05-04 
15:53:57 UTC (rev 4061)
@@ -0,0 +1,4089 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import sys
+import os
+import copy
+import inspect
+import dabo
+from dabo.dLocalize import _
+import dabo.dEvents as dEvents
+if __name__ == "__main__":
+       dabo.ui.loadUI("wx")
+# This is because I'm a lazy typist
+dui = dabo.ui
+from ClassDesignerFormMixin import ClassDesignerFormMixin as dfm
+from ClassDesignerPemForm import PemForm
+from ClassDesignerEditor import EditorForm
+from ClassDesignerComponents import LayoutPanel
+from ClassDesignerComponents import LayoutBasePanel
+from ClassDesignerComponents import LayoutSpacerPanel
+from ClassDesignerComponents import LayoutSizer
+from ClassDesignerComponents import LayoutBorderSizer
+from ClassDesignerComponents import LayoutGridSizer
+from ClassDesignerComponents import LayoutSaverMixin
+from ClassDesignerComponents import NoSizerBasePanel
+from ClassDesignerComponents import szItemDefaults
+from ClassDesignerComponents import classFlagProp
+from ClassDesignerControlMixin import ClassDesignerControlMixin as cmix
+from ClassDesignerCustomPropertyDialog import ClassDesignerCustomPropertyDialog
+from ClassDesignerSizerPalette import SizerPaletteForm
+from dabo.lib.DesignerXmlConverter import DesignerXmlConverter
+import ClassDesignerMenu
+import dabo.lib.xmltodict as xtd
+import dabo.ui.dialogs as dlgs
+from dabo.lib.utils import dictStringify
+from ClassDesignerExceptions import PropertyUpdateException
+# Temporary fix for wxPython 2.6 users
+try:
+       dabo.ui.dDockForm
+       _USE_DOCKFORM = True
+except:
+       dabo.ui.dDockForm = None
+       _USE_DOCKFORM = False
+
+
+
+class ClassDesigner(dabo.dApp):
+       # Behaviors which are normal in the framework may need to
+       # be modified when run as the ClassDesigner. This flag will
+       # distinguish between the two states.
+       isDesigner = True
+
+       def __init__(self, clsFile=""):
+               super(ClassDesigner, self).__init__(showSplashScreen=False,
+                               splashTimeout=10)
+
+               self._basePrefKey = "dabo.ide.ClassDesigner"
+               self._desFormClass = None
+               self._selectedClass = dui.dForm
+               self._currentForm = None
+               self._editorForm = None
+               self._pemForm = None
+               self._tree = None
+               self._palette = None
+               self._sizerPalette = None
+               self._selection = []
+               self._editors = []
+               self._srcObj = None
+               self._srcPos = None
+               self._codeDict = {}
+               self._classCodeDict = {}
+               self._classPropDict = {}
+               self._classImportDict = {}
+               self._classDefaultVals = {}
+               self._mixedControlClasses = {}
+               self._superClassInfo = {}
+               self._addingClass = False
+               # Tuple of all paged-control classes
+               self.pagedControls = (dui.dPageFrame, dui.dPageList, 
dui.dPageSelect,
+                               dui.dPageFrameNoTabs)
+               self.MainFormClass = None
+               self.setAppInfo("appName", "Class Designer")
+               # Some processes need to behave differently when we are
+               # importing a class from a cdxml file; this flag lets them
+               # determine what process is being run.
+               self.openingClassXML = False
+               # Create the clipboard
+               self._clipboard = None
+               # This holds a reference to the target object when
+               # there is a context menu event.
+               self._contextObj = None
+               # When saving classes, we need to note when we are inside
+               # a class definition. The list is used as the class stack.
+               self._classStack = []
+               # We also need to save child class definitions on a stack, when
+               # saving/recreating class components with nested objects.
+               self._classChildDefStack = []
+               # Flag for indicating that all props, not just non-default ones,
+               # are saved in the .cdxml file
+               self.saveAllProps = False
+               # When we set the DefaultBorder for a sizer, should we
+               # resize all its children?
+               self._propagateDefaultBorder = True
+               # Store the name of the custom class menu here instead of
+               # hard-coding it in several places.
+               self._customClassCaption = _("Custom Classes")
+               # Add this to the persistent MRUs
+               self._persistentMRUs[self._customClassCaption] = 
self.addCustomClass
+               # Save the default atts for sizers. This way we can distinguish
+               # from default sizers that can be replaced from customized
+               # sizers which should remain.
+               self._defBoxSizerAtts = bsa = {}
+               atts = 
LayoutSizer().getDesignerDict(allProps=True)["attributes"]
+               bsa["DefaultBorder"] = atts["DefaultBorder"]
+               bsa["DefaultBorderTop"] = atts["DefaultBorderTop"]
+               bsa["DefaultBorderBottom"] = atts["DefaultBorderBottom"]
+               bsa["DefaultBorderLeft"] = atts["DefaultBorderLeft"]
+               bsa["DefaultBorderRight"] = atts["DefaultBorderRight"]
+               self._defGridSizerAtts = gsa = {}
+               atts = 
LayoutGridSizer().getDesignerDict(allProps=True)["attributes"]
+               gsa["HGap"] = atts["HGap"]
+               gsa["VGap"] = atts["VGap"]
+               gsa["MaxDimension"] = atts["MaxDimension"]
+               # Get rid of the update/refresh delays
+               dabo.useUpdateDelays = False
+
+
+               # Define the controls that can be added to the ClassDesigner. 
The
+               # 'order' value will determine their order in the menu. One plan
+               # is to keep track of the user's choices, and weight the orders
+               # so that their most frequent choices are at the top.
+               self.designerControls = ({"name" : "Box", "class" : dui.dBox, 
"order" : 0},
+                               {"name" : "Bitmap", "class" : dui.dBitmap, 
"order" : 10},
+                               {"name" : "BitmapButton", "class" : 
dui.dBitmapButton, "order" : 20},
+                               {"name" : "Button", "class" : dui.dButton, 
"order" : 30},
+                               {"name" : "CheckBox", "class" : dui.dCheckBox, 
"order" : 40},
+                               {"name" : "CodeEditor", "class" : dui.dEditor, 
"order" : 45},
+                               {"name" : "ComboBox", "class" : dui.dComboBox, 
"order" : 50},
+                               {"name" : "DateTextBox", "class" : 
dui.dDateTextBox, "order" : 60},
+                               {"name" : "DropdownList", "class" : 
dui.dDropdownList, "order" : 70},
+                               {"name" : "EditBox", "class" : dui.dEditBox, 
"order" : 80},
+                               {"name" : "Gauge", "class" : dui.dGauge, 
"order" : 90},
+                               {"name" : "Grid", "class" : dui.dGrid, "order" 
: 100},
+                               {"name" : "Image", "class" : dui.dImage, 
"order" : 110},
+                               {"name" : "Label", "class" : dui.dLabel, 
"order" : 120},
+                               {"name" : "Line", "class" : dui.dLine, "order" 
: 130},
+                               {"name" : "ListBox", "class" : dui.dListBox, 
"order" : 140},
+                               {"name" : "ListControl", "class" : 
dui.dListControl, "order" : 150},
+                               {"name" : "RadioList", "class" : 
dui.dRadioList, "order" : 160},
+                               {"name" : "Page", "class" : dui.dPage, "order" 
: 170},
+                               {"name" : "Panel", "class" : dui.dPanel, 
"order" : 180},
+                               {"name" : "ScrollPanel", "class" : 
dui.dScrollPanel, "order" : 190},
+                               {"name" : "PageFrame", "class" : 
dui.dPageFrame, "order" : 200},
+                               {"name" : "PageList", "class" : dui.dPageList, 
"order" : 210},
+                               {"name" : "PageSelect", "class" : 
dui.dPageSelect, "order" : 220},
+                               {"name" : "PageFrameNoTabs", "class" : 
dui.dPageFrameNoTabs, "order" : 230},
+                               {"name" : "Slider", "class" : dui.dSlider, 
"order" : 240},
+                               {"name" : "Spinner", "class" : dui.dSpinner, 
"order" : 250},
+                               {"name" : "Splitter", "class" : dui.dSplitter, 
"order" : 260},
+                               {"name" : "TextBox", "class" : dui.dTextBox, 
"order" : 270},
+                               {"name" : "ToggleButton", "class" : 
dui.dToggleButton, "order" : 280},
+                               {"name" : "TreeView", "class" : dui.dTreeView, 
"order" : 290}
+                               )
+               self._initSizerDefaults()
+               self._initClassEvents()
+
+               self.setup()
+
+               clsOK = False
+               if clsFile:
+                       try:
+                               frm = self.openClass(clsFile)
+                               clsOK = True
+                       except IOError, e:
+                               dui.stop(str(e))
+
+               if not clsOK:
+                       # Define the form class, and instantiate it.
+                       frmClass = self.getFormClass()
+
+                       # Temp! for development
+#                      useSz = not os.path.exists("/Users/ed/dls")
+#                      frm = frmClass(UseSizers=useSz)
+                       frm = frmClass(UseSizers=True)
+
+                       frm._setupPanels()
+                       # Use this to determine if an empty class should be 
released
+                       frm._initialStateDict = frm.getDesignerDict()
+               else:
+                       frm._initialStateDict = {}
+               frm.Controller = self
+               self.MainForm = frm
+               # When more than one ClassDesigner is open, this will
+               # hold the active reference.
+               self.CurrentForm = frm
+               # Create the form the holds the PropSheet, Method listing
+               # and object tree if it hasn't already been created.
+               pf = self._pemForm
+               if pf is None:
+                       pf = self._pemForm = PemForm(None)
+               pf.Controller = self
+               pf.Visible = True
+
+               # Create the control palette
+               palette = self.ControlPalette
+               palette.Controller = self
+               palette.Visible = False
+
+               # Create the sizer palette, but make it hidden to start
+               palette = self.SizerPalette
+               palette.Controller = self
+               palette.Visible = False
+
+               # Create the Code Editor
+               ed = self.EditorForm
+               ed.Controller = self
+               ed.Visible = True
+
+               # Set the initial selection to the form
+               self.select(self.CurrentForm)
+
+               frm.Visible = True
+               dui.callAfter(frm.layout)
+               dui.callAfterInterval(100, self.updateLayout)
+               dui.callAfter(frm.bringToFront)
+               dui.callAfter(frm.saveState)
+               self.start()
+
+
+       def _initSizerDefaults(self):
+               """Create a dict containing the sizer default settings
+               for each designer class.
+               """
+               self._sizerDefaults = {}
+               defVals = {"BorderSides": ["All"], "Proportion": 1, "HAlign": 
"Left",
+                               "VAlign": "Top", "Border": 0, "Expand": True}
+               # Use the defaults for each class, except where specified
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dBox] = dct
+               dct = defVals.copy()
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dBitmap] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0, "Expand" : False})
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dBitmapButton] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0, "Expand" : False})
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dButton] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0})
+               self._sizerDefaults[dui.dCheckBox] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0})
+               self._sizerDefaults[dui.dComboBox] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0})
+               self._sizerDefaults[dui.dDateTextBox] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dDialog] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0})
+               self._sizerDefaults[dui.dDropdownList] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dEditBox] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dEditor] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0})
+               self._sizerDefaults[dui.dGauge] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dGrid] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dGridSizer] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dHtmlBox] = dct
+               dct = defVals.copy()
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dImage] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0, "Expand" : False})
+               self._sizerDefaults[dui.dLabel] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0})
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dLine] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dListBox] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dListControl] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dOkCancelDialog] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dRadioList] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dPage] = dct
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dPanel] = dct
+               dct = defVals.copy()
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dScrollPanel] = dct
+               dct = defVals.copy()
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dPageFrame] = dct
+               dct = defVals.copy()
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dPageList] = dct
+               dct = defVals.copy()
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dPageSelect] = dct
+               dct = defVals.copy()
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dPageFrameNoTabs] = dct
+               dct = defVals.copy()
+               self._sizerDefaults[dui.dSizer] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0})
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dSlider] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0})
+               self._sizerDefaults[dui.dSpinner] = dct
+               dct = defVals.copy()
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dSplitter] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0})
+               self._sizerDefaults[dui.dTextBox] = dct
+               dct = defVals.copy()
+               dct.update({"Proportion" : 0, "Expand" : False})
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dToggleButton] = dct
+               dct = defVals.copy()
+               dct.update({"HAlign" : "center", "VAlign" : "middle"})
+               self._sizerDefaults[dui.dTreeView] = dct
+               return
+
+
+       def _initClassEvents(self):
+               """Create a dict by baseclass of all applicable events."""
+               self._classEvents = {}
+               self._classMethods = {}
+               baseEvents = ("DataEvent", "EditorEvent", "GridEvent", 
"KeyEvent",
+                               "ListEvent", "MenuEvent", "MouseEvent", 
"SashEvent",
+                               "CalendarEvent", "TreeEvent")
+               classes = (dui.dBox, dui.dBitmap, dui.dBitmapButton, 
dui.dButton, dui.dCheckBox,
+                               dui.dComboBox, dui.dDateTextBox, dui.dDialog, 
dui.dDropdownList,
+                               dui.dEditBox, dui.dEditor, dui.dForm, 
dui.dDockForm, dui.dGauge, dui.dGrid, dui.dImage, 
+                               dui.dLabel, dui.dLine, dui.dListBox, 
dui.dListControl, dui.dOkCancelDialog,
+                               dui.dPanel, dui.dPage, dui.dScrollPanel, 
dui.dPage, dui.dPageFrame,
+                               dui.dPageList, dui.dPageSelect, 
dui.dPageFrameNoTabs, dui.dRadioList,
+                               dui.dSlider, dui.dSpinner, dui.dSplitter, 
dui.dTextBox, dui.dToggleButton,
+                               dui.dTreeView, dlgs.Wizard, dlgs.WizardPage)
+
+               def evtsForClass(cls):
+                       ret = []
+                       for kk, vv in dEvents.__dict__.items():
+                               if kk in baseEvents:
+                                       # These are superclasses of individual 
events.
+                                       continue
+                               try:
+                                       if vv.appliesToClass(cls):
+                                               ret.append("on%s" % kk)
+                               except:
+                                       pass
+                       ret.sort()
+                       return ret
+
+               def mthdsForClass(cls):
+                       ret = []
+                       mthds = inspect.getmembers(cls, inspect.ismethod)
+                       ret = [mthd[0] for mthd in mthds
+                                       if mthd[0][0] in 
"abcdefghijklmnopqrstuvwxyz"]
+                       return ret
+
+               for cls in classes:
+                       self._classEvents[cls] = evtsForClass(cls)
+                       self._classMethods[cls] = mthdsForClass(cls)
+
+       def getFormClass(self, filepath=None):
+               """If the selected class is a form/dialog, return a mixed-in
+               subclass of it. Otherwise, return the base ClassDesignerForm.
+               """
+               formIsMain = issubclass(self._selectedClass, (dui.dForm, 
dui.dDialog))
+               isDialog = issubclass(self._selectedClass, (dui.dDialog, ))
+               isWizard = issubclass(self._selectedClass, (dlgs.Wizard, ))
+               isDockForm = _USE_DOCKFORM and issubclass(self._selectedClass, 
(dui.dDockForm, ))
+               if formIsMain:
+                       if isDockForm:
+                               base = self._selectedClass              
##dui.dForm
+                       elif not isDialog and self._desFormClass is not None:
+                               return self._desFormClass
+                       else:
+                               base = self._selectedClass
+               else:
+                       base = dui.dForm
+               class DesForm(dfm, base):
+                       _superBase = base
+                       _superMixin = dfm
+                       _classFile = filepath
+                       def __init__(self, parent=None, *args, **kwargs):
+                               self._isMain = formIsMain
+                               if isDialog:
+                                       kwargs["BorderResizable"] = True
+                                       kwargs["ShowCloseButton"] = True
+                               if isWizard:
+                                       kwargs["Caption"] = "Dabo Wizard 
Designer"
+                               base.__init__(self, parent=parent, *args, 
**kwargs)
+                               dfm.__init__(self, parent=parent, *args, 
**kwargs)
+                               self._basePrefKey = 
"dabo.ide.ClassDesigner.ClassDesignerForm"
+
+                       def _afterInit(self):
+                               self._designerMode = True
+                               self._formMode = True
+                               if isDockForm:
+                                       self._configureForDockForm()
+                               super(DesForm, self)._afterInit()
+
+                       def addControls(self):
+                               if not isinstance(self, dui.dOkCancelDialog):
+                                       # Could be a wizard, or some other 
object with an 'addControls' method
+                                       self._superBase.addControls(self)
+                                       return
+                               if self.UseSizers:
+                                       self.mainPanel = LayoutBasePanel(self)
+                                       self.Sizer.append1x(self.mainPanel)
+                                       self.mainPanel.Sizer = LayoutSizer("v")
+                                       # Use a Layout Sizer instead of the 
default sizer.
+                                       self.initLayoutPanel = 
LayoutPanel(self.mainPanel)
+                               else:
+                                       self.mainPanel = self.initLayoutPanel = 
NoSizerBasePanel(self, BackColor=(222,222,255))
+                                       self.Sizer.append1x(self.mainPanel)
+                                       self.layout()
+                               # We need to 'deactivate' the built-in buttons
+                               self.btnOK.unbindEvent(dEvents.Hit)
+                               self.btnCancel.unbindEvent(dEvents.Hit)
+                               self.btnOK.Enabled = self.btnCancel.Enabled = 
False
+
+
+                       def _setupPanels(self, fromNew=True):
+                               if isinstance(self, dlgs.Wizard):
+                                       self.mainPanel = self.pagePanel
+                                       if self.UseSizers:
+                                               self.mainPanel.Sizer = 
LayoutSizer("v")
+                                       if fromNew:
+                                               # Need to ask for number of 
pages.
+                                               numPages = 
dabo.ui.getInt(_("How many pages?"), caption=_("Wizard Pages"),
+                                                               defaultValue=3)
+                                               pgCls = 
self.getControlClass(dlgs.WizardPage)
+                                               pgs = [pgCls] * max(1, numPages)
+                                               self.append(pgs)
+                                               for num, p in 
enumerate(self._pages):
+                                                       # Remove the title and 
line from the current sizer
+                                                       p.Caption = _("Page %s 
Title") % num
+                                                       if self.UseSizers:
+                                                               # This will 
automatically add itself to the sizer
+                                                               LayoutPanel(p)
+                                                       else:
+                                                               
p.Sizer.append1x(NoSizerBasePanel(p))
+                                               self.initLayoutPanel = 
self._pages[0].Children[0]
+                                       else:
+                                               self.initLayoutPanel = 
self.mainPanel
+                                       self.CurrentPage = 0
+                                       self.btnCancel.Enabled = False
+                                       # Prevent the Finish button from 
closing the design surface.
+                                       self.finish = lambda: False
+                                       return
+
+                               if self.UseSizers:
+                                       if isinstance(self, 
dui.dOkCancelDialog):
+                                               # already done
+                                               return
+                                       if _USE_DOCKFORM and isinstance(self, 
dui.dDockForm):
+                                               self.mainPanel = 
self.CenterPanel
+                                       else:
+                                               self.Sizer = dui.dSizer("v")
+                                               self.mainPanel = 
LayoutBasePanel(self)
+                                               
self.Sizer.append1x(self.mainPanel)
+                                       
+                                       self.mainPanel.Sizer = LayoutSizer("v")
+                                       # Use a Layout Sizer instead of the 
default sizer.
+                                       self.initLayoutPanel = 
LayoutPanel(self.mainPanel)
+                               else:
+                                       self.Sizer.release()
+                                       self.Sizer = None
+                                       self.mainPanel = self.initLayoutPanel = 
NoSizerBasePanel(self, BackColor=(222,222,255))
+                                       self.layout()
+               ret = DesForm
+               if formIsMain and not isDialog and not isDockForm:
+                       self._desFormClass = ret
+               return ret
+
+
+       def _reuseMainForm(self, useSizers=False):
+               """Determines if the MainForm for the Class Designer is a 
blank, unedited
+               form, which can be re-used when the user opens an existing 
class or
+               creates a new class.
+               """
+               mf = self.MainForm
+               if mf:
+                       if mf.UseSizers != useSizers:
+                               return False
+                       mfCurrDict = mf.getDesignerDict()
+                       # Position and size of the form may have changed; 
delete those
+                       # since they are irrelevant. Also, it seems that on 
Windows these
+                       # atts are set while the object is being created, so we 
have to
+                       # clear them in the _initialStateDict, too.
+                       for att in ("Left", "Top", "Width", "Height"):
+                               try:
+                                       del mfCurrDict["attributes"][att]
+                               except: pass
+                               try:
+                                       del 
mf._initialStateDict["attributes"][att]
+                               except: pass
+               ret = mf and (mf._initialStateDict == mfCurrDict)
+               return ret
+
+
+       def onEditUndo(self, evt):
+               dabo.infoLog.write(_("Not implemented yet"))
+       def onEditRedo(self, evt):
+               dabo.infoLog.write(_("Not implemented yet"))
+
+
+       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.
+               """
+               try:
+                       if not os.path.exists(pth):
+                               if os.path.exists(os.path.abspath(pth)):
+                                       pth = os.path.abspath(pth)
+                       dct = xtd.xmltodict(pth, addCodeFile=True)
+               except StandardError, e:
+                       if pth.strip().startswith("<?xml") or 
os.path.exists(pth):
+                               raise IOError, _("This does not appear to be a 
valid class file.")
+                       else:
+                               raise IOError, _("The class file '%s' was not 
found.") % pth
+                       
+
+               # Traverse the dct, looking for superclass information
+               super = xtd.flattenClassDict(dct)
+               if super:
+                       # We need to modify the info to incorporate the 
superclass info
+                       xtd.addInheritedInfo(dct, super)
+                       # Store the base code so that we can determine if 
instances have
+                       # modified it.
+                       self._updateClassCodeRepository(super)
+               return dct
+
+
+       def _updateClassCodeRepository(self, dct):
+               """Take a flattened dict of class IDs and store any code
+               associated with those IDs, so that we can later compare it to
+               an object's code in order to determine if it has been changed.
+               """
+               cds = [(kk, vv["code"]) for kk, vv in dct.items()
+                               if vv["code"]]
+               for cd in cds:
+                       self._classCodeDict.update({cd[0]: cd[1]})
+
+
+       def _getClassMethod(self, clsID, mthd):
+               """Given a class ID and a method name, returns the code for that
+               classID/method combination (if any) from self._classCodeDict.
+               """
+               cd = self._classCodeDict.get(clsID, {})
+               return cd.get(mthd, "")
+
+
+       def _findSizerInClassDict(self, clsd):
+               """Recursively search until a child is found with sizer 
information.
+               If no such child is found, return False.
+               """
+               ret = False
+               atts = clsd.get("attributes", {})
+               szinf = atts.get("sizerInfo", "{}")
+               if szinf != "{}":
+                       ret = True
+               else:
+                       kids = clsd.get("children", [])
+                       for kid in kids:
+                               ret = self._findSizerInClassDict(kid)
+                               if ret:
+                                       break
+               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.
+               """
+               # Set the flag so that components know what process we're in.
+               self.openingClassXML = True
+               # Clear any existing superclass info
+               self._superClassInfo = {}
+               # Translate the file path into a class dictionary.
+               clsd = self._importClassXML(pth)
+               # See if the class name requires a separate import
+               nm = clsd["name"]
+               try:
+                       imp, clsname = nm.rsplit(".", 1)
+                       imptSt = "from %(imp)s import %(clsname)s" % locals()
+                       exec imptSt in locals()
+                       clsd["fullname"] = nm
+                       clsd["name"] = clsname
+               except ValueError:
+                       clsd["fullname"] = nm
+
+               # See if it is a full form-based class, or an individual 
component.
+               isFormClass = (clsd["name"] in ("dForm", "dDockForm", 
"dDialog", "dOkCancelDialog", "Wizard"))
+               if isFormClass:
+                       atts = clsd["attributes"]
+                       del atts["designerClass"]
+                       nm = clsd["name"]
+               else:
+                       atts = {"UseSizers": self._findSizerInClassDict(clsd)}
+                       nm = "ClassDesignerForm"
+
+               isDlg = (clsd["name"] in ("dDialog", "dOkCancelDialog", 
"Wizard"))
+               isWiz = (clsd["name"] in ("Wizard",))
+               if isDlg:
+                       self._selectedClass = {"dDialog": dui.dDialog,
+                                       "dOkCancelDialog": dui.dOkCancelDialog,
+                                       "Wizard": dlgs.Wizard}[clsd["name"]]
+
+               # Convert any paths in the atts
+               self._basePath = pth
+               dabo.lib.utils.resolveAttributePathing(atts, pth)
+               # Read in any .cnxml connection defs.
+               currdir = os.path.dirname(pth)
+               self._initDB(currdir)
+               if os.path.split(currdir)[-1].lower() == "ui":
+                       # Standard directory structure; process the parent 
directory
+                       self._initDB(os.path.dirname(currdir))
+               if self._reuseMainForm(useSizers=atts.get("UseSizers", False)):
+                       # Original form hasn't changed, so just use it.
+                       frm = self.MainForm
+                       frm.setPropertiesFromAtts(atts)
+               else:
+                       # For now, just create a standard dForm mixed-in 
ClassDesigner
+                       # form as the base.
+                       frmClass = self.getFormClass(filepath=pth)
+                       if isWiz:
+                               self._extractKey(atts, "PageCount")
+                       frm = frmClass(None, Name=nm, SaveRestorePosition=False,
+                                       attProperties=atts)
+                       if isWiz:
+                               self._recreateWizardPages(frm, clsd["children"])
+                               # Clear the children dict
+                               clsd["children"] = []
+                       frm._setupPanels(fromNew=False)
+               lp = frm.initLayoutPanel
+               if isFormClass and frm.UseSizers and not isWiz:
+                       # Remove the LayoutPanel that was added
+                       lp.ControllingSizer.remove(lp, True)
+                       self._srcObj = frm.mainPanel
+               else:
+                       self._srcObj = lp
+                       if not isFormClass:
+                               # Set the Caption of the form to the class name
+                               fname = os.path.split(pth)[1]
+                               frm.Caption = os.path.splitext(fname)[0]
+               frm.Controller = self
+               self.CurrentForm = frm
+               frm._classFile = pth
+               frm._formMode = frm.SaveRestorePosition = isFormClass
+               if isFormClass:
+                       # See if there is any code associated with the form
+                       code = clsd.get("code", "")
+                       if code:
+                               self._codeDict[frm] = {}
+                               # Each method will be a separate dict
+                               for mthd, cd in code.items():
+                                       cd = cd.replace("\n]", "]")
+                                       if mthd == "importStatements":
+                                               self._classImportDict[frm] = cd
+                                       else:
+                                               self._codeDict[frm][mthd] = cd
+                       # Do the same for the properties
+                       propDefs = clsd.get("properties", {})
+                       # Restore any prop definitions.
+                       if propDefs:
+                               self._classPropDict[frm] = propDefs
+                       # Set the child objects
+                       kids = clsd["children"]
+               else:
+                       # Add the class to the form
+                       kids = clsd
+                       if frm.UseSizers:
+                               self._extractKey(clsd["attributes"], "Top")
+                               self._extractKey(clsd["attributes"], "Left")
+                               self._extractKey(clsd["attributes"], "Height")
+                               self._extractKey(clsd["attributes"], "Width")
+               # Add the child objects recursively
+               obj = self.recreateChildren(frm.mainPanel, kids, None, False)
+               # Clear the superclass info
+               self._superClassInfo = {}
+               self._basePath = None
+               if isFormClass and obj:
+                       self.select(obj)
+               else:
+                       self.select(frm)
+               # Clear the process flag
+               self.openingClassXML = False
+               # Show it!
+               frm.Centered = True
+               frm.Visible = True
+               # Save the initial state
+               dabo.ui.callAfter(frm.saveState)
+
+               return frm
+
+
+       def extractSuperClassInfo(self, pth):
+               try:
+                       superdct = xtd.xmltodict(pth, addCodeFile=True)
+               except:
+                       raise IOError, _("This does not appear to be a valid 
class file.")
+               # Traverse the dct, looking for superclass information
+               sup = xtd.flattenClassDict(superdct)
+               # Store the base code so that we can determine if instances have
+               # modified it.
+               self._updateClassCodeRepository(sup)
+               # Add it to the current class definitions
+               self._superClassInfo.update(sup)
+
+
+       def inherit(self, dct):
+               super = self._superClassInfo
+               if super:
+                       # We need to modify the info to incorporate the 
superclass info
+                       xtd.addInheritedInfo(dct, super)
+               return dct
+
+
+       def recreateChildren(self, parent, chld, szr, fromSzr, debug=0):
+               """Recursive routine to re-create the sizer/object structure of
+               the class.
+               """
+               ret = None
+               if isinstance(chld, dict):
+                       # Single child passed
+                       chld = [chld]
+               for dct in chld:
+                       atts = dct["attributes"]
+                       # Convert any paths in the atts
+                       dabo.lib.utils.resolveAttributePathing(atts, 
self._basePath)
+                       clsname = self._extractKey(atts, "designerClass", "")
+                       # See if this is a saved class inserted into another 
design
+                       isCustomClass = False
+                       customClassPath = None
+                       if os.path.exists(clsname) and atts.has_key("classID"):
+                               isCustomClass = True
+                               customClassPath = clsname
+                               # Start with the custom class, and then update 
it with the current stuff
+                               self.extractSuperClassInfo(clsname)
+                       self.inherit(dct)
+                       cls = dct["name"]
+                       classID = self._extractKey(atts, "classID", "")
+                       kids = dct.get("children", None)
+                       if self._addingClass:
+                               code = {}
+                       else:
+                               code = dct.get("code", {})
+                       propDefs = dct.get("properties", {})
+                       sizerInfo = self._extractKey(atts, "sizerInfo", "{}")
+                       if isinstance(sizerInfo, basestring):
+                               sizerInfoDict = eval(sizerInfo)
+                       else:
+                               sizerInfoDict = sizerInfo
+
+                       rowColAtts = self._extractKey(atts, "rowColPos", 
"(None,None)")
+                       if clsname == "LayoutPanel":
+                               # Panel has already been created by the sizer's 
slots;
+                               # just set any sizer item props.
+                               pnl = self._srcObj
+                               sz = pnl.ControllingSizer
+                               itm = pnl.ControllingSizerItem
+                               sz.setItemProps(itm, sizerInfoDict)
+                               if classID:
+                                       pnl.classID = classID
+                               if kids:
+                                       self.recreateChildren(pnl, kids, None, 
False)
+
+                       elif clsname == "LayoutSpacerPanel":
+                               spc = int(atts.get("Spacing", "20"))
+                               pnl = self._srcObj
+                               prnt = pnl.Parent
+                               pos = pnl.getPositionInSizer()
+                               sz = pnl.ControllingSizer
+                               sz.remove(pnl)
+                               dui.callAfter(pnl.release)
+                               obj = LayoutSpacerPanel(prnt, Spacing=spc)
+                               if isinstance(sz, dui.dGridSizer):
+                                       itm = sz.append(obj, row=pos[0], 
col=pos[1])
+                               else:
+                                       itm = sz.insert(pos, obj)
+                               sz.setItemProps(itm, sizerInfoDict)
+                               if classID:
+                                       obj.classID = classID
+                               ret = obj
+
+                       elif clsname in ("LayoutSizer", "LayoutBorderSizer"):
+                               ornt = self._extractKey(atts, "Orientation", 
"h")
+                               slots = int(self._extractKey(atts, "SlotCount", 
"1"))
+                               useBox, boxCaption = None, None
+                               if clsname == "LayoutBorderSizer":
+                                       useBox = True
+                                       boxCaption = self._extractKey(atts, 
"Caption", None)
+                               sz, pnl = self.addSizer("box", orient=ornt, 
slots=slots,
+                                               useBox=useBox, 
boxCaption=boxCaption)
+                               szCont = sz.ControllingSizer
+                               itm = sz.ControllingSizerItem
+
+                               is2D = isinstance(szCont, dabo.ui.dGridSizer)
+                               defaults = {True: szItemDefaults[2],
+                                               False: szItemDefaults[1]}[is2D]
+                               defAtts = {}
+                               for key, val in defaults.items():
+                                       defAtts["Sizer_%s" % key] = val
+                               defAtts.update(dictStringify(atts))
+                               atts = defAtts
+                               sz.setPropertiesFromAtts(atts)
+                               if classID:
+                                       sz.classID = classID
+                               if not fromSzr:
+                                       parent.Sizer = sz
+                               if szCont is not None and itm is not None:
+                                       szCont.setItemProps(itm, sizerInfoDict)
+                               if kids:
+                                       # We need to set the value of _srcObj 
to the individual
+                                       # LayoutPanel in the sizer. The number 
of kids should
+                                       # match the number of slots created 
when the sizer
+                                       # was created.
+                                       childWindowList = sz.ChildWindows[:]
+                                       for pos, kid in enumerate(kids):
+                                               # Set the LayoutPanel to the 
'source' object
+                                               pnl = self._srcObj = 
childWindowList[pos]
+                                               # Pass the 'kid' as a list, 
since that's what
+                                               # recreateChildren() expects.
+                                               self.recreateChildren(parent, 
[kid], sz, True)
+                               ret = sz
+
+                       elif clsname == "LayoutGridSizer":
+                               rows = int(self._extractKey(atts, "Rows", "1"))
+                               cols = int(self._extractKey(atts, "Columns", 
"1"))
+                               sz, pnl = self.addSizer("grid", rows=rows, 
cols=cols)
+                               szCont = sz.ControllingSizer
+                               is2D = isinstance(szCont, dabo.ui.dGridSizer)
+                               defaults = {True: szItemDefaults[2],
+                                               False: szItemDefaults[1]}[is2D]
+                               defAtts = {}
+                               for key, val in defaults.items():
+                                       defAtts["Sizer_%s" % key] = val
+                               defAtts.update(dictStringify(atts))
+                               atts = defAtts
+                               sz.setPropertiesFromAtts(atts)
+                               if not fromSzr:
+                                       parent.Sizer = sz
+                               itm = sz.ControllingSizerItem
+                               if szCont is not None and itm is not None:
+                                       szCont.setItemProps(itm, sizerInfoDict)
+                               if classID:
+                                       sz.classID = classID
+                               if kids:
+                                       for kid in kids:
+                                               kidatts = kid["attributes"]
+                                               rowCol = 
kidatts.get("rowColPos")
+                                               if isinstance(rowCol, tuple):
+                                                       row, col = rowCol
+                                               else:
+                                                       row, col = 
eval(kidatts.get("rowColPos"))
+                                               # Set the LayoutPanel to the 
'source' object
+                                               pnl = self._srcObj = 
sz.getItemByRowCol(row, col)
+                                               # Pass the 'kid' as a list, 
since that's what
+                                               # recreateChildren() expects.
+                                               obj = 
self.recreateChildren(parent, [kid], sz, True)
+                               ret = sz
+
+                       else:
+                               # An actual control!
+                               if szr:
+                                       if isinstance(szr, LayoutGridSizer):
+                                               if isinstance(rowColAtts, 
tuple):
+                                                       row, col = rowColAtts
+                                               else:
+                                                       row, col = 
eval(rowColAtts)
+                                               if row is not None and col is 
not None:
+                                                       # It has a given 
position, so use that. Otherwise,
+                                                       # they may be pasting 
into a grid sizer.
+                                                       self._srcObj = 
szr.getItemByRowCol(row, col)
+                               props = {}
+
+                               try:
+                                       imp, clsname = cls.rsplit(".", 1)
+                                       imptSt = "from %(imp)s import 
%(clsname)s" % locals()
+                                       exec imptSt in locals()
+                                       dct["fullname"] = cls
+                                       dct["name"] = clsname
+                                       newClass = eval(clsname)
+                               except ValueError:
+                                       dct["fullname"] = cls
+                                       newClass = dui.__dict__[cls]
+
+                               isGrid = issubclass(newClass, dui.dGrid)
+                               isTree = issubclass(newClass, dui.dTreeView)
+                               isSplitter = issubclass(newClass, dui.dSplitter)
+                               isPageControl = issubclass(newClass, 
self.pagedControls)
+                               noTabs = issubclass(newClass, 
dui.dPageFrameNoTabs)
+                               if isGrid:
+                                       try:
+                                               # The column entries will 
create themselves, so
+                                               # we don't want to create them 
now.
+                                               del atts["ColumnCount"]
+                                       except:
+                                               pass
+                                       props["ColumnCount"] = 0
+                               elif isPageControl:
+                                       props["PageCount"] = 
int(atts.get("PageCount", "0"))
+                                       props["TabPosition"] = 
atts.get("TabPosition", "")
+                                       try:
+                                               del atts["PageCount"]
+                                       except: pass
+                                       try:
+                                               del atts["TabPosition"]
+                                       except: pass
+                                       if noTabs:
+                                               del props["TabPosition"]
+                               elif isSplitter:
+                                       ornt = self._extractKey(atts, 
"Orientation", "Vertical")
+                                       splt = self._extractKey(atts, "Split", 
"False")
+                                       props["createPanes"] = False
+                                       atts["Split"] = False
+                               # If we are pasting, we can get two objects 
with the same
+                               # Name value, so change it to NameBase.
+                               nm = self._extractKey(atts, "Name", clsname)
+                               props["NameBase"] = nm
+                               obj = self.addNewControl(None, newClass, 
props=props,
+                                               skipUpdate=True, 
attProperties=atts)
+                               ret = obj
+                               if isSplitter:
+                                       
obj.setPropertiesFromAtts({"Orientation": ornt})
+                                       if splt:
+                                               dabo.ui.setAfter(obj, "Split", 
True)
+                               sz = obj.ControllingSizer
+                               itm = obj.ControllingSizerItem
+                               if sz is not None and itm is not None:
+                                       sz.setItemProps(itm, sizerInfoDict)
+                               if classID:
+                                       obj.classID = classID
+
+                               for mthd, cd in code.items():
+                                       if not self._codeDict.g

 (721584 bytes were truncated as it was too long for the email (max 40000 
bytes.)


_______________________________________________
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]

Reply via email to