dabo Commit
Revision 7152
Date: 2012-04-27 11:56:49 -0700 (Fri, 27 Apr 2012)
Author: Ed
Trac: http://trac.dabodev.com/changeset/7152
Changed:
D trunk/ide/MenuBarPanel.py
D trunk/ide/MenuDesignerComponents.py
U trunk/ide/MenuDesignerForm.py
U trunk/ide/MenuDesignerMenu.mnxml
D trunk/ide/MenuHyperLink.py
U trunk/ide/MenuPanel.py
Log:
A reworking of the MenuDesigner.
This greatly increases the stability and flexibility of the designer, and
allows for better integration with the other visual design tools.
Diff:
Deleted: trunk/ide/MenuBarPanel.py
Deleted: trunk/ide/MenuDesignerComponents.py
Modified: trunk/ide/MenuDesignerForm.py
===================================================================
--- trunk/ide/MenuDesignerForm.py 2012-04-27 17:06:01 UTC (rev 7151)
+++ trunk/ide/MenuDesignerForm.py 2012-04-27 18:56:49 UTC (rev 7152)
@@ -4,6 +4,7 @@
import codecs
import os
+
import dabo
dabo.ui.loadUI("wx")
@@ -12,11 +13,10 @@
import dabo.dEvents as dEvents
import dabo.lib.xmltodict as xtd
from ClassDesignerExceptions import PropertyUpdateException
-from MenuHyperLink import MenuBarHyperLink
+import MenuPanel
from MenuDesignerPropForm import MenuPropForm
-
class MenuDesignerForm(dabo.ui.dForm):
def __init__(self, *args, **kwargs):
self._selection = None
@@ -25,20 +25,26 @@
self._propForm = None
self._propSheet = None
self._inPropertyEditing = False
- kwargs["MenuBarFile"] = "MenuDesignerMenu.mnxml"
+ appDir = self.Application.HomeDirectory
+ kwargs["MenuBarFile"] = os.path.join(appDir,
"MenuDesignerMenu.mnxml")
self.Controller = self
super(MenuDesignerForm, self).__init__(*args, **kwargs)
self.Caption = "Dabo Menu Designer"
self.mainPanel = dabo.ui.dPanel(self)
self.Sizer.append1x(self.mainPanel)
- self.mainMenubarLink = None
+ self.topLevelMenuBar = None
sz = self.mainPanel.Sizer = dabo.ui.dSizerV()
+ self.initMenuBar()
+ self._dragObject = None
+ self._dragImage = None
+ self._dragOrigPos = (0, 0)
+ self._dragObjOffset = (0, 0)
+ self._dragDrawPos = (0, 0)
+ self.bindEvent(dEvents.MouseMove, self.handleMouseMove)
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)
- mb_link = self.initMenuBar()
- self.layout()
+ dabo.ui.callAfter(self.layout)
def afterInitAll(self):
@@ -47,53 +53,113 @@
if not self._menuFile:
# No menu file was opened; create a base menu
self.createBaseMenu()
- self.Selection = self.mainMenubarLink
+ try:
+ self.topLevelMenuBar.childItems[0].select()
+ except IndexError:
+ self.topLevelMenuBar.select()
+ dabo.ui.callAfter(self.layout)
dabo.ui.callAfter(self.bringToFront)
def initMenuBar(self, addBaseMenu=False):
"""Start from scratch with a basic menu bar."""
try:
- self.mainMenubarLink.release()
+ self.topLevelMenuBar.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",
+ self.mainPanel.BackColor = "darkgrey"
+ mbar = self.topLevelMenuBar =
MenuPanel.MenuBarPanel(self.mainPanel, Caption="- MenuBar -",
Controller=self)
- mbsz = mbp.Sizer = dabo.ui.dSizerV()
- mbsz.append(mbar)
- mbp.menuSizer = dabo.ui.dSizerH()
- mbsz.append1x(mbp.menuSizer)
+
+ self.mainPanel.Sizer.append1x(mbar)
if addBaseMenu:
self.createBaseMenu()
return mbar
+ def handleMouseMove(self, evt):
+ # Not implemented yet, so just return
+ return
+ if evt.dragging:
+ self.handleMouseDrag(evt)
+
+
+ def processLeftUp(self, obj, evt):
+ # Not implemented yet
+ return
+ # When I have time to finish implementing drag n drop...
+ if self.DragObject:
+ drobj = self.DragObject
+ cont = drobj.Parent
+ print "ORIG", self._dragOrigPos
+ print "CONT TL:", cont.Position
+ print "CONT BR:", (cont.Right, cont.Bottom)
+ mp = dabo.ui.getMousePosition()
+ print "NOW", mp
+ print "NOW FMP", dabo.ui.getFormMousePosition()
+ print "FORM MP", drobj.formCoordinates(mp)
+ print "FORM CONT TL",
cont.formCoordinates(cont.Position)
+ print "FORM CONT BR", cont.formCoordinates((cont.Right,
cont.Bottom))
+
+ objat = dabo.ui.getObjectAtPosition(mp)
+ print "OBJ AT", objat
+ print "VIS", self._dragImage.Visible
+ print "PARENT", objat.Parent is self.DragObject.Parent
+ print "GPAR", objat.Parent.Parent is
self.DragObject.Parent
+ try: print objat.Caption
+ except: print "no cap"
+
+ self.DragObject = None
+ if self._dragImage:
+ self.removeDrawnObject(self._dragImage)
+ self._dragImage = None
+ self.clear()
+ self.refresh()
+
+
+ def handleMouseDrag(self, evt):
+ # The EventObject is the object being dragged over.
+ obj = evt.EventObject
+ if evt.dragging:
+ if not self.DragObject:
+ self.DragObject = obj
+ if self._dragImage:
+ self._dragImage.Visible = (obj.Parent is
self.DragObject.Parent)
+ auto = self.autoClearDrawings
+ self.autoClearDrawings = True
+ currX, currY = self.getMousePosition()
+ drawX = currX - self._dragObjOffset[0]
+ drawY = currY - self._dragObjOffset[1]
+ self._dragImage.Xpos = drawX
+ self._dragImage.Ypos = drawY
+ self._redraw()
+ self.autoClearDrawings = auto
+ else:
+ self.DragObject = None
+
+
+ def treeSelect(self):
+ dabo.ui.stop("Not implemented yet - sorry!")
+
+
def createBaseMenu(self):
- """This creates a base menu."""
+ """Creates a base menu with common menuitems."""
menu_dict = self._createBaseMenuDict()
self.makeMenuBar(menu_dict)
- self._savedState = self._getState()
+ dabo.ui.callAfter(self.saveState)
def makeMenuBar(self, dct=None):
- lnk = self.mainMenubarLink
+ mb = self.topLevelMenuBar
if dct is None:
- lnk.showTopLevel()
+ mb.showTopLevel()
else:
- lnk.createMenuFromDict(dct)
+ mb.createMenuFromDict(dct)
self.layout()
def clearMenus(self):
- self.menubarPanel.menus = []
+ self.topLevelMenuBar.menus = []
def getPropDictForObject(self, obj):
@@ -128,23 +194,29 @@
self.Sizer.append1x(mp)
sz = mp.Sizer = dabo.ui.dSizer("v")
sz.appendSpacer(30)
- self.lblResult = dabo.ui.dLabel(mp,
Caption="Menu Selection: \n ", FontBold=True,
+ self.lblResult = dabo.ui.dLabel(mp,
Caption="Menu Selection: \n\n ", FontBold=True,
ForeColor="darkred",
AutoResize=True, Alignment="Center")
- self.lblResult.FontSize += 4
+ self.lblResult.FontSize += 2
sz.append(self.lblResult, "x", halign="center",
border=10)
btn = dabo.ui.dButton(mp, Caption="Close Menu
Preview",
- OnHit=self.onDeactivate)
+ OnHit=self.onClose)
sz.append(btn, halign="center", border=30)
mp.fitToSizer()
- def onDeactivate(self, evt):
+ dabo.ui.callAfter(self.refresh)
+ def onClose(self, evt):
self.release()
def notify(self, evt):
itm = evt.EventObject
- cap = "Menu Selection: %s\n" % itm.Caption
- fncText = itm._bindingText
- if fncText:
- cap = "%sFunction: %s" % (cap, fncText)
- self.lblResult.Caption = cap
+ pth = [itm.Caption]
+ mp = itm.Parent
+ while mp and not isinstance(mp,
dabo.ui.dMenuBar):
+ pth.append(mp.Caption)
+ mp = mp.Parent
+ pth.reverse()
+ cap = " - ".join(pth)
+ fncText = "Function: %s" % itm._bindingText
+ seltxt = "Menu Selection: %s\n\n%s" % (cap,
fncText)
+ self.lblResult.Caption = seltxt
self.layout()
propDict = self._getState()
@@ -159,7 +231,7 @@
iconPath = "themes/tango/16x16"
sep = {"attributes": {},
"children": [],
- "name": "SeparatorHyperLink"}
+ "name": "SeparatorPanel"}
m_new = {"attributes": {
"Caption": _("&New"),
@@ -169,7 +241,7 @@
"ItemID": "file_new",
"Icon": "new"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_open = {"attributes": {
"Caption": _("&Open"),
"Action": "form.onOpen",
@@ -178,7 +250,7 @@
"ItemID": "file_open",
"Icon": "open"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_close = {"attributes": {
"Caption": _("&Close"),
"Action": "form.onClose",
@@ -187,7 +259,7 @@
"ItemID": "file_close",
"Icon": "close"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_save = {"attributes": {
"Caption": _("&Save"),
"Action": "form.onSave",
@@ -196,7 +268,7 @@
"ItemID": "file_save",
"Icon": "save"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_saveas = {"attributes": {
"Caption": _("Save &As"),
"Action": "form.onSaveAs",
@@ -205,7 +277,7 @@
"ItemID": "file_saveas",
"Icon": "saveas"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_cmd = {"attributes": {
"Caption": _("Command Win&dow"),
"Action": "app.onCmdWin",
@@ -214,7 +286,7 @@
"ItemID": "file_commandwin",
"Icon": "%s/apps/utilities-terminal.png" %
iconPath},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_quit = {"attributes": {
"Caption": _("&Quit"),
"Action": "app.onFileExit",
@@ -223,13 +295,13 @@
"ItemID": "file_quit",
"Icon": "quit"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
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"}
+ "name": "MenuPanel"}
m_undo = {"attributes": {
"Caption": _("&Undo"),
@@ -239,7 +311,7 @@
"ItemID": "edit_",
"Icon": "undo"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_redo = {"attributes": {
"Caption": _("&Redo"),
"Action": "app.onEditRedo",
@@ -248,7 +320,7 @@
"ItemID": "edit_undo",
"Icon": "redo"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_copy = {"attributes": {
"Caption": _("&Copy"),
"Action": "app.onEditCopy",
@@ -257,7 +329,7 @@
"ItemID": "edit_copy",
"Icon": "copy"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_cut = {"attributes": {
"Caption": _("Cu&t"),
"Action": "app.onEditCut",
@@ -266,7 +338,7 @@
"ItemID": "edit_cut",
"Icon": "cut"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_paste = {"attributes": {
"Caption": _("&Paste"),
"Action": "app.onEditPaste",
@@ -275,7 +347,7 @@
"ItemID": "edit_paste",
"Icon": "paste"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_selectall = {"attributes": {
"Caption": _("Select &All"),
"Action": "app.onEditSelectAll",
@@ -284,7 +356,7 @@
"ItemID": "edit_selectall",
"Icon": None},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_find = {"attributes": {
"Caption": _("&Find / Replace"),
"Action": "app.onEditFind",
@@ -293,7 +365,7 @@
"ItemID": "edit_find",
"Icon": "find"},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_findagain = {"attributes": {
"Caption": _("Find A&gain"),
"Action": "app.onEditFindAgain",
@@ -302,14 +374,14 @@
"ItemID": "edit_findagain",
"Icon": None},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
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"}
+ "name": "MenuPanel"}
m_zoomin = {"attributes": {
"Caption": _("&Increase Font Size"),
@@ -319,16 +391,16 @@
"ItemID": "view_zoomin",
"Icon": None},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_zoomout = {"attributes": {
"Caption": _("&Decrease Font Size"),
"Action": "app.fontZoomOut",
"HelpText": "",
- "HotKey": "Ctrl+r-+",
+ "HotKey": "Ctrl+-",
"ItemID": "view_zoomout",
"Icon": None},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
m_zoomnormal = {"attributes": {
"Caption": _("&Normal Font Size"),
"Action": "app.fontZoomNormal",
@@ -337,53 +409,113 @@
"ItemID": "view_zoomnormal",
"Icon": None},
"children": [],
- "name": "MenuItemHyperLink"}
+ "name": "MenuItemPanel"}
view_menu = {"attributes": {
"Caption": u"View",
"HelpText": "",
"MRU": False},
"children": [m_zoomin, m_zoomout, m_zoomnormal],
- "name": "MenuHyperLink"}
+ "name": "MenuPanel"}
help_menu = {"attributes": {
"Caption": u"Help",
"HelpText": "",
"MRU": False},
"children": [],
- "name": "MenuHyperLink"}
+ "name": "MenuPanel"}
return {"attributes": {},
- "name": "MenuBarHyperLink",
+ "name": "MenuBarPanel",
"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 onAppendMenu(self, evt):
+ """Handler for the menu item selection."""
+ cap = dabo.ui.getString(_("Caption?"))
+ if cap:
+ return self.topLevelMenuBar.appendMenu(cap)
- 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 onAppendMenuItem(self, evt):
+ """Handler for the menu item selection."""
+ menu = None
+ sel = self.Selection
+ while sel:
+ if isinstance(sel, MenuPanel.MenuPanel):
+ menu = sel
+ break
+ sel = sel.MenuParent
+ if not menu:
+ dabo.ui.stop(_("Please select a menu first."))
+ return
+ cap = dabo.ui.getString(_("Caption?"))
+ if cap:
+ return menu.appendMenuItem(cap)
+ def onAppendSeparator(self, evt):
+ """Handler for the menu item selection."""
+ menu = None
+ sel = self.Selection
+ while sel:
+ if isinstance(sel, MenuPanel.MenuPanel):
+ menu = sel
+ break
+ sel = sel.MenuParent
+ if not menu:
+ dabo.ui.stop(_("Please select a menu first."))
+ return
+ return menu.appendSeparator()
+
+
+ def onMoveItemUp(self, evt):
+ self.Controller.Selection.onMoveUp(evt)
+
+
+ def onMoveItemDown(self, evt):
+ self.Controller.Selection.onMoveDown(evt)
+
+
+ def onDeleteSelection(self, evt):
+ sel = self.Controller.Selection
+ itemType = {MenuPanel.MenuPanel: "menu",
+ MenuPanel.MenuItemPanel: "menu item",
+ MenuPanel.SeparatorPanel:
"separator"}.get(sel.__class__)
+ if itemType is None:
+ # Not a valid selection to delete
+ dabo.log.info(_("The current selection cannot be
deleted"))
+ return
+ cap = sel.Caption
+ if itemType == "separator":
+ msg = "Are you sure you want to delete this separator?"
+ else:
+ msg = "Are you sure you want to delete the %(itemType)s
'%(cap)s'?" % locals()
+ if dabo.ui.areYouSure(msg, "Delete", defaultNo=True,
cancelButton=False):
+ sel.onDelete(evt)
+
+
+ def copyAsJSON(self, evt):
+ """
+ Places a JSON-ified copy of the dict representing the current
+ state of the menu design onto the clipboard.
+ """
+ dct = self._getState()
+ jsonDct = dabo.lib.jsonEncode(dct)
+ self.Application.copyToClipboard(jsonDct)
+
+
def getObjectHierarchy(self, parent=None, level=0):
- """Returns a list of 2-tuples representing the structure of
+ """
+ Returns a list of 2-tuples representing the structure of
the objects on this form. The first element is the nesting
level,
and the second is the object. The objects are in the order
created, irrespective of sizer position.
"""
if parent is None:
- parent = self.menubar
+ parent = self.topLevelMenuBar
ret = [(level, parent)]
- for kid in parent.Children:
+ for kid in parent.childItems:
ret += self.getObjectHierarchy(kid, level+1)
return ret
@@ -401,7 +533,7 @@
def _getState(self):
- return self.mainMenubarLink.getDesignerDict()
+ return self.topLevelMenuBar.getDesignerDict()
def beforeClose(self, evt):
@@ -452,9 +584,40 @@
def onSaveAs(self, evt):
- print "SaveAs"
+ dabo.ui.stop("SaveAs Not Implemented Yet")
+ def onKeyChar(self, evt):
+ """Trap the arrow keys and use them for navigation, if
possible."""
+ kc = evt.keyCode
+ dk = dabo.ui.dKeys
+ if ((kc not in dk.allArrowKeys.values()) or
+ any((evt.shiftDown, evt.altDown,
evt.controlDown, evt.metaDown))):
+ # Only handle unmodified arrow keys.
+ return
+ # Necessary to prevent duplicate key events.
+ evt.stop()
+ curr = self.Controller.Selection
+ sz = curr.ControllingSizer
+ pos = curr.getPositionInSizer()
+ plusKeys = {"Horizontal": (dk.key_Right, dk.key_Numpad_right),
+ "Vertical": (dk.key_Down,
dk.key_Numpad_down)}[sz.Orientation]
+ minusKeys = {"Horizontal": (dk.key_Left, dk.key_Numpad_left),
+ "Vertical": (dk.key_Up,
dk.key_Numpad_up)}[sz.Orientation]
+ if kc in plusKeys:
+ change = 1
+ elif kc in minusKeys:
+ change = -1
+ else:
+ # Not an appropriate arrow key for the orientation
+ return
+ try:
+ self.Controller.select(sz.ChildObjects[pos + change])
+ except IndexError:
+ # Will happen when the last item is selected; wrap to
first.
+ self.Controller.select(sz.ChildObjects[0])
+
+
def openFile(self, pth):
if not os.path.exists(pth):
dabo.ui.stop("The file '%s' does not exist" % pth)
@@ -500,13 +663,12 @@
def onShowPanel(self, menu):
"""Called when code makes a menu panel visible."""
- self.menubar.hideAllBut(menu)
+ self.topLevelMenuBar.hideAllBut(menu)
def select(self, obj):
if obj is self._selection:
return
- self.lockDisplay()
if self._selection is not None:
self._selection.Selected = False
self._selection = obj
@@ -517,7 +679,6 @@
def _selectAfter(self):
self.update()
self.refresh()
- self.unlockDisplay()
def startPropEdit(self):
@@ -540,6 +701,30 @@
return s.replace(sl, sl+sl).replace(qt, sl+qt)
+ def _getDragObject(self):
+ return self._dragObject
+
+ def _setDragObject(self, val):
+ if val is self._dragObject:
+ # redundant
+ return
+ # If there is an existing object, make it visible again
+ if self._dragObject:
+ self._dragObject.Visible = True
+ if self._dragImage:
+ self.removeDrawnObject(self._dragImage)
+ self._dragImage = None
+ self._dragOrigPos = (0, 0)
+ if val is not None:
+ # Save the original position of the mouse down
+ (formX, formY) = self._dragOrigPos =
self.getMousePosition()
+ (objX, objY) = self._dragObjOffset =
val.getMousePosition()
+ # Create an image of the control
+ self._dragImage =
self.drawBitmap(val.getCaptureBitmap(),
+ x=formX-objX, y=formY-objY)
+ self._dragObject = val
+
+
def _getPropForm(self):
noProp = self._propForm is None
if not noProp:
@@ -550,7 +735,7 @@
noProp = True
if noProp:
pf = self._propForm = MenuPropForm(self, Visible=False,
- Controller=self,
MenuBarFile=self.MenuBarFile)
+ MenuBarFile=self.MenuBarFile,
Controller=self)
pf.restoreSizeAndPosition()
self.updateLayout()
pf.Visible = True
@@ -570,6 +755,9 @@
self.select(val)
+ DragObject = property(_getDragObject, _setDragObject, None,
+ _("Reference to the object being dragged on the form
(MenuPanel/MenuItemPanel)"))
+
PropForm = property(_getPropForm, None, None,
_("""Reference to the form that contains the PropSheet
object (MenuPropForm)"""))
@@ -579,4 +767,3 @@
Selection = property(_getSelection, _setSelection, None,
_("Currently selected item (CaptionPanel)"))
-
Modified: trunk/ide/MenuDesignerMenu.mnxml
===================================================================
--- trunk/ide/MenuDesignerMenu.mnxml 2012-04-27 17:06:01 UTC (rev 7151)
+++ trunk/ide/MenuDesignerMenu.mnxml 2012-04-27 18:56:49 UTC (rev 7152)
@@ -1,36 +1,44 @@
<?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="&&New" HelpText="" Action="form.Controller.onNew"
Icon="new"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="file_open" HotKey="Ctrl+O"
Caption="&&Open" HelpText="" Action="form.Controller.onOpen"
Icon="open"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="file_close" HotKey="Ctrl+W"
Caption="&&Close" HelpText="" Action="form.Controller.onClose"
Icon="close"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="file_save" HotKey="Ctrl+S"
Caption="&&Save" HelpText="" Action="form.Controller.onSave"
Icon="save"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="file_saveas" HotKey="" Caption="Save
&&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&&dow" HelpText="" Action="app.onCmdWin"
Icon="themes/tango/16x16/apps/utilities-terminal.png"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="file_objectinspector"
HotKey="Ctrl+Shift+I" Caption="Object &&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="&&Quit" HelpText="" Action="app.onFileExit"
Icon="quit"></MenuItemHyperLink>
- </MenuHyperLink>
- <MenuHyperLink ItemID="None" Caption="Edit" HelpText="" MRU="False">
- <MenuItemHyperLink ItemID="edit_" HotKey="Ctrl+Z"
Caption="&&Undo" HelpText="" Action="app.onEditUndo"
Icon="undo"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="edit_undo" HotKey="Ctrl+Shift+Z"
Caption="&&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&&t" HelpText="" Action="app.onEditCut"
Icon="cut"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="edit_copy" HotKey="Ctrl+C"
Caption="&&Copy" HelpText="" Action="app.onEditCopy"
Icon="copy"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="edit_paste" HotKey="Ctrl+V"
Caption="&&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 &&All" HelpText="" Action="app.onEditSelectAll"
Icon="None"></MenuItemHyperLink>
- <SeparatorHyperLink ItemID="None"
Caption="----------------------------------------" HelpText=""
MRU="False"></SeparatorHyperLink>
- <MenuItemHyperLink ItemID="edit_find" HotKey="Ctrl+F"
Caption="&&Find / Replace" HelpText="" Action="app.onEditFind"
Icon="find"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="edit_findagain" HotKey="Ctrl+G"
Caption="Find A&&gain" HelpText="" Action="app.onEditFindAgain"
Icon="None"></MenuItemHyperLink>
- </MenuHyperLink>
- <MenuHyperLink ItemID="None" Caption="View" HelpText="" MRU="False">
- <MenuItemHyperLink ItemID="view_zoomin" HotKey="Ctrl+="
Caption="&&Increase Font Size" HelpText="" Action="app.fontZoomIn"
Icon="zoomIn"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="view_zoomout" HotKey="Ctrl+-"
Caption="&&Decrease Font Size" HelpText="" Action="app.fontZoomOut"
Icon="zoomOut"></MenuItemHyperLink>
- <MenuItemHyperLink ItemID="view_zoomnormal" HotKey="Ctrl+/"
Caption="&&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="&&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>
+<MenuBarPanel ItemID="None" Caption="- MenuBar -" HelpText="" MRU="False">
+ <MenuPanel ItemID="None" Caption="File" HelpText="" MRU="True">
+ <MenuItemPanel ItemID="file_new" HotKey="Ctrl+N"
Caption="&&New" HelpText="" Action="form.Controller.onNew"
Icon="new"></MenuItemPanel>
+ <MenuItemPanel ItemID="file_open" HotKey="Ctrl+O"
Caption="&&Open" HelpText="" Action="form.Controller.onOpen"
Icon="open"></MenuItemPanel>
+ <MenuItemPanel ItemID="file_close" HotKey="Ctrl+W"
Caption="&&Close" HelpText="" Action="form.Controller.onClose"
Icon="close"></MenuItemPanel>
+ <MenuItemPanel ItemID="file_save" HotKey="Ctrl+S"
Caption="&&Save" HelpText="" Action="form.Controller.onSave"
Icon="save"></MenuItemPanel>
+ <MenuItemPanel ItemID="file_saveas" HotKey="" Caption="Save
&&As" HelpText="" Action="form.Controller.onSaveAs"
Icon="saveas"></MenuItemPanel>
+ <SeparatorPanel ItemID="None" Caption="-separator-" HelpText=""
MRU="False"></SeparatorPanel>
+ <MenuItemPanel ItemID="file_commandwin" HotKey="Ctrl+D"
Caption="Command Win&&dow" HelpText="" Action="app.onCmdWin"
Icon="themes/tango/16x16/apps/utilities-terminal.png"></MenuItemPanel>
+ <MenuItemPanel ItemID="file_objectinspector"
HotKey="Ctrl+Shift+I" Caption="Object &&Inspector" HelpText="Open the
Object Inspector tool" Action="app.onObjectInspectorWin"
Icon=""></MenuItemPanel>
+ <SeparatorPanel ItemID="None" Caption="-separator-" HelpText=""
MRU="False"></SeparatorPanel>
+ <MenuItemPanel ItemID="file_quit" HotKey="Ctrl+Q"
Caption="&&Quit" HelpText="" Action="app.onFileExit"
Icon="quit"></MenuItemPanel>
+ <MenuItemPanel ItemID="file_copyasdict" HotKey="Ctrl+Shift+T"
Caption="Copy as Dict" HelpText="Copies the current menu structure to the
clipboard as a dictionary" Action="form.Controller.copyAsJSON"
Icon=""></MenuItemPanel>
+ </MenuPanel>
+ <MenuPanel ItemID="None" Caption="Edit" HelpText="" MRU="False">
+ <MenuItemPanel ItemID="edit_" HotKey="Ctrl+Z"
Caption="&&Undo" HelpText="" Action="app.onEditUndo"
Icon="undo"></MenuItemPanel>
+ <MenuItemPanel ItemID="edit_undo" HotKey="Ctrl+Shift+Z"
Caption="&&Redo" HelpText="" Action="app.onEditRedo"
Icon="redo"></MenuItemPanel>
+ <SeparatorPanel ItemID="None" Caption="-separator-" HelpText=""
MRU="False"></SeparatorPanel>
+ <MenuItemPanel ItemID="edit_cut" HotKey="Ctrl+X"
Caption="Cu&&t" HelpText="" Action="app.onEditCut"
Icon="cut"></MenuItemPanel>
+ <MenuItemPanel ItemID="edit_copy" HotKey="Ctrl+C"
Caption="&&Copy" HelpText="" Action="app.onEditCopy"
Icon="copy"></MenuItemPanel>
+ <MenuItemPanel ItemID="edit_paste" HotKey="Ctrl+V"
Caption="&&Paste" HelpText="" Action="app.onEditPaste"
Icon="paste"></MenuItemPanel>
+ <SeparatorPanel ItemID="None" Caption="-separator-" HelpText=""
MRU="False"></SeparatorPanel>
+ <MenuItemPanel ItemID="edit_selectall" HotKey="Ctrl+A"
Caption="Select &&All" HelpText="" Action="app.onEditSelectAll"
Icon="None"></MenuItemPanel>
+ <SeparatorPanel ItemID="None" Caption="-separator-" HelpText=""
MRU="False"></SeparatorPanel>
+ <MenuItemPanel ItemID="edit_find" HotKey="Ctrl+F"
Caption="&&Find / Replace" HelpText="" Action="app.onEditFind"
Icon="find"></MenuItemPanel>
+ <MenuItemPanel ItemID="edit_findagain" HotKey="Ctrl+G"
Caption="Find A&&gain" HelpText="" Action="app.onEditFindAgain"
Icon="None"></MenuItemPanel>
+ </MenuPanel>
+ <MenuPanel ItemID="None" Caption="View" HelpText="" MRU="False">
+ <MenuItemPanel ItemID="view_zoomin" HotKey="Ctrl++"
Caption="&&Increase Font Size" HelpText="" Action="app.fontZoomIn"
Icon="zoomIn"></MenuItemPanel>
+ <MenuItemPanel ItemID="view_zoomout" HotKey="Ctrl+-"
Caption="&&Decrease Font Size" HelpText="" Action="app.fontZoomOut"
Icon="zoomOut"></MenuItemPanel>
+ <MenuItemPanel ItemID="view_zoomnormal" HotKey="Ctrl+/"
Caption="&&Normal Font Size" HelpText="" Action="app.fontZoomNormal"
Icon="zoomNormal"></MenuItemPanel>
+ <SeparatorPanel ItemID="None" Caption="-separator-" HelpText=""
MRU="False"></SeparatorPanel>
+ <MenuItemPanel ItemID="view_preview" HotKey="Ctrl+Shift+P"
Caption="&&Preview Menu" HelpText="Temporarily display this menu as the
active menu" Action="form.Controller.onPreview"
Icon="event_watcher"></MenuItemPanel>
+ </MenuPanel>
+ <MenuPanel ItemID="menu_menus" Caption="Menus" HelpText="" MRU="False">
+ <MenuItemPanel ItemID="menus_addmenu" HotKey="Ctrl+M"
Caption="Add Menu" HelpText="Append a new menu to the menu bar"
Action="form.Controller.onAppendMenu" Icon=""></MenuItemPanel>
+ <MenuItemPanel ItemID="menus_appendmenuitem" HotKey="Ctrl+I"
Caption="Append MenuItem" HelpText="Append a new menu item to the current
menu." Action="form.Controller.onAppendMenuItem" Icon=""></MenuItemPanel>
+ <MenuItemPanel ItemID="menus_appendseparator" HotKey="Ctrl+P"
Caption="Append Separator" HelpText="Append a new separator to the current
menu." Action="form.Controller.onAppendSeparator" Icon=""></MenuItemPanel>
+ <SeparatorPanel ItemID="None" Caption="-separator-" HelpText=""
MRU="False"></SeparatorPanel>
+ <MenuItemPanel ItemID="menus_delete" HotKey="Ctrl+Del"
Caption="Delete..." HelpText="Delete the currently selected item"
Action="form.Controller.onDeleteSelection" Icon=""></MenuItemPanel>
+ </MenuPanel>
+ <MenuPanel ItemID="None" Caption="Help" HelpText=""
MRU="False"></MenuPanel>
+</MenuBarPanel>
Deleted: trunk/ide/MenuHyperLink.py
Modified: trunk/ide/MenuPanel.py
===================================================================
--- trunk/ide/MenuPanel.py 2012-04-27 17:06:01 UTC (rev 7151)
+++ trunk/ide/MenuPanel.py 2012-04-27 18:56:49 UTC (rev 7152)
@@ -1,288 +1,895 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-import os
+
import dabo
dabo.ui.loadUI("wx")
+import dabo.dEvents as dEvents
from dabo.dLocalize import _
-import dabo.dEvents as dEvents
-from MenuDesignerComponents import CaptionPanel
-from MenuDesignerComponents import CaptionBitmapPanel
-from MenuDesignerComponents import SeparatorPanel
-from dabo.ui import makeDynamicProperty
-from dabo.ui import makeProxyProperty
+from dabo.lib.propertyHelperMixin import _DynamicList
+from dabo.lib.utils import ustr
+import dabo.lib.xmltodict as xtd
+from MenuDesignerComponents import MenuSaverMixin
+FONT_SIZE_DIFF = 2
+BASE_BACKCOLOR = "#eeeeee"
-class MenuPanel(CaptionPanel):
- """This class represents a menu."""
- def afterInit(self):
- # Name for the saved mnxml file
- self._className = "MenuPanel"
- # Displayed name
- self._commonName = "Menu"
+class MenuItemContainer(dabo.ui.dPanel):
+ """
+ This is the container used to hold menu items for a given
+ menu. It can be shown/hidden as needed to reflect the user's
+ current selection.
+ """
+ def __init__(self, *args, **kwargs):
+ kwargs["AlwaysResetSizer"] = True
+ super(MenuItemContainer, self).__init__(*args, **kwargs)
+ self.Sizer = dabo.ui.dSizerV(DefaultBorder=8,
DefaultBorderLeft=True,
+ DefaultBorderRight=True)
- class _ItemPanel(dabo.ui.dPanel):
- _className = "MenuItemPanel"
- def __init__(self, *args, **kwargs):
- # Name for the saved mnxml file
- self._controller = None
- super(_ItemPanel, self).__init__(*args,
**kwargs)
- self.DynamicWidth = self._calcWidth
- def _calcWidth(self):
- kids = self.Children
- if not kids:
- return 0
- else:
- wd = max([kid.Width for kid in kids])
- dabo.ui.callAfter(self._resizeItems, wd)
- return wd
+class AbstractMenuPanel(MenuSaverMixin, dabo.ui.dPanel):
+ """
+ Handles all the interactions with the user as they create
+ and modify menu designs.
+ """
+ def __init__(self, parent, *args, **kwargs):
+ self._menuParent = None
+ self._MRU = False
+ self._selected = False
+ self._isMenuItem = False
+ self._isSeparator = False
+ self._isMenuBarLink = False
+ self._inUpdate = False
+ self._helpText = ""
+ # Minimum amount of space between the caption and hot key
+ self._minCaptionHotKeySpacing = 5
+ # 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
+ # Collection of contained sub-items
+ self.childItems = []
+ kwargs["BackColor"] = BASE_BACKCOLOR
+ super(AbstractMenuPanel, self).__init__(parent, *args, **kwargs)
+ self._baseClass = self.__class__
+ self.Sizer = dabo.ui.dSizerV()
+ self.FontSize += FONT_SIZE_DIFF
+ self._initCaptions()
+ self.layout()
+ self.bindEvent(dEvents.MouseMove,
self.Controller.handleMouseMove)
+ self.bindEvent(dEvents.MouseLeftUp, self.onMouseLeftUp)
- def _resizeItems(self, wd):
- if not self:
- return
- for kid in self.Children:
- kid.Width = wd
- self.layout()
+
+ def _initCaptions(self):
+ """Customize for each subclass as needed."""
+ pass
+
+
+ def onMouseLeftClick(self, evt):
+ raise NotImplementedError
+
+
+ def onMouseLeftUp(self, evt):
+ self.Controller.processLeftUp(self, evt)
+
+
+ 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.childItems]
+ 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 processContextMenu(self, obj, evt):
- self.Controller.processContextMenu(obj, evt)
- def _getController(self):
- return self._controller
+ 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 _setController(self, val):
- self._controller = val
- Controller = property(_getController, _setController,
None,
- _("Object to which this panel is
associated (MenuPanel)"))
+ 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
- # Add the panel that will hold the menu items. It needs to
- # be a child of the menu bar's parent, which would be this
- # control's grandparent.
- gp = self.Parent.Parent
- localPos = (self.Left, self.Bottom)
- formPos = self.Parent.formCoordinates(localPos)
- self.itemList = lst = _ItemPanel(gp, Controller=self,
Position=formPos,
- Visible=True)
+ def select(self):
+ self.Controller.Selection = self
+ # Customize behavior here
+ self.afterSelect()
- sz = lst.Sizer = dabo.ui.dSizer("V")
- sz.DefaultBorder = 1
- sz.DefaultBorderTop = True
- # Dict to hold additional item information
- self.itemDict = {}
- # Holds the active object during context menu actions
- self._contextObj = None
+ def afterSelect(self):
+ pass
- def __del__(self):
- try:
- self.itemList.release()
- except: pass
+ 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 layout(self):
-# dabo.ui.callAfterInterval(100, self.itemList.layout,
resetMin=True)
-# dabo.ui.callAfterInterval(100, self.itemList.fitToSizer)
+ ## 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 append(self, caption, key=None, picture=None, help=None,
- separator=False):
- return self.insert(None, caption, key=None, picture=picture,
- help=help, separator=separator)
+ def _getCaption(self):
+ return super(AbstractMenuPanel, self)._getCaption()
- def insert(self, pos, caption, key=None, picture=None, help=None,
- separator=False):
- if pos is None:
- # Called from append
- pos = len(self.itemList.Children)
- if separator:
- itm = SeparatorPanel(self.itemList, Controller=self,
Visible=False)
+ def _setCaption(self, val):
+ if self._constructed():
+ super(AbstractMenuPanel, self)._setCaption(val)
+ def _deferCaption():
+ try:
+ self.lblCaption.Caption = val
+ except AttributeError:
+ # Separators won't have lblCaption
+ pass
+ self.Parent.layout()
+ self.Parent.fitToSizer()
+ dabo.ui.callAfter(_deferCaption)
else:
- itm = CaptionBitmapPanel(self.itemList, Caption=caption,
- Controller=self, Visible=False)
- itm._className = "MenuItemPanel"
- itm._commonName = "Menu Item"
- itm.isMenuItem = True
- # Add the item to the dict
- self.itemDict[itm] = {"caption": caption, "key": key,
"picture": picture}
- if picture:
- itm.Picture = picture
+ self._properties["Caption"] = val
- itm.Visible = True
- self.itemList.Height += itm.Height
- self.itemList.Sizer.insert(pos, itm, "x")
- self.layout()
- self.Controller.updateLayout()
- return itm
+ def _getController(self):
+ try:
+ return self._controller
+ except AttributeError:
+ self._controller = self.Form
+ return self._controller
- def appendSeparator(self):
- ret = self.append("", separator=True)
- self.layout()
- self.Controller.updateLayout()
- return ret
+ def _setController(self, val):
+ if self._constructed():
+ self._controller = val
+ else:
+ self._properties["Controller"] = val
- def insertSeparator(self, pos):
- ret = self.insert(pos, "", separator=True)
- self.layout()
- self.Controller.updateLayout()
+ def _getDesignerProps(self):
+ ret = {"Caption": {"type" : unicode, "readonly" : (self._
(21992 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]