#---------------------------------------------------------------------- # Name: PropertyEditors.py # Purpose: # # Author: Riaan Booysen # # Created: 1999 # RCS-ID: $Id: PropertyEditors.py,v 1.37 2005/07/11 10:00:59 riaan Exp $ # Copyright: (c) 1999 - 2005 Riaan Booysen # Licence: GPL #---------------------------------------------------------------------- """ Property editors provide a design time interface for the inspector to examine and manipulate properties of controls. Some properties are live and also update the design time control, others only update the source and changes may only be seen when the frame is reloaded or the control is recreated. """ print 'importing PropertyEditors' # XXX Value getting setting of value between internal and sometime control value # XXX Is still too fuzzy from types import * import os, string import wx from InspectorEditorControls import * import Utils import Enumerations StringTypes = [StringType] try: StringTypes.append(UnicodeType) except: pass class EditorStyles:pass class esExpandable(EditorStyles):pass class esDialog(EditorStyles):pass class esReadOnly(EditorStyles):pass class esRecreateProp(EditorStyles):pass class PropertyRegistry: """ Factory to return propery editors from recognisable types It does not return property editors for certain design-time types like sets, enumerations, booleans, etc. """ def __init__(self): self.classRegistry = {} self.typeRegistry = {}#{type(None): None} def registerClasses(self, propClass, propEditors): for propEdit in propEditors: self.classRegistry[propClass.__name__] = propEdit def registerTypes(self, propType, propEditors): for propEdit in propEditors: self.typeRegistry[propType] = propEdit def factory(self, name, parent, companion, rootCompanion, propWrapper, idx, width): try: propWrapper.connect(companion.control, companion) value = propWrapper.getValue() except Exception, message: print 'Error on accessing Getter for', name, ':', message value = None #2.4 if type(value) == InstanceType: if self.classRegistry.has_key(value.__class__.__name__): return self.classRegistry[value.__class__.__name__](name, parent, companion, rootCompanion, propWrapper, idx, width) else: pass ## print 'e:class', value, value.__class__.__name__, 'for', name, 'not supported' #2.5 if self.typeRegistry.has_key(type(value)): return self.typeRegistry[type(value)](name, parent, companion, rootCompanion, propWrapper, idx, width) elif isinstance(value, object) and hasattr(value, '__class__') and \ self.classRegistry.has_key(value.__class__.__name__): return self.classRegistry[value.__class__.__name__](name, parent, companion, rootCompanion, propWrapper, idx, width) else: if type(value) == type(None): return None elif self.typeRegistry.has_key(type(value)): return self.typeRegistry[type(value)](name, parent, companion, rootCompanion, propWrapper, idx, width) else: pass ## print 'e:type', value, type(value), 'for', name, 'not supported' # XXX Check IEC initialisation not from Display value but from 'valueFromIEC' class PropertyEditor: """ Class associated with a design time identified type, it manages the behaviour of a NameValue in the Inspector """ def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, _1=None , _2=None): self.name = name self.parent = parent self.idx = idx self.width = width self.editorCtrl = None self.companion = companion self.obj = companion.control self.propWrapper = propWrapper self.propWrapper.connect(self.obj, self.companion) self.rootCompanion = rootCompanion self.root = rootCompanion.control self.style = [] self.ownerPropEdit = None self.expanded = False self.initFromComponent() def initFromComponent(self): self.value = self.propWrapper.getValue() if self.editorCtrl: self.editorCtrl.setValue(self.valueToIECValue()) def edit(self): pass def inspectorEdit(self): """ Start a property editing operation and opens the inplace editor """ pass def refreshCompCtrl(self): if self.obj and hasattr(self.obj, 'Refresh'): self.obj.Refresh() def isValuesEqual(self, propVal, ctrlVal): if isinstance(propVal, wx.Font) and isinstance(ctrlVal, wx.Font): return fontAsExpr(propVal) == fontAsExpr(ctrlVal) elif isinstance(propVal, (StringType, UnicodeType)) and \ isinstance(ctrlVal, (StringType, UnicodeType)): return propVal == ctrlVal else: return propVal == ctrlVal def validateProp(self, oldVal, newVal): pass def inspectorPost(self, closeEditor = True): """ Post inspector editor control, update ctrl and persist value """ if self.editorCtrl: v = self.getValue() cv = self.getCtrlValue() # Only post changes if not self.isValuesEqual(v, cv): self.validateProp(v, cv) self.setCtrlValue(cv, v) self.refreshCompCtrl() self.persistValue(self.valueAsExpr()) # When sub properties post, update their main properies if self.ownerPropEdit: self.companion.updateOwnerFromObj() self.ownerPropEdit.initFromComponent() # XXX Font's want new objects assigned to them before # XXX they update if esRecreateProp in self.ownerPropEdit.getStyle(): v = self.companion.eval(self.ownerPropEdit.valueAsExpr()) self.ownerPropEdit.setCtrlValue(v, v) self.ownerPropEdit.persistValue(self.ownerPropEdit.valueAsExpr()) self.ownerPropEdit.refreshCompCtrl() if self.name in self.companion.mutualDepProps: for prop in self.companion.mutualDepProps: if prop != self.name: insp = self.companion.designer.inspector insp.constructorUpdate(prop) insp.propertyUpdate(prop) if closeEditor and self.editorCtrl: self.editorCtrl.destroyControl() self.editorCtrl = None def inspectorCancel(self): """ Cancel a property editor operation """ if self.editorCtrl: self.editorCtrl.destroyControl() self.editorCtrl = None def getStyle(self): return self.style def getValue(self): """ Returns and initialises value for prop editor. If in edit mode, value should be read from the editor control Override if needed. """ if self.editorCtrl: self.value = self.editorCtrl.getValue() return self.value def setValue(self, value): """ Initialise the prop editor and if needed the editor control """ self.value = value if self.editorCtrl: self.editorCtrl.setValue(self.valueToIECValue()) def getCtrlValue(self): """ Read current prop value from designed object """ return self.propWrapper.getValue() def setCtrlValue(self, oldValue, value): """ Update designed object with current prop """ # If overridden, rem to call check triggers if not calling parent method self.companion.checkTriggers(self.name, oldValue, value) self.propWrapper.setValue(value) def persistValue(self, value): funcName = self.propWrapper.getSetterName() self.companion.persistProp(self.name, funcName, value) def getDisplayValue(self): """ Value that should display when the prop editor is not in edit mode """ return `self.value` def valueAsExpr(self): """ Return value as evaluatable source """ return self.getDisplayValue() def getValues(self): """ Return list of options """ return self.values def setValues(self, values): """ Sets list of options """ self.values = values def valueToIECValue(self): """ Return prop value in the form that the form that the editor control expects """ return self.value def setValueFromIECValue(self, value): """ Set value from the format that the editor control produces """ self.value = value def setWidth(self, width): self.width = width if self.editorCtrl: self.editorCtrl.setWidth(width) def setIdx(self, idx): self.idx = idx if self.editorCtrl: self.editorCtrl.setIdx(idx) class FactoryPropEdit(PropertyEditor): pass class LockedPropEdit(PropertyEditor): def getDisplayValue(self): return str(self.value) #------------------------------------------------------------------------------- class ConfPropEdit(PropertyEditor): def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options, names): PropertyEditor.__init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width) self.setValues(names) def getDisplayValue(self): return str(self.value) def initFromComponent(self): self.value = self.getCtrlValue() def persistValue(self, value): pass class ContainerConfPropEdit(ConfPropEdit): def getStyle(self): return [esExpandable] def inspectorEdit(self): self.editorCtrl = BevelIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width) class StrConfPropEdit(ConfPropEdit): def valueToIECValue(self): return self.value # return eval(self.value) def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getValue(self): if self.editorCtrl: try: self.value = self.editorCtrl.getValue() except Exception, message: self.value = self.getCtrlValue() print 'invalid constr prop value', message else: self.value = self.getCtrlValue() return self.value class PasswdStrConfPropEdit(StrConfPropEdit): def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width, style=wx.TE_PASSWORD) def getDisplayValue(self): return '*'*len(self.value) class EvalConfPropEdit(ConfPropEdit): def valueToIECValue(self): return `self.value` def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, `self.value`) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getValue(self): if self.editorCtrl: try: self.value = eval(self.editorCtrl.getValue(), {}) except Exception, message: self.value = self.getCtrlValue() print 'invalid constr prop value', message else: self.value = self.getCtrlValue() return self.value class EnumConfPropEdit(ConfPropEdit): def inspectorEdit(self): self.editorCtrl = ChoiceIEC(self, self.getValue()) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.editorCtrl.setValue(self.value) ## ## def getValues(self): ## return self.names class ColourConfPropEdit(ConfPropEdit): def inspectorEdit(self): self.editorCtrl = ButtonIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) def edit(self, event): data = wx.ColourData() data.SetColour(self.companion.eval(self.value)) data.SetChooseFull(True) dlg = wx.ColourDialog(self.parent, data) try: if dlg.ShowModal() == wx.ID_OK: col = dlg.GetColourData().GetColour() self.editorCtrl.value = \ 'wx.Colour(%d, %d, %d)'%(col.Red(),col.Green(),col.Blue()) self.inspectorPost(False) finally: dlg.Destroy() class FilepathConfPropEdit(ConfPropEdit): def inspectorEdit(self): self.editorCtrl = ButtonIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) def edit(self, event): from FileDlg import wxFileDialog dlg = wxFileDialog(self.parent, 'Choose the file', '.', '', 'AllFiles', wx.SAVE) try: if dlg.ShowModal() == wx.ID_OK: self.editorCtrl.setValue(`dlg.GetFilePath()`) self.inspectorPost(False) else: if wx.MessageBox('Clear the current property value?', 'Clear filepath?', style=wx.ICON_QUESTION | wx.YES_NO) == wx.YES: self.editorCtrl.setValue("''") self.inspectorPost(False) finally: dlg.Destroy() class DirpathConfPropEdit(ConfPropEdit): def inspectorEdit(self): self.editorCtrl = ButtonIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) def edit(self, event): dlg = wx.DirDialog(self.parent)#, defaultPath=self.editorCtrl.value) try: dlg.SetPath(self.companion.eval(self.editorCtrl.value)) if dlg.ShowModal() == wx.ID_OK: self.editorCtrl.setValue(`dlg.GetPath()`) self.inspectorPost(False) else: if wx.MessageBox('Clear the current property value?', 'Clear dirpath?', style=wx.ICON_QUESTION | wx.YES_NO) == wx.YES: self.editorCtrl.setValue("''") self.inspectorPost(False) finally: dlg.Destroy() class BoolConfPropEdit(ConfPropEdit): truths = ['on', 'true', '1'] def getDisplayValue(self): return self.valueToIECValue() def valueToIECValue(self): return self.value.lower() in self.truths and 'True' or 'False' def inspectorEdit(self): self.editorCtrl = CheckBoxIEC(self, self.value in self.truths) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.editorCtrl.setValue(self.value) #------------------------------------------------------------------------------- class OptionedPropEdit(PropertyEditor): """ Property editors initialised with options """ def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options, names): PropertyEditor.__init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width) self.options = options self.names = names if names: self.revNames = Enumerations.reverseDict(names) else: self.revNames = None class ConstrPropEditFacade: def initFromComponent(self): self.value = '' def getCtrlValue(self): return '' def getValue(self): return '' def setValue(self, value): self.value = value class ConstrPropEdit(ConstrPropEditFacade, PropertyEditor): def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options, names): PropertyEditor.__init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width) def initFromComponent(self): self.value = self.getValue() def valueToIECValue(self): return self.value def getDisplayValue(self): return self.getValue() def getCtrlValue(self): return self.companion.textConstr.params[ \ self.companion.constructor()[self.name]] def setCtrlValue(self, oldValue, value): self.companion.checkTriggers(self.name, oldValue, value) if hasattr(self.companion, 'index'): self.propWrapper.setValue(self.companion.eval(value), self.companion.index) else: self.propWrapper.setValue(value) class ReadOnlyConstrPropEdit(ConstrPropEdit): def getValue(self): self.value = self.getCtrlValue() return self.value def inspectorEdit(self): val = self.getValue() self.editorCtrl = BeveledLabelIEC(self, val) self.editorCtrl.createControl(self.parent, self.idx, self.width) ## def getDisplayValue(self): ## return 'RO:`self.getValue()` class ColourConstrPropEdit(ConstrPropEdit): def getValue(self): if self.editorCtrl: self.value = self.editorCtrl.getValue() else: self.value = self.getCtrlValue() return self.value def inspectorEdit(self): self.editorCtrl = ButtonIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) def edit(self, event): data = wx.ColourData() data.SetColour(self.companion.eval(self.value)) data.SetChooseFull(True) dlg = wx.ColourDialog(self.parent, data) try: if dlg.ShowModal() == wx.ID_OK: col = dlg.GetColourData().GetColour() self.value = 'wx.Colour(%d, %d, %d)'%(col.Red(),col.Green(),col.Blue()) self.editorCtrl.setValue(self.value) self.inspectorPost(False) finally: dlg.Destroy() # Collection id name class ItemIdConstrPropEdit(ConstrPropEdit): def inspectorEdit(self): val = self.valueToIECValue() self.editorCtrl = TextCtrlIEC(self, val) self.editorCtrl.createControl(self.parent, val, self.idx, self.width) def valueToIECValue(self): return self.getDisplayValue() def getDisplayValue(self): base = self.companion.newWinId('') return self.getValue()[len(base):] def fixupName(self, name): newname = [] for c in name: if c == ' ': c = '_' if c in string.digits + string.letters + '_': newname.append(c) return ''.join(newname).upper() def getValue(self): if self.editorCtrl and self.editorCtrl.getValue(): base = self.companion.newWinId('') self.value = base + self.fixupName(self.editorCtrl.getValue()) else: self.value = self.getCtrlValue() return self.value def valueAsExpr(self): return self.getValue() def setCtrlValue(self, oldValue, value): self.companion.checkTriggers(self.name, oldValue, value) self.propWrapper.setValue(value, self.companion.index) class IntConstrPropEdit(ConstrPropEdit): def inspectorEdit(self): self.editorCtrl = SpinCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getValue(self): if self.editorCtrl: # and self.editorCtrl.getValue(): self.value = str(self.editorCtrl.getValue()) else: self.value = self.getCtrlValue() return self.value class SBFWidthConstrPropEdit(IntConstrPropEdit): def getCtrlValue(self): return self.companion.GetWidth() def setCtrlValue(self, oldValue, value): self.companion.SetWidth(value) def persistValue(self, value): pass class ClassLinkConstrPropEdit(IntConstrPropEdit): pass class BitmapPropEditMix: extTypeMap = {'.bmp': 'wx.BITMAP_TYPE_BMP', '.gif': 'wx.BITMAP_TYPE_GIF', '.jpg': 'wx.BITMAP_TYPE_JPEG', '.png': 'wx.BITMAP_TYPE_PNG', '.py': 'ResourceModule'} srcClass = 'wx.Bitmap' ctrlClass = wx.Bitmap nullClass = 'wx.NullBitmap' onlyIcons = False def showImgDlg(self, dir, name, tpe='Bitmap'): model = self.companion.designer.model selImg = '' if tpe == 'Bitmap' and not os.path.isdir(dir): wx.MessageBox('The given directory is invalid, using current ' 'directory.\n(%s)'%dir, 'Warning', wx.OK | wx.ICON_EXCLAMATION) dir = '.' elif tpe == 'ResourceModule': selImg = name from FileDlg import wxFileDialog keepShowing = True while keepShowing: keepShowing = False if tpe == 'ResourceModule': mod = model.resources[dir] ext = '.py' pth = abspth = os.path.splitext(mod.__file__)[0]+ext else: dlg = wxFileDialog(self.parent, 'Choose an image', dir, name, 'ImageFiles', wx.OPEN) try: if dlg.ShowModal() != wx.ID_OK: return '', '', '' pth = abspth = dlg.GetFilePath().replace('\\', '/') finally: dlg.Destroy() if not Preferences.cgAbsoluteImagePaths: pth = Utils.pathRelativeToModel(pth, model) ext = os.path.splitext(pth)[-1].lower() if ext == '.py': if os.path.isabs(pth): pth = Utils.pathRelativeToModel(pth, model) resInfo = self.handleResourceFiles(abspth, pth, selImg) if resInfo: if resInfo == -1: return '', '', '' if resInfo == 'FileDlg': dir, name = os.path.split(abspth) keepShowing = True tpe = 'Bitmap' continue return resInfo[0], resInfo[1], 'ResourceModule' try: ext = self.extTypeMap[ext] except KeyError, err: raise Exception('Files of type %s not allowed for this ' 'property editor.\n The following types ' 'are allowed %s'%(str(err), ', '.join(self.extTypeMap.keys()))) else: return abspth, pth, ext def extractPathFromSrc(self, src): if src: if src.startswith(self.nullClass): return os.path.join('.', self.nullClass, 'Bitmap'), '.', '', 'Bitmap' elif src.startswith('wx.Bitmap(') or src.startswith('wx.Icon('): if src.startswith('wx.Bitmap('): filename = src[len('wx.Bitmap(')+1:] else: filename = src[len('wx.Icon(')+1:] pth = filename[:filename.rfind(',')-1] if not os.path.isabs(pth): mbd = Utils.getModelBaseDir(self.companion.designer.model) if mbd: mbd = mbd[7:] pth = os.path.normpath(os.path.join(mbd, pth)).replace('\\', '/') dir, name = os.path.split(pth) if not dir: dir = '.' return os.path.join(pth, 'Bitmap'), dir, name, 'Bitmap' else: import moduleparse m = moduleparse.is_resource_bitmap.search(src) if m: importName, imageName = m.group('imppath'), m.group('imgname') src = os.path.join(importName, imageName, 'ResourceModule') return (src, importName, imageName, 'ResourceModule') return './Unknown/Unknown', '.', '', 'Unknown' def handleResourceFiles(self, resourceFilename, relResourceFilename, image=''): from Models import Controllers Model, main = Controllers.identifyFile(resourceFilename) for ResourceClass in Controllers.resourceClasses: if issubclass(Model, ResourceClass): break else: return # not a resource module idx, imageName = self.showResourceDlg(resourceFilename, image) if idx is None: return 'FileDlg' if idx == -1: return -1 importName = os.path.splitext(relResourceFilename)[0].replace('\\', '/').replace('/', '.') if os.path.isabs(relResourceFilename): importName = os.path.splitdrive(importName)[1][1:] impNameDlg = wx.TextEntryDialog(self.parent, 'Correct the module ' 'name that must be imported', 'Resource module', importName) try: if impNameDlg.ShowModal() != wx.ID_OK: return importName = impNameDlg.GetValue() # XXX test with imp? finally: impNameDlg.Destroy() else: if relResourceFilename.startswith('../'): while importName.startswith('../'): importName = importName[3:] importName = importName.replace('/', '.') return importName, imageName def getSrcForResPath(self, importName, imageName): if self.onlyIcons: cls = 'Icon' else: cls = 'Bitmap' return '%s.get%s%s()'%(importName, imageName, cls) def showResourceDlg(self, filename, image=''): from Models import ResourceSupport resDlg = ResourceSupport.ResourceSelectDlg(self.parent, self.companion.designer.model.editor, filename, image, self.onlyIcons) try: result = resDlg.ShowModal() if result == wx.ID_CANCEL: return -1, '' if result == wx.ID_YES: return None, None if result == wx.ID_OK: idx = resDlg.resources.selected return idx, resDlg.resources.imageSrcInfo[idx][0] return -1, '' finally: resDlg.Destroy() def assureResourceLoaded(self, importName, imageName): model = self.companion.designer.model if model.assureResourceLoaded(importName, model.resources, specialAttrs=model.specialAttrs): src = self.getSrcForResPath(importName, imageName) value = self.companion.eval(src) bmpPath = os.path.join(importName, imageName, 'ResourceModule') self.companion.registerResourceModule(importName) return src, value, bmpPath else: raise Exception, '%s could not be loaded as a Resource Module'%importName #wx.LogError('%s could not be loaded as a Resource Module'%importName) #return '', None, '' class BitmapConstrPropEdit(IntConstrPropEdit, BitmapPropEditMix): def inspectorEdit(self): self.editorCtrl = ButtonIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) def edit(self, event): model = self.companion.designer.model dummy, dir, name, tpe = self.extractPathFromSrc(self.value) abspth, pth, tpe = self.showImgDlg(dir, name, tpe) if not tpe: return elif tpe == 'ResourceModule': self.value, ctrlVal, bmpPath = self.assureResourceLoaded(abspth, pth) elif abspth: self.value = 'wx.Bitmap(%s, %s)'%(`pth`, tpe) ctrlVal = wx.Bitmap(abspth, self.companion.eval(tpe)) self.persistValue(self.value) self.propWrapper.setValue(ctrlVal, self.companion.index) self.refreshCompCtrl() def getValue(self): if self.editorCtrl: return self.value else: return self.getCtrlValue() class BitmapPropEdit(PropertyEditor, BitmapPropEditMix): def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options = None, names = None): PropertyEditor.__init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width) ## def getStyle(self): ## return ClassPropEdit.getStyle(self) + [esDialog, esReadOnly] def getDisplayValue(self): return '(%s)'%self.srcClass def inspectorEdit(self): self.editorCtrl = ButtonIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) constrs = self.companion.constructor() if constrs.has_key(self.name): constr = self.companion.textConstr.params[constrs[self.name]] else: constr = self.companion.persistedPropVal(self.name, self.propWrapper.getSetterName()) if constr is not None: constr = constr[0] self.bmpPath = self.extractPathFromSrc(constr)[0] def edit(self, event): if self.bmpPath: path, tpe = os.path.split(self.bmpPath) dir, name = os.path.split(path) else: dir, name, tpe = '.', '', 'Bitmap' abspth, pth, tpe = self.showImgDlg(dir, name, tpe) if not tpe or not abspth: return if tpe == 'ResourceModule': self.value, self.bmpPath = self.assureResourceLoaded(abspth, pth)[1:] else: self.value = self.ctrlClass(abspth, self.companion.eval(tpe)) self.bmpPath = os.path.join(pth, 'Bitmap') self.inspectorPost(False) def getValue(self): return self.value def valueAsExpr(self): if self.bmpPath: path, tpe = os.path.split(self.bmpPath) dir, name = os.path.split(path) if tpe == 'Bitmap': # XXX path and name both? if path == self.nullClass: return self.nullClass elif name == self.nullClass: return self.nullClass else: return '%s(%s, %s)'%(self.srcClass, `path`, self.extTypeMap[os.path.splitext(path)[-1].lower()]) elif tpe == 'ResourceModule': return self.getSrcForResPath(dir, name) elif tpe == 'Unknown': return self.nullClass else: raise Exception, 'Unhandled image handling type: %s'%tpe else: return self.nullClass class IconPropEdit(BitmapPropEdit): srcClass = 'wx.Icon' ctrlClass = wx.Icon nullClass = 'wx.NullIcon' onlyIcons = True extTypeMap = {'.ico': 'wx.BITMAP_TYPE_ICO', '.py': 'ResourceModule'} class EnumConstrPropEdit(IntConstrPropEdit): def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options, names): IntConstrPropEdit.__init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options, names) self.names = names def valueToIECValue(self): return self.getValue() def inspectorEdit(self): value = self.getValue() self.editorCtrl = ChoiceIEC(self, value) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.editorCtrl.setValue(value) def getDisplayValue(self): return self.valueToIECValue() def getValues(self): return self.names class ClassConstrPropEdit(ConstrPropEdit): def inspectorEdit(self): val = self.getValue() if self.companion.designer.model.customClasses.has_key(val): self.editorCtrl = ChoiceIEC(self, val) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.editorCtrl.setValue(val) else: self.editorCtrl = BeveledLabelIEC(self, val) self.editorCtrl.createControl(self.parent, self.idx, self.width) def setCtrlValue(self, oldValue, value): #self.companion.checkTriggers(self.name, oldValue, value) self.propWrapper.setValue(value) def getCtrlValue(self): return self.propWrapper.getValue() def getValue(self): if self.editorCtrl: self.value = self.editorCtrl.getValue() else: self.value = self.getCtrlValue() return self.value def getValues(self): custClss = self.companion.designer.model.customClasses MyCls = custClss[self.value] vals = [] for name, Cls in custClss.items(): if MyCls == Cls: vals.append(name) vals.remove(Utils.getWxPyNameForClass(MyCls)) vals.insert(0, Utils.getWxPyNameForClass(MyCls)) return vals ## def getDisplayValue(self): ## dv = EnumConstrPropEdit.getDisplayValue(self) ## print dv ## return dv class BoolConstrPropEdit(EnumConstrPropEdit): def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options, names): EnumConstrPropEdit.__init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options, ['True', 'False']) def inspectorEdit(self): self.editorCtrl = CheckBoxIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.editorCtrl.setValue(self.value) class LCCEdgeConstrPropEdit(EnumConstrPropEdit): def getCtrlValue(self): return self.companion.GetEdge() def getValue(self): if self.editorCtrl: try: if self.editorCtrl.getValue(): self.value = self.editorCtrl.getValue() else: self.value = self.getCtrlValue() except Exception, message: self.value = self.getCtrlValue() else: self.value = self.getCtrlValue() return self.value def setCtrlValue(self, oldValue, value): self.companion.SetEdge(value) def persistValue(self, value): pass def getValues(self): objName = self.companion.__class__.sourceObjName return [self.getCtrlValue()] + \ ['%s.%s'%(objName, ai) for ai in self.companion.availableItems()] class ObjEnumConstrPropEdit(EnumConstrPropEdit): def getValue(self): if self.editorCtrl: try: if self.editorCtrl.getValue(): self.value = self.editorCtrl.getValue() else: self.value = self.getCtrlValue() except Exception, message: self.value = self.getCtrlValue() else: self.value = self.getCtrlValue() return self.value def persistValue(self, value): pass def getObjects(self): return self.companion.designer.getAllObjects().keys() def getValues(self): vals = self.getObjects() try: val = self.getValue() if val == 'self': vals.remove('self') else: vals.remove('self.'+val) except: pass return vals class WinEnumConstrPropEdit(ObjEnumConstrPropEdit): def getObjects(self): return ['None'] + self.companion.designer.getObjectsOfClassWithParent( wx.Window, self.companion.name).keys() def getCtrlValue(self): return self.companion.GetOtherWin() def setCtrlValue(self, oldValue, value): self.companion.SetOtherWin(value) class MenuEnumConstrPropEdit(ObjEnumConstrPropEdit): def getValues(self): return ['wx.Menu()'] + ObjEnumConstrPropEdit.getValues(self) def getObjects(self): menus = self.companion.designer.getObjectsOfClass(wx.Menu).keys() if isinstance(self.companion.control, wx.Menu): menus.remove(Utils.srcRefFromCtrlName(self.companion.name)) return menus def setCtrlValue(self, oldValue, value): self.companion.SetMenu(value) def getCtrlValue(self): return self.companion.GetMenu() ##class ControlEnumConstrPropEdit(ObjEnumConstrPropEdit): #### def getValues(self): #### return ['wxMenu()'] + ObjEnumConstrPropEdit.getValues(self) ## def getObjects(self): ## return self.companion.designer.getObjectsOfClass(wx.Control).keys() ## def setCtrlValue(self, oldValue, value): ## self.companion.SetControl(value) ## def getCtrlValue(self): ## return self.companion.GetControl() class SizerEnumConstrPropEdit(ObjEnumConstrPropEdit): ## def getValues(self): ## return ['wx.Menu()'] + ObjEnumConstrPropEdit.getValues(self) def getObjects(self): return self.companion.designer.getObjectsOfClass(wx.BoxSizer).keys() ## def setCtrlValue(self, oldValue, value): ## self.companion.SetMenu(value) ## def getCtrlValue(self): ## return self.companion.GetMenu() class BaseFlagsConstrPropEdit(ConstrPropEdit): def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getStyle(self): return [esExpandable] def getValue(self): """ For efficiency override the entire getValue""" if self.editorCtrl: try: anInt = self.companion.eval(self.editorCtrl.getValue()) if type(anInt) is IntType: self.value = ' | '.join(map(string.strip, self.editorCtrl.getValue().split('|'))) else: self.value = self.getCtrlValue() except Exception, message: self.value = self.getCtrlValue() print 'invalid constr prop value', message else: self.value = self.getCtrlValue() return self.value class StyleConstrPropEdit(BaseFlagsConstrPropEdit): def getSubCompanion(self): from Companions.Companions import WindowStyleDTC return WindowStyleDTC class FlagsConstrPropEdit(BaseFlagsConstrPropEdit): def getSubCompanion(self): from Companions.Companions import FlagsDTC return FlagsDTC class StrConstrPropEdit(ConstrPropEdit): def valueToIECValue(self): return self.companion.eval(self.value) def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getValue(self): if self.editorCtrl: try: aStr = self.editorCtrl.getValue() if type(aStr) in StringTypes: self.value = `aStr` else: self.value = self.getCtrlValue() except Exception, message: self.value = self.getCtrlValue() print 'invalid constr prop value', message else: self.value = self.getCtrlValue() return self.value ## self.editorCtrl = TextCtrlButtonIEC(self, self.value) ## self.editorCtrl.createControl(self.parent, self.idx, ## self.width, self.OnButton) ## def OnButton(self, event): ## import StringEditDlg ## dlg = StringEditDlg.StringEditDlg(self.parent, self.value) ## try: ## if dlg.ShowModal() == wx.ID_OK: ## filename = dlg.GetPath() ## # Your code ## finally: ## dlg.Destroy() class SizeConstrPropEdit(ConstrPropEdit): def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getValue(self): if self.editorCtrl: try: self.value = self.editorCtrl.getValue() except Exception, message: self.value = self.getCtrlValue() print 'invalid constr prop value', message else: self.value = self.getCtrlValue() return self.value # XXX Check for name conflicts class NameConstrPropEdit(StrConstrPropEdit): def getValue(self): if self.editorCtrl: value = self.editorCtrl.getValue() if type(value) in StringTypes: value = `self.editorCtrl.getValue()` else: value = self.getCtrlValue() if value != self.value: strVal = self.companion.eval(value) if not strVal: message = 'Invalid name for Python object' wx.LogError(message) return self.value for c in strVal: if c not in string.letters+string.digits+'_':#"\'': message = 'Invalid name for Python object' wx.LogError(message) return self.value #raise message if self.companion.designer.objects.has_key(value): wx.LogError('Name already used by another control.') return self.value #raise 'Name already used by another control.' self.value = value else: self.value = self.getCtrlValue() return self.value def getCtrlValue(self): return `self.companion.name` def setCtrlValue(self, oldValue, newValue): self.companion.checkTriggers(self.name, self.companion.eval(oldValue), self.companion.eval(newValue)) def persistValue(self, value): pass class ChoicesConstrPropEdit(ConstrPropEdit): def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getValue(self): if self.editorCtrl: try: aList = self.companion.eval(self.editorCtrl.getValue()) if type(aList) is ListType: self.value = self.editorCtrl.getValue() else: self.value = self.getCtrlValue() except Exception, message: self.value = self.getCtrlValue() print 'invalid constr prop value', message else: self.value = self.getCtrlValue() return self.value class MajorDimensionConstrPropEdit(ConstrPropEdit): def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getValue(self): if self.editorCtrl: try: anInt = self.companion.eval(self.editorCtrl.getValue()) if type(anInt) is IntType: self.value = self.editorCtrl.getValue() else: self.value = self.getCtrlValue() except Exception, message: self.value = self.getCtrlValue() print 'invalid constr prop value', message else: self.value = self.getCtrlValue() return self.value class EventPropEdit(OptionedPropEdit): """ Property editor to handle design time definition of events """ def initFromComponent(self): # unlike other propedit getter setters these are methods not funcs self.value = self.propWrapper.getValue(self.name) def valueToIECValue(self): v = self.value return v def inspectorEdit(self): self.editorCtrl = ChoiceIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.editorCtrl.setValue(self.value) def setCtrlValue(self, oldValue, value): self.propWrapper.setValue(value, self.name) def getDisplayValue(self): return self.valueToIECValue() extraOpts = ['(delete)', '(rename)'] scopeOpts = {'(show all)': 'all', '(show own)': 'own'} def getValues(self): """ Build event list based on currently selected scope for the event """ # XXX Should ideally do this one day: # XXX Show event's of similar types, e.g. mouse events, cmd events. # XXX Also show events from the code not bound to the frame vals = [] showScope = 'own' if self.companion: for evt in self.companion.textEventList: if evt.event_name == self.name: showScope = evt.show_scope if evt.trigger_meth not in self.extraOpts: try: vals.index(evt.trigger_meth) except ValueError: vals.append(evt.trigger_meth) if showScope != 'own': # Add evts from other scopes # XXX Collection items' events aren't handled correctly # XXX designer != CollEditorView for comp, ctrl, prnt in self.companion.designer.objects.values(): if comp != self.companion and showScope == 'all': #or showScope == 'same' and comp.__class__ == self.companion.__class__): for evt in comp.textEventList: if evt.trigger_meth not in self.extraOpts: try: vals.index(evt.trigger_meth) except ValueError: vals.append(evt.trigger_meth) scopeChoices = self.scopeOpts.keys() del scopeChoices[self.scopeOpts.values().index(showScope)] vals.extend(self.extraOpts + scopeChoices) return vals def _repopulateChoice(self, value): self.editorCtrl.repopulate() self.editorCtrl.setValue(value) def getValue(self): """ Return current value, or if a special (*) value is selected, process it, and return previous 'current value' """ if self.editorCtrl: oldVal = defVal = self.value value = self.editorCtrl.getValue() # Event rename if value == '(rename)': if oldVal == '(delete)': for evt in self.companion.textEventList: if evt.trigger_meth == oldVal: defVal = evt.prev_trigger_meth break ted = wx.TextEntryDialog(self.parent, 'Enter a new method name:', 'Rename event method', defVal) try: if ted.ShowModal() == wx.ID_OK: self.value = ted.GetValue() # XXX All references should be renamed !!!! # XXX Add as method on designer for evt in self.companion.textEventList: if evt.trigger_meth == oldVal: if not evt.prev_trigger_meth: evt.prev_trigger_meth = oldVal evt.trigger_meth = self.value break self._repopulateChoice(self.value) finally: ted.Destroy() # Event deletion elif value == '(delete)': for evt in self.companion.textEventList: if evt.trigger_meth == oldVal: if not evt.prev_trigger_meth: evt.prev_trigger_meth = oldVal break self.value = self.editorCtrl.getValue() # Event scope change elif value in self.scopeOpts.keys(): self.value = oldVal for evt in self.companion.textEventList: if evt.event_name == self.name: evt.show_scope = self.scopeOpts[value] self._repopulateChoice(oldVal) break # Normal event selection else: self.value = self.editorCtrl.getValue() return self.value def persistValue(self, value): self.companion.persistEvt(self.name, value) class BITPropEditor(FactoryPropEdit): """ Editors for Built-in Python Types """ def valueToIECValue(self): return `self.value` def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getValue(self): if self.editorCtrl: try: value = self.companion.eval(self.editorCtrl.getValue()) except Exception, mess: wx.LogError('Invalid value: %s' % str(mess)) raise self.value = value return self.value class IntPropEdit(BITPropEditor): def inspectorEdit(self): self.editorCtrl = SpinCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getValue(self): if self.editorCtrl: self.value = self.editorCtrl.getValue() return self.value class StrPropEdit(BITPropEditor): def valueToIECValue(self): return self.value def getValue(self): return FactoryPropEdit.getValue(self) # The following is a work in progress for having a string editor dlg that # also handles gettext formatted strings # # The current problem is that for normal string properties, the property # refers to a string object, not to the source reference, iow _() is not a string ## def inspectorEdit(self): ## self.editorCtrl = TextCtrlButtonIEC(self, self.value) ## self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) ## def edit(self, event): ## import StringPropEditorDlg ## dlg = StringPropEditorDlg.create(self.parent, repr(self.value)) ## try: ## if dlg.ShowModal() == wx.ID_OK: ## self.inspectorPost(False) ## pass ## finally: ## dlg.Destroy() class NamePropEdit(StrPropEdit): def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options, names): StrPropEdit.__init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width) identifier = string.letters+string.digits+'_' def getValue(self): # XXX Currently returning the old value in case of error because # XXX an exception here cannot be gracefully handled yet. # XXX Specifically closing the frame with the focus on the if self.editorCtrl: value = self.editorCtrl.getValue() if value != self.value: if self.companion.designer.objects.has_key(value): wx.LogError('Name already used by another control.') return self.value if not value: message = 'Invalid name for Python object' wx.LogError(message) return self.value for c in value: if c not in self.identifier: message = 'Invalid name for Python object' wx.LogError(message) return self.value self.value = value return self.value class TuplePropEdit(BITPropEditor): pass class BoolPropEdit(OptionedPropEdit): def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options=None, names=None): OptionedPropEdit.__init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, options, names) def valueToIECValue(self): v = self.value if type(v) == IntType: return self.getValues()[v] else: return `v` def inspectorEdit(self): self.editorCtrl = CheckBoxIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.editorCtrl.setValue(self.getValues()[self.value]) def getDisplayValue(self): return self.valueToIECValue() def getValues(self): return ['False', 'True'] def getValue(self): if self.editorCtrl: # trick to convert boolean string to integer v = self.editorCtrl.getValue() self.value = self.getValues().index(self.editorCtrl.getValue()) #self.value = self.companion.eval(self.editorCtrl.getValue()) return self.value class EnumPropEdit(OptionedPropEdit): def valueToIECValue(self): if self.revNames: try: return self.revNames[self.value] except KeyError: return `self.value` else: OptionedPropEdit.getDisplayValue(self) def inspectorEdit(self): self.editorCtrl = ChoiceIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.setValue(self.value) def getDisplayValue(self): return self.valueToIECValue() def getValues(self): vals = self.names.keys() try: name = self.revNames[self.value] except KeyError: name = `self.value` if name not in vals: vals.append(name) # XXX ! vals.sort() return vals def setValue(self, value): self.value = value if self.editorCtrl: try: self.editorCtrl.setValue(self.revNames[value]) except KeyError: self.editorCtrl.setValue(`value`) def getValue(self): if self.editorCtrl: strVal = self.editorCtrl.getValue() try: self.value = self.names[strVal] except KeyError: self.value = self.companion.eval(strVal) return self.value class StringEnumPropEdit(EnumPropEdit): def getDisplayValue(self): return `self.value` # Property editors for classes class ClassPropEdit(FactoryPropEdit): def getDisplayValue(self): return '(%s)'%Utils.getWxPyNameForClass(self.value.__class__) def getStyle(self): return [esExpandable] class ClassLinkPropEdit(OptionedPropEdit): defaults = {'None': None} linkClass = None def getStyle(self): return [] def valueToIECValue(self): return self.getNameForValue(self.value, self.linkClass) def getNameForValue(self, value, LinkClass): for k, v in self.defaults.items(): if value == v: return k objs = self.companion.designer.getObjectsOfClass(LinkClass) for objName in objs.keys(): if objs[objName] and value and objs[objName] == value: return objName return `None` def inspectorEdit(self): self.editorCtrl = ChoiceIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.setValue(self.value) def getDisplayValue(self): return self.valueToIECValue() def getValues(self): defs = self.defaults.keys() defs.sort() return defs + self.companion.designer.getObjectsOfClass(self.linkClass).keys() def setValue(self, value): self.value = value if self.editorCtrl: self.editorCtrl.setValue(self.valueToIECValue()) def getValue(self): if self.editorCtrl: strVal = self.editorCtrl.getValue() if self.defaults.has_key(strVal): self.value = self.defaults[strVal] else: objs = self.companion.designer.getObjectsOfClass(self.linkClass) self.value = objs[strVal] return self.value class WindowClassLinkPropEdit(ClassLinkPropEdit): linkClass = wx.Window class WindowClassLinkWithParentPropEdit(WindowClassLinkPropEdit): def getValues(self): return ['None'] + self.companion.designer.getObjectsOfClassWithParent( self.linkClass, self.companion.name).keys() class StatusBarClassLinkPropEdit(ClassLinkPropEdit): linkClass = wx.StatusBar class ToolBarClassLinkPropEdit(ClassLinkPropEdit): linkClass = wx.ToolBarBase class MenuBarClassLinkPropEdit(ClassLinkPropEdit): linkClass = wx.MenuBar class ImageListClassLinkPropEdit(ClassLinkPropEdit): linkClass = wx.ImageList class ButtonClassLinkPropEdit(ClassLinkPropEdit): linkClass = wx.Button class CursorClassLinkPropEdit(ClassLinkPropEdit): defaults = {'None': wx.NullCursor, 'wx.STANDARD_CURSOR': wx.STANDARD_CURSOR, 'wx.HOURGLASS_CURSOR': wx.HOURGLASS_CURSOR, 'wx.CROSS_CURSOR': wx.CROSS_CURSOR} linkClass = wx.Cursor class ListCtrlImageListClassLinkPropEdit(ImageListClassLinkPropEdit): listTypeMap = {wx.IMAGE_LIST_SMALL : 'wx.IMAGE_LIST_SMALL', wx.IMAGE_LIST_NORMAL: 'wx.IMAGE_LIST_NORMAL'} def valueToIECValue(self): if self.value[0] is None: return `None` objs = self.companion.designer.getObjectsOfClass(self.linkClass) for objName in objs.keys(): if objs[objName] and self.value[0] and objs[objName] == self.value[0]: return objName return `None` def inspectorEdit(self): self.editorCtrl = ChoiceIEC(self, self.valueToIECValue()) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.editorCtrl.setValue(self.valueToIECValue()) def getValue(self): if self.editorCtrl: strVal = self.editorCtrl.getValue() if strVal == `None`: self.value = (None, self.value[1]) else: objs = self.companion.designer.getObjectsOfClass(self.linkClass) self.value = (objs[strVal], self.value[1]) return self.value def valueAsExpr(self): return '%s, %s'%(self.valueToIECValue(), self.listTypeMap[self.value[1]]) class SplitterWindowLinkPropEdit(WindowClassLinkPropEdit): def getValues(self): children = self.companion.designer.getObjectsOfClassWithParent( self.linkClass, self.companion.name).keys() otherWin = self.getOtherWindow() if otherWin: otherWinName = 'self.%s'%otherWin.GetName() if otherWinName in children: children.remove(otherWinName) return ['None'] + children def getOtherWindow(self): return None class SplitterWindow1LinkPropEdit(SplitterWindowLinkPropEdit): def getOtherWindow(self): return self.companion.GetWindow2(None) class SplitterWindow2LinkPropEdit(SplitterWindowLinkPropEdit): def getOtherWindow(self): return self.companion.GetWindow1(None) def getValidSizers(parent, designer, value): # build a list of nested parent sizers sizerParents = [parent] while hasattr(parent, '_sub_sizer'): parent = parent._sub_sizer sizerParents.append(parent) sizers = designer.getObjectsOfClass(wx.Sizer) # remove invalid sizers from the list for n, s in sizers.items(): if s in sizerParents or \ hasattr(s, '_sub_sizer') or hasattr(s, '_has_control'): del sizers[n] sizerNames = sizers.keys() sizerNames.sort() res = ['None'] + sizerNames if value != 'None': res.insert(1, value) return res class SizerEnumConstrPropEdit(ObjEnumConstrPropEdit): def getObjects(self): return getValidSizers(self.companion.parentCompanion.control, self.companion.designer, self.value) def getCtrlValue(self): return self.companion.GetSizer() def setCtrlValue(self, oldValue, value): self.companion.SetSizer(value) class SizerClassLinkPropEdit(ClassLinkPropEdit): linkClass = wx.Sizer def getValues(self): if self.value is None: value = 'None' else: value = self.getNameForValue(self.value, self.linkClass) return getValidSizers(self.companion.control, self.companion.designer, value) class ColPropEdit(ClassPropEdit): def getStyle(self): return [esExpandable] def getSubCompanion(self): from Companions.Companions import ColourDTC return ColourDTC def inspectorEdit(self): self.editorCtrl = ButtonIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) def edit(self, event): data = wx.ColourData() data.SetColour(self.value) data.SetChooseFull(True) dlg = wx.ColourDialog(self.parent, data) try: if dlg.ShowModal() == wx.ID_OK: self.value = dlg.GetColourData().GetColour() self.inspectorPost(False) self.editorCtrl.setValue(self.value) #self.propWrapper.setValue(self.value) #self.obj.Refresh() finally: dlg.Destroy() def getValue(self): return self.value#wx.Colour(self.value.Red(), self.value.Green(), self.value.Blue()) def valueAsExpr(self): return 'wx.Colour(%d, %d, %d)'%(self.value.Red(), self.value.Green(), self.value.Blue()) class SizePropEdit(ClassPropEdit): def getDisplayValue(self): return self.valueToIECValue() def valueToIECValue(self): return `self.value` def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, self.valueToIECValue()) self.editorCtrl.createControl(self.parent, self.valueToIECValue(), self.idx, self.width) def getValue(self): if self.editorCtrl: try: tuplePos = self.companion.eval(self.editorCtrl.getValue()) except Exception, mess: Utils.ShowErrorMessage(self.parent, 'Invalid value', mess) raise self.value = wx.Size(tuplePos[0], tuplePos[1]) return self.value def valueAsExpr(self): return 'wx.Size(%d, %d)'%(self.value.x, self.value.y) def getSubCompanion(self): from Companions.Companions import SizeDTC return SizeDTC class PosPropEdit(ClassPropEdit): def getDisplayValue(self): return self.valueToIECValue() def valueToIECValue(self): return `self.value` def inspectorEdit(self): self.editorCtrl = TextCtrlIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.value, self.idx, self.width) def getValue(self): if self.editorCtrl: try: tuplePos = self.companion.eval(self.editorCtrl.getValue()) except Exception, mess: Utils.ShowErrorMessage(self.parent, 'Invalid value', mess) raise self.value = wx.Point(tuplePos[0], tuplePos[1]) return self.value def valueAsExpr(self): return 'wx.Point(%d, %d)'%(self.value.x, self.value.y) def getSubCompanion(self): from Companions.Companions import PosDTC return PosDTC class FontPropEdit(ClassPropEdit): # def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, _1=None , _2=None): # ClassPropEdit.__init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width) def getStyle(self): return ClassPropEdit.getStyle(self) + [esDialog, esReadOnly, esRecreateProp] def getSubCompanion(self): from Companions.Companions import FontDTC return FontDTC def inspectorEdit(self): self.editorCtrl = ButtonIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) def getValue(self): return self.value def edit(self, event): data = wx.FontData() dlg = wx.FontDialog(self.parent, data) dlg.GetFontData().SetInitialFont(self.value) try: if dlg.ShowModal() == wx.ID_OK: self.value = dlg.GetFontData().GetChosenFont() self.inspectorPost(False) finally: dlg.Destroy() def valueAsExpr(self): fnt = self.value return fontAsExpr(fnt) def fontAsExpr(fnt): fontFamily = Enumerations.reverseDict(Enumerations.fontFamilyNames) fontStyle = Enumerations.reverseDict(Enumerations.fontStyleNames) fontWeight = Enumerations.reverseDict(Enumerations.fontWeightNames) family = fontFamily.get(fnt.GetFamily(), fnt.GetFamily()) style = fontStyle.get(fnt.GetStyle(), fnt.GetStyle()) weight = fontWeight.get(fnt.GetWeight(), fnt.GetWeight()) return 'wx.Font(%d, %s, %s, %s, %s, %s)'%( fnt.GetPointSize(), family, style, weight, fnt.GetUnderlined() and 'True' or 'False', `fnt.GetFaceName()`) class AnchorPropEdit(OptionedPropEdit): def getStyle(self): return [esExpandable] def getSubCompanion(self): from Companions.Companions import AnchorsDTC return AnchorsDTC def inspectorEdit(self): self.editorCtrl = ButtonIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) def edit(self, event): if self.expanded: wx.MessageBox('Anchors can not be reset while the property is expanded', 'Anchors') else: if self.companion.anchorSettings: message = 'Remove anchors?' else: message = 'Define default Anchors?' dlg = wx.MessageDialog(self.parent, message, 'Anchors', wx.YES_NO | wx.ICON_QUESTION) try: if dlg.ShowModal() == wx.ID_YES: if self.companion.anchorSettings: self.companion.removeAnchors() self.propWrapper.setValue(self.getValue()) else: self.companion.defaultAnchors() self.inspectorPost(False) finally: dlg.Destroy() def getValue(self): return self.companion.GetAnchors(self.companion) def getDisplayValue(self): if self.companion.anchorSettings: l, t, r, b = self.companion.anchorSettings set = [] if l: set.append('left') if t: set.append('top') if r: set.append('right') if b: set.append('bottom') return '('+', '.join(set)+')' else: return 'None' def valueAsExpr(self): if self.companion.anchorSettings: l, t, r, b = self.companion.anchorSettings return 'LayoutAnchors(self.%s, %s, %s, %s, %s)'%(self.companion.name, l and 'True' or 'False', t and 'True' or 'False', r and 'True' or 'False', b and 'True' or 'False') else: return 'None' class SashVisiblePropEdit(BoolPropEdit): sashEdgeMap = {wx.SASH_LEFT: 'wx.SASH_LEFT', wx.SASH_TOP: 'wx.SASH_TOP', wx.SASH_RIGHT: 'wx.SASH_RIGHT', wx.SASH_BOTTOM: 'wx.SASH_BOTTOM'} def valueToIECValue(self): v = self.value[1] if type(v) == IntType: return self.getValues()[v] else: return `v` def inspectorEdit(self): self.editorCtrl = CheckBoxIEC(self, self.value[1]) self.editorCtrl.createControl(self.parent, self.idx, self.width) self.editorCtrl.setValue(self.getValues()[self.value[1]]) ## def getDisplayValue(self): ## return self.valueToIECValue() ## def getValues(self): ## return ['False', 'True'] def getValue(self): if self.editorCtrl: # trick to convert boolean string to integer v = self.editorCtrl.getValue() self.value = (self.value[0], self.getValues().index(self.editorCtrl.getValue())) return self.value def valueAsExpr(self): return '%s, %s'%(self.sashEdgeMap[self.value[0]], self.value[1] and 'True' or 'False') class CollectionPropEdit(PropertyEditor): """ Class associated with a design time identified type, it manages the behaviour of a NameValue in the Inspector """ def __init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width, names, options): PropertyEditor.__init__(self, name, parent, companion, rootCompanion, propWrapper, idx, width) def inspectorEdit(self): self.editorCtrl = ButtonIEC(self, self.value) self.editorCtrl.createControl(self.parent, self.idx, self.width, self.edit) def inspectorPost(self, closeEditor = True): """ Code persistance taken over by companion because collection transactions live longer than properties """ if self.editorCtrl and closeEditor: self.editorCtrl.destroyControl() self.editorCtrl = None self.refreshCompCtrl() def getDisplayValue(self): return '(%s)'%self.name def valueAsExpr(self): return self.getDisplayValue() def edit(self, event): self.companion.designer.showCollectionEditor(\ self.companion.name, self.name) class ListColumnsColPropEdit(CollectionPropEdit): pass class AcceleratorEntriesColPropEdit(CollectionPropEdit): pass class MenuBarColPropEdit(CollectionPropEdit): pass class MenuColPropEdit(CollectionPropEdit): pass class ImagesColPropEdit(CollectionPropEdit): pass class NotebookPagesColPropEdit(CollectionPropEdit): pass # Property editor registration def registerEditors(reg): for theType, theClass, editors in registeredTypes: if theType == 'Type': reg.registerTypes(theClass, editors) elif theType == 'Class': reg.registerClasses(theClass, editors) registeredTypes = [ ('Type', IntType, [IntPropEdit]), ('Type', StringType, [StrPropEdit]), ('Type', UnicodeType, [StrPropEdit]), ('Type', TupleType, [TuplePropEdit]), ('Class', wx.Size, [SizePropEdit]), ('Class', wx.Point, [PosPropEdit]), ('Class', wx.Font, [FontPropEdit]), ('Class', wx.Colour, [ColPropEdit]), ('Class', wx.Bitmap, [BitmapPropEdit]), ('Class', wx.Icon, [IconPropEdit]), ] try: registeredTypes.append( ('Type', BooleanType, [BoolPropEdit]) ) except NameError: # 2.2 pass