laurent@738: 
laurent@738: import os
laurent@738: import types
laurent@738: 
laurent@738: import wx
laurent@738: 
Laurent@814: from EditorPanel import EditorPanel
Laurent@814: 
Laurent@814: from IDEFrame import TITLE, FILEMENU, PROJECTTREE, PAGETITLES
Laurent@814: 
Laurent@814: from controls import TextCtrlAutoComplete
Laurent@814: from dialogs import BrowseValuesLibraryDialog
Laurent@814: from util.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@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@1162: class GenStaticBitmap(wx.StaticBitmap):
Edouard@1451:     """ 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"):
Edouard@1451: 
Laurent@1162:         bitmap = GetBitmap(bitmapname)
Laurent@1162:         if bitmap is None:
Laurent@1162:             bitmap = wx.EmptyBitmap(0, 0)
Edouard@1451: 
Edouard@1451:         wx.StaticBitmap.__init__(self, parent, ID,
Laurent@1162:                  bitmap,
laurent@738:                  pos, size,
laurent@738:                  style,
laurent@738:                  name)
laurent@738: 
laurent@738: class ConfTreeNodeEditor(EditorPanel):
Edouard@1451: 
laurent@775:     SHOW_BASE_PARAMS = True
laurent@762:     SHOW_PARAMS = True
Laurent@920:     CONFNODEEDITOR_TABS = []
Edouard@1451: 
laurent@781:     def _init_Editor(self, parent):
Laurent@920:         tabs_num = len(self.CONFNODEEDITOR_TABS)
Laurent@1055:         if self.SHOW_PARAMS and len(self.Controler.GetParamsAttributes()) > 0:
Laurent@920:             tabs_num += 1
Edouard@1451: 
Laurent@1055:         if tabs_num > 1 or self.SHOW_BASE_PARAMS:
Edouard@1451:             self.Editor = wx.Panel(parent,
Laurent@920:                 style=wx.SUNKEN_BORDER|wx.SP_3D)
Edouard@1451: 
Laurent@1055:             self.MainSizer = wx.BoxSizer(wx.VERTICAL)
Edouard@1451: 
laurent@775:             if self.SHOW_BASE_PARAMS:
laurent@775:                 baseparamseditor_sizer = wx.BoxSizer(wx.HORIZONTAL)
Edouard@1451:                 self.MainSizer.AddSizer(baseparamseditor_sizer, border=5,
Laurent@1055:                       flag=wx.GROW|wx.ALL)
Edouard@1451: 
Laurent@1055:                 self.FullIECChannel = wx.StaticText(self.Editor, -1)
laurent@775:                 self.FullIECChannel.SetFont(
Edouard@1451:                     wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL,
laurent@775:                             wx.BOLD, faceName = faces["helv"]))
Edouard@1451:                 baseparamseditor_sizer.AddWindow(self.FullIECChannel,
laurent@781:                       flag=wx.ALIGN_CENTER_VERTICAL)
Edouard@1451: 
laurent@775:                 updownsizer = wx.BoxSizer(wx.VERTICAL)
Edouard@1451:                 baseparamseditor_sizer.AddSizer(updownsizer, border=5,
laurent@781:                       flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL)
Edouard@1451: 
Edouard@1451:                 self.IECCUpButton = wx.lib.buttons.GenBitmapTextButton(self.Editor,
laurent@781:                       bitmap=GetBitmap('IECCDown'), size=wx.Size(16, 16), style=wx.NO_BORDER)
Edouard@1451:                 self.IECCUpButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(1),
laurent@781:                       self.IECCUpButton)
laurent@781:                 updownsizer.AddWindow(self.IECCUpButton, flag=wx.ALIGN_LEFT)
Edouard@1451: 
Edouard@1451:                 self.IECCDownButton = wx.lib.buttons.GenBitmapButton(self.Editor,
laurent@781:                       bitmap=GetBitmap('IECCUp'), size=wx.Size(16, 16), style=wx.NO_BORDER)
Edouard@1451:                 self.IECCDownButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(-1),
laurent@781:                       self.IECCDownButton)
laurent@781:                 updownsizer.AddWindow(self.IECCDownButton, flag=wx.ALIGN_LEFT)
Edouard@1451: 
Edouard@1451:                 self.ConfNodeName = wx.TextCtrl(self.Editor,
Laurent@1162:                       size=wx.Size(150, 25))
laurent@775:                 self.ConfNodeName.SetFont(
Edouard@1451:                     wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL,
laurent@775:                             wx.BOLD, faceName = faces["helv"]))
Edouard@1451:                 self.ConfNodeName.Bind(wx.EVT_TEXT,
Edouard@1451:                       self.GetTextCtrlCallBackFunction(self.ConfNodeName, "BaseParams.Name", True),
laurent@781:                       self.ConfNodeName)
Edouard@1451:                 baseparamseditor_sizer.AddWindow(self.ConfNodeName, border=5,
laurent@781:                       flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
Edouard@1451: 
laurent@775:                 buttons_sizer = self.GenerateMethodButtonSizer()
laurent@781:                 baseparamseditor_sizer.AddSizer(buttons_sizer, flag=wx.ALIGN_CENTER)
Edouard@1451: 
Laurent@1055:             if tabs_num > 1:
Laurent@1055:                 self.ConfNodeNoteBook = wx.Notebook(self.Editor)
Laurent@1055:                 parent = self.ConfNodeNoteBook
Laurent@1055:                 self.MainSizer.AddWindow(self.ConfNodeNoteBook, 1, flag=wx.GROW)
laurent@775:             else:
Laurent@1059:                 parent = self.Editor
Laurent@1055:                 self.ConfNodeNoteBook = None
Edouard@1451: 
Laurent@1055:             self.Editor.SetSizer(self.MainSizer)
Laurent@1055:         else:
Laurent@1055:             self.ConfNodeNoteBook = None
Laurent@1055:             self.Editor = None
Edouard@1451: 
Laurent@1055:         for title, create_func_name in self.CONFNODEEDITOR_TABS:
Laurent@1055:             editor = getattr(self, create_func_name)(parent)
Laurent@1055:             if self.ConfNodeNoteBook is not None:
Laurent@1055:                 self.ConfNodeNoteBook.AddPage(editor, title)
Laurent@1055:             elif self.SHOW_BASE_PARAMS:
Laurent@1055:                 self.MainSizer.AddWindow(editor, 1, flag=wx.GROW)
Laurent@1055:             else:
Laurent@1055:                 self.Editor = editor
Edouard@1451: 
Laurent@1055:         if self.SHOW_PARAMS and len(self.Controler.GetParamsAttributes()) > 0:
Edouard@1451: 
Laurent@1055:             panel_style = wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL
Laurent@1059:             if self.ConfNodeNoteBook is None and parent != self.Editor:
Laurent@1055:                 panel_style |= wx.SUNKEN_BORDER
Edouard@1451:             self.ParamsEditor = wx.ScrolledWindow(parent,
Laurent@1055:                   style=panel_style)
Laurent@1180:             self.ParamsEditor.Bind(wx.EVT_SIZE, self.OnParamsEditorResize)
Laurent@1180:             self.ParamsEditor.Bind(wx.EVT_SCROLLWIN, self.OnParamsEditorScroll)
Edouard@1451: 
Laurent@1055:             self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=5)
Laurent@1055:             self.ParamsEditorSizer.AddGrowableCol(0)
Laurent@1055:             self.ParamsEditorSizer.AddGrowableRow(0)
Laurent@1055:             self.ParamsEditor.SetSizer(self.ParamsEditorSizer)
Edouard@1451: 
laurent@762:             self.ConfNodeParamsSizer = wx.BoxSizer(wx.VERTICAL)
Edouard@1451:             self.ParamsEditorSizer.AddSizer(self.ConfNodeParamsSizer, border=5,
laurent@781:                   flag=wx.LEFT|wx.RIGHT|wx.BOTTOM)
Edouard@1451: 
laurent@775:             self.RefreshConfNodeParamsSizer()
Edouard@1451: 
Laurent@920:             if self.ConfNodeNoteBook is not None:
Laurent@920:                 self.ConfNodeNoteBook.AddPage(self.ParamsEditor, _("Config"))
Laurent@1055:             elif self.SHOW_BASE_PARAMS:
Laurent@1055:                 self.MainSizer.AddWindow(self.ParamsEditor, 1, flag=wx.GROW)
Laurent@920:             else:
Laurent@920:                 self.Editor = self.ParamsEditor
laurent@762:         else:
laurent@762:             self.ParamsEditor = None
Edouard@1451: 
laurent@743:     def __init__(self, parent, controler, window, tagname=""):
laurent@738:         EditorPanel.__init__(self, parent, tagname, window, controler)
Edouard@1451: 
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"))
Edouard@1451: 
laurent@738:     def __del__(self):
laurent@738:         self.Controler.OnCloseEditor(self)
Edouard@1451: 
laurent@738:     def GetTagName(self):
laurent@738:         return self.Controler.CTNFullName()
Edouard@1451: 
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
Edouard@1451: 
laurent@738:     def HasNoModel(self):
laurent@738:         return False
Edouard@1451: 
laurent@743:     def GetBufferState(self):
laurent@743:         return False, False
Edouard@1451: 
laurent@743:     def Undo(self):
laurent@743:         pass
Edouard@1451: 
laurent@743:     def Redo(self):
laurent@743:         pass
Edouard@1451: 
laurent@746:     def RefreshView(self):
laurent@746:         EditorPanel.RefreshView(self)
Laurent@1055:         if self.SHOW_BASE_PARAMS:
Laurent@1055:             self.ConfNodeName.ChangeValue(self.Controler.MandatoryParams[1].getName())
Laurent@1055:             self.RefreshIECChannelControlsState()
laurent@762:         if self.ParamsEditor is not None:
laurent@762:             self.RefreshConfNodeParamsSizer()
Laurent@840:             self.RefreshScrollbars()
Edouard@1451: 
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@1059:         self.MainSizer.Layout()
Edouard@1451: 
laurent@738:     def RefreshConfNodeParamsSizer(self):
laurent@738:         self.Freeze()
laurent@738:         self.ConfNodeParamsSizer.Clear(True)
Edouard@1451: 
laurent@738:         confnode_infos = self.Controler.GetParamsAttributes()
laurent@738:         if len(confnode_infos) > 0:
laurent@738:             self.GenerateSizerElements(self.ConfNodeParamsSizer, confnode_infos, None, False)
Edouard@1451: 
laurent@738:         self.ParamsEditorSizer.Layout()
laurent@738:         self.Thaw()
Edouard@1451: 
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"])
Edouard@1451: 
laurent@738:         msizer = wx.BoxSizer(wx.HORIZONTAL)
Edouard@1451: 
laurent@738:         for confnode_method in self.Controler.ConfNodeMethods:
laurent@738:             if "method" in confnode_method and confnode_method.get("shown",True):
Laurent@1055:                 button = GenBitmapTextButton(self.Editor,
Edouard@1451:                     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
Edouard@1451: 
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@1282:                 name = element_infos["name"]
laurent@1282:                 value = element_infos["value"]
laurent@1282:                 label = _(name)
laurent@1282:                 if value is not None:
laurent@1282:                     label += " - %s" % _(value)
Edouard@1451:                 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:
Edouard@1451:                     sizer.AddSizer(staticboxsizer, border=5,
laurent@781:                           flag=wx.GROW|wx.TOP|wx.BOTTOM)
laurent@738:                 else:
Edouard@1451:                     sizer.AddSizer(staticboxsizer, border=5,
laurent@781:                           flag=wx.GROW|wx.BOTTOM)
Edouard@1451:                 self.GenerateSizerElements(staticboxsizer,
Edouard@1451:                                            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:
Edouard@1451:                     sizer.AddSizer(boxsizer, border=5,
laurent@781:                           flag=wx.GROW|wx.ALL)
laurent@738:                 else:
Edouard@1451:                     sizer.AddSizer(boxsizer, border=5,
laurent@781:                           flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
Edouard@1451: 
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)
Edouard@1451: 
Edouard@1451:                 statictext = wx.StaticText(self.ParamsEditor,
laurent@781:                       label="%s:"%_(element_infos["name"]))
Edouard@1451:                 boxsizer.AddWindow(statictext, border=5,
laurent@781:                       flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT)
Edouard@1451: 
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)
Edouard@1451: 
Edouard@1451:                         textctrl = wx.TextCtrl(self.ParamsEditor,
laurent@846:                               size=wx.Size(275, -1), 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)
Edouard@1451: 
Edouard@1451:                         button = wx.Button(self.ParamsEditor,
laurent@781:                               label="...", size=wx.Size(25, 25))
laurent@781:                         browse_boxsizer.AddWindow(button)
Edouard@1451:                         button.Bind(wx.EVT_BUTTON,
Edouard@1451:                                     self.GetBrowseCallBackFunction(element_infos["name"], textctrl, element_infos["type"],
Edouard@1451:                                                                    value_infos, element_path),
laurent@781:                                     button)
laurent@738:                     else:
Edouard@1451:                         combobox = wx.ComboBox(self.ParamsEditor,
laurent@846:                               size=wx.Size(300, -1), style=wx.CB_READONLY)
laurent@781:                         boxsizer.AddWindow(combobox)
Edouard@1451: 
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"]
Edouard@1451: 
Edouard@1451:                             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)
Edouard@1451: 
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"]
Edouard@1451:                     spinctrl = wx.SpinCtrl(self.ParamsEditor,
laurent@846:                           size=wx.Size(300, -1), 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"])
Edouard@1451:                     spinctrl.Bind(wx.EVT_SPINCTRL,
laurent@781:                                   self.GetTextCtrlCallBackFunction(spinctrl, element_path),
laurent@781:                                   spinctrl)
Edouard@1451: 
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"])
Edouard@1451:                         checkbox.Bind(wx.EVT_CHECKBOX,
Edouard@1451:                                       self.GetCheckBoxCallBackFunction(checkbox, element_path),
laurent@781:                                       checkbox)
Edouard@1451: 
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
Edouard@1451:                         spinctrl = wx.SpinCtrl(self.ParamsEditor,
laurent@846:                               size=wx.Size(300, -1), 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"])
Edouard@1451:                         spinctrl.Bind(wx.EVT_SPINCTRL,
Edouard@1451:                                       self.GetTextCtrlCallBackFunction(spinctrl, element_path),
laurent@781:                                       spinctrl)
Edouard@1451: 
laurent@738:                     else:
laurent@738:                         choices = self.ParentWindow.GetConfigEntry(element_path, [""])
Edouard@1451:                         textctrl = TextCtrlAutoComplete(name=element_infos["name"],
Edouard@1451:                                                         parent=self.ParamsEditor,
Edouard@1451:                                                         choices=choices,
laurent@781:                                                         element_path=element_path,
laurent@846:                                                         size=wx.Size(300, -1))
Edouard@1451: 
laurent@781:                         boxsizer.AddWindow(textctrl)
laurent@738:                         if element_infos["value"] is not None:
laurent@738:                             textctrl.ChangeValue(str(element_infos["value"]))
Laurent@1180:                         callback = self.GetTextCtrlCallBackFunction(textctrl, element_path)
Laurent@1180:                         textctrl.Bind(wx.EVT_TEXT_ENTER, callback)
Laurent@1180:                         textctrl.Bind(wx.EVT_KILL_FOCUS, callback)
laurent@738:             first = False
Edouard@1451: 
Edouard@1451: 
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:             event.Skip()
laurent@738:         return OnConfNodeTreeItemChannelChanged
Edouard@1451: 
laurent@738:     def SetConfNodeParamsAttribute(self, *args, **kwargs):
laurent@738:         res, StructChanged = self.Controler.SetParamsAttribute(*args, **kwargs)
Laurent@1111:         if StructChanged and self.ParamsEditor is not None:
laurent@738:             wx.CallAfter(self.RefreshConfNodeParamsSizer)
laurent@738:         wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU)
laurent@738:         return res
Edouard@1451: 
laurent@767:     def GetButtonCallBackFunction(self, method, push=False):
laurent@738:         """ Generate the callbackfunc for a given confnode method"""
laurent@738:         def OnButtonClick(event):
Edouard@1451:             # Disable button to prevent re-entrant call
laurent@738:             event.GetEventObject().Disable()
laurent@738:             # Call
laurent@738:             getattr(self.Controler,method)()
Edouard@1451:             # Re-enable button
laurent@738:             event.GetEventObject().Enable()
Edouard@1451: 
laurent@767:             if not push:
laurent@767:                 event.Skip()
laurent@738:         return OnButtonClick
Edouard@1451: 
laurent@738:     def GetChoiceCallBackFunction(self, choicectrl, path):
laurent@738:         def OnChoiceChanged(event):
laurent@738:             res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection())
Laurent@1315:             if res is None:
Laurent@1315:                 res = ""
laurent@738:             choicectrl.SetStringSelection(res)
laurent@738:             event.Skip()
laurent@738:         return OnChoiceChanged
Edouard@1451: 
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
Edouard@1451: 
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@844:                 if isinstance(textctrl, wx.SpinCtrl):
laurent@844:                     textctrl.SetValue(res)
Laurent@1179:                 elif res is not None:
Laurent@1179:                     textctrl.ChangeValue(str(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
Edouard@1451: 
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
Edouard@1451: 
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
Edouard@1451: 
Laurent@840:     def RefreshScrollbars(self):
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)
Edouard@1451:         self.ParamsEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
laurent@738:                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
Edouard@1451: 
Laurent@1180:     def OnParamsEditorResize(self, event):
Laurent@840:         self.RefreshScrollbars()
laurent@738:         event.Skip()
Edouard@1451: 
Laurent@1180:     def OnParamsEditorScroll(self, event):
Laurent@1180:         control = self.ParamsEditor.FindFocus()
Laurent@1180:         if isinstance(control, TextCtrlAutoComplete):
Laurent@1180:             control.DismissListBox()
Laurent@1180:             self.Refresh()
Laurent@1180:         event.Skip()
Edouard@1451: