editors/ConfTreeNodeEditor.py
branch1.1 Korean release
changeset 968 eee7625de1f7
parent 920 1499a4d225db
child 1055 da483f620668
equal deleted inserted replaced
808:6e205c1f05a0 968:eee7625de1f7
       
     1 
       
     2 import os
       
     3 import types
       
     4 
       
     5 import wx
       
     6 import wx.lib.buttons
       
     7 
       
     8 from EditorPanel import EditorPanel
       
     9 
       
    10 from IDEFrame import TITLE, FILEMENU, PROJECTTREE, PAGETITLES
       
    11 
       
    12 from controls import TextCtrlAutoComplete
       
    13 from dialogs import BrowseValuesLibraryDialog
       
    14 from util.BitmapLibrary import GetBitmap
       
    15 
       
    16 if wx.Platform == '__WXMSW__':
       
    17     faces = { 'times': 'Times New Roman',
       
    18               'mono' : 'Courier New',
       
    19               'helv' : 'Arial',
       
    20               'other': 'Comic Sans MS',
       
    21               'size' : 16,
       
    22              }
       
    23 else:
       
    24     faces = { 'times': 'Times',
       
    25               'mono' : 'Courier',
       
    26               'helv' : 'Helvetica',
       
    27               'other': 'new century schoolbook',
       
    28               'size' : 18,
       
    29              }
       
    30 
       
    31 SCROLLBAR_UNIT = 10
       
    32 WINDOW_COLOUR = wx.Colour(240, 240, 240)
       
    33 
       
    34 CWD = os.path.split(os.path.realpath(__file__))[0]
       
    35 
       
    36 def Bpath(*args):
       
    37     return os.path.join(CWD,*args)
       
    38 
       
    39 # Some helpers to tweak GenBitmapTextButtons
       
    40 # TODO: declare customized classes instead.
       
    41 gen_mini_GetBackgroundBrush = lambda obj:lambda dc: wx.Brush(obj.GetParent().GetBackgroundColour(), wx.SOLID)
       
    42 gen_textbutton_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenButton._GetLabelSize(obj)[:-1] + (False,))
       
    43 
       
    44 def make_genbitmaptogglebutton_flat(button):
       
    45     button.GetBackgroundBrush = gen_mini_GetBackgroundBrush(button)
       
    46     button.labelDelta = 0
       
    47     button.SetBezelWidth(0)
       
    48     button.SetUseFocusIndicator(False)
       
    49 
       
    50 # Patch wx.lib.imageutils so that gray is supported on alpha images
       
    51 import wx.lib.imageutils
       
    52 from wx.lib.imageutils import grayOut as old_grayOut
       
    53 def grayOut(anImage):
       
    54     if anImage.HasAlpha():
       
    55         AlphaData = anImage.GetAlphaData()
       
    56     else :
       
    57         AlphaData = None
       
    58 
       
    59     old_grayOut(anImage)
       
    60 
       
    61     if AlphaData is not None:
       
    62         anImage.SetAlphaData(AlphaData)
       
    63 
       
    64 wx.lib.imageutils.grayOut = grayOut
       
    65 
       
    66 class GenBitmapTextButton(wx.lib.buttons.GenBitmapTextButton):
       
    67     def _GetLabelSize(self):
       
    68         """ used internally """
       
    69         w, h = self.GetTextExtent(self.GetLabel())
       
    70         if not self.bmpLabel:
       
    71             return w, h, False       # if there isn't a bitmap use the size of the text
       
    72 
       
    73         w_bmp = self.bmpLabel.GetWidth()+2
       
    74         h_bmp = self.bmpLabel.GetHeight()+2
       
    75         height = h + h_bmp
       
    76         if w_bmp > w:
       
    77             width = w_bmp
       
    78         else:
       
    79             width = w
       
    80         return width, height, False
       
    81 
       
    82     def DrawLabel(self, dc, width, height, dw=0, dy=0):
       
    83         bmp = self.bmpLabel
       
    84         if bmp != None:     # if the bitmap is used
       
    85             if self.bmpDisabled and not self.IsEnabled():
       
    86                 bmp = self.bmpDisabled
       
    87             if self.bmpFocus and self.hasFocus:
       
    88                 bmp = self.bmpFocus
       
    89             if self.bmpSelected and not self.up:
       
    90                 bmp = self.bmpSelected
       
    91             bw,bh = bmp.GetWidth(), bmp.GetHeight()
       
    92             if not self.up:
       
    93                 dw = dy = self.labelDelta
       
    94             hasMask = bmp.GetMask() != None
       
    95         else:
       
    96             bw = bh = 0     # no bitmap -> size is zero
       
    97 
       
    98         dc.SetFont(self.GetFont())
       
    99         if self.IsEnabled():
       
   100             dc.SetTextForeground(self.GetForegroundColour())
       
   101         else:
       
   102             dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
       
   103 
       
   104         label = self.GetLabel()
       
   105         tw, th = dc.GetTextExtent(label)        # size of text
       
   106         if not self.up:
       
   107             dw = dy = self.labelDelta
       
   108 
       
   109         pos_x = (width-bw)/2+dw      # adjust for bitmap and text to centre
       
   110         pos_y = (height-bh-th)/2+dy
       
   111         if bmp !=None:
       
   112             dc.DrawBitmap(bmp, pos_x, pos_y, hasMask) # draw bitmap if available
       
   113             pos_x = (width-tw)/2+dw      # adjust for bitmap and text to centre
       
   114             pos_y += bh + 2
       
   115 
       
   116         dc.DrawText(label, pos_x, pos_y)      # draw the text
       
   117 
       
   118 
       
   119 class GenStaticBitmap(wx.lib.statbmp.GenStaticBitmap):
       
   120     """ Customized GenStaticBitmap, fix transparency redraw bug on wx2.8/win32, 
       
   121     and accept image name as __init__ parameter, fail silently if file do not exist"""
       
   122     def __init__(self, parent, ID, bitmapname,
       
   123                  pos = wx.DefaultPosition, size = wx.DefaultSize,
       
   124                  style = 0,
       
   125                  name = "genstatbmp"):
       
   126         
       
   127         wx.lib.statbmp.GenStaticBitmap.__init__(self, parent, ID, 
       
   128                  GetBitmap(bitmapname),
       
   129                  pos, size,
       
   130                  style,
       
   131                  name)
       
   132         
       
   133     def OnPaint(self, event):
       
   134         dc = wx.PaintDC(self)
       
   135         colour = self.GetParent().GetBackgroundColour()
       
   136         dc.SetPen(wx.Pen(colour))
       
   137         dc.SetBrush(wx.Brush(colour ))
       
   138         dc.DrawRectangle(0, 0, *dc.GetSizeTuple())
       
   139         if self._bitmap:
       
   140             dc.DrawBitmap(self._bitmap, 0, 0, True)
       
   141 
       
   142 class ConfTreeNodeEditor(EditorPanel):
       
   143     
       
   144     SHOW_BASE_PARAMS = True
       
   145     SHOW_PARAMS = True
       
   146     CONFNODEEDITOR_TABS = []
       
   147     
       
   148     def _init_Editor(self, parent):
       
   149         tabs_num = len(self.CONFNODEEDITOR_TABS)
       
   150         if self.SHOW_PARAMS:
       
   151             tabs_num += 1
       
   152             
       
   153         if tabs_num > 1:
       
   154             self.Editor = wx.Panel(parent, 
       
   155                 style=wx.SUNKEN_BORDER|wx.SP_3D)
       
   156             
       
   157             main_sizer = wx.BoxSizer(wx.VERTICAL)
       
   158             
       
   159             self.ConfNodeNoteBook = wx.Notebook(self.Editor)
       
   160             parent = self.ConfNodeNoteBook
       
   161             main_sizer.AddWindow(self.ConfNodeNoteBook, 1, flag=wx.GROW)
       
   162             
       
   163             self.Editor.SetSizer(main_sizer)
       
   164         else:
       
   165             self.ConfNodeNoteBook = None
       
   166             self.Editor = None
       
   167         
       
   168         for title, create_func_name in self.CONFNODEEDITOR_TABS:
       
   169             editor = getattr(self, create_func_name)(parent)
       
   170             if self.ConfNodeNoteBook is not None:
       
   171                 self.ConfNodeNoteBook.AddPage(editor, title)
       
   172             else:
       
   173                 self.Editor = editor
       
   174         
       
   175         if self.SHOW_PARAMS:
       
   176             
       
   177             panel_style = wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL
       
   178             if self.ConfNodeNoteBook is None:
       
   179                 panel_style |= wx.SUNKEN_BORDER
       
   180             self.ParamsEditor = wx.ScrolledWindow(parent, 
       
   181                   style=panel_style)
       
   182             self.ParamsEditor.SetBackgroundColour(WINDOW_COLOUR)
       
   183             self.ParamsEditor.Bind(wx.EVT_SIZE, self.OnWindowResize)
       
   184             self.ParamsEditor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
       
   185             
       
   186             # Variable allowing disabling of ParamsEditor scroll when Popup shown 
       
   187             self.ScrollingEnabled = True
       
   188             
       
   189             if self.SHOW_BASE_PARAMS:
       
   190                 self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
   191                 self.ParamsEditorSizer.AddGrowableCol(0)
       
   192                 self.ParamsEditorSizer.AddGrowableRow(1)
       
   193                 
       
   194                 self.ParamsEditor.SetSizer(self.ParamsEditorSizer)
       
   195                 
       
   196                 baseparamseditor_sizer = wx.BoxSizer(wx.HORIZONTAL)
       
   197                 self.ParamsEditorSizer.AddSizer(baseparamseditor_sizer, border=5, 
       
   198                       flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP)
       
   199                 
       
   200                 self.FullIECChannel = wx.StaticText(self.ParamsEditor, -1)
       
   201                 self.FullIECChannel.SetFont(
       
   202                     wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, 
       
   203                             wx.BOLD, faceName = faces["helv"]))
       
   204                 baseparamseditor_sizer.AddWindow(self.FullIECChannel, 
       
   205                       flag=wx.ALIGN_CENTER_VERTICAL)
       
   206                 
       
   207                 updownsizer = wx.BoxSizer(wx.VERTICAL)
       
   208                 baseparamseditor_sizer.AddSizer(updownsizer, border=5, 
       
   209                       flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL)
       
   210                 
       
   211                 self.IECCUpButton = wx.lib.buttons.GenBitmapTextButton(self.ParamsEditor, 
       
   212                       bitmap=GetBitmap('IECCDown'), size=wx.Size(16, 16), style=wx.NO_BORDER)
       
   213                 self.IECCUpButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(1), 
       
   214                       self.IECCUpButton)
       
   215                 updownsizer.AddWindow(self.IECCUpButton, flag=wx.ALIGN_LEFT)
       
   216                 
       
   217                 self.IECCDownButton = wx.lib.buttons.GenBitmapButton(self.ParamsEditor, 
       
   218                       bitmap=GetBitmap('IECCUp'), size=wx.Size(16, 16), style=wx.NO_BORDER)
       
   219                 self.IECCDownButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(-1), 
       
   220                       self.IECCDownButton)
       
   221                 updownsizer.AddWindow(self.IECCDownButton, flag=wx.ALIGN_LEFT)
       
   222                 
       
   223                 self.ConfNodeName = wx.TextCtrl(self.ParamsEditor, 
       
   224                       size=wx.Size(150, 25), style=wx.NO_BORDER)
       
   225                 self.ConfNodeName.SetFont(
       
   226                     wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, 
       
   227                             wx.BOLD, faceName = faces["helv"]))
       
   228                 self.ConfNodeName.Bind(wx.EVT_TEXT, 
       
   229                       self.GetTextCtrlCallBackFunction(self.ConfNodeName, "BaseParams.Name", True), 
       
   230                       self.ConfNodeName)
       
   231                 baseparamseditor_sizer.AddWindow(self.ConfNodeName, border=5, 
       
   232                       flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
       
   233                 
       
   234                 buttons_sizer = self.GenerateMethodButtonSizer()
       
   235                 baseparamseditor_sizer.AddSizer(buttons_sizer, flag=wx.ALIGN_CENTER)
       
   236             
       
   237             else:
       
   238                 self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=5)
       
   239                 self.ParamsEditorSizer.AddGrowableCol(0)
       
   240                 self.ParamsEditorSizer.AddGrowableRow(0)
       
   241             
       
   242             self.ConfNodeParamsSizer = wx.BoxSizer(wx.VERTICAL)
       
   243             self.ParamsEditorSizer.AddSizer(self.ConfNodeParamsSizer, border=5, 
       
   244                   flag=wx.LEFT|wx.RIGHT|wx.BOTTOM)
       
   245             
       
   246             self.RefreshConfNodeParamsSizer()
       
   247         
       
   248             if self.ConfNodeNoteBook is not None:
       
   249                 self.ConfNodeNoteBook.AddPage(self.ParamsEditor, _("Config"))
       
   250             else:
       
   251                 self.Editor = self.ParamsEditor
       
   252         else:
       
   253             self.ParamsEditor = None
       
   254     
       
   255     def __init__(self, parent, controler, window, tagname=""):
       
   256         EditorPanel.__init__(self, parent, tagname, window, controler)
       
   257         
       
   258         icon_name = self.Controler.GetIconName()
       
   259         if icon_name is not None:
       
   260             self.SetIcon(GetBitmap(icon_name))
       
   261         else:
       
   262             self.SetIcon(GetBitmap("Extension"))
       
   263         
       
   264     def __del__(self):
       
   265         self.Controler.OnCloseEditor(self)
       
   266     
       
   267     def GetTagName(self):
       
   268         return self.Controler.CTNFullName()
       
   269     
       
   270     def GetTitle(self):
       
   271         fullname = self.Controler.CTNFullName()
       
   272         if self.Controler.CTNTestModified():
       
   273             return "~%s~" % fullname
       
   274         return fullname
       
   275     
       
   276     def HasNoModel(self):
       
   277         return False
       
   278     
       
   279     def GetBufferState(self):
       
   280         return False, False
       
   281     
       
   282     def Undo(self):
       
   283         pass
       
   284     
       
   285     def Redo(self):
       
   286         pass
       
   287     
       
   288     def RefreshView(self):
       
   289         EditorPanel.RefreshView(self)
       
   290         if self.ParamsEditor is not None:
       
   291             if self.SHOW_BASE_PARAMS:
       
   292                 self.ConfNodeName.ChangeValue(self.Controler.MandatoryParams[1].getName())
       
   293                 self.RefreshIECChannelControlsState()
       
   294             self.RefreshConfNodeParamsSizer()
       
   295             self.RefreshScrollbars()
       
   296     
       
   297     def EnableScrolling(self, enable):
       
   298         self.ScrollingEnabled = enable
       
   299     
       
   300     def RefreshIECChannelControlsState(self):
       
   301         self.FullIECChannel.SetLabel(self.Controler.GetFullIEC_Channel())
       
   302         self.IECCDownButton.Enable(self.Controler.BaseParams.getIEC_Channel() > 0)
       
   303     
       
   304     def RefreshConfNodeParamsSizer(self):
       
   305         self.Freeze()
       
   306         self.ConfNodeParamsSizer.Clear(True)
       
   307         
       
   308         confnode_infos = self.Controler.GetParamsAttributes()
       
   309         if len(confnode_infos) > 0:
       
   310             self.GenerateSizerElements(self.ConfNodeParamsSizer, confnode_infos, None, False)
       
   311         
       
   312         self.ParamsEditorSizer.Layout()
       
   313         self.Thaw()
       
   314     
       
   315     def GenerateMethodButtonSizer(self):
       
   316         normal_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"])
       
   317         mouseover_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, underline=True, faceName = faces["helv"])
       
   318         
       
   319         msizer = wx.BoxSizer(wx.HORIZONTAL)
       
   320         
       
   321         for confnode_method in self.Controler.ConfNodeMethods:
       
   322             if "method" in confnode_method and confnode_method.get("shown",True):
       
   323                 button = GenBitmapTextButton(self.ParamsEditor,
       
   324                     bitmap=GetBitmap(confnode_method.get("bitmap", "Unknown")), 
       
   325                     label=confnode_method["name"], style=wx.NO_BORDER)
       
   326                 button.SetFont(normal_bt_font)
       
   327                 button.SetToolTipString(confnode_method["tooltip"])
       
   328                 if confnode_method.get("push", False):
       
   329                     button.Bind(wx.EVT_LEFT_DOWN, self.GetButtonCallBackFunction(confnode_method["method"], True))
       
   330                 else:
       
   331                     button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(confnode_method["method"]), button)
       
   332                 # a fancy underline on mouseover
       
   333                 def setFontStyle(b, s):
       
   334                     def fn(event):
       
   335                         b.SetFont(s)
       
   336                         b.Refresh()
       
   337                         event.Skip()
       
   338                     return fn
       
   339                 button.Bind(wx.EVT_ENTER_WINDOW, setFontStyle(button, mouseover_bt_font))
       
   340                 button.Bind(wx.EVT_LEAVE_WINDOW, setFontStyle(button, normal_bt_font))
       
   341                 #hack to force size to mini
       
   342                 if not confnode_method.get("enabled",True):
       
   343                     button.Disable()
       
   344                 msizer.AddWindow(button, flag=wx.ALIGN_CENTER)
       
   345         return msizer
       
   346     
       
   347     def GenerateSizerElements(self, sizer, elements, path, clean = True):
       
   348         if clean:
       
   349             sizer.Clear(True)
       
   350         first = True
       
   351         for element_infos in elements:
       
   352             if path:
       
   353                 element_path = "%s.%s"%(path, element_infos["name"])
       
   354             else:
       
   355                 element_path = element_infos["name"]
       
   356             if element_infos["type"] == "element":
       
   357                 label = element_infos["name"]
       
   358                 staticbox = wx.StaticBox(self.ParamsEditor, 
       
   359                       label=_(label), size=wx.Size(10, 0))
       
   360                 staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL)
       
   361                 if first:
       
   362                     sizer.AddSizer(staticboxsizer, border=5, 
       
   363                           flag=wx.GROW|wx.TOP|wx.BOTTOM)
       
   364                 else:
       
   365                     sizer.AddSizer(staticboxsizer, border=5, 
       
   366                           flag=wx.GROW|wx.BOTTOM)
       
   367                 self.GenerateSizerElements(staticboxsizer, 
       
   368                                            element_infos["children"], 
       
   369                                            element_path)
       
   370             else:
       
   371                 boxsizer = wx.FlexGridSizer(cols=3, rows=1)
       
   372                 boxsizer.AddGrowableCol(1)
       
   373                 if first:
       
   374                     sizer.AddSizer(boxsizer, border=5, 
       
   375                           flag=wx.GROW|wx.ALL)
       
   376                 else:
       
   377                     sizer.AddSizer(boxsizer, border=5, 
       
   378                           flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
       
   379                 
       
   380                 staticbitmap = GenStaticBitmap(ID=-1, bitmapname=element_infos["name"],
       
   381                     name="%s_bitmap"%element_infos["name"], parent=self.ParamsEditor,
       
   382                     pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0)
       
   383                 boxsizer.AddWindow(staticbitmap, border=5, flag=wx.RIGHT)
       
   384                 
       
   385                 statictext = wx.StaticText(self.ParamsEditor, 
       
   386                       label="%s:"%_(element_infos["name"]))
       
   387                 boxsizer.AddWindow(statictext, border=5, 
       
   388                       flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT)
       
   389                 
       
   390                 if isinstance(element_infos["type"], types.ListType):
       
   391                     if isinstance(element_infos["value"], types.TupleType):
       
   392                         browse_boxsizer = wx.BoxSizer(wx.HORIZONTAL)
       
   393                         boxsizer.AddSizer(browse_boxsizer)
       
   394                         
       
   395                         textctrl = wx.TextCtrl(self.ParamsEditor, 
       
   396                               size=wx.Size(275, -1), style=wx.TE_READONLY)
       
   397                         if element_infos["value"] is not None:
       
   398                             textctrl.SetValue(element_infos["value"][0])
       
   399                             value_infos = element_infos["value"][1]
       
   400                         else:
       
   401                             value_infos = None
       
   402                         browse_boxsizer.AddWindow(textctrl)
       
   403                         
       
   404                         button = wx.Button(self.ParamsEditor, 
       
   405                               label="...", size=wx.Size(25, 25))
       
   406                         browse_boxsizer.AddWindow(button)
       
   407                         button.Bind(wx.EVT_BUTTON, 
       
   408                                     self.GetBrowseCallBackFunction(element_infos["name"], textctrl, element_infos["type"], 
       
   409                                                                    value_infos, element_path), 
       
   410                                     button)
       
   411                     else:
       
   412                         combobox = wx.ComboBox(self.ParamsEditor, 
       
   413                               size=wx.Size(300, -1), style=wx.CB_READONLY)
       
   414                         boxsizer.AddWindow(combobox)
       
   415                         
       
   416                         if element_infos["use"] == "optional":
       
   417                             combobox.Append("")
       
   418                         if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], types.TupleType):
       
   419                             for choice, xsdclass in element_infos["type"]:
       
   420                                 combobox.Append(choice)
       
   421                             name = element_infos["name"]
       
   422                             value = element_infos["value"]
       
   423                         
       
   424                             staticbox = wx.StaticBox(self.ParamsEditor, 
       
   425                                   label="%s - %s"%(_(name), _(value)), size=wx.Size(10, 0))
       
   426                             staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL)
       
   427                             sizer.AddSizer(staticboxsizer, border=5, flag=wx.GROW|wx.BOTTOM)
       
   428                             self.GenerateSizerElements(staticboxsizer, element_infos["children"], element_path)
       
   429                             callback = self.GetChoiceContentCallBackFunction(combobox, staticboxsizer, element_path)
       
   430                         else:
       
   431                             for choice in element_infos["type"]:
       
   432                                 combobox.Append(choice)
       
   433                             callback = self.GetChoiceCallBackFunction(combobox, element_path)
       
   434                         if element_infos["value"] is None:
       
   435                             combobox.SetStringSelection("")
       
   436                         else:
       
   437                             combobox.SetStringSelection(element_infos["value"])
       
   438                         combobox.Bind(wx.EVT_COMBOBOX, callback, combobox)
       
   439                 
       
   440                 elif isinstance(element_infos["type"], types.DictType):
       
   441                     scmin = -(2**31)
       
   442                     scmax = 2**31-1
       
   443                     if "min" in element_infos["type"]:
       
   444                         scmin = element_infos["type"]["min"]
       
   445                     if "max" in element_infos["type"]:
       
   446                         scmax = element_infos["type"]["max"]
       
   447                     spinctrl = wx.SpinCtrl(self.ParamsEditor, 
       
   448                           size=wx.Size(300, -1), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT)
       
   449                     spinctrl.SetRange(scmin, scmax)
       
   450                     boxsizer.AddWindow(spinctrl)
       
   451                     if element_infos["value"] is not None:
       
   452                         spinctrl.SetValue(element_infos["value"])
       
   453                     spinctrl.Bind(wx.EVT_SPINCTRL, 
       
   454                                   self.GetTextCtrlCallBackFunction(spinctrl, element_path),
       
   455                                   spinctrl)
       
   456                 
       
   457                 else:
       
   458                     if element_infos["type"] == "boolean":
       
   459                         checkbox = wx.CheckBox(self.ParamsEditor, size=wx.Size(17, 25))
       
   460                         boxsizer.AddWindow(checkbox)
       
   461                         if element_infos["value"] is not None:
       
   462                             checkbox.SetValue(element_infos["value"])
       
   463                         checkbox.Bind(wx.EVT_CHECKBOX, 
       
   464                                       self.GetCheckBoxCallBackFunction(checkbox, element_path), 
       
   465                                       checkbox)
       
   466                     
       
   467                     elif element_infos["type"] in ["unsignedLong", "long","integer"]:
       
   468                         if element_infos["type"].startswith("unsigned"):
       
   469                             scmin = 0
       
   470                         else:
       
   471                             scmin = -(2**31)
       
   472                         scmax = 2**31-1
       
   473                         spinctrl = wx.SpinCtrl(self.ParamsEditor, 
       
   474                               size=wx.Size(300, -1), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT)
       
   475                         spinctrl.SetRange(scmin, scmax)
       
   476                         boxsizer.AddWindow(spinctrl)
       
   477                         if element_infos["value"] is not None:
       
   478                             spinctrl.SetValue(element_infos["value"])
       
   479                         spinctrl.Bind(wx.EVT_SPINCTRL, 
       
   480                                       self.GetTextCtrlCallBackFunction(spinctrl, element_path), 
       
   481                                       spinctrl)
       
   482                     
       
   483                     else:
       
   484                         choices = self.ParentWindow.GetConfigEntry(element_path, [""])
       
   485                         textctrl = TextCtrlAutoComplete(name=element_infos["name"], 
       
   486                                                         parent=self.ParamsEditor, 
       
   487                                                         appframe=self, 
       
   488                                                         choices=choices, 
       
   489                                                         element_path=element_path,
       
   490                                                         size=wx.Size(300, -1))
       
   491                         
       
   492                         boxsizer.AddWindow(textctrl)
       
   493                         if element_infos["value"] is not None:
       
   494                             textctrl.ChangeValue(str(element_infos["value"]))
       
   495                         textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, element_path))
       
   496             first = False
       
   497     
       
   498     
       
   499     def GetItemChannelChangedFunction(self, dir):
       
   500         def OnConfNodeTreeItemChannelChanged(event):
       
   501             confnode_IECChannel = self.Controler.BaseParams.getIEC_Channel()
       
   502             res = self.SetConfNodeParamsAttribute("BaseParams.IEC_Channel", confnode_IECChannel + dir)
       
   503             wx.CallAfter(self.RefreshIECChannelControlsState)
       
   504             wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE)
       
   505             wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName())
       
   506             event.Skip()
       
   507         return OnConfNodeTreeItemChannelChanged
       
   508     
       
   509     def SetConfNodeParamsAttribute(self, *args, **kwargs):
       
   510         res, StructChanged = self.Controler.SetParamsAttribute(*args, **kwargs)
       
   511         if StructChanged:
       
   512             wx.CallAfter(self.RefreshConfNodeParamsSizer)
       
   513         wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU)
       
   514         return res
       
   515     
       
   516     def GetButtonCallBackFunction(self, method, push=False):
       
   517         """ Generate the callbackfunc for a given confnode method"""
       
   518         def OnButtonClick(event):
       
   519             # Disable button to prevent re-entrant call 
       
   520             event.GetEventObject().Disable()
       
   521             # Call
       
   522             getattr(self.Controler,method)()
       
   523             # Re-enable button 
       
   524             event.GetEventObject().Enable()
       
   525             
       
   526             if not push:
       
   527                 event.Skip()
       
   528         return OnButtonClick
       
   529     
       
   530     def GetChoiceCallBackFunction(self, choicectrl, path):
       
   531         def OnChoiceChanged(event):
       
   532             res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection())
       
   533             choicectrl.SetStringSelection(res)
       
   534             event.Skip()
       
   535         return OnChoiceChanged
       
   536     
       
   537     def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, path):
       
   538         def OnChoiceContentChanged(event):
       
   539             res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection())
       
   540             wx.CallAfter(self.RefreshConfNodeParamsSizer)
       
   541             event.Skip()
       
   542         return OnChoiceContentChanged
       
   543     
       
   544     def GetTextCtrlCallBackFunction(self, textctrl, path, refresh=False):
       
   545         def OnTextCtrlChanged(event):
       
   546             res = self.SetConfNodeParamsAttribute(path, textctrl.GetValue())
       
   547             if res != textctrl.GetValue():
       
   548                 if isinstance(textctrl, wx.SpinCtrl):
       
   549                     textctrl.SetValue(res)
       
   550                 else:
       
   551                     textctrl.ChangeValue(res)
       
   552             if refresh:
       
   553                 wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE, PAGETITLES)
       
   554                 wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName())
       
   555             event.Skip()
       
   556         return OnTextCtrlChanged
       
   557     
       
   558     def GetCheckBoxCallBackFunction(self, chkbx, path):
       
   559         def OnCheckBoxChanged(event):
       
   560             res = self.SetConfNodeParamsAttribute(path, chkbx.IsChecked())
       
   561             chkbx.SetValue(res)
       
   562             event.Skip()
       
   563         return OnCheckBoxChanged
       
   564     
       
   565     def GetBrowseCallBackFunction(self, name, textctrl, library, value_infos, path):
       
   566         infos = [value_infos]
       
   567         def OnBrowseButton(event):
       
   568             dialog = BrowseValuesLibraryDialog(self, name, library, infos[0])
       
   569             if dialog.ShowModal() == wx.ID_OK:
       
   570                 value, value_infos = self.SetConfNodeParamsAttribute(path, dialog.GetValueInfos())
       
   571                 textctrl.ChangeValue(value)
       
   572                 infos[0] = value_infos
       
   573             dialog.Destroy()
       
   574             event.Skip()
       
   575         return OnBrowseButton
       
   576     
       
   577     def RefreshScrollbars(self):
       
   578         self.ParamsEditor.GetBestSize()
       
   579         xstart, ystart = self.ParamsEditor.GetViewStart()
       
   580         window_size = self.ParamsEditor.GetClientSize()
       
   581         maxx, maxy = self.ParamsEditorSizer.GetMinSize()
       
   582         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
       
   583         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
       
   584         self.ParamsEditor.Scroll(posx, posy)
       
   585         self.ParamsEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
       
   586                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
       
   587     
       
   588     def OnWindowResize(self, event):
       
   589         self.RefreshScrollbars()
       
   590         event.Skip()
       
   591     
       
   592     def OnMouseWheel(self, event):
       
   593         if self.ScrollingEnabled:
       
   594             event.Skip()
       
   595