dabo Commit
Revision 7171
Date: 2012-05-01 11:55:52 -0700 (Tue, 01 May 2012)
Author: Ed
Trac: http://trac.dabodev.com/changeset/7171
Changed:
A trunk/ide/MenuDesignerComponents.py
Log:
Adding this file to svn - should have been added with the rest of the
MenuDesigner changes.
Diff:
Added: trunk/ide/MenuDesignerComponents.py
===================================================================
--- trunk/ide/MenuDesignerComponents.py (rev 0)
+++ trunk/ide/MenuDesignerComponents.py 2012-05-01 18:55:52 UTC (rev 7171)
@@ -0,0 +1,581 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import os
+import dabo
+from dabo.dLocalize import _
+import dabo.dEvents as dEvents
+from dabo.ui import makeDynamicProperty
+from dabo.ui import makeProxyProperty
+
+
+
+class MenuSaverMixin(object):
+ """Contains the basic code for generating the dict required
+ to save the MenuDesigner's contents.
+ """
+ def getDesignerDict(self):
+ ret = {}
+ ret["name"] = self.__class__.__name__
+ ret["attributes"] = ra = {}
+ propsToExclude = ("HotKeyChar", "HotKeyControl",
+ "HotKeyAlt", "HotKeyShift")
+ for prop in self.DesignerProps:
+ if prop in propsToExclude:
+ continue
+ if hasattr(self, prop):
+ val = eval("self.%s" % prop)
+ else:
+ # Custom-defined property; that's saved
elsewhere
+ continue
+ if isinstance(val, basestring) and os.path.exists(val):
+ # It's a path; convert it to a relative path
+ if isinstance(self, dabo.ui.dForm):
+ ref = self.Form._menuBarFile
+ else:
+ ref = "."
+ ref = os.path.abspath(ref)
+ val = dabo.lib.utils.getPathAttributePrefix() +
\
+
dabo.lib.utils.relativePath(val, ref)
+ if isinstance(val, basestring):
+ strval = val
+ else:
+ strval = unicode(val)
+ # Special cases
+ try:
+ evalStrVal = eval(strval)
+ except:
+ evalStrVal = None
+ ra[prop] = val
+ ret["children"] = [kid.getDesignerDict()
+ for kid in self.Children
+ if hasattr(kid, "getDesignerDict")]
+ return ret
+
+
+
+class CaptionPanel(MenuSaverMixin, dabo.ui.dPanel):
+ # Name for the saved mnxml file
+ _className = "CaptionPanel"
+ # Displayed name
+ _commonName = "Generic Item"
+ _kids = []
+
+ def __init__(self, parent, *args, **kwargs):
+ self._caption = ""
+ self._MRU = False
+ self._selected = False
+ self._inUpdate = False
+ # The draw object representing the Caption
+ self._capText = None
+ # The draw object representing the HotKey
+ self._hotKeyText = None
+ # Minimum spacing between the caption and hot key
+ self._captionHotKeySpacing = 20
+ # Function to be called when a menu item is selected. This
+ # is a string representation that will be eval'd at runtime
+ self._action = ""
+ # Flag to let the Menu Designer know that this is a MenuItem
+ self.isMenuItem = False
+ # The following underlie the HotKey property and its components
+ self._hotKey = ""
+ self._hotKeyAlt = False
+ self._hotKeyChar = ""
+ self._hotKeyControl = False
+ self._hotKeyShift = False
+ super(CaptionPanel, self).__init__(parent, *args, **kwargs)
+ self.BorderWidth = 1
+ self.BorderColor = (222, 222, 222)
+ self.Height = 24
+ self._unselectedBackColor = "white"
+ self._selectedBackColor = (255, 255, 192)
+ self._unselectedForeColor = "black"
+ self._selectedForeColor = "blue"
+ # This is the background draw object
+ self._background = self.drawRectangle(0, 0, -1, -1,
+ penWidth=0,
fillColor=self._unselectedBackColor, visible=False)
+ self._capText = self.drawText(self.Caption, 5, 5, visible=False)
+ self._hotKeyText = self.drawText(self.AbbreviatedHotKey, 5, 5,
visible=False)
+ self.DynamicBackColor = self.getBack #lambda: {True:
self._selectedBackColor, False: self._unselectedBackColor}[self._selected]
+ self._background.DynamicFillColor =
self._capText.DynamicFillColor = \
+ self._hotKeyText.DynamicFillColor =
self.getBack #lambda: {True: self._selectedBackColor, False:
self._unselectedBackColor}[self._selected]
+ self._capText.DynamicForeColor = lambda: {True:
self._selectedForeColor, False: self._unselectedForeColor}[self._selected]
+ # This will allow the hot key text position to stay
right-aligned.
+ self._hotKeyText.DynamicXpos = self.positionHotKeyText
+ self.refresh()
+ self.Parent.update()
+ self._dragging = False
+ self._dragImg = None
+ self._helpText = ""
+ # We want the drawing surface cleared between drawings
+ self.autoClearDrawings = True
+ # We want Hover behavior
+ self.Hover = True
+ # Smooth the drawing
+ self.Buffered = True
+
+ self._kids = [self._background, self._hotKeyText, self._capText]
+
+ def getBack(self):
+ if self._selected:
+ ret = self._selectedBackColor
+ else:
+ ret = self._unselectedBackColor
+ return ret
+
+
+ # These two methods will display the item's HelpText
+ # in the form's Status Bar when the mouse is over them.
+ def onHover(self, evt):
+ self.Form.StatusText = self.HelpText
+ def endHover(self, evt):
+ self.Form.StatusText = ""
+
+#### Someday I hope to have the time to enable dragging menus
+#### around to re-arrange them!
+# def onMouseLeftDown(self, evt):
+# self._dragging = True
+# self._dragImg = dabo.ui.dDragImage(self)
+#
+# def onMouseMove(self, evt):
+# if not self._dragging:
+# return
+# if evt.mouseDown:
+# self._dragImg.updatePosition()
+# else:
+# self._dragImg.clear()
+# self._dragImg = None
+# self._dragging = False
+#
+# def onMouseLeftUp(self, evt):
+# print "LEFT UP", self._caption, self._dragging,
+# self._dragging = False
+# x, y = evt.mousePosition
+# print x, y, self.posIsWithin(x, y)
+# if self._dragImg:
+# self._dragImg.clear()
+# self._dragImg = None
+
+
+ def setWidth(self):
+ """Set the width to the width of the text, plus 5 pixels on
each side."""
+ curr = self.Width
+ capwd = dabo.ui.fontMetricFromDrawObject(self._capText)[0]
+ hkwd = dabo.ui.fontMetricFromDrawObject(self._hotKeyText)[0]
+ addlwd = self.getAdditionalWidth()
+ if self._hotKey:
+ addlwd += self._captionHotKeySpacing
+ calc = capwd + hkwd + addlwd
+ if curr < calc:
+ self.Width = calc
+
+
+ def positionHotKeyText(self):
+ "This is the function for the DynamicXPos property of the
HotKey."""
+ hkt = self._hotKeyText
+ wd = dabo.ui.fontMetricFromDrawObject(hkt)[0]
+ margin = 10
+ return (self.Width - wd) - margin
+
+
+ def getAdditionalWidth(self):
+ """Provide for a little 'breathing room' on the panel.
Subclasses
+ can override as needed if they contain additional items.
+ """
+ return 10
+
+
+ def refresh(self):
+ if self._capText is not None:
+ dabo.ui.callAfterInterval(60, self._refresh)
+ def _refresh(self):
+ """By linking this to a 'callAfterInterval', when several events
+ that require a refresh occur quickly, the 'slow stuff' only gets
+ called once.
+ """
+ super(CaptionPanel, self).refresh()
+ self.setWidth()
+ self.Parent.update()
+ self.Parent.layout()
+
+
+ def onContextMenu(self, evt):
+ self.Parent.processContextMenu(self, evt)
+
+
+ def onMouseLeftClick(self, evt):
+ self.Form.select(self)
+
+
+ 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 _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 _getAction(self):
+ return self._action
+
+ def _setAction(self, val):
+ if self._constructed():
+ self._action = val
+ else:
+ self._properties["Action"] = val
+
+
+ def _getCaption(self):
+ return self._caption
+
+ def _setCaption(self, val):
+ self._caption = val
+ if self._capText is not None:
+ self._capText.Text = val
+ self.refresh()
+
+
+ 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" : False},
+ "HelpText" : {"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}})
+ del ret["MRU"]
+ return ret
+
+
+ def _getDisplayText(self):
+ return "%s: '%s'" % (self._commonName, self.Caption)
+
+
+ def _getHelpText(self):
+ return self._helpText
+
+ def _setHelpText(self, val):
+ if self._constructed():
+ self._helpText = 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.Text = self._getAbbreviatedHotKey()
+ self.update()
+ 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 _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.clear()
+# self.lockDisplay()
+# backcolor = {True: self._selectedBackColor,
+# False: self._unselectedBackColor}[val]
+# forecolor = {True: self._selectedForeColor,
+# False: self._unselectedForeColor}[val]
+# self._capText.ForeColor = self._capText.PenColor =
forecolor
+# self._capText.FontBold = val
+# self.BackColor = self._background.FillColor = backcolor
+ self.Parent.refresh()
+# self.unlockDisplay()
+ else:
+ self._properties["Selected"] = val
+
+
+ # Tree display is the same as the displayed text
+ def _getTreeDisplayCaption(self):
+ return ("'%s'" % self.Caption, self._commonName)
+
+
+ AbbreviatedHotKey = property(_getAbbreviatedHotKey, None, None,
+ _("Short version of the HotKey string (read-only)
(str)"))
+
+ Action = property(_getAction, _setAction, None,
+ _("Action to be called when a menu item is selected.
(str)"))
+
+ Caption = property(_getCaption, _setCaption, None,
+ _("Caption displayed on this panel (str)"))
+
+ 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)"))
+
+ DisplayText = property(_getDisplayText, None, None,
+ _("Text used in the prop sheet to identify this object
(read-only) (str)"))
+
+ 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)"))
+
+ 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)"))
+
+ TreeDisplayCaption = property(_getTreeDisplayCaption, None, None,
+ _("Identifying label displayed in the prop sheet tree
(read-only) (str)"))
+
+
+ _proxyDict = {}
+ Visible = makeProxyProperty(_proxyDict, "Visible", ("self", "_kids"))
+
+
+class CaptionBitmapPanel(CaptionPanel):
+ """Like the CaptionPanel, but can also display a bitmap image
+ to the left of the caption.
+ """
+ # Name for the saved mnxml file
+ _className = "CaptionBitmapPanel"
+
+ def __init__(self, parent, *args, **kwargs):
+ self._bitmap = None
+ self._bmp = None
+ self._picture = None
+ super(CaptionBitmapPanel, self).__init__(parent, *args,
**kwargs)
+
+
+ def getAdditionalWidth(self):
+ """Add in the width of the bitmap."""
+ ret = super(CaptionBitmapPanel, self).getAdditionalWidth()
+ if self._bmp is not None:
+ ret += self._bmp.Width + 5
+ return ret
+
+
+ def _getBitmap(self):
+ return self._bitmap
+
+ def _setBitmap(self, val):
+ self._bitmap = val
+ if isinstance(val, basestring):
+ bmp = dabo.ui.strToBmp(val)
+ else:
+ bmp = val
+ # Create the bitmap object
+ if self._bmp:
+ # Remove it.
+ self.removeDrawnObject(self._bmp)
+ self._kids.remove(self._bmp)
+ self._bmp = None
+ self._bmp = self.drawBitmap(bmp, 5, 5,
visible=self.Parent.Visible)
+
+ self._kids.append(self._bmp)
+
+ wd = self._bmp.Width
+ # Move the text over to fit
+ self._capText.Xpos = wd + 10
+ self.refresh()
+
+
+ def _getDesignerProps(self):
+ ret = super(CaptionBitmapPanel, self)._getDesignerProps()
+ ret.update({"Picture": {"type" : "path", "readonly" : False,
+ "customEditor": "editStdPicture"}})
+ return ret
+
+
+ def _getPicture(self):
+ return self._picture
+
+ def _setPicture(self, val):
+ self._picture = val
+ if isinstance(val, dabo.ui.dBitmap):
+ bmp = val
+ else:
+ bmp = dabo.ui.strToBmp(val)
+ self._setBitmap(bmp)
+
+
+ Bitmap = property(_getBitmap, _setBitmap, None,
+ _("Bitmap to display on the panel (bitmap)"))
+
+ DesignerProps = property(_getDesignerProps, None, None,
+ _("Properties exposed in the Menu Designer (read-only)
(dict)"))
+
+ Picture = property(_getPicture, _setPicture, None,
+ _("The file used as the source for the displayed image.
(str)") )
+
+
+
+class SeparatorPanel(CaptionBitmapPanel):
+ """Represents a menu separator item."""
+ # Name for the saved mnxml file
+ _className = "SeparatorPanel"
+ # Displayed name
+ _commonName = "Separator"
+ # Displayed separator line
+ _line = None
+
+ def afterInitAll(self):
+ self.Height = 16
+ midHt = self.Height / 2.0
+ self._line = self.drawLine(4, midHt, self.Width-4, midHt,
+ penColor="gray", penWidth=1)
+ self._line.DynamicPoints = self.setLineWidth
+ self._line.DynamicPenWidth = self.setLineThick
+ self._kids.append(self._line)
+
+
+ def onResize(self, evt):
+ if self._line:
+ self.update()
+
+
+ def setLineWidth(self):
+ """We want the line to be the full width of the panel,
+ with a few pixels 'breathing room' on each side.
+ """
+ midHt = self.Height / 2.0
+ x1 = 4
+ x2 = self.Width - 4
+ y1 = y2 = midHt
+ return ((x1, y1), (x2, y2))
+
+
+ def setLineThick(self):
+ """Make it look thicker when selected."""
+ return {True: 2, False: 1}[self.Selected]
+
+
+ def _getDesignerProps(self):
+ return {}
+
+
+ def _getDisplayText(self):
+ return "Separator"
+
+
+ DesignerProps = property(_getDesignerProps, None, None,
+ _("Properties exposed in the Menu Designer (read-only)
(dict)"))
+
+ DisplayText = property(_getDisplayText, None, None,
+ _("Text used in the prop sheet to identify this object
(read-only) (str)"))
+
_______________________________________________
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]