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.TextCtrlAutoComplete import TextCtrlAutoComplete laurent@738: from util.BrowseValuesLibraryDialog import BrowseValuesLibraryDialog laurent@781: from utils.BitmapLibrary import GetBitmap 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@746: 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@781: wx.lib.statbmp.GenStaticBitmap.__init__(self, parent, ID, laurent@781: GetBitmap(bitmapname), 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@775: SHOW_BASE_PARAMS = True laurent@762: SHOW_PARAMS = True laurent@738: laurent@738: def _init_ConfNodeEditor(self, prnt): laurent@738: self.ConfNodeEditor = None laurent@738: laurent@781: def _init_Editor(self, parent): laurent@781: self.Editor = wx.SplitterWindow(parent, laurent@781: style=wx.SUNKEN_BORDER|wx.SP_3D) laurent@738: self.SetNeedUpdating(True) laurent@738: self.SetMinimumPaneSize(1) laurent@738: laurent@762: if self.SHOW_PARAMS: laurent@781: self.ParamsEditor = wx.ScrolledWindow(self.Editor, laurent@781: style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL) laurent@762: self.ParamsEditor.SetBackgroundColour(WINDOW_COLOUR) laurent@762: self.ParamsEditor.Bind(wx.EVT_SIZE, self.OnWindowResize) laurent@762: self.ParamsEditor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel) laurent@762: laurent@762: # Variable allowing disabling of ParamsEditor scroll when Popup shown laurent@762: self.ScrollingEnabled = True laurent@762: laurent@775: if self.SHOW_BASE_PARAMS: laurent@775: self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) laurent@775: self.ParamsEditorSizer.AddGrowableCol(0) laurent@775: self.ParamsEditorSizer.AddGrowableRow(1) laurent@775: laurent@775: self.ParamsEditor.SetSizer(self.ParamsEditorSizer) laurent@775: laurent@775: baseparamseditor_sizer = wx.BoxSizer(wx.HORIZONTAL) laurent@781: self.ParamsEditorSizer.AddSizer(baseparamseditor_sizer, border=5, laurent@781: flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP) laurent@775: laurent@775: self.FullIECChannel = wx.StaticText(self.ParamsEditor, -1) laurent@775: self.FullIECChannel.SetFont( laurent@775: wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, laurent@775: wx.BOLD, faceName = faces["helv"])) laurent@781: baseparamseditor_sizer.AddWindow(self.FullIECChannel, laurent@781: flag=wx.ALIGN_CENTER_VERTICAL) laurent@775: laurent@775: updownsizer = wx.BoxSizer(wx.VERTICAL) laurent@781: baseparamseditor_sizer.AddSizer(updownsizer, border=5, laurent@781: flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL) laurent@781: laurent@781: self.IECCUpButton = wx.lib.buttons.GenBitmapTextButton(self.ParamsEditor, laurent@781: bitmap=GetBitmap('IECCDown'), size=wx.Size(16, 16), style=wx.NO_BORDER) laurent@775: self.IECCUpButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(1), laurent@781: self.IECCUpButton) laurent@781: updownsizer.AddWindow(self.IECCUpButton, flag=wx.ALIGN_LEFT) laurent@781: laurent@781: self.IECCDownButton = wx.lib.buttons.GenBitmapButton(self.ParamsEditor, laurent@781: bitmap=GetBitmap('IECCUp'), size=wx.Size(16, 16), style=wx.NO_BORDER) laurent@775: self.IECCDownButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(-1), laurent@781: self.IECCDownButton) laurent@781: updownsizer.AddWindow(self.IECCDownButton, flag=wx.ALIGN_LEFT) laurent@781: laurent@781: self.ConfNodeName = wx.TextCtrl(self.ParamsEditor, laurent@775: size=wx.Size(150, 25), style=wx.NO_BORDER) laurent@775: self.ConfNodeName.SetFont( laurent@775: wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, laurent@775: wx.BOLD, faceName = faces["helv"])) laurent@775: self.ConfNodeName.Bind(wx.EVT_TEXT, laurent@781: self.GetTextCtrlCallBackFunction(self.ConfNodeName, "BaseParams.Name", True), laurent@781: self.ConfNodeName) laurent@781: baseparamseditor_sizer.AddWindow(self.ConfNodeName, border=5, laurent@781: flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) laurent@775: laurent@775: buttons_sizer = self.GenerateMethodButtonSizer() laurent@781: baseparamseditor_sizer.AddSizer(buttons_sizer, flag=wx.ALIGN_CENTER) laurent@775: laurent@775: else: laurent@775: self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=5) laurent@775: self.ParamsEditorSizer.AddGrowableCol(0) laurent@775: self.ParamsEditorSizer.AddGrowableRow(0) laurent@762: laurent@762: self.ConfNodeParamsSizer = wx.BoxSizer(wx.VERTICAL) laurent@781: self.ParamsEditorSizer.AddSizer(self.ConfNodeParamsSizer, border=5, laurent@781: flag=wx.LEFT|wx.RIGHT|wx.BOTTOM) laurent@775: laurent@775: self.RefreshConfNodeParamsSizer() laurent@762: else: laurent@762: self.ParamsEditor = None laurent@738: laurent@738: self._init_ConfNodeEditor(self.Editor) laurent@738: laurent@738: if self.ConfNodeEditor is not None: laurent@762: if self.ParamsEditor is not None: laurent@762: min_size = self.ParamsEditorSizer.GetMinSize() laurent@762: self.Editor.SplitHorizontally(self.ParamsEditor, laurent@762: self.ConfNodeEditor, laurent@762: min(min_size.height, 200)) laurent@762: else: laurent@762: self.Editor.Initialize(self.ConfNodeEditor) laurent@762: elif self.ParamsEditor is not None: laurent@738: self.Editor.Initialize(self.ParamsEditor) laurent@738: laurent@743: def __init__(self, parent, controler, window, tagname=""): laurent@738: EditorPanel.__init__(self, parent, tagname, window, controler) laurent@743: laurent@781: icon_name = self.Controler.GetIconName() laurent@781: if icon_name is not None: laurent@781: self.SetIcon(GetBitmap(icon_name)) laurent@781: else: laurent@781: self.SetIcon(GetBitmap("Extension")) laurent@781: 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@743: def GetBufferState(self): laurent@743: return False, False laurent@743: laurent@743: def Undo(self): laurent@743: pass laurent@743: laurent@743: def Redo(self): laurent@743: pass laurent@743: laurent@746: def RefreshView(self): laurent@746: EditorPanel.RefreshView(self) laurent@762: if self.ParamsEditor is not None: laurent@775: if self.SHOW_BASE_PARAMS: laurent@775: self.ConfNodeName.ChangeValue(self.Controler.MandatoryParams[1].getName()) laurent@775: self.RefreshIECChannelControlsState() laurent@762: self.RefreshConfNodeParamsSizer() laurent@746: 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@781: button = GenBitmapTextButton(self.ParamsEditor, laurent@781: bitmap=GetBitmap(confnode_method.get("bitmap", "Unknown")), laurent@781: label=confnode_method["name"], style=wx.NO_BORDER) laurent@738: button.SetFont(normal_bt_font) laurent@738: button.SetToolTipString(confnode_method["tooltip"]) laurent@767: if confnode_method.get("push", False): laurent@767: button.Bind(wx.EVT_LEFT_DOWN, self.GetButtonCallBackFunction(confnode_method["method"], True)) laurent@767: else: laurent@781: button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(confnode_method["method"]), button) 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@781: msizer.AddWindow(button, 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@781: staticbox = wx.StaticBox(self.ParamsEditor, laurent@781: label=_(label), size=wx.Size(10, 0)) laurent@738: staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) laurent@738: if first: laurent@781: sizer.AddSizer(staticboxsizer, border=5, laurent@781: flag=wx.GROW|wx.TOP|wx.BOTTOM) laurent@738: else: laurent@781: sizer.AddSizer(staticboxsizer, border=5, laurent@781: flag=wx.GROW|wx.BOTTOM) laurent@781: self.GenerateSizerElements(staticboxsizer, laurent@781: element_infos["children"], laurent@781: element_path) laurent@738: else: laurent@738: boxsizer = wx.FlexGridSizer(cols=3, rows=1) laurent@738: boxsizer.AddGrowableCol(1) laurent@738: if first: laurent@781: sizer.AddSizer(boxsizer, border=5, laurent@781: flag=wx.GROW|wx.ALL) laurent@738: else: laurent@781: sizer.AddSizer(boxsizer, border=5, laurent@781: flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) laurent@781: laurent@781: staticbitmap = GenStaticBitmap(ID=-1, bitmapname=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@781: boxsizer.AddWindow(staticbitmap, border=5, flag=wx.RIGHT) laurent@781: laurent@781: statictext = wx.StaticText(self.ParamsEditor, laurent@781: label="%s:"%_(element_infos["name"])) laurent@781: boxsizer.AddWindow(statictext, border=5, laurent@781: flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT) laurent@781: 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@781: boxsizer.AddSizer(browse_boxsizer) laurent@738: laurent@781: textctrl = wx.TextCtrl(self.ParamsEditor, laurent@781: 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@781: browse_boxsizer.AddWindow(textctrl) laurent@781: laurent@781: button = wx.Button(self.ParamsEditor, laurent@781: label="...", size=wx.Size(25, 25)) laurent@781: browse_boxsizer.AddWindow(button) 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@781: button) laurent@738: else: laurent@781: combobox = wx.ComboBox(self.ParamsEditor, laurent@781: size=wx.Size(300, 28), style=wx.CB_READONLY) laurent@781: boxsizer.AddWindow(combobox) laurent@781: 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@781: laurent@781: staticbox = wx.StaticBox(self.ParamsEditor, laurent@781: label="%s - %s"%(_(name), _(value)), size=wx.Size(10, 0)) laurent@738: staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) laurent@781: sizer.AddSizer(staticboxsizer, 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@781: combobox.Bind(wx.EVT_COMBOBOX, callback, combobox) laurent@781: 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@781: spinctrl = wx.SpinCtrl(self.ParamsEditor, laurent@781: size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) laurent@781: spinctrl.SetRange(scmin, scmax) laurent@781: boxsizer.AddWindow(spinctrl) laurent@738: if element_infos["value"] is not None: laurent@738: spinctrl.SetValue(element_infos["value"]) laurent@781: spinctrl.Bind(wx.EVT_SPINCTRL, laurent@781: self.GetTextCtrlCallBackFunction(spinctrl, element_path), laurent@781: spinctrl) laurent@781: laurent@738: else: laurent@738: if element_infos["type"] == "boolean": laurent@781: checkbox = wx.CheckBox(self.ParamsEditor, size=wx.Size(17, 25)) laurent@781: boxsizer.AddWindow(checkbox) laurent@738: if element_infos["value"] is not None: laurent@738: checkbox.SetValue(element_infos["value"]) laurent@781: checkbox.Bind(wx.EVT_CHECKBOX, laurent@781: self.GetCheckBoxCallBackFunction(checkbox, element_path), laurent@781: checkbox) laurent@781: 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@781: spinctrl = wx.SpinCtrl(self.ParamsEditor, laurent@781: size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) laurent@738: spinctrl.SetRange(scmin, scmax) laurent@781: boxsizer.AddWindow(spinctrl) laurent@738: if element_infos["value"] is not None: laurent@738: spinctrl.SetValue(element_infos["value"]) laurent@781: spinctrl.Bind(wx.EVT_SPINCTRL, laurent@781: self.GetTextCtrlCallBackFunction(spinctrl, element_path), laurent@781: spinctrl) laurent@781: laurent@738: else: laurent@738: choices = self.ParentWindow.GetConfigEntry(element_path, [""]) laurent@781: textctrl = TextCtrlAutoComplete(name=element_infos["name"], laurent@781: parent=self.ParamsEditor, laurent@781: appframe=self, laurent@781: choices=choices, laurent@781: element_path=element_path, laurent@781: size=wx.Size(300, 25)) laurent@738: laurent@781: boxsizer.AddWindow(textctrl) 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@767: def GetButtonCallBackFunction(self, method, push=False): 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@767: if not push: laurent@767: 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@746: wx.CallAfter(self.RefreshConfNodeParamsSizer) laurent@738: event.Skip() laurent@738: return OnChoiceContentChanged laurent@738: laurent@746: def GetTextCtrlCallBackFunction(self, textctrl, path, refresh=False): 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@746: if refresh: 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@746: self.ParamsEditor.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: