laurent@738: laurent@738: import os laurent@738: import types laurent@738: laurent@738: import wx laurent@738: import wx.lib.buttons laurent@738: laurent@738: from controls import EditorPanel laurent@738: laurent@738: from PLCOpenEditor import TITLE, FILEMENU, PROJECTTREE, PAGETITLES laurent@738: laurent@738: from util import opjimg laurent@738: from util.TextCtrlAutoComplete import TextCtrlAutoComplete laurent@738: from util.BrowseValuesLibraryDialog import BrowseValuesLibraryDialog laurent@738: laurent@738: if wx.Platform == '__WXMSW__': laurent@738: faces = { 'times': 'Times New Roman', laurent@738: 'mono' : 'Courier New', laurent@738: 'helv' : 'Arial', laurent@738: 'other': 'Comic Sans MS', laurent@738: 'size' : 16, laurent@738: } laurent@738: else: laurent@738: faces = { 'times': 'Times', laurent@738: 'mono' : 'Courier', laurent@738: 'helv' : 'Helvetica', laurent@738: 'other': 'new century schoolbook', laurent@738: 'size' : 18, laurent@738: } laurent@738: laurent@738: SCROLLBAR_UNIT = 10 laurent@738: WINDOW_COLOUR = wx.Colour(240,240,240) laurent@738: laurent@738: CWD = os.path.split(os.path.realpath(__file__))[0] laurent@738: laurent@738: def Bpath(*args): laurent@738: return os.path.join(CWD,*args) laurent@738: laurent@738: # Some helpers to tweak GenBitmapTextButtons laurent@738: # TODO: declare customized classes instead. laurent@738: gen_mini_GetBackgroundBrush = lambda obj:lambda dc: wx.Brush(obj.GetParent().GetBackgroundColour(), wx.SOLID) laurent@738: gen_textbutton_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenButton._GetLabelSize(obj)[:-1] + (False,)) laurent@738: laurent@738: def make_genbitmaptogglebutton_flat(button): laurent@738: button.GetBackgroundBrush = gen_mini_GetBackgroundBrush(button) laurent@738: button.labelDelta = 0 laurent@738: button.SetBezelWidth(0) laurent@738: button.SetUseFocusIndicator(False) laurent@738: laurent@738: # Patch wx.lib.imageutils so that gray is supported on alpha images laurent@738: import wx.lib.imageutils laurent@738: from wx.lib.imageutils import grayOut as old_grayOut laurent@738: def grayOut(anImage): laurent@738: if anImage.HasAlpha(): laurent@738: AlphaData = anImage.GetAlphaData() laurent@738: else : laurent@738: AlphaData = None laurent@738: laurent@738: old_grayOut(anImage) laurent@738: laurent@738: if AlphaData is not None: laurent@738: anImage.SetAlphaData(AlphaData) laurent@738: laurent@738: wx.lib.imageutils.grayOut = grayOut laurent@738: laurent@738: class GenBitmapTextButton(wx.lib.buttons.GenBitmapTextButton): laurent@738: def _GetLabelSize(self): laurent@738: """ used internally """ laurent@738: w, h = self.GetTextExtent(self.GetLabel()) laurent@738: if not self.bmpLabel: laurent@738: return w, h, False # if there isn't a bitmap use the size of the text laurent@738: laurent@738: w_bmp = self.bmpLabel.GetWidth()+2 laurent@738: h_bmp = self.bmpLabel.GetHeight()+2 laurent@738: height = h + h_bmp laurent@738: if w_bmp > w: laurent@738: width = w_bmp laurent@738: else: laurent@738: width = w laurent@738: return width, height, False laurent@738: laurent@738: def DrawLabel(self, dc, width, height, dw=0, dy=0): laurent@738: bmp = self.bmpLabel laurent@738: if bmp != None: # if the bitmap is used laurent@738: if self.bmpDisabled and not self.IsEnabled(): laurent@738: bmp = self.bmpDisabled laurent@738: if self.bmpFocus and self.hasFocus: laurent@738: bmp = self.bmpFocus laurent@738: if self.bmpSelected and not self.up: laurent@738: bmp = self.bmpSelected laurent@738: bw,bh = bmp.GetWidth(), bmp.GetHeight() laurent@738: if not self.up: laurent@738: dw = dy = self.labelDelta laurent@738: hasMask = bmp.GetMask() != None laurent@738: else: laurent@738: bw = bh = 0 # no bitmap -> size is zero laurent@738: laurent@738: dc.SetFont(self.GetFont()) laurent@738: if self.IsEnabled(): laurent@738: dc.SetTextForeground(self.GetForegroundColour()) laurent@738: else: laurent@738: dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) laurent@738: laurent@738: label = self.GetLabel() laurent@738: tw, th = dc.GetTextExtent(label) # size of text laurent@738: if not self.up: laurent@738: dw = dy = self.labelDelta laurent@738: laurent@738: pos_x = (width-bw)/2+dw # adjust for bitmap and text to centre laurent@738: pos_y = (height-bh-th)/2+dy laurent@738: if bmp !=None: laurent@738: dc.DrawBitmap(bmp, pos_x, pos_y, hasMask) # draw bitmap if available laurent@738: pos_x = (width-tw)/2+dw # adjust for bitmap and text to centre laurent@738: pos_y += bh + 2 laurent@738: laurent@738: dc.DrawText(label, pos_x, pos_y) # draw the text laurent@738: laurent@738: laurent@738: class GenStaticBitmap(wx.lib.statbmp.GenStaticBitmap): laurent@738: """ Customized GenStaticBitmap, fix transparency redraw bug on wx2.8/win32, laurent@738: and accept image name as __init__ parameter, fail silently if file do not exist""" laurent@738: def __init__(self, parent, ID, bitmapname, laurent@738: pos = wx.DefaultPosition, size = wx.DefaultSize, laurent@738: style = 0, laurent@738: name = "genstatbmp"): laurent@738: laurent@738: bitmappath = Bpath( "images", bitmapname) laurent@738: if os.path.isfile(bitmappath): laurent@738: bitmap = wx.Bitmap(bitmappath) laurent@738: else: laurent@738: bitmap = None laurent@738: wx.lib.statbmp.GenStaticBitmap.__init__(self, parent, ID, bitmap, laurent@738: pos, size, laurent@738: style, laurent@738: name) laurent@738: laurent@738: def OnPaint(self, event): laurent@738: dc = wx.PaintDC(self) laurent@738: colour = self.GetParent().GetBackgroundColour() laurent@738: dc.SetPen(wx.Pen(colour)) laurent@738: dc.SetBrush(wx.Brush(colour )) laurent@738: dc.DrawRectangle(0, 0, *dc.GetSizeTuple()) laurent@738: if self._bitmap: laurent@738: dc.DrawBitmap(self._bitmap, 0, 0, True) laurent@738: laurent@738: class ConfTreeNodeEditor(EditorPanel): laurent@738: laurent@738: HAS_BASE_PARAMS = True laurent@738: laurent@738: def _init_ConfNodeEditor(self, prnt): laurent@738: self.ConfNodeEditor = None laurent@738: laurent@738: def _init_Editor(self, prnt): laurent@738: self.Editor = wx.SplitterWindow(id=self.ID, name='EditorSplitter', parent=prnt, laurent@738: size=wx.Size(0, 0), style=wx.SUNKEN_BORDER|wx.SP_3D) laurent@738: self.SetNeedUpdating(True) laurent@738: self.SetMinimumPaneSize(1) laurent@738: laurent@738: self.ParamsEditor = wx.ScrolledWindow(self.Editor, -1, size=wx.Size(-1, -1), laurent@738: style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL) laurent@738: self.ParamsEditor.SetBackgroundColour(WINDOW_COLOUR) laurent@738: self.ParamsEditor.Bind(wx.EVT_SIZE, self.OnWindowResize) laurent@738: self.ParamsEditor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel) laurent@738: laurent@738: # Variable allowing disabling of ParamsEditor scroll when Popup shown laurent@738: self.ScrollingEnabled = True laurent@738: laurent@738: self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) laurent@738: self.ParamsEditorSizer.AddGrowableCol(0) laurent@738: self.ParamsEditorSizer.AddGrowableRow(1) laurent@738: laurent@738: self.ParamsEditor.SetSizer(self.ParamsEditorSizer) laurent@738: laurent@738: baseparamseditor_sizer = wx.BoxSizer(wx.HORIZONTAL) laurent@738: self.ParamsEditorSizer.AddSizer(baseparamseditor_sizer, 0, border=5, laurent@738: flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP) laurent@738: laurent@738: self.FullIECChannel = wx.StaticText(self.ParamsEditor, -1) laurent@738: self.FullIECChannel.SetFont( laurent@738: wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, laurent@738: wx.BOLD, faceName = faces["helv"])) laurent@738: baseparamseditor_sizer.AddWindow(self.FullIECChannel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL) laurent@738: laurent@738: updownsizer = wx.BoxSizer(wx.VERTICAL) laurent@738: baseparamseditor_sizer.AddSizer(updownsizer, 0, border=5, laurent@738: flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL) laurent@738: laurent@738: ieccdownbutton_id = wx.NewId() laurent@738: self.IECCDownButton = wx.lib.buttons.GenBitmapButton( laurent@738: id=ieccdownbutton_id, bitmap=wx.Bitmap(opjimg('IECCDown')), laurent@738: name='IECDownButton', parent=self.ParamsEditor, pos=wx.Point(0, 0), laurent@738: size=wx.Size(16, 16), style=wx.NO_BORDER) laurent@738: self.IECCDownButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(-1), laurent@738: id=ieccdownbutton_id) laurent@738: updownsizer.AddWindow(self.IECCDownButton, 0, border=0, flag=wx.ALIGN_LEFT) laurent@738: laurent@738: ieccupbutton_id = wx.NewId() laurent@738: self.IECCUpButton = wx.lib.buttons.GenBitmapTextButton( laurent@738: id=ieccupbutton_id, bitmap=wx.Bitmap(opjimg('IECCUp')), laurent@738: name='IECUpButton', parent=self.ParamsEditor, pos=wx.Point(0, 0), laurent@738: size=wx.Size(16, 16), style=wx.NO_BORDER) laurent@738: self.IECCUpButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(1), laurent@738: id=ieccupbutton_id) laurent@738: updownsizer.AddWindow(self.IECCUpButton, 0, border=0, flag=wx.ALIGN_LEFT) laurent@738: laurent@738: self.RefreshIECChannelControlsState() laurent@738: laurent@738: confnodename_id = wx.NewId() laurent@738: self.ConfNodeName = wx.TextCtrl( laurent@738: self.ParamsEditor, confnodename_id, laurent@738: size=wx.Size(150, 25), style=wx.NO_BORDER) laurent@738: self.ConfNodeName.SetFont( laurent@738: wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, laurent@738: wx.BOLD, faceName = faces["helv"])) laurent@738: self.ConfNodeName.ChangeValue(self.Controler.MandatoryParams[1].getName()) laurent@738: self.ConfNodeName.Bind(wx.EVT_TEXT, laurent@738: self.GetTextCtrlCallBackFunction(self.ConfNodeName, "BaseParams.Name"), laurent@738: id=confnodename_id) laurent@738: baseparamseditor_sizer.AddWindow(self.ConfNodeName, 0, border=5, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) laurent@738: laurent@738: buttons_sizer = self.GenerateMethodButtonSizer() laurent@738: baseparamseditor_sizer.AddSizer(buttons_sizer, 0, border=0, flag=wx.ALIGN_CENTER) laurent@738: laurent@738: self.ConfNodeParamsSizer = wx.BoxSizer(wx.VERTICAL) laurent@738: self.ParamsEditorSizer.AddSizer(self.ConfNodeParamsSizer, 0, border=5, laurent@738: flag=wx.LEFT|wx.RIGHT|wx.BOTTOM) laurent@738: laurent@738: self.RefreshConfNodeParamsSizer() laurent@738: laurent@738: self._init_ConfNodeEditor(self.Editor) laurent@738: laurent@738: if self.ConfNodeEditor is not None: laurent@738: min_size = self.ParamsEditorSizer.GetMinSize() laurent@738: self.Editor.SplitHorizontally(self.ParamsEditor, laurent@738: self.ConfNodeEditor, laurent@738: min(min_size.height, 200)) laurent@738: else: laurent@738: self.Editor.Initialize(self.ParamsEditor) laurent@738: laurent@738: def __init__(self, parent, tagname, controler, window): laurent@738: EditorPanel.__init__(self, parent, tagname, window, controler) laurent@738: laurent@738: self.SetIcon(wx.Bitmap(self.Controler.GetIconPath(), wx.BITMAP_TYPE_PNG)) laurent@738: laurent@738: def __del__(self): laurent@738: self.Controler.OnCloseEditor(self) laurent@738: laurent@738: def GetTagName(self): laurent@738: return self.Controler.CTNFullName() laurent@738: laurent@738: def GetTitle(self): laurent@738: fullname = self.Controler.CTNFullName() laurent@738: if self.Controler.CTNTestModified(): laurent@738: return "~%s~" % fullname laurent@738: return fullname laurent@738: laurent@738: def HasNoModel(self): laurent@738: return False laurent@738: laurent@738: def EnableScrolling(self, enable): laurent@738: self.ScrollingEnabled = enable laurent@738: laurent@738: def RefreshIECChannelControlsState(self): laurent@738: self.FullIECChannel.SetLabel(self.Controler.GetFullIEC_Channel()) laurent@738: self.IECCDownButton.Enable(self.Controler.BaseParams.getIEC_Channel() > 0) laurent@738: laurent@738: def RefreshConfNodeParamsSizer(self): laurent@738: self.Freeze() laurent@738: self.ConfNodeParamsSizer.Clear(True) laurent@738: laurent@738: confnode_infos = self.Controler.GetParamsAttributes() laurent@738: if len(confnode_infos) > 0: laurent@738: self.GenerateSizerElements(self.ConfNodeParamsSizer, confnode_infos, None, False) laurent@738: laurent@738: self.ParamsEditorSizer.Layout() laurent@738: self.Thaw() laurent@738: laurent@738: def GenerateMethodButtonSizer(self): laurent@738: normal_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"]) laurent@738: mouseover_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, underline=True, faceName = faces["helv"]) laurent@738: laurent@738: msizer = wx.BoxSizer(wx.HORIZONTAL) laurent@738: laurent@738: for confnode_method in self.Controler.ConfNodeMethods: laurent@738: if "method" in confnode_method and confnode_method.get("shown",True): laurent@738: id = wx.NewId() laurent@738: label = confnode_method["name"] laurent@738: button = GenBitmapTextButton(id=id, parent=self.ParamsEditor, laurent@738: bitmap=wx.Bitmap(Bpath("images", "%s.png"%confnode_method.get("bitmap", "Unknown"))), label=label, laurent@738: name=label, pos=wx.DefaultPosition, style=wx.NO_BORDER) laurent@738: button.SetFont(normal_bt_font) laurent@738: button.SetToolTipString(confnode_method["tooltip"]) laurent@738: button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(confnode_method["method"]), id=id) laurent@738: # a fancy underline on mouseover laurent@738: def setFontStyle(b, s): laurent@738: def fn(event): laurent@738: b.SetFont(s) laurent@738: b.Refresh() laurent@738: event.Skip() laurent@738: return fn laurent@738: button.Bind(wx.EVT_ENTER_WINDOW, setFontStyle(button, mouseover_bt_font)) laurent@738: button.Bind(wx.EVT_LEAVE_WINDOW, setFontStyle(button, normal_bt_font)) laurent@738: #hack to force size to mini laurent@738: if not confnode_method.get("enabled",True): laurent@738: button.Disable() laurent@738: msizer.AddWindow(button, 0, border=0, flag=wx.ALIGN_CENTER) laurent@738: return msizer laurent@738: laurent@738: def GenerateSizerElements(self, sizer, elements, path, clean = True): laurent@738: if clean: laurent@738: sizer.Clear(True) laurent@738: first = True laurent@738: for element_infos in elements: laurent@738: if path: laurent@738: element_path = "%s.%s"%(path, element_infos["name"]) laurent@738: else: laurent@738: element_path = element_infos["name"] laurent@738: if element_infos["type"] == "element": laurent@738: label = element_infos["name"] laurent@738: staticbox = wx.StaticBox(id=-1, label=_(label), laurent@738: name='%s_staticbox'%element_infos["name"], parent=self.ParamsEditor, laurent@738: pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0) laurent@738: staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) laurent@738: if first: laurent@738: sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW|wx.TOP) laurent@738: else: laurent@738: sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW) laurent@738: self.GenerateSizerElements(staticboxsizer, element_infos["children"], element_path) laurent@738: else: laurent@738: boxsizer = wx.FlexGridSizer(cols=3, rows=1) laurent@738: boxsizer.AddGrowableCol(1) laurent@738: if first: laurent@738: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) laurent@738: else: laurent@738: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) laurent@738: staticbitmap = GenStaticBitmap(ID=-1, bitmapname="%s.png"%element_infos["name"], laurent@738: name="%s_bitmap"%element_infos["name"], parent=self.ParamsEditor, laurent@738: pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) laurent@738: boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) laurent@738: label = element_infos["name"] laurent@738: statictext = wx.StaticText(id=-1, label="%s:"%_(label), laurent@738: name="%s_label"%element_infos["name"], parent=self.ParamsEditor, laurent@738: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@738: boxsizer.AddWindow(statictext, 0, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT) laurent@738: id = wx.NewId() laurent@738: if isinstance(element_infos["type"], types.ListType): laurent@738: if isinstance(element_infos["value"], types.TupleType): laurent@738: browse_boxsizer = wx.BoxSizer(wx.HORIZONTAL) laurent@738: boxsizer.AddSizer(browse_boxsizer, 0, border=0, flag=0) laurent@738: laurent@738: textctrl = wx.TextCtrl(id=id, name=element_infos["name"], parent=self.ParamsEditor, laurent@738: pos=wx.Point(0, 0), size=wx.Size(275, 25), style=wx.TE_READONLY) laurent@738: if element_infos["value"] is not None: laurent@738: textctrl.SetValue(element_infos["value"][0]) laurent@738: value_infos = element_infos["value"][1] laurent@738: else: laurent@738: value_infos = None laurent@738: browse_boxsizer.AddWindow(textctrl, 0, border=0, flag=0) laurent@738: button_id = wx.NewId() laurent@738: button = wx.Button(id=button_id, name="browse_%s" % element_infos["name"], parent=self.ParamsEditor, laurent@738: label="...", pos=wx.Point(0, 0), size=wx.Size(25, 25)) laurent@738: browse_boxsizer.AddWindow(button, 0, border=0, flag=0) laurent@738: button.Bind(wx.EVT_BUTTON, laurent@738: self.GetBrowseCallBackFunction(element_infos["name"], textctrl, element_infos["type"], laurent@738: value_infos, element_path), laurent@738: id=button_id) laurent@738: else: laurent@738: combobox = wx.ComboBox(id=id, name=element_infos["name"], parent=self.ParamsEditor, laurent@738: pos=wx.Point(0, 0), size=wx.Size(300, 28), style=wx.CB_READONLY) laurent@738: boxsizer.AddWindow(combobox, 0, border=0, flag=0) laurent@738: if element_infos["use"] == "optional": laurent@738: combobox.Append("") laurent@738: if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], types.TupleType): laurent@738: for choice, xsdclass in element_infos["type"]: laurent@738: combobox.Append(choice) laurent@738: name = element_infos["name"] laurent@738: value = element_infos["value"] laurent@738: staticbox = wx.StaticBox(id=-1, label="%s - %s"%(_(name), _(value)), laurent@738: name='%s_staticbox'%element_infos["name"], parent=self.ParamsEditor, laurent@738: pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0) laurent@738: staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) laurent@738: sizer.AddSizer(staticboxsizer, 0, border=5, flag=wx.GROW|wx.BOTTOM) laurent@738: self.GenerateSizerElements(staticboxsizer, element_infos["children"], element_path) laurent@738: callback = self.GetChoiceContentCallBackFunction(combobox, staticboxsizer, element_path) laurent@738: else: laurent@738: for choice in element_infos["type"]: laurent@738: combobox.Append(choice) laurent@738: callback = self.GetChoiceCallBackFunction(combobox, element_path) laurent@738: if element_infos["value"] is None: laurent@738: combobox.SetStringSelection("") laurent@738: else: laurent@738: combobox.SetStringSelection(element_infos["value"]) laurent@738: combobox.Bind(wx.EVT_COMBOBOX, callback, id=id) laurent@738: elif isinstance(element_infos["type"], types.DictType): laurent@738: scmin = -(2**31) laurent@738: scmax = 2**31-1 laurent@738: if "min" in element_infos["type"]: laurent@738: scmin = element_infos["type"]["min"] laurent@738: if "max" in element_infos["type"]: laurent@738: scmax = element_infos["type"]["max"] laurent@738: spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=self.ParamsEditor, laurent@738: pos=wx.Point(0, 0), size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) laurent@738: spinctrl.SetRange(scmin,scmax) laurent@738: boxsizer.AddWindow(spinctrl, 0, border=0, flag=0) laurent@738: if element_infos["value"] is not None: laurent@738: spinctrl.SetValue(element_infos["value"]) laurent@738: spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, element_path), id=id) laurent@738: else: laurent@738: if element_infos["type"] == "boolean": laurent@738: checkbox = wx.CheckBox(id=id, name=element_infos["name"], parent=self.ParamsEditor, laurent@738: pos=wx.Point(0, 0), size=wx.Size(17, 25), style=0) laurent@738: boxsizer.AddWindow(checkbox, 0, border=0, flag=0) laurent@738: if element_infos["value"] is not None: laurent@738: checkbox.SetValue(element_infos["value"]) laurent@738: checkbox.Bind(wx.EVT_CHECKBOX, self.GetCheckBoxCallBackFunction(checkbox, element_path), id=id) laurent@738: elif element_infos["type"] in ["unsignedLong", "long","integer"]: laurent@738: if element_infos["type"].startswith("unsigned"): laurent@738: scmin = 0 laurent@738: else: laurent@738: scmin = -(2**31) laurent@738: scmax = 2**31-1 laurent@738: spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=self.ParamsEditor, laurent@738: pos=wx.Point(0, 0), size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) laurent@738: spinctrl.SetRange(scmin, scmax) laurent@738: boxsizer.AddWindow(spinctrl, 0, border=0, flag=0) laurent@738: if element_infos["value"] is not None: laurent@738: spinctrl.SetValue(element_infos["value"]) laurent@738: spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, element_path), id=id) laurent@738: else: laurent@738: choices = self.ParentWindow.GetConfigEntry(element_path, [""]) laurent@738: textctrl = TextCtrlAutoComplete(id=id, laurent@738: name=element_infos["name"], laurent@738: parent=self.ParamsEditor, laurent@738: appframe=self, laurent@738: choices=choices, laurent@738: element_path=element_path, laurent@738: pos=wx.Point(0, 0), laurent@738: size=wx.Size(300, 25), laurent@738: style=0) laurent@738: laurent@738: boxsizer.AddWindow(textctrl, 0, border=0, flag=0) laurent@738: if element_infos["value"] is not None: laurent@738: textctrl.ChangeValue(str(element_infos["value"])) laurent@738: textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, element_path)) laurent@738: first = False laurent@738: laurent@738: laurent@738: def GetItemChannelChangedFunction(self, dir): laurent@738: def OnConfNodeTreeItemChannelChanged(event): laurent@738: confnode_IECChannel = self.Controler.BaseParams.getIEC_Channel() laurent@738: res = self.SetConfNodeParamsAttribute("BaseParams.IEC_Channel", confnode_IECChannel + dir) laurent@738: wx.CallAfter(self.RefreshIECChannelControlsState) laurent@738: wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE) laurent@738: wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName()) laurent@738: event.Skip() laurent@738: return OnConfNodeTreeItemChannelChanged laurent@738: laurent@738: def SetConfNodeParamsAttribute(self, *args, **kwargs): laurent@738: res, StructChanged = self.Controler.SetParamsAttribute(*args, **kwargs) laurent@738: if StructChanged: laurent@738: wx.CallAfter(self.RefreshConfNodeParamsSizer) laurent@738: wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU) laurent@738: return res laurent@738: laurent@738: def GetButtonCallBackFunction(self, method): laurent@738: """ Generate the callbackfunc for a given confnode method""" laurent@738: def OnButtonClick(event): laurent@738: # Disable button to prevent re-entrant call laurent@738: event.GetEventObject().Disable() laurent@738: # Call laurent@738: getattr(self.Controler,method)() laurent@738: # Re-enable button laurent@738: event.GetEventObject().Enable() laurent@738: laurent@738: event.Skip() laurent@738: return OnButtonClick laurent@738: laurent@738: def GetChoiceCallBackFunction(self, choicectrl, path): laurent@738: def OnChoiceChanged(event): laurent@738: res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection()) laurent@738: choicectrl.SetStringSelection(res) laurent@738: event.Skip() laurent@738: return OnChoiceChanged laurent@738: laurent@738: def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, path): laurent@738: def OnChoiceContentChanged(event): laurent@738: res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection()) laurent@738: event.Skip() laurent@738: return OnChoiceContentChanged laurent@738: laurent@738: def GetTextCtrlCallBackFunction(self, textctrl, path): laurent@738: def OnTextCtrlChanged(event): laurent@738: res = self.SetConfNodeParamsAttribute(path, textctrl.GetValue()) laurent@738: if res != textctrl.GetValue(): laurent@738: textctrl.ChangeValue(res) laurent@738: if textctrl == self.ConfNodeName: laurent@738: wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE, PAGETITLES) laurent@738: wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName()) laurent@738: event.Skip() laurent@738: return OnTextCtrlChanged laurent@738: laurent@738: def GetCheckBoxCallBackFunction(self, chkbx, path): laurent@738: def OnCheckBoxChanged(event): laurent@738: res = self.SetConfNodeParamsAttribute(path, chkbx.IsChecked()) laurent@738: chkbx.SetValue(res) laurent@738: event.Skip() laurent@738: return OnCheckBoxChanged laurent@738: laurent@738: def GetBrowseCallBackFunction(self, name, textctrl, library, value_infos, path): laurent@738: infos = [value_infos] laurent@738: def OnBrowseButton(event): laurent@738: dialog = BrowseValuesLibraryDialog(self, name, library, infos[0]) laurent@738: if dialog.ShowModal() == wx.ID_OK: laurent@738: value, value_infos = self.SetConfNodeParamsAttribute(path, dialog.GetValueInfos()) laurent@738: textctrl.ChangeValue(value) laurent@738: infos[0] = value_infos laurent@738: dialog.Destroy() laurent@738: event.Skip() laurent@738: return OnBrowseButton laurent@738: laurent@738: def OnWindowResize(self, event): laurent@738: self.GetBestSize() laurent@738: xstart, ystart = self.ParamsEditor.GetViewStart() laurent@738: window_size = self.ParamsEditor.GetClientSize() laurent@738: maxx, maxy = self.ParamsEditorSizer.GetMinSize() laurent@738: posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT)) laurent@738: posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT)) laurent@738: self.ParamsEditor.Scroll(posx, posy) laurent@738: self.ParamsEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, laurent@738: maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy) laurent@738: event.Skip() laurent@738: laurent@738: def OnMouseWheel(self, event): laurent@738: if self.ScrollingEnabled: laurent@738: event.Skip() laurent@738: