# -*- coding: utf-8 -*- import os import sys import time import random import new import dabo from dabo.dLocalize import _ from dabo.lib.utils import padl import dabo.dEvents as dEvents import ClassDesignerPropSheet import dabo.dConstants as kons import dabo.lib.utils as utils from ClassDesignerControlMixin import ClassDesignerControlMixin as dcm import ClassDesignerMenu from DragHandle import DragHandle from wizards.QuickLayoutWizard import QuickLayoutWizard from ClassDesignerComponents import LayoutPanel from ClassDesignerComponents import LayoutBasePanel from ClassDesignerComponents import LayoutSpacerPanel from ClassDesignerComponents import LayoutSizer from ClassDesignerComponents import LayoutBorderSizer from ClassDesignerComponents import LayoutGridSizer from ClassDesignerComponents import LayoutSaverMixin from ClassDesignerComponents import NoSizerBasePanel from ClassDesignerComponents import classFlagProp import dabo.lib.xmltodict as xtd import dabo.lib.DesignerUtils as desUtil import dabo.ui.dialogs as dlgs from dabo.ui import dKeys dui = dabo.ui class ClassDesignerFormMixin(LayoutSaverMixin): def __init__(self, parent=None, properties=None, *args, **kwargs): if not self.Caption: self.Caption = _("Dabo Class Designer") self._controls = [] self._namedConnection = "" self._selection = [self] self._classFile = "" self.redrawOutlines = False self._canContain = self._isMain self._currContainer = None self._dragObject = None self._draggedObjects = None self._dragImage = None self._dragOrigPos = (0, 0) self._dragObjOffset = (0, 0) self._dragDrawPos = (0, 0) self._appNotifiedClose = False # Need to store references to handles along with a reference # to the control they are enclosing self.handles = {} # Name of each handle in a set. The names are abbreviations for # "Top Left", "Top Middle", etc. self.handleNames = ("TL", "TM", "TR", "ML", "MR", "BL", "BM", "BR") # When dragging a handle, this holds the reference to the handle self._handleDragged = None # Denotes if we are dragging to select controls self._selecting = False # Windows has some issues with drawing and control layering. In order # to get around this, create dummy drawing panel on top of the rest. self._drawSurface = None # When editing non-sizer designs, this holds the active container # for adding controls. self._activeContainer = None # Convenient flag for controls determining if # they are being modified on a design surface # or run interactively. self.isDesignerForm = True # The auto-binding happens too late in this case, so call # this method here. self.onActivate(None) def afterInitAll(self): self.refresh() def bringToFront(self): super(ClassDesignerFormMixin, self).bringToFront() def saveState(self): self._savedState = self._getSavedState() def _getSavedState(self): if self._formMode: # Save the whole form return self.getDesignerDict(propsToExclude=("Top", "Left")) else: # The main object is the child of the main panel. obj = self.mainPanel.Children[0] # Make sure it has its class flag set obj.__setattr__(classFlagProp, self._classFile) contr = self.Controller saveall = contr.saveAllProps contr.saveAllProps = True ret = self.getClassDesignerDict(obj, propsToExclude=("Top", "Left")) contr.saveAllProps = saveall return ret def onKeyChar(self, evt): code = evt.keyCode if code not in (dKeys.key_Left, dKeys.key_Right, dKeys.key_Up, dKeys.key_Down, dKeys.key_Back, dKeys.key_Delete): # We don't need to do anything return if self.UseSizers: return modAlt = evt.altDown modControl = evt.controlDown modShift = evt.shiftDown # Control modifies shifting by 10 pixels instead of just 1 distance = 1 + (modControl * 9) h = v = 0 if code == dKeys.key_Left: h = -1 * distance if code == dKeys.key_Right: h = distance if code == dKeys.key_Up: v = -1 * distance if code == dKeys.key_Down: v = distance deleting = code in (dKeys.key_Back, dKeys.key_Delete) for obj in self.Controller.Selection: if deleting: self.selectControl(obj, True) dabo.ui.callAfter(obj.release) elif modShift: obj.growControl(h, v) else: obj.nudgeControl(h, v) def onActivate(self, evt): cntrl = self.Controller if cntrl is not None: try: cf = cntrl.CurrentForm if cf is not self: cntrl.CurrentForm = self self._selection = [obj for obj in self._selection if obj] cntrl.Selection = self._selection dabo.ui.callAfterInterval(200, cntrl.updateLayout) except: # no current form at the moment pass def onDeactivate(self, evt): if self.Controller is not None: self._selection = self.Controller.Selection def beforeClose(self, evt): ret = True curr = self._getSavedState() if curr != self._savedState: cf = self._classFile 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 = False elif saveIt is True: # They want to save ret = self.Controller.wrapSave(self.onSaveDesign, None) # Otherwise, they said 'No' return ret def closing(self, evt=None): if self.Controller is not None: if not self._appNotifiedClose: self._appNotifiedClose = True self._finito = True self.Controller.designerFormClosing(self) return True def _configureForDockForm(self): """If the form being edited is a dDockForm, we need to fake it by adding all the functionality to the DesignerForm. """ pass # from dabo.ui.uiwx.dDockForm import _dDockManager # self._mgr = _dDockManager(self) # # def addMethod(func, nm): # method = new.instancemethod(func, self) # setattr(self, nm, method) # def _addDockPanel(self, *args, **kwargs): # pnl = self._basePanelClass(self, *args, **kwargs) # def _refreshState(self, interval=None): # if interval is None: # interval = 100 # if interval == 0: # self._mgr.Update() # else: # dabo.ui.callAfterInterval(interval, self._mgr.Update) # addMethod(_addDockPanel, "addDockPanel") # addMethod(_refreshState, "_refreshState") # pc = dabo.ui.dDockForm.getBasePanelClass() # self._basePanelClass = self.Controller.getControlClass(pc) # self.CenterPanel = self._basePanelClass(self, name="CenterPanel", # typ="center") # self.CenterPanel = LayoutBasePanel(self) # self.CenterPanel = pc(self) def onPageChanged(self, evt): """Called when a wizard page is selected""" pg = self._pages[evt.newPageNum] try: obj = self.Controller.Selection[0] if obj.isContainedBy(pg): # No need to do anything return except: pass self.selectControl(pg, False) dabo.ui.callAfter(self._refreshPage, pg) def _refreshPage(self, pg): acd = pg.autoClearDrawings pg.autoClearDrawings = True self.refresh() pg.autoClearDrawings = acd def refresh(self): self.clear() super(ClassDesignerFormMixin, self).refresh() def onResize(self, evt): dabo.ui.callAfterInterval(100, self.refresh) def onMenuOpen(self, evt): self.Controller.menuUpdate(evt, self.MenuBar) def afterSetMenuBar(self): ClassDesignerMenu.mkDesignerMenu(self) def onPanelCreate(self): self.Controller.updateLayout() def objectClick(self, obj, shift=False): """Called when the user selects an object.""" if isinstance(obj, NoSizerBasePanel): self.ActiveContainer = obj # That's just a dummy base, so select the form instead obj = self else: if not self.UseSizers: # We need to determine if the object is a child of the active # container, If so, select it normally. If not, see if it is contained # at some level by the active container, or if it is completely # outside of it. If it is within, treat this as a click on the parent # container that is the outermost child of the ActiveContainer. # If it is outside of the ActiveContainer, make the new # ActiveContainer the first common container between the clicked # object and the old ActiveContainer. ac = self.ActiveContainer if obj.Parent is ac: # Normal pass elif obj is ac: # Background click; deselect all objects obj = [] elif self.objectIsContainedBy(obj, ac): # Find ac child that contains obj obj = self.findActiveContainerChild(obj) else: # Not contained. Find the first common container for obj and ac # and select that. cnt = self.firstCommonContainer(obj, ac) self.ActiveContainer = cnt origSel = self.Controller.Selection self.Controller.select(obj, shift) newSel = self.Controller.Selection if newSel is origSel: self.redrawHandles(newSel) def objectIsContainedBy(self, obj, cntr): """Returns True if the object is contained at some level by cntr.""" return obj.isContainedBy(cntr) def findActiveContainerChild(self, obj): """Returns the object that is a child of the ActiveContainer that the passed object is contained by. """ ret = obj while ret: if ret.Parent is self.ActiveContainer: break ret = ret.Parent return ret def firstCommonContainer(self, o1, o2): """Returns the first container that contains both o1 and o2.""" cnt1 = [] cnt2 = [] p1 = o1.Parent p2 = o2.Parent while p1 is not self: cnt1.insert(0, p1) p1 = p1.Parent while p2 is not self: cnt2.insert(0, p2) p2 = p2.Parent # OK, at the very least, they have the form in common. ret = self # Pop off the first object of each list until they differ. while cnt1 and cnt2: pop1 = cnt1.pop(0) pop2 = cnt2.pop(0) if pop1 is pop2: ret = pop1 else: break return ret def selectControl(self, obj, shift=False): """Pass-through method when an object needs to be selected""" self.Controller.select(obj, shift) def updateApp(self): """Called by contained objects when their state changes and requires the ClassDesigner to update itself. """ self.Controller.updateLayout() self.layout() def getObjectHierarchy(self): """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 self._formMode: obj = self else: obj = self.Children[0] return self._recurseObjects(obj, 0) def _recurseObjects(self, obj, level): ret = [(level, obj)] kids = None if isinstance(obj, (dui.dComboBox, dui.dSpinner, dui.dListControl, dui.dRadioList)): # These compound controls don't need their parts listed children = None else: try: kids = obj.Children except: # Not an object that has a Children prop; ignore it kids = None if kids is not None: for ch in kids: if isinstance(ch, (dui.dForm, dui.dToolForm, dui.dDialog, dui.dStatusBar, LayoutPanel)): continue elif str(ch).startswith(" 1: self.StatusText = _("-multiple selection-") elif len(ctls) == 0: self.StatusText = _("Selected Object: %s") % self.Name else: ct0 = ctls[0] if ct0: self.StatusText = _("Selected Object: %s") % ctls[0].Name else: self.StatusText = "" self.unlockDisplay() def ensureVisible(self, obj): """When selecting an object on a page, make sure that that page is selected. """ if isinstance(obj, (list, tuple)): obj = obj[-1] if not hasattr(obj, "showContainingPage"): if isinstance(obj, dabo.ui.dTreeView.getBaseNodeClass()): # Make sure that it is expanded in the tree obj.show() # Now make sure that the tree is visible. obj = obj.tree else: while obj.Parent: obj = obj.Parent if hasattr(obj, "showContainingPage"): break obj.showContainingPage() # def getControlClass(self, base): # class controlMix(dcm, base): # _superBase = base # _superMixin = dcm # def __init__(self, *args, **kwargs): # if hasattr(base, "__init__"): # apply(base.__init__,(self,) + args, kwargs) # parent = args[0] # dcm.__init__(self, parent, **kwargs) # return controlMix # def close(self): # # Needed to avoid resizing errors when quitting # self.Controller.isClosing = True # super(ClassDesignerFormMixin, self).close() # def onSizePosChg(self, evt): # if self.controlPanel and self.mainControl: # self.controlPanel.Size = self.mainControl.Size # self.Layout() # self.Controller.PropSheet.updatePropVal( ("Left", "Right", "Top", "Bottom", # "Size", "Height", "Width", "Position") ) # def updatePropVal(self, valNames): # """Pass-through method""" # self.Controller.PropSheet.updatePropVal(valNames) def redrawHandles(self, ctls, showEm=True): if self.UseSizers: # Not applicable return if not isinstance(ctls, (list, tuple)): ctls = [ctls] for ctl in ctls: if (ctl is self): # Nothing to hilite self.hideAllHandles() return elif isinstance(ctl, (dabo.ui.dSizer, LayoutPanel, LayoutBasePanel)): # Not an actual control continue hnds = self.createControlHandles(ctl) try: left, top = ctl.Position except AttributeError: # This is an object that doesn't have 'Position', such as a # grid column, so skip the handle drawing. return wid, ht = ctl.Size handleW, handleH = hnds["TL"].Size handleMid = int(handleH /2) hnds["TL"].Position = left-handleW+handleMid, top-handleH+handleMid hnds["TM"].Position = (left+(wid/2)-handleMid), top-handleH+handleMid hnds["TR"].Position = left+wid-handleMid, top-handleH+handleMid hnds["ML"].Position = left-handleW+handleMid, top+(ht/2)-handleMid hnds["MR"].Position = left+wid-handleMid, top+(ht/2)-handleMid hnds["BL"].Position = left-handleW+handleMid, top+ht-handleMid hnds["BM"].Position = (left+(wid/2)-handleMid), top+ht-handleMid hnds["BR"].Position = left+wid-handleMid, top+ht-handleMid for hnd in hnds.values(): hnd.bringToFront() hnd.Visible = showEm def createControlHandles(self, ctl): try: handleSet = self.handles[ctl] except: handleSet = {} for nm in self.handleNames: h = DragHandle(ctl.Parent, handleName=nm) h.ownerCtl = ctl handleSet[nm] = h self.handles[ctl] = handleSet return handleSet def startResize(self, handle, evt): if not handle: return ctl = handle.ownerCtl up, right, down, left = handle.up, handle.right, handle.down, handle.left ctl.startResize(evt, up, right, down, left) self._handleDragged = handle self.DragObject = ctl self.dragging = True self.hideHandles(ctl) self.iterateCall("setMouseHandling", True) def stopResize(self, handle, evt): if not handle: return ctl = handle.ownerCtl up, right, down, left = handle.up, handle.right, handle.down, handle.left ctl.stopResize(evt, up, right, down, left) self._handleDragged.dragging = False self._handleDragged = None self.redrawHandles(ctl) self.dragging = False self.iterateCall("setMouseHandling", False) def resizeCtrl(self, handle, evt): if not handle or not handle.ownerCtl: return ctl = handle.ownerCtl up, right, down, left = handle.up, handle.right, handle.down, handle.left ctl.resize(evt, up, right, down, left) def hideAllHandles(self): ks = self.handles.keys() for key in ks: self.hideHandles(key) def hideHandles(self, ctl=None, release=False): if ctl is None: return if self.handles.has_key(ctl): hnd = self.handles[ctl] for nm,h in hnd.items(): h.Visible = False if release: h.release() if release: del self.handles[ctl] def alignControls(self, evt, edge): """Aligns the currently selected controls along the specified edge. Normally the alignment is to the topmost position if Top alignment is chosen; rightmost position if Right alignment; etc. However, if the control key is depressed, the opposite alignment is chosen. IOW, if control is down and Top alignment is selected, the controls are top aligned to the control whose Top is the closest to the bottom. """ slc = self.Controller.Selection controlPressed = dabo.ui.isControlDown() if edge in ("Top", "Left"): memberFunc = {True: max, False: min}[controlPressed] else: memberFunc = {True: min, False: max}[controlPressed] newval = memberFunc([eval("ctl.%s" % edge) for ctl in slc]) for ctl in slc: dabo.ui.setAfter(ctl, edge, newval) dabo.ui.callAfter(self.redrawHandles, slc) def iterateCall(self, funcName, *args, **kwargs): """We need to override this because of a hack that was done to remap the Children property, which iterateCall() relies upon, to the children of the 'mainPanel' object. We need to be sure that the mainPanel gets the call instead. """ if self.mainPanel: # This is ignored in the Children prop self.mainPanel.iterateCall(funcName, *args, **kwargs) else: super(ClassDesignerFormMixin, self).iterateCall(funcName, *args, **kwargs) def onControlLeftDown(self, evt): obj = evt.EventObject ac = self.ActiveContainer self.iterateCall("setMouseHandling", True) if obj is ac: # We're clicking within the active container, so start # drawing the marquee. self.onLeftDown(evt) return elif obj.Parent is ac: if self.Controller.Selection: self.hideAllHandles() if obj in self.Controller.Selection: self._draggedObjects = self.Controller.Selection else: if evt.shiftDown: # Add the object self._draggedObjects = self.Controller.Selection self._draggedObjects.append(obj) else: self.Controller.deselect(self.Controller.Selection) self._draggedObjects = [obj] else: self._draggedObjects = [obj] elif self.objectIsContainedBy(obj, ac): # Find ac child that contains obj self._draggedObjects = [self.findActiveContainerChild(obj)] self.hideAllHandles() else: # Not contained. Find the first common container for obj and ac # and select that. cnt = self.firstCommonContainer(obj, ac) self.ActiveContainer = cnt self.onLeftDown(evt) return # Need to record the starting position for the dragged controls for ctl in self._draggedObjects: ctl._startDragPos = ctl.Position self._dragOrigPos = obj.absoluteCoordinates(evt.mousePosition) self._dragObjOffset = evt.mousePosition def processLeftDoubleClick(self, evt): """Called from an object when it is double-clicked.""" obj = evt.EventObject if obj.IsContainer: self.ActiveContainer = obj def processLeftDown(self, obj, evt): if isinstance(obj, NoSizerBasePanel): self.onLeftDown(evt) def onLeftDown(self, evt): if True: self._selecting = True self._dragDrawPos = self._dragOrigPos = \ evt.EventObject.absoluteCoordinates(evt.mousePosition) if self._drawSurface is None: self._drawSurface = self.ActiveContainer self.iterateCall("setMouseHandling", True) ## else: ## self._drawSurface = self # else: # self.drawing = True # self.drawX, self.drawY = self.ScreenToClient( wx.GetMousePosition() ) #(evt.m_x, evt.m_y) def onLeftUp(self, evt, obj=None): if obj is None: obj = evt.EventObject if isinstance(obj.Parent, dabo.ui.dRadioList): obj = obj.Parent drobj = self._draggedObjects dabo.ui.callAfter(self._clearDraggedObjects) if self._selecting: mp = evt.mousePosition ac = self.ActiveContainer # Clear the marquee self.drawMarquee(self._dragDrawPos) self._selecting = False origPos = self._dragOrigPos if obj: endPos = obj.absoluteCoordinates(mp) else: endPos = mp relOrigPos = ac.relativeCoordinates(origPos) relEndPos = ac.relativeCoordinates(endPos) # Was there a selected class? cls = self.Controller.SelectedClass if cls is not None: self.Controller.addDrawnClass(cls, ac, relOrigPos, relEndPos) else: #self._drawSurface = None # Any selected? sel = [ctl for ctl in ac.Children if self.intesects(ctl, relOrigPos, relEndPos) and not isinstance(ctl, DragHandle)] self.selectControl(sel, evt.shiftDown) self._dragOrigPos = self._dragDrawPos = (0, 0) else: self.objectClick(obj, evt.shiftDown) def intesects(self, ctl, p1, p2): """Returns True if any part of ctl is within the rectangle defined by p1, p2.""" cLeft, cTop = ctl.Position cRight = cLeft + ctl.Width cBottom = cTop + ctl.Height pLeft = min(p1[0], p2[0]) pTop = min(p1[1], p2[1]) pRight = pLeft + abs(p1[0] - p2[0]) pBottom = pTop + abs(p1[1] - p2[1]) if (cLeft > pRight) or (cRight < pLeft) or (cTop > pBottom) or (cBottom < pTop): return False else: ret = ( ((cLeft <= pRight) or (cRight >= pLeft)) and ((cTop <= pBottom) or (cBottom >= pTop)) ) return ret def setMouseHandling(self, turnOn): """When turnOn is True, sets all the mouse event bindings. When it is False, removes the bindings. """ if turnOn: self.bindEvent(dEvents.MouseMove, self.handleMouseMove) else: self.unbindEvent(dEvents.MouseMove) # This is also being passed on to the base panel, which will pass # it on to its child objects, so there is no need to duplicate the # calls. raise dException.StopIterationException def handleMouseMove(self, evt): if evt.dragging: self.onMouseDrag(evt) else: self.DragObject = None def onMouseDrag(self, evt): obj = evt.EventObject if isinstance(obj.Parent, dabo.ui.dRadioList): obj = obj.Parent if evt.dragging: if self.UseSizers: return if not self.DragObject and not self._selecting: if not isinstance(obj, dabo.ui.dSplitter): self.DragObject = obj if self._dragImage: 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: # no sizers; see if we're dragging any controls if self._handleDragged: hd = self._handleDragged self.resizeCtrl(hd, evt) elif self._draggedObjects is not None: self.moveDraggedObjects(evt) elif self._selecting: pos = evt.EventObject.absoluteCoordinates(evt.mousePosition) self.drawMarquee(self._dragDrawPos) self.drawMarquee(pos) else: self.DragObject = None def moveDraggedObjects(self, evt): # newX, newY = evt.EventObject.containerCoordinates(self.ActiveContainer, # evt.mousePosition) newX, newY = evt.EventObject.absoluteCoordinates(evt.mousePosition) oldX, oldY = self._dragOrigPos diffX = newX - oldX diffY = newY - oldY for ctl in self._draggedObjects: ctlX, ctlY = ctl._startDragPos ctl.Position = (ctlX + diffX, ctlY + diffY) def drawMarquee(self, pos): # Adjust the pos for the container offX, offY = 0,0 #self.ActiveContainer.formCoordinates() x1, y1 = self._dragOrigPos x2, y2 = pos x2 -= offX y2 -= offY xpos = min(x1, x2) wd = abs(x1 - x2) ypos = min(y1, y2) ht = abs(y1 - y2) #self._drawSurface.Visible = True if self.Controller.SelectedClass: penColor = "gold" penWidth = 2 lineStyle = "dash" else: penColor = "black" penWidth = 1 lineStyle = "dot" xpos, ypos = self.ActiveContainer.relativeCoordinates((xpos, ypos)) self.ActiveContainer.drawRectangle(xpos, ypos, wd, ht, lineStyle=lineStyle, penColor=penColor, penWidth=penWidth, mode="invert", persist=False) self._dragDrawPos = pos def processLeftUp(self, obj, evt): if isinstance(obj.Parent, dabo.ui.dRadioList): obj = obj.Parent if self.UseSizers: self.onLeftUp(evt, obj) return self.iterateCall("setMouseHandling", False) dabo.ui.callAfter(self._clearDraggedObjects) ox, oy = self._dragOrigPos nx, ny = obj.absoluteCoordinates(evt.mousePosition) dist = abs(nx-ox) + abs(ny-oy) wasSelecting = self._selecting if wasSelecting and (dist > 2): self.onLeftUp(evt, obj) return if (self._draggedObjects is not None) and (dist > 2): # We're finishing a drag operation self.Controller.Selection = self._draggedObjects self.redrawHandles(self._draggedObjects) return srcObj = self.DragObject if not srcObj: if obj is not self.ActiveContainer or wasSelecting: self.objectClick(obj, evt.shiftDown) else: # Clear the reference self.DragObject = None if self.UseSizers: # Make sure that the object wasn't dropped on itself. if srcObj is obj: self._redraw() return if isinstance(obj, dabo.ui.dPanel) and not isinstance(obj, (LayoutPanel, LayoutSpacerPanel)): # Make sure that it not just empty border space around # child objects nonLPkids = [kid for kid in obj.Children if not isinstance(kid, (LayoutPanel, LayoutSpacerPanel))] if nonLPkids: # Don't allow the drop self._redraw() return # An item was dragged from somewhere else on # the design surface and dropped on the srcObj oSz = obj.ControllingSizer oSzIt = obj.ControllingSizerItem oProps = oSz.getItemProps(oSzIt) oPos = obj.getPositionInSizer() pSz = srcObj.ControllingSizer pSzIt = srcObj.ControllingSizerItem pProps = pSz.getItemProps(pSzIt) pPos = srcObj.getPositionInSizer() # Switch 'em! First, remove the objects from their sizers oSz.remove(obj) pSz.remove(srcObj) # Now add this panel to the object's old Sizer if isinstance(oSz, dabo.ui.dGridSizer): oSz.append(srcObj, "x", row=oPos[0], col=oPos[1]) else: oSz.insert(oPos, srcObj) newSzit = srcObj.ControllingSizerItem oSz.setItemProps(newSzit, oProps) # Now add the object to the old panel Sizer if isinstance(pSz, dabo.ui.dGridSizer): pSz.append(obj, "x", row=pPos[0], col=pPos[1]) else: pSz.insert(pPos, obj) newSzit = obj.ControllingSizerItem pSz.setItemProps(newSzit, pProps) self.Controller.updateLayout() self.layout() else: # Not using sizers self.stopResize(self._handleDragged, evt) def _clearDraggedObjects(self): self._draggedObjects = None def getBizobjTemplate(self): return """ class %(tblTitle)sBizobj(dabo.biz.dBizobj): def afterInit(self): self.DataSource = "%(tbl)s" self.KeyField = "%(pk)s" self.addFrom("%(tbl)s") %(fldDefs)s def validateRecord(self): %(tq)sReturning anything other than an empty string from this method will prevent the data from being saved. %(tq)s ret = "" # Add your business rules here. return ret %(lowbiz)s = %(tblTitle)sBizobj(self.Connection) self.addBizobj(%(lowbiz)s) """ def escapeQt(self, s): sl = "\\" qt = "\'" return s.replace(sl, sl+sl).replace(qt, sl+qt) ### Begin Property Definitions ### def _getActiveContainer(self): if self._activeContainer is None: self._activeContainer = self.mainPanel return self._activeContainer def _setActiveContainer(self, val): if self._constructed(): if val is not self._activeContainer: # Changing! First clear any hilite if self._activeContainer is not None: self._activeContainer.HiliteBorderWidth = 0 self._activeContainer = val if val is not None: self._activeContainer.HiliteBorderWidth = 2 self._activeContainer.HiliteBorderLineStyle = "dash" else: self._properties["ActiveContainer"] = val def _getController(self): try: return self._controller except AttributeError: self._controller = self.Application return self._controller def _setController(self, val): if self._constructed(): self._controller = val else: self._properties["Controller"] = val def _getControls(self): return self._controls def _setControls(self, ctls): self._controls = ctls def _getChildren(self): ret = [] if isinstance(self, dlgs.Wizard): ret = self._pages else: try: if self.mainPanel: ret = self.mainPanel.Children except: pass return ret def _getDesEvents(self): if self.Controller: return self.Controller.getClassEvents(self._baseClass) else: return [] def _getDesProps(self): ret = {"Caption": {"type" : unicode, "readonly" : False}, "Height": {"type" : int, "readonly" : False}, "Width": {"type" : int, "readonly" : False}, "Name" : {"type" : unicode, "readonly" : False}, "Left": {"type" : int, "readonly" : False}, "Right": {"type" : int, "readonly" : False}, "Top": {"type" : int, "readonly" : False}, "Bottom": {"type" : int, "readonly" : False}, "ShowCaption": {"type" : bool, "readonly" : False}, "MenuBarFile": {"type" : "path", "readonly" : False, "customEditor": "editMenuBarFile"}, "CxnFile": {"type" : "path", "readonly" : False, "customEditor": "editCxnFile"}, "CxnName": {"type" : unicode, "readonly" : False}, "Tag" : {"type" : "multi", "readonly" : False}, "SaveRestorePosition": {"type" : bool, "readonly" : False}} if isinstance(self, dlgs.Wizard): ret["Picture"] = {"type" : "path", "readonly" : False, "customEditor": "editStdPicture"} ret["PictureHeight"] = {"type" : int, "readonly" : False} ret["PictureWidth"] = {"type" : int, "readonly" : False} elif isinstance(self, dabo.ui.dDialog): ret["AutoSize"] = {"type" : bool, "readonly" : False} ret["Centered"] = {"type" : bool, "readonly" : False} ret["ReleaseOnEscape"] = {"type" : bool, "readonly" : False} return ret 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: if not self._handleDragged: # 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 _getIsContainer(self): return self._canContain def _getMenuBarFile(self): return self._menuBarFile def _setMenuBarFile(self, val): self._menuBarFile = val def _getSelection(self): return self.selectedControls def _setSelection(self, ctls): self.selectedControls = ctls def _getUseSizers(self): try: ret = self._useSizers except AttributeError: ret = self._useSizers = True return ret def _setUseSizers(self, val): if self._constructed(): self._useSizers = val else: self._properties["UseSizers"] = val ActiveContainer = property(_getActiveContainer, _setActiveContainer, None, _("Container currently active for creating controls (dPanel (usually))")) Controller = property(_getController, _setController, None, _("Object to which this one reports events (object (varies))")) Controls = property(_getControls, _setControls, None, _("List of all control(s) in the designer. (list)") ) Children = property(_getChildren, None, None, _("""Children of the main panel of this form.""")) DesignerEvents = property(_getDesEvents, None, None, _("""Returns a list of the most common events for the control. This will determine which events are displayed in the PropSheet for the developer to attach code to. (list)""") ) DesignerProps = property(_getDesProps, None, None, _("""Returns a dict of editable properties for the form, with the prop names as the keys, and the value for each another dict, containing the following keys: 'type', which controls how to display and edit the property, and 'readonly', which will prevent editing when True. (dict)""") ) DragObject = property(_getDragObject, _setDragObject, None, _("Reference to the object being dragged on the form (ClassDesignerControlMixin)")) IsContainer = property(_getIsContainer, None, None, _("Can we add controls to this form? (bool)") ) MenuBarFile = property(_getMenuBarFile, _setMenuBarFile, None, _("Path to the menu designer file used for this form's MenuBarClass (str)")) Selection = property(_getSelection, _setSelection, None, _("List of control(s) currently selected for editing. (list)") ) UseSizers = property(_getUseSizers, _setUseSizers, None, _("Does the this form use sizers for its layout? (bool)"))