dabo Commit
Revision 7074
Date: 2012-02-01 19:40:12 -0800 (Wed, 01 Feb 2012)
Author: Ed
Trac: http://trac.dabodev.com/changeset/7074

Changed:
U   trunk/ide/MenuDesigner.py
U   trunk/ide/MenuDesignerComponents.py
U   trunk/ide/MenuDesignerForm.py
A   trunk/ide/MenuDesignerMenu.mnxml
U   trunk/ide/MenuDesignerPropForm.py
A   trunk/ide/MenuHyperLink.py

Log:
This is an overhaul of the MenuDesigner that I've been working on for a while. 
It's finally at the point where it pretty much works as it should.

I cheated a little from my original idea, which was to create panels with the 
menu item captions and hot keys drawn on them, but that proved to be too slow 
to get working. So I used hyperlinks, taking advantage of their clickability, 
even though their appearance is not all that controllable. I plan on replacing 
the hyperlink-based classes with something that looks much better, but for now 
this is working.


Diff:
Modified: trunk/ide/MenuDesigner.py
===================================================================
--- trunk/ide/MenuDesigner.py   2012-01-31 02:50:05 UTC (rev 7073)
+++ trunk/ide/MenuDesigner.py   2012-02-02 03:40:12 UTC (rev 7074)
@@ -9,9 +9,22 @@
 dabo.ui.loadUI("wx")
 from MenuDesignerForm import MenuDesignerForm
 
+
+
+class MenuDesigner(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(MenuDesigner, self).__init__(showSplashScreen=False,
+                               splashTimeout=10, ignoreScriptDir=True)
+
+
 def main():
        files = sys.argv[1:]
-       app = dabo.dApp()
+       app = MenuDesigner()
        app.BasePrefKey = "ide.MenuDesigner"
        app.setAppInfo("appName", _("Dabo Menu Designer"))
        app.setAppInfo("appShortName", _("MenuDesigner"))
@@ -20,8 +33,9 @@
        app.setup()
 
        frm = app.MainForm = MenuDesignerForm()
-       for file in files:
-               frm.openFile(file)
+       if files:
+               for filename in files:
+                       frm.openFile(filename)
        frm.show()
        app.start()
 

Modified: trunk/ide/MenuDesignerComponents.py
===================================================================
--- trunk/ide/MenuDesignerComponents.py 2012-01-31 02:50:05 UTC (rev 7073)
+++ trunk/ide/MenuDesignerComponents.py 2012-02-02 03:40:12 UTC (rev 7074)
@@ -15,7 +15,7 @@
        """
        def getDesignerDict(self):
                ret = {}
-               ret["name"] = self._className
+               ret["name"] = self.__class__.__name__
                ret["attributes"] = ra = {}
                propsToExclude = ("HotKeyChar", "HotKeyControl",
                                "HotKeyAlt", "HotKeyShift")

Modified: trunk/ide/MenuDesignerForm.py
===================================================================
--- trunk/ide/MenuDesignerForm.py       2012-01-31 02:50:05 UTC (rev 7073)
+++ trunk/ide/MenuDesignerForm.py       2012-02-02 03:40:12 UTC (rev 7074)
@@ -1,44 +1,123 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
+
+import codecs
 import os
+
 import dabo
 dabo.ui.loadUI("wx")
+
 from dabo.dLocalize import _
 from dabo.lib.utils import ustr
 import dabo.dEvents as dEvents
 import dabo.lib.xmltodict as xtd
 from ClassDesignerExceptions import PropertyUpdateException
-from MenuBarPanel import MenuBarPanel
-from MenuPanel import MenuPanel
+from MenuHyperLink import MenuBarHyperLink
 from MenuDesignerPropForm import MenuPropForm
-from MenuDesignerComponents import CaptionBitmapPanel
-from MenuDesignerComponents import SeparatorPanel
 
 
 
 class MenuDesignerForm(dabo.ui.dForm):
        def __init__(self, *args, **kwargs):
                self._selection = None
+               self._savedState = {}
                self._menuFile = None
                self._propForm = None
                self._propSheet = None
+               self._inPropertyEditing = False
+               kwargs["MenuBarFile"] = "MenuDesignerMenu.mnxml"
+               self.Controller = self
                super(MenuDesignerForm, self).__init__(*args, **kwargs)
-               self.autoClearDrawings = True
                self.Caption = "Dabo Menu Designer"
                self.mainPanel = dabo.ui.dPanel(self)
                self.Sizer.append1x(self.mainPanel)
-               sz = self.mainPanel.Sizer = dabo.ui.dSizer("v")
+               self.mainMenubarLink = None
+               sz = self.mainPanel.Sizer = dabo.ui.dSizerV()
                self.previewButton = btn = dabo.ui.dButton(self.mainPanel,
                                Caption="Preview", OnHit=self.onPreview)
                sz.append(btn, border=10, halign="center")
                sz.append(dabo.ui.dLine(self.mainPanel), "x", border=10)
-               self.menubar = MenuBarPanel(self.mainPanel)
-               sz.append(self.menubar, border=30)
-               self.menubar.Controller = self
-               self.clear()
+               mb_link = self.initMenuBar()
                self.layout()
 
 
+       def afterInitAll(self):
+               self.PropSheet.Controller = self
+               self.PropForm.show()
+               if not self._menuFile:
+                       # No menu file was opened; create a base menu
+                       self.createBaseMenu()
+               self.Selection = self.mainMenubarLink
+               dabo.ui.callAfter(self.bringToFront)
+
+
+       def initMenuBar(self, addBaseMenu=False):
+               """Start from scratch with a basic menu bar."""
+               try:
+                       self.mainMenubarLink.release()
+               except AttributeError:
+                       pass
+               try:
+                       self.menubarPanel.release()
+               except AttributeError:
+                       pass
+               mbp = self.menubarPanel = dabo.ui.dPanel(self.mainPanel, 
BackColor="lightgrey")
+               mbp.Controller = self
+               mbp.menus = []
+               self.mainPanel.Sizer.append1x(mbp, border=30)
+               mbar = self.mainMenubarLink = MenuBarHyperLink(mbp, 
Caption="MenuBar",
+                               Controller=self)
+               mbsz = mbp.Sizer = dabo.ui.dSizerV()
+               mbsz.append(mbar)
+               mbp.menuSizer = dabo.ui.dSizerH()
+               mbsz.append1x(mbp.menuSizer)
+               if addBaseMenu:
+                       self.createBaseMenu()
+               return mbar
+
+
+       def createBaseMenu(self):
+               """This creates a base menu."""
+               menu_dict = self._createBaseMenuDict()
+               self.makeMenuBar(menu_dict)
+               self._savedState = self._getState()
+
+
+       def makeMenuBar(self, dct=None):
+               lnk = self.mainMenubarLink
+               if dct is None:
+                       lnk.showTopLevel()
+               else:
+                       lnk.createMenuFromDict(dct)
+               self.layout()
+
+
+       def clearMenus(self):
+               self.menubarPanel.menus = []
+
+
+       def getPropDictForObject(self, obj):
+               return {}
+
+
+       def saveMenu(self):
+               if not self._menuFile:
+                       self._menuFile = dabo.ui.getSaveAs(wildcard="mnxml")
+                       if not self._menuFile:
+                               # User canceled
+                               return
+                       else:
+                               if not os.path.splitext(self._menuFile)[1] == 
".mnxml":
+                                       self._menuFile += ".mnxml"
+               propDict = self._getState()
+               xml = xtd.dicttoxml(propDict)
+               fname = self._menuFile
+               # Try opening the file. If it is read-only, it will raise an
+               # IOErrorrror that the calling method can catch.
+               codecs.open(fname, "wb", encoding="utf-8").write(xml)
+               self.saveState()
+
+
        def onPreview(self, evt):
                class PreviewWindow(dabo.ui.dForm):
                        def initProperties(self):
@@ -52,7 +131,7 @@
                                self.lblResult = dabo.ui.dLabel(mp, 
Caption="Menu Selection: \n ", FontBold=True,
                                                ForeColor="darkred", 
AutoResize=True, Alignment="Center")
                                self.lblResult.FontSize += 4
-                               sz.append(self.lblResult, halign="center", 
border=10)
+                               sz.append(self.lblResult, "x", halign="center", 
border=10)
                                btn = dabo.ui.dButton(mp, Caption="Close Menu 
Preview",
                                                OnHit=self.onDeactivate)
                                sz.append(btn, halign="center", border=30)
@@ -68,47 +147,233 @@
                                self.lblResult.Caption = cap
                                self.layout()
 
-               propDict = self.menubar.getDesignerDict()
-               xml = xtd.dicttoxml(propDict)
+               propDict = self._getState()
                win = PreviewWindow(self, Centered=True)
-               mb = dabo.ui.createMenuBar(xml, win, win.notify)
+               mb = dabo.ui.createMenuBar(propDict, win, win.notify)
                win.MenuBar = mb
                win.show()
 
 
-       def afterInitAll(self):
-               self.PropSheet.Controller = self
-               self.PropForm.show()
-               self.Selection = None
-               #dabo.ui.callAfterInterval(300, self.initialLayout)
-               self.initialLayout()
+       def _createBaseMenuDict(self):
+               """This creates the dict that represents a base menu."""
+               iconPath = "themes/tango/16x16"
+               sep = {"attributes": {},
+                               "children": [],
+                               "name": "SeparatorHyperLink"}
 
+               m_new = {"attributes": {
+                               "Caption": _("&New"),
+                               "Action": "form.onNew",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+N",
+                               "ItemID": "file_new",
+                               "Icon": "new"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_open = {"attributes": {
+                               "Caption": _("&Open"),
+                               "Action": "form.onOpen",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+O",
+                               "ItemID": "file_open",
+                               "Icon": "open"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_close = {"attributes": {
+                               "Caption": _("&Close"),
+                               "Action": "form.onClose",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+W",
+                               "ItemID": "file_close",
+                               "Icon": "close"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_save = {"attributes": {
+                               "Caption": _("&Save"),
+                               "Action": "form.onSave",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+S",
+                               "ItemID": "file_save",
+                               "Icon": "save"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_saveas = {"attributes": {
+                               "Caption": _("Save &As"),
+                               "Action": "form.onSaveAs",
+                               "HelpText": "",
+                               "HotKey": "",
+                               "ItemID": "file_saveas",
+                               "Icon": "saveas"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_cmd = {"attributes": {
+                               "Caption": _("Command Win&dow"),
+                               "Action": "app.onCmdWin",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+D",
+                               "ItemID": "file_commandwin",
+                               "Icon": "%s/apps/utilities-terminal.png" % 
iconPath},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_quit = {"attributes": {
+                               "Caption": _("&Quit"),
+                               "Action": "app.onFileExit",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+Q",
+                               "ItemID": "file_quit",
+                               "Icon": "quit"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               file_menu = {"attributes": {
+                               "Caption": u"File",
+                               "HelpText": "",
+                               "MRU": True},
+                               "children": [m_new, m_open, m_close, m_save, 
m_saveas, sep, m_cmd, sep, m_quit],
+                               "name": "MenuHyperLink"}
 
-       def initialLayout(self):
-#              print "INITLAY"
-               self.menubar.clear()
-               self.mainPanel.clear()
-#              self.menubar.quickMenu()
-               self.layout()
-#              dabo.ui.callAfterInterval(500, self.foo)
-#      def foo(self):
-#              try:
-#                      firstMenu = self.menubar.Menus[0]
-# #                    self.menubar.hideAllBut(firstMenu)
-#                      self.Selection = firstMenu
-#                      firstMenu.PanelVisible = True
-#              except IndexError:
-#                      # No such menu
-#                      pass
+               m_undo = {"attributes": {
+                               "Caption": _("&Undo"),
+                               "Action": "app.onEditUndo",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+Z",
+                               "ItemID": "edit_",
+                               "Icon": "undo"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_redo = {"attributes": {
+                               "Caption": _("&Redo"),
+                               "Action": "app.onEditRedo",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+Shift+Z",
+                               "ItemID": "edit_undo",
+                               "Icon": "redo"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_copy = {"attributes": {
+                               "Caption": _("&Copy"),
+                               "Action": "app.onEditCopy",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+C",
+                               "ItemID": "edit_copy",
+                               "Icon": "copy"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_cut = {"attributes": {
+                               "Caption": _("Cu&t"),
+                               "Action": "app.onEditCut",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+X",
+                               "ItemID": "edit_cut",
+                               "Icon": "cut"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_paste = {"attributes": {
+                               "Caption": _("&Paste"),
+                               "Action": "app.onEditPaste",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+V",
+                               "ItemID": "edit_paste",
+                               "Icon": "paste"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_selectall = {"attributes": {
+                               "Caption": _("Select &All"),
+                               "Action": "app.onEditSelectAll",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+A",
+                               "ItemID": "edit_selectall",
+                               "Icon": None},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_find = {"attributes": {
+                               "Caption": _("&Find / Replace"),
+                               "Action": "app.onEditFind",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+F",
+                               "ItemID": "edit_find",
+                               "Icon": "find"},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_findagain = {"attributes": {
+                               "Caption": _("Find A&gain"),
+                               "Action": "app.onEditFindAgain",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+G",
+                               "ItemID": "edit_findagain",
+                               "Icon": None},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               edit_menu = {"attributes": {
+                               "Caption": u"Edit",
+                               "HelpText": "",
+                               "MRU": False},
+                               "children": [m_undo, m_redo, sep, m_cut, 
m_copy, m_paste, sep, m_selectall,
+                                       sep, m_find, m_findagain],
+                               "name": "MenuHyperLink"}
 
+               m_zoomin = {"attributes": {
+                               "Caption": _("&Increase Font Size"),
+                               "Action": "app.fontZoomIn",
+                               "HelpText": "",
+                               "HotKey": "Ctrl++",
+                               "ItemID": "view_zoomin",
+                               "Icon": None},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_zoomout = {"attributes": {
+                               "Caption": _("&Decrease Font Size"),
+                               "Action": "app.fontZoomOut",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+r-+",
+                               "ItemID": "view_zoomout",
+                               "Icon": None},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               m_zoomnormal = {"attributes": {
+                               "Caption": _("&Normal Font Size"),
+                               "Action": "app.fontZoomNormal",
+                               "HelpText": "",
+                               "HotKey": "Ctrl+/",
+                               "ItemID": "view_zoomnormal",
+                               "Icon": None},
+                               "children": [],
+                               "name": "MenuItemHyperLink"}
+               view_menu = {"attributes": {
+                               "Caption": u"View",
+                               "HelpText": "",
+                               "MRU": False},
+                               "children": [m_zoomin, m_zoomout, m_zoomnormal],
+                               "name": "MenuHyperLink"}
 
-       def afterSetMenuBar(self):
-               mbar = self.MenuBar
-               fm = mbar.getMenu("base_file")
-               fm.append(_("Save"), HotKey="Ctrl+S", OnHit=self.onSave,
-                               help=_("Save the menu"))
+               help_menu = {"attributes": {
+                               "Caption": u"Help",
+                               "HelpText": "",
+                               "MRU": False},
+                               "children": [],
+                               "name": "MenuHyperLink"}
 
+               return {"attributes": {},
+                               "name": "MenuBarHyperLink",
+                               "children": [file_menu, edit_menu, view_menu, 
help_menu],
+                               }
 
+
+       def appendMenu(self, caption, useMRU=False):
+               mn = menubarPanel(self, Caption=caption, MRU=useMRU, 
Visible=True)
+               self.Sizer.append(mn)
+               self.fit()
+               self.Controller.updateLayout()
+               return mn
+
+
+       def insertMenu(self, pos, caption, useMRU=False):
+               mn = menubarPanel(self, Caption=caption, MRU=useMRU)
+               self.Sizer.insert(pos, mn)
+               self.fit()
+               self.Controller.updateLayout()
+               return mn
+
+
        def getObjectHierarchy(self, parent=None, level=0):
                """Returns a list of 2-tuples representing the structure of
                the objects on this form. The first element is the nesting 
level,
@@ -131,36 +396,78 @@
                        pass
 
 
+       def saveState(self):
+               self._savedState = self._getState()
+
+
+       def _getState(self):
+               return self.mainMenubarLink.getDesignerDict()
+
+
+       def beforeClose(self, evt):
+               return not self._isDirty()
+
+
+       def _isDirty(self):
+               ret = False
+               curr = self._getState()
+               if curr != self._savedState:
+                       cf = self._menuFile
+                       if cf:
+                               fname = os.path.split(cf)[1]
+                       else:
+                               fname = _("Untitled")
+                       saveIt = dabo.ui.areYouSure(_("Do you want to save the 
changes to '%s'?") % fname, _("Unsaved Changes"))
+                       if saveIt is None:
+                               # They canceled
+                               ret = True
+                       elif saveIt is True:
+                               # They want to save
+                               ret = self.saveMenu()
+                       # Otherwise, they said 'No'
+               return ret
+
+
+       def onNew(self, evt):
+               if not self._isDirty():
+                       self.initMenuBar(addBaseMenu=True)
+
+
+       def onOpen(self, evt):
+               if self._isDirty():
+                       return
+               pth = dabo.ui.getFile("mnxml")
+               if not pth:
+                       # They canceled
+                       return
+               self.openFile(pth)
+
+
+       def onClose(self, evt):
+               self.raiseEvent(dEvents.Close, evt._uiEvent)
+
+
        def onSave(self, evt):
                self.saveMenu()
 
 
-       def saveMenu(self):
-               if not self._menuFile:
-                       self._menuFile = dabo.ui.getSaveAs(wildcard="mnxml")
-                       if not self._menuFile:
-                               # User canceled
-                               return
-                       else:
-                               if not os.path.splitext(self._menuFile)[1] == 
".mnxml":
-                                       self._menuFile += ".mnxml"
+       def onSaveAs(self, evt):
+               print "SaveAs"
 
-               propDict = self.menubar.getDesignerDict()
-               xml = xtd.dicttoxml(propDict)
-               open(self._menuFile, "wb").write(xml)
 
-
        def openFile(self, pth):
                if not os.path.exists(pth):
                        dabo.ui.stop("The file '%s' does not exist" % pth)
                        return
+               self._menuFile = pth
                xml = open(pth).read()
                try:
                        dct = xtd.xmltodict(xml)
                except:
                        raise IOError(_("This does not appear to be a valid 
menu file."))
-               self.menubar.restore(dct)
+               self.makeMenuBar(dct)
                self.layout()
+               self.saveState()
 
 
        def updatePropVal(self, prop, val, typ):
@@ -213,32 +520,18 @@
                self.unlockDisplay()
 
 
-       def treeSelect(self):
-               """Called by the tree when a new selection has been made
-               by the user.
-               """
-               dabo.ui.callAfter(self.afterTreeSelect)
+       def startPropEdit(self):
+               self._inPropertyEditing = True
 
 
-       def afterTreeSelect(self):
-               self.PropForm.Tree._inAppSelection = True
-               try:
-                       selObj = self.PropForm.Tree.getSelection()
-               except AttributeError:
-                       # The tree hasn't been instantiated yet
-                       return
-               self.select(selObj)
-               self.PropForm.Tree._inAppSelection = False
+       def endPropEdit(self):
+               self._inPropertyEditing = False
 
 
        def ensureVisible(self, obj):
                """When selecting a menu item, make sure that its menu is 
open."""
                if isinstance(obj, (list, tuple)):
                        obj = obj[-1]
-               if isinstance(obj, (CaptionBitmapPanel, SeparatorPanel)):
-                       obj.Controller.PanelVisible = True
-               elif isinstance(obj, MenuPanel):
-                       obj.PanelVisible = True
 
 
        def escapeQt(self, s):
@@ -257,7 +550,7 @@
                                noProp = True
                if noProp:
                        pf = self._propForm = MenuPropForm(self, Visible=False,
-                                       Controller=self)
+                                       Controller=self, 
MenuBarFile=self.MenuBarFile)
                        pf.restoreSizeAndPosition()
                        self.updateLayout()
                        pf.Visible = True

Added: trunk/ide/MenuDesignerMenu.mnxml
===================================================================
--- trunk/ide/MenuDesignerMenu.mnxml                            (rev 0)
+++ trunk/ide/MenuDesignerMenu.mnxml    2012-02-02 03:40:12 UTC (rev 7074)
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<MenuBarHyperLink ItemID="main_menubarlink" Caption="MenuBar" HelpText="" 
MRU="False">
+       <MenuHyperLink ItemID="None" Caption="File" HelpText="" MRU="True">
+               <MenuItemHyperLink ItemID="file_new" HotKey="Ctrl+N" 
Caption="&amp;&amp;New" HelpText="" Action="form.Controller.onNew" 
Icon="new"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="file_open" HotKey="Ctrl+O" 
Caption="&amp;&amp;Open" HelpText="" Action="form.Controller.onOpen" 
Icon="open"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="file_close" HotKey="Ctrl+W" 
Caption="&amp;&amp;Close" HelpText="" Action="form.Controller.onClose" 
Icon="close"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="file_save" HotKey="Ctrl+S" 
Caption="&amp;&amp;Save" HelpText="" Action="form.Controller.onSave" 
Icon="save"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="file_saveas" HotKey="" Caption="Save 
&amp;&amp;As" HelpText="" Action="form.Controller.onSaveAs" 
Icon="saveas"></MenuItemHyperLink>
+               <SeparatorHyperLink ItemID="None" 
Caption="----------------------------------------" HelpText="" 
MRU="False"></SeparatorHyperLink>
+               <MenuItemHyperLink ItemID="file_commandwin" HotKey="Ctrl+D" 
Caption="Command Win&amp;&amp;dow" HelpText="" Action="app.onCmdWin" 
Icon="themes/tango/16x16/apps/utilities-terminal.png"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="file_objectinspector" 
HotKey="Ctrl+Shift+I" Caption="Object &amp;&amp;Inspector" HelpText="Open the 
Object Inspector tool" Action="app.onObjectInspectorWin" 
Icon=""></MenuItemHyperLink>
+               <SeparatorHyperLink ItemID="None" 
Caption="----------------------------------------" HelpText="" 
MRU="False"></SeparatorHyperLink>
+               <MenuItemHyperLink ItemID="file_quit" HotKey="Ctrl+Q" 
Caption="&amp;&amp;Quit" HelpText="" Action="app.onFileExit" 
Icon="quit"></MenuItemHyperLink>
+       </MenuHyperLink>
+       <MenuHyperLink ItemID="None" Caption="Edit" HelpText="" MRU="False">
+               <MenuItemHyperLink ItemID="edit_" HotKey="Ctrl+Z" 
Caption="&amp;&amp;Undo" HelpText="" Action="app.onEditUndo" 
Icon="undo"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="edit_undo" HotKey="Ctrl+Shift+Z" 
Caption="&amp;&amp;Redo" HelpText="" Action="app.onEditRedo" 
Icon="redo"></MenuItemHyperLink>
+               <SeparatorHyperLink ItemID="None" 
Caption="----------------------------------------" HelpText="" 
MRU="False"></SeparatorHyperLink>
+               <MenuItemHyperLink ItemID="edit_cut" HotKey="Ctrl+X" 
Caption="Cu&amp;&amp;t" HelpText="" Action="app.onEditCut" 
Icon="cut"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="edit_copy" HotKey="Ctrl+C" 
Caption="&amp;&amp;Copy" HelpText="" Action="app.onEditCopy" 
Icon="copy"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="edit_paste" HotKey="Ctrl+V" 
Caption="&amp;&amp;Paste" HelpText="" Action="app.onEditPaste" 
Icon="paste"></MenuItemHyperLink>
+               <SeparatorHyperLink ItemID="None" 
Caption="----------------------------------------" HelpText="" 
MRU="False"></SeparatorHyperLink>
+               <MenuItemHyperLink ItemID="edit_selectall" HotKey="Ctrl+A" 
Caption="Select &amp;&amp;All" HelpText="" Action="app.onEditSelectAll" 
Icon="None"></MenuItemHyperLink>
+               <SeparatorHyperLink ItemID="None" 
Caption="----------------------------------------" HelpText="" 
MRU="False"></SeparatorHyperLink>
+               <MenuItemHyperLink ItemID="edit_find" HotKey="Ctrl+F" 
Caption="&amp;&amp;Find / Replace" HelpText="" Action="app.onEditFind" 
Icon="find"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="edit_findagain" HotKey="Ctrl+G" 
Caption="Find A&amp;&amp;gain" HelpText="" Action="app.onEditFindAgain" 
Icon="None"></MenuItemHyperLink>
+       </MenuHyperLink>
+       <MenuHyperLink ItemID="None" Caption="View" HelpText="" MRU="False">
+               <MenuItemHyperLink ItemID="view_zoomin" HotKey="Ctrl+=" 
Caption="&amp;&amp;Increase Font Size" HelpText="" Action="app.fontZoomIn" 
Icon="zoomIn"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="view_zoomout" HotKey="Ctrl+-" 
Caption="&amp;&amp;Decrease Font Size" HelpText="" Action="app.fontZoomOut" 
Icon="zoomOut"></MenuItemHyperLink>
+               <MenuItemHyperLink ItemID="view_zoomnormal" HotKey="Ctrl+/" 
Caption="&amp;&amp;Normal Font Size" HelpText="" Action="app.fontZoomNormal" 
Icon="zoomNormal"></MenuItemHyperLink>
+               <SeparatorHyperLink ItemID="None" 
Caption="----------------------------------------" HelpText="" 
MRU="False"></SeparatorHyperLink>
+               <MenuItemHyperLink ItemID="view_preview" HotKey="Ctrl+Shift+P" 
Caption="&amp;&amp;Preview Menu" HelpText="Temporarily display this menu as the 
active menu" Action="form.Controller.onPreview" 
Icon="event_watcher"></MenuItemHyperLink>
+       </MenuHyperLink>
+       <MenuHyperLink ItemID="None" Caption="Help" HelpText="" 
MRU="False"></MenuHyperLink>
+</MenuBarHyperLink>

Modified: trunk/ide/MenuDesignerPropForm.py
===================================================================
--- trunk/ide/MenuDesignerPropForm.py   2012-01-31 02:50:05 UTC (rev 7073)
+++ trunk/ide/MenuDesignerPropForm.py   2012-02-02 03:40:12 UTC (rev 7074)
@@ -117,7 +117,7 @@
                if obj is None:
                        lbl = ""
                else:
-                       lbl = obj.DisplayText
+                       lbl = obj.Caption
                self.txtObj.Value = lbl
                self.PropSheet.select(obj)
                self.Tree.select(obj)
@@ -129,7 +129,7 @@
                try:
                        return self._controller
                except AttributeError:
-                       self._controller = self.Application
+                       self._controller = self
                        return self._controller
 
        def _setController(self, val):

Added: trunk/ide/MenuHyperLink.py
===================================================================
--- trunk/ide/MenuHyperLink.py                          (rev 0)
+++ trunk/ide/MenuHyperLink.py  2012-02-02 03:40:12 UTC (rev 7074)
@@ -0,0 +1,830 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import dabo
+dabo.ui.loadUI("wx")
+from dabo.dLocalize import _
+from dabo.lib.propertyHelperMixin import _DynamicList
+from dabo.lib.utils import ustr
+import dabo.lib.xmltodict as xtd
+from MenuDesignerComponents import MenuSaverMixin
+
+
+SEPARATOR_CAPTION = "-" * 16
+
+
+
+class MenuPanel(dabo.ui.dPanel):
+       def __init__(self, *args, **kwargs):
+               kwargs["BackColor"] = "lightgrey"
+               kwargs["BorderWidth"] = 2
+               super(MenuPanel, self).__init__(*args, **kwargs)
+
+
+class AbstractMenuHyperLink(MenuSaverMixin, dabo.ui.dHyperLink):
+       """Handles all the interactions with the user as they create
+       and modify menu designs.
+       """
+       def __init__(self, parent, *args, **kwargs):
+               kwargs["ShowInBrowser"] = False
+               kwargs["HoverUnderline"] = False
+               kwargs["LinkUnderline"] = False
+               kwargs["VisitedUnderline"] = False
+               kwargs["ShowHover"] = False
+               kwargs["LinkColor"] = "darkblue"
+               kwargs["HoverColor"] = "blue"
+               kwargs["VisitedColor"] = "darkblue"
+               kwargs["BackColor"] = "lightgrey"
+               self._menuParent = None
+               self._MRU = False
+               self._selected = False
+               self._isMenuItem = False
+               self._isSeparator = False
+               self._isMenuBarLink = False
+               self._inUpdate = False
+               self._helpText = ""
+               # The text string representing the HotKey
+               self._hotKeyText = ""
+               # Minimum number of spaces between the caption and hot key
+               self._minCaptionHotKeySpacing = 4
+               # Base width of the text for the menu
+               self._textWidth = 40
+               # The image associated with a menu item.
+               self._icon = ""
+               # Function to be called when a menu item is selected. This
+               # is a string representation that will be eval'd at runtime
+               self._action = ""
+               # The optional ItemID
+               self._itemID = None
+               # The following underlie the HotKey property and its components
+               self._hotKey = ""
+               self._hotKeyAlt = False
+               self._hotKeyChar = ""
+               self._hotKeyControl = False
+               self._hotKeyShift = False
+               self._children = []
+               super(AbstractMenuHyperLink, self).__init__(parent, *args, 
**kwargs)
+               self._baseClass = self.__class__
+               self.FontSize += 1
+
+
+       def onHit(self, evt):
+               raise NotImplementedError
+
+
+       def onContextMenu(self, evt):
+               raise NotImplementedError
+
+
+       def getDesignerDict(self):
+               ret = {}
+               ret["name"] = self.getClass()
+               ret["attributes"] = ra = {}
+               for prop in self.DesignerProps:
+                       if prop.startswith("HotKey") and prop != "HotKey":
+                               # This is one of the derivative props.
+                               continue
+                       ra[prop] = getattr(self, prop)
+               ret["children"] = [kid.getDesignerDict() for kid in 
self.Children]
+               return ret
+
+
+       def _updateHotKey(self):
+               """Called when the user changes any component of the hotkey 
combo."""
+               if not self._inUpdate:
+                       self._inUpdate = True
+                       currHK = self.HotKey
+                       ctlTxt = {True: "Ctrl+", False: ""}[self.HotKeyControl]
+                       shiftTxt = {True: "Shift+", False: ""}[self.HotKeyShift]
+                       altTxt = {True: "Alt+", False: ""}[self.HotKeyAlt]
+                       newHK = ctlTxt + altTxt + shiftTxt + self.HotKeyChar
+                       if newHK != currHK:
+                               self.HotKey = newHK
+                               self.refresh()
+                       self._inUpdate = False
+
+
+       def _calcCaption(self):
+               if self._isSeparator:
+                       self.Caption = "-" * self._textWidth
+               else:
+                       # This will force the re-evaluation of the HotKey text.
+                       self.Caption = self.Caption
+
+
+       def _updateHotKeyProps(self, val=None):
+               """Called when the user changes the hotkey combo to reset the 
components."""
+               if not self._inUpdate:
+                       self._inUpdate = True
+                       if val is None:
+                               val = self.HotKey
+                       self.HotKeyControl = ("Ctrl+" in val)
+                       self.HotKeyShift = ("Shift+" in val)
+                       self.HotKeyAlt = ("Alt+" in val)
+                       self.HotKeyChar = val.split("+")[-1]
+                       self._inUpdate = False
+
+
+       def _getAbbreviatedHotKey(self):
+               ctlTxt = {True: "C", False: ""}[self.HotKeyControl]
+               shiftTxt = {True: "S", False: ""}[self.HotKeyShift]
+               altTxt = {True: "A", False: ""}[self.HotKeyAlt]
+               prefix = ctlTxt + altTxt + shiftTxt
+               if prefix:
+                       prefix += "+"
+               return prefix + self.HotKeyChar
+
+
+       def select(self):
+               self.Controller.Selection = self
+               # Customize behavior here
+               self.afterSelect()
+
+
+       def getClass(self):
+               """Return a string representing the item's class. Can
+               be overridden by subclasses.
+               """
+               return ustr(self.BaseClass).split("'")[1].split(".")[-1]
+
+
+       def afterSelect(self):
+               pass
+
+
+       def displayedCaption(self):
+               return super(AbstractMenuHyperLink, self)._getCaption()
+
+
+       ## Begin property definitions ##
+       def _getAction(self):
+               return self._action
+
+       def _setAction(self, val):
+               if self._constructed():
+                       self._action = val
+               else:
+                       self._properties["Action"] = val
+
+
+       def _getCaption(self):
+               cap = super(AbstractMenuHyperLink, self)._getCaption()
+               return cap.rstrip(self._hotKeyText).rstrip()
+
+
+       def _setCaption(self, val):
+               txt = val
+               if self._hotKeyText:
+                       if self.MenuParent:
+                               txtwd = self.MenuParent._textWidth
+                       else:
+                               txtwd = self._textWidth
+                       padWidth = txtwd - len(val) - len(self._hotKeyText)
+                       padding = " " * padWidth
+                       txt = "".join((val, padding, self._hotKeyText))
+               super(AbstractMenuHyperLink, self)._setCaption(txt)
+
+
+       def _getChildren(self):
+               try:
+                       _children = self._children
+               except AttributeError:
+                       _children = self._children = []
+               return _DynamicList(_children, self, "Children")
+
+       def _setChildren(self, val):
+               self._children = val
+
+
+       def _getController(self):
+               try:
+                       return self._controller
+               except AttributeError:
+                       self._controller = self.Form
+                       return self._controller
+
+       def _setController(self, val):
+               if self._constructed():
+                       self._controller = val
+               else:
+                       self._properties["Controller"] = val
+
+
+       def _getDesignerProps(self):
+               ret = {"Caption": {"type" : unicode, "readonly" : 
(self._isSeparator or self._isMenuBarLink)},
+                               "HelpText" : {"type" : unicode, "readonly" : 
self._isSeparator},
+                               "ItemID" : {"type" : unicode, "readonly" : 
False},
+                               "MRU": {"type" : bool, "readonly" : False}}
+               if self._isMenuItem:
+                       ret.update({
+                                       "HotKey": {"type" : unicode, "readonly" 
: False,
+                                               "customEditor": "editHotKey"},
+                                       "HotKeyAlt": {"type" : bool, "readonly" 
: False},
+                                       "HotKeyChar": {"type" : unicode, 
"readonly" : False},
+                                       "HotKeyControl": {"type" : bool, 
"readonly" : False},
+                                       "HotKeyShift": {"type" : bool, 
"readonly" : False},
+                                       "Action": {"type" : unicode, "readonly" 
: False},
+                                       "Icon": {"type" : unicode, "readonly" : 
False,
+                                               "customEditor": 
"editStdPicture"}})
+                       del ret["MRU"]
+               return ret
+
+
+       def _getHelpText(self):
+               return self._helpText
+
+       def _setHelpText(self, val):
+               if self._constructed():
+                       self._helpText = self.ToolTipText = val
+               else:
+                       self._properties["HelpText"] = val
+
+
+       def _getHotKey(self):
+               return self._hotKey
+
+       def _setHotKey(self, val):
+               if self._constructed():
+                       self._hotKey = val
+                       self._updateHotKeyProps(val)
+                       self._hotKeyText = self._getAbbreviatedHotKey()
+                       # Force an update
+                       self.Caption = self.Caption
+               else:
+                       self._properties["HotKey"] = val
+
+
+       def _getHotKeyAlt(self):
+               return self._hotKeyAlt
+
+       def _setHotKeyAlt(self, val):
+               if self._constructed():
+                       self._hotKeyAlt = val
+                       self._updateHotKey()
+               else:
+                       self._properties["HotKeyAlt"] = val
+
+
+       def _getHotKeyChar(self):
+               return self._hotKeyChar
+
+       def _setHotKeyChar(self, val):
+               if self._constructed():
+                       self._hotKeyChar = val
+                       self._updateHotKey()
+               else:
+                       self._properties["HotKeyChar"] = val
+
+
+       def _getHotKeyControl(self):
+               return self._hotKeyControl
+
+       def _setHotKeyControl(self, val):
+               if self._constructed():
+                       self._hotKeyControl = val
+                       self._updateHotKey()
+               else:
+                       self._properties["HotKeyControl"] = val
+
+
+       def _getHotKeyShift(self):
+               return self._hotKeyShift
+
+       def _setHotKeyShift(self, val):
+               if self._constructed():
+                       self._hotKeyShift = val
+                       self._updateHotKey()
+               else:
+                       self._properties["HotKeyShift"] = val
+
+
+       def _getIcon(self):
+               return self._icon
+
+       def _setIcon(self, val):
+               if self._constructed():
+                       self._icon = val
+               else:
+                       self._properties["Icon"] = val
+
+
+       def _getItemID(self):
+               return self._itemID
+
+       def _setItemID(self, val):
+               if self._constructed():
+                       self._itemID = val
+               else:
+                       self._properties["ItemID"] = val
+
+
+       def _getMenuParent(self):
+               return self._menuParent
+
+       def _setMenuParent(self, val):
+               self._menuParent = val
+
+
+       def _getMRU(self):
+               return self._MRU
+
+       def _setMRU(self, val):
+               self._MRU = val
+
+
+       def _getSelected(self):
+               return self._selected
+
+       def _setSelected(self, val):
+               if self._constructed():
+                       self._selected = val
+                       self.BackColor = {True: "white", False: 
"lightgrey"}[val]
+                       self.Parent.refresh()
+               else:
+                       self._properties["Selected"] = val
+
+
+       Action = property(_getAction, _setAction, None,
+                       _("""Action (method/handler) to be called when a menu 
item is
+                       selected. To specify a method on the associated form, 
use
+                       'form.onSomeMethod'; likewise, you can specify an 
application
+                       method using 'app.onSomeMethod'.  (str)"""))
+
+       Caption = property(_getCaption, _setCaption, None,
+                       _("The caption displayed on the hyperlink, minus any 
hot key.  (str)")) 
+
+       Children = property(_getChildren, _setChildren, None,
+                       _("""The links representing menus, menuitems, etc., 
that are logically
+                       'contained' by this object.  (list)"""))
+
+       Controller = property(_getController, _setController, None,
+                       _("Object to which this one reports events  (object 
(varies))"))
+
+       DesignerProps = property(_getDesignerProps, None, None,
+                       _("Properties exposed in the Menu Designer (read-only) 
(dict)"))
+
+       HelpText = property(_getHelpText, _setHelpText, None,
+                       _("Help string displayed when the menu item is 
selected.  (str)"))
+
+       HotKey = property(_getHotKey, _setHotKey, None,
+                       _("Displayed version of the hotkey combination  (str)"))
+
+       HotKeyAlt = property(_getHotKeyAlt, _setHotKeyAlt, None,
+                       _("Is the Alt key part of the hotkey combo?  (bool)"))
+
+       HotKeyChar = property(_getHotKeyChar, _setHotKeyChar, None,
+                       _("Character part of the hot key for this menu  (str)"))
+
+       HotKeyControl = property(_getHotKeyControl, _setHotKeyControl, None,
+                       _("Is the Control key part of the hotkey combo?  
(bool)"))
+
+       HotKeyShift = property(_getHotKeyShift, _setHotKeyShift, None,
+                       _("Is the Shift key part of the hotkey combo?  (bool)"))
+
+       Icon = property(_getIcon, _setIcon, None,
+                       _("Specifies the icon for the menu item.  (str)"))
+
+       ItemID = property(_getItemID, _setItemID, None,
+                       _("""Identifying value for this menuitem. NOTE: there 
is no checking for
+                       duplicate values; it is the responsibility to ensure 
that ItemID values
+                       are unique within a menu.  (varies)"""))
+
+       MenuParent = property(_getMenuParent, _setMenuParent, None,
+                       _("The logical 'parent' for this item (not the panel 
container it sits in.)"))
+
+       MRU = property(_getMRU, _setMRU, None,
+                       _("Should this menu be tracked for MRU lists  (bool)"))
+
+       Selected = property(_getSelected, _setSelected, None,
+                       _("Is this the currently selected item?  (bool)"))
+
+
+
+class MenuBarHyperLink(AbstractMenuHyperLink):
+       """Used for the top-level menu bar."""
+       def __init__(self, parent, *args, **kwargs):
+               super(MenuBarHyperLink, self).__init__(parent, *args, **kwargs)
+               self._isMenuBarLink = True
+
+
+       def onHit(self, evt):
+               self.select()
+
+
+       def afterSelect(self):
+               self.Controller.makeMenuBar()
+
+
+       def onContextMenu(self, evt):
+               pop = dabo.ui.dMenu()
+               pop.append(_("Create Base Menu"), OnHit=self.onCreateBaseMenu, 
Help="BASE")
+               pop.append(_("Add Menu"), OnHit=self.onAddMenu)
+               self.showContextMenu(pop)
+
+
+       def showTopLevel(self):
+               self.showMenu(None)
+
+               
+       def createMenuFromDict(self, menu_dict):
+               """Create the menu objects from the supplied dict."""
+               cont = self.Controller
+               mbp = cont.menubarPanel
+               msz = mbp.menuSizer
+               msz.clear(destroy=True)
+               self.clearMenus()
+               for att, val in  menu_dict.get("attributes", {}).items():
+                       setattr(self, att, val)
+               for dct in menu_dict.get("children", []):
+                       mn = self._createMenuFromDict(dct)
+                       msz.append(mn, border=10)
+                       self.Children.append(mn)
+                       mbp.menus.append(mn)
+               mbp.layout()
+
+
+       def _createMenuFromDict(self, menu_dict):
+               atts = menu_dict["attributes"]
+               atts["Caption"] = atts.get("Caption", SEPARATOR_CAPTION)
+               mn = MenuHyperLink(self.Controller.menubarPanel, 
attProperties=atts)
+               mn.MenuBar = mn.MenuParent = self
+               mn.Controller = self.Controller
+               mn.addItemsFromDictList(menu_dict.get("children", []))
+               return mn
+
+
+       def addMenu(self, menu, side, caption):
+               """Add a menu to either the right or left of the specified 
menu."""
+               mn = self._createBlankMenu(caption)
+               cont = self.Controller
+               mbp = cont.menubarPanel
+               msz = mbp.menuSizer
+               pos = self.Children.index(menu)
+               if side.lower().startswith("r"):
+                       pos = pos + 1
+               msz.insert(pos, mn, border=10)
+               self.Children.insert(pos, mn)
+               mbp.menus.insert(pos, mn)
+               self.Parent.layout()
+               mn.select()
+
+
+       def moveMenu(self, menu, direction):
+               currPos = self.Children.index(menu)
+               newPos = currPos + direction
+
+
+       def deleteMenu(self, menu):
+               self.Children.remove(menu)
+               mbp = self.Controller.menubarPanel
+               mbp.menus.remove(menu)
+               menu.release()
+               self.Parent.layout()
+
+
+       def clearMenus(self):
+               for mn in self.Children[::-1]:
+                       try:
+                               mn.release()
+                       except dabo.ui.deadObjectException:
+                               # Already deleted
+                               pass
+               self.Children = []
+               self.Controller.clearMenus()
+
+
+       def showMenu(self, menu):
+               """Show the specified menu, hiding others."""
+               for mn in self.Children:
+                       isShown = (mn is menu)
+                       mn.menu_panel.Visible = isShown
+                       if isShown:
+                               mn.menu_panel.Left = mn.Left
+                               mn.menu_panel.Top = mn.Bottom + 5
+               self.refresh()
+
+
+       def _createBlankMenu(self, caption=None):
+               if caption is None:
+                       caption = "BLANK"
+               blank = {"attributes": {"Caption": caption,
+                               "HelpText": "",
+                               "MRU": False},
+                               "children": [],
+                               "name": "MenuHyperLink"}
+               return self._createMenuFromDict(blank)
+
+
+       def onCreateBaseMenu(self, evt):
+               menuExists = bool(self.Children)
+               if menuExists:
+                       if not dabo.ui.areYouSure(_("Proceeding will destroy 
the exising menu. "
+                                       "Do you really want to do that?"), 
"Menu Exists", defaultNo=True,
+                                       cancelButton=False):
+                               return
+               self.Controller.createBaseMenu()
+
+
+       def onAddMenu(self, evt):
+               cap = dabo.ui.getString(_("Caption?"))
+               mn = self._createBlankMenu(cap)
+               cont = self.Controller
+               mbp = cont.menubarPanel
+               msz = mbp.menuSizer
+               msz.append(mn, border=10)
+               self.Children.append(mn)
+               mbp.menus.append(mn)
+               mn.select()
+               self.Parent.layout()
+
+
+
+class MenuHyperLink(AbstractMenuHyperLink):
+       """Used for the menus in the menu bar."""
+       def onHit(self, evt):
+               self.select()
+
+
+       def afterSelect(self):
+               self.MenuBar.showMenu(self)
+               self.Parent.layout()
+
+
+       def release(self):
+               """Augment this to also release the child menus."""
+               for itm in self.Children:
+                       print "RELEASING", itm.Caption
+                       itm.release()
+               super(MenuHyperLink, self).release()
+
+
+       def onContextMenu(self, evt):
+               pop = dabo.ui.dMenu()
+               pos = self.getPositionInSizer()
+               isFirst = (pos == 0)
+               isLast = (pos == (len(self.MenuBar.Children) - 1))
+               pop.append(_("Append MenuItem"), OnHit=self.onAppendMenuItem)
+               pop.append(_("Append Separator"), OnHit=self.onAppendSeparator)
+               pop.append(_("Add Menu Left"), OnHit=self.onAddMenuLeft)
+               pop.append(_("Add Menu Right"), OnHit=self.onAddMenuRight)
+               if not isFirst:
+                       pop.append(_("Move Left"), OnHit=self.onMoveLeft)
+               if not isLast:
+                       pop.append(_("Move Right"), OnHit=self.onMoveRight)
+               pop.append(_("Delete"), OnHit=self.onDelete)
+               self.showContextMenu(pop)
+
+
+       def addItemsFromDictList(self, dctlst):
+               """Create the menu item links from the supplied list of 
menuitem dicts."""
+               try:
+                       self.menu_panel.release()
+               except AttributeError:
+                       pass
+               cont = self.Controller
+               mp = self.menu_panel = MenuPanel(self.Parent)
+               sz = mp.Sizer = dabo.ui.dSizerV(DefaultBorder=5)
+               seps = []
+               max_cap = 0
+               for itm_dct in dctlst:
+                       atts = itm_dct["attributes"]
+                       if itm_dct["name"] == "SeparatorHyperLink":
+                               itm = SeparatorHyperLink(mp)
+                               seps.append(itm)
+                       else:
+                               itm = MenuItemHyperLink(mp, attProperties=atts)
+                               max_cap = max(max_cap, 

 (5990 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