ConfTreeNodeEditor.py
changeset 814 5743cbdff669
parent 813 1460273f40ed
child 815 e4f24593a758
equal deleted inserted replaced
813:1460273f40ed 814:5743cbdff669
     1 
       
     2 import os
       
     3 import types
       
     4 
       
     5 import wx
       
     6 import wx.lib.buttons
       
     7 
       
     8 from controls import EditorPanel
       
     9 
       
    10 from PLCOpenEditor import TITLE, FILEMENU, PROJECTTREE, PAGETITLES
       
    11 
       
    12 from util.TextCtrlAutoComplete import TextCtrlAutoComplete
       
    13 from util.BrowseValuesLibraryDialog import BrowseValuesLibraryDialog
       
    14 from utils.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     
       
   147     def _init_ConfNodeEditor(self, prnt):
       
   148         self.ConfNodeEditor = None
       
   149     
       
   150     def _init_Editor(self, parent):
       
   151         self.Editor = wx.SplitterWindow(parent,
       
   152               style=wx.SUNKEN_BORDER|wx.SP_3D)
       
   153         self.SetNeedUpdating(True)
       
   154         self.SetMinimumPaneSize(1)
       
   155         
       
   156         if self.SHOW_PARAMS:
       
   157             self.ParamsEditor = wx.ScrolledWindow(self.Editor, 
       
   158                   style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL)
       
   159             self.ParamsEditor.SetBackgroundColour(WINDOW_COLOUR)
       
   160             self.ParamsEditor.Bind(wx.EVT_SIZE, self.OnWindowResize)
       
   161             self.ParamsEditor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
       
   162             
       
   163             # Variable allowing disabling of ParamsEditor scroll when Popup shown 
       
   164             self.ScrollingEnabled = True
       
   165             
       
   166             if self.SHOW_BASE_PARAMS:
       
   167                 self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
   168                 self.ParamsEditorSizer.AddGrowableCol(0)
       
   169                 self.ParamsEditorSizer.AddGrowableRow(1)
       
   170                 
       
   171                 self.ParamsEditor.SetSizer(self.ParamsEditorSizer)
       
   172                 
       
   173                 baseparamseditor_sizer = wx.BoxSizer(wx.HORIZONTAL)
       
   174                 self.ParamsEditorSizer.AddSizer(baseparamseditor_sizer, border=5, 
       
   175                       flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP)
       
   176                 
       
   177                 self.FullIECChannel = wx.StaticText(self.ParamsEditor, -1)
       
   178                 self.FullIECChannel.SetFont(
       
   179                     wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, 
       
   180                             wx.BOLD, faceName = faces["helv"]))
       
   181                 baseparamseditor_sizer.AddWindow(self.FullIECChannel, 
       
   182                       flag=wx.ALIGN_CENTER_VERTICAL)
       
   183                 
       
   184                 updownsizer = wx.BoxSizer(wx.VERTICAL)
       
   185                 baseparamseditor_sizer.AddSizer(updownsizer, border=5, 
       
   186                       flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL)
       
   187                 
       
   188                 self.IECCUpButton = wx.lib.buttons.GenBitmapTextButton(self.ParamsEditor, 
       
   189                       bitmap=GetBitmap('IECCDown'), size=wx.Size(16, 16), style=wx.NO_BORDER)
       
   190                 self.IECCUpButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(1), 
       
   191                       self.IECCUpButton)
       
   192                 updownsizer.AddWindow(self.IECCUpButton, flag=wx.ALIGN_LEFT)
       
   193                 
       
   194                 self.IECCDownButton = wx.lib.buttons.GenBitmapButton(self.ParamsEditor, 
       
   195                       bitmap=GetBitmap('IECCUp'), size=wx.Size(16, 16), style=wx.NO_BORDER)
       
   196                 self.IECCDownButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(-1), 
       
   197                       self.IECCDownButton)
       
   198                 updownsizer.AddWindow(self.IECCDownButton, flag=wx.ALIGN_LEFT)
       
   199                 
       
   200                 self.ConfNodeName = wx.TextCtrl(self.ParamsEditor, 
       
   201                       size=wx.Size(150, 25), style=wx.NO_BORDER)
       
   202                 self.ConfNodeName.SetFont(
       
   203                     wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, 
       
   204                             wx.BOLD, faceName = faces["helv"]))
       
   205                 self.ConfNodeName.Bind(wx.EVT_TEXT, 
       
   206                       self.GetTextCtrlCallBackFunction(self.ConfNodeName, "BaseParams.Name", True), 
       
   207                       self.ConfNodeName)
       
   208                 baseparamseditor_sizer.AddWindow(self.ConfNodeName, border=5, 
       
   209                       flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
       
   210                 
       
   211                 buttons_sizer = self.GenerateMethodButtonSizer()
       
   212                 baseparamseditor_sizer.AddSizer(buttons_sizer, flag=wx.ALIGN_CENTER)
       
   213             
       
   214             else:
       
   215                 self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=5)
       
   216                 self.ParamsEditorSizer.AddGrowableCol(0)
       
   217                 self.ParamsEditorSizer.AddGrowableRow(0)
       
   218             
       
   219             self.ConfNodeParamsSizer = wx.BoxSizer(wx.VERTICAL)
       
   220             self.ParamsEditorSizer.AddSizer(self.ConfNodeParamsSizer, border=5, 
       
   221                   flag=wx.LEFT|wx.RIGHT|wx.BOTTOM)
       
   222             
       
   223             self.RefreshConfNodeParamsSizer()
       
   224         else:
       
   225             self.ParamsEditor = None
       
   226         
       
   227         self._init_ConfNodeEditor(self.Editor)
       
   228             
       
   229         if self.ConfNodeEditor is not None:
       
   230             if self.ParamsEditor is not None:
       
   231                 min_size = self.ParamsEditorSizer.GetMinSize()
       
   232                 self.Editor.SplitHorizontally(self.ParamsEditor, 
       
   233                                               self.ConfNodeEditor, 
       
   234                                               min(min_size.height, 200))
       
   235             else:
       
   236                 self.Editor.Initialize(self.ConfNodeEditor)
       
   237         elif self.ParamsEditor is not None:
       
   238             self.Editor.Initialize(self.ParamsEditor)
       
   239     
       
   240     def __init__(self, parent, controler, window, tagname=""):
       
   241         EditorPanel.__init__(self, parent, tagname, window, controler)
       
   242         
       
   243         icon_name = self.Controler.GetIconName()
       
   244         if icon_name is not None:
       
   245             self.SetIcon(GetBitmap(icon_name))
       
   246         else:
       
   247             self.SetIcon(GetBitmap("Extension"))
       
   248         
       
   249     def __del__(self):
       
   250         self.Controler.OnCloseEditor(self)
       
   251     
       
   252     def GetTagName(self):
       
   253         return self.Controler.CTNFullName()
       
   254     
       
   255     def GetTitle(self):
       
   256         fullname = self.Controler.CTNFullName()
       
   257         if self.Controler.CTNTestModified():
       
   258             return "~%s~" % fullname
       
   259         return fullname
       
   260     
       
   261     def HasNoModel(self):
       
   262         return False
       
   263     
       
   264     def GetBufferState(self):
       
   265         return False, False
       
   266     
       
   267     def Undo(self):
       
   268         pass
       
   269     
       
   270     def Redo(self):
       
   271         pass
       
   272     
       
   273     def RefreshView(self):
       
   274         EditorPanel.RefreshView(self)
       
   275         if self.ParamsEditor is not None:
       
   276             if self.SHOW_BASE_PARAMS:
       
   277                 self.ConfNodeName.ChangeValue(self.Controler.MandatoryParams[1].getName())
       
   278                 self.RefreshIECChannelControlsState()
       
   279             self.RefreshConfNodeParamsSizer()
       
   280     
       
   281     def EnableScrolling(self, enable):
       
   282         self.ScrollingEnabled = enable
       
   283     
       
   284     def RefreshIECChannelControlsState(self):
       
   285         self.FullIECChannel.SetLabel(self.Controler.GetFullIEC_Channel())
       
   286         self.IECCDownButton.Enable(self.Controler.BaseParams.getIEC_Channel() > 0)
       
   287     
       
   288     def RefreshConfNodeParamsSizer(self):
       
   289         self.Freeze()
       
   290         self.ConfNodeParamsSizer.Clear(True)
       
   291         
       
   292         confnode_infos = self.Controler.GetParamsAttributes()
       
   293         if len(confnode_infos) > 0:
       
   294             self.GenerateSizerElements(self.ConfNodeParamsSizer, confnode_infos, None, False)
       
   295         
       
   296         self.ParamsEditorSizer.Layout()
       
   297         self.Thaw()
       
   298     
       
   299     def GenerateMethodButtonSizer(self):
       
   300         normal_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"])
       
   301         mouseover_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, underline=True, faceName = faces["helv"])
       
   302         
       
   303         msizer = wx.BoxSizer(wx.HORIZONTAL)
       
   304         
       
   305         for confnode_method in self.Controler.ConfNodeMethods:
       
   306             if "method" in confnode_method and confnode_method.get("shown",True):
       
   307                 button = GenBitmapTextButton(self.ParamsEditor,
       
   308                     bitmap=GetBitmap(confnode_method.get("bitmap", "Unknown")), 
       
   309                     label=confnode_method["name"], style=wx.NO_BORDER)
       
   310                 button.SetFont(normal_bt_font)
       
   311                 button.SetToolTipString(confnode_method["tooltip"])
       
   312                 if confnode_method.get("push", False):
       
   313                     button.Bind(wx.EVT_LEFT_DOWN, self.GetButtonCallBackFunction(confnode_method["method"], True))
       
   314                 else:
       
   315                     button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(confnode_method["method"]), button)
       
   316                 # a fancy underline on mouseover
       
   317                 def setFontStyle(b, s):
       
   318                     def fn(event):
       
   319                         b.SetFont(s)
       
   320                         b.Refresh()
       
   321                         event.Skip()
       
   322                     return fn
       
   323                 button.Bind(wx.EVT_ENTER_WINDOW, setFontStyle(button, mouseover_bt_font))
       
   324                 button.Bind(wx.EVT_LEAVE_WINDOW, setFontStyle(button, normal_bt_font))
       
   325                 #hack to force size to mini
       
   326                 if not confnode_method.get("enabled",True):
       
   327                     button.Disable()
       
   328                 msizer.AddWindow(button, flag=wx.ALIGN_CENTER)
       
   329         return msizer
       
   330     
       
   331     def GenerateSizerElements(self, sizer, elements, path, clean = True):
       
   332         if clean:
       
   333             sizer.Clear(True)
       
   334         first = True
       
   335         for element_infos in elements:
       
   336             if path:
       
   337                 element_path = "%s.%s"%(path, element_infos["name"])
       
   338             else:
       
   339                 element_path = element_infos["name"]
       
   340             if element_infos["type"] == "element":
       
   341                 label = element_infos["name"]
       
   342                 staticbox = wx.StaticBox(self.ParamsEditor, 
       
   343                       label=_(label), size=wx.Size(10, 0))
       
   344                 staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL)
       
   345                 if first:
       
   346                     sizer.AddSizer(staticboxsizer, border=5, 
       
   347                           flag=wx.GROW|wx.TOP|wx.BOTTOM)
       
   348                 else:
       
   349                     sizer.AddSizer(staticboxsizer, border=5, 
       
   350                           flag=wx.GROW|wx.BOTTOM)
       
   351                 self.GenerateSizerElements(staticboxsizer, 
       
   352                                            element_infos["children"], 
       
   353                                            element_path)
       
   354             else:
       
   355                 boxsizer = wx.FlexGridSizer(cols=3, rows=1)
       
   356                 boxsizer.AddGrowableCol(1)
       
   357                 if first:
       
   358                     sizer.AddSizer(boxsizer, border=5, 
       
   359                           flag=wx.GROW|wx.ALL)
       
   360                 else:
       
   361                     sizer.AddSizer(boxsizer, border=5, 
       
   362                           flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
       
   363                 
       
   364                 staticbitmap = GenStaticBitmap(ID=-1, bitmapname=element_infos["name"],
       
   365                     name="%s_bitmap"%element_infos["name"], parent=self.ParamsEditor,
       
   366                     pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0)
       
   367                 boxsizer.AddWindow(staticbitmap, border=5, flag=wx.RIGHT)
       
   368                 
       
   369                 statictext = wx.StaticText(self.ParamsEditor, 
       
   370                       label="%s:"%_(element_infos["name"]))
       
   371                 boxsizer.AddWindow(statictext, border=5, 
       
   372                       flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT)
       
   373                 
       
   374                 if isinstance(element_infos["type"], types.ListType):
       
   375                     if isinstance(element_infos["value"], types.TupleType):
       
   376                         browse_boxsizer = wx.BoxSizer(wx.HORIZONTAL)
       
   377                         boxsizer.AddSizer(browse_boxsizer)
       
   378                         
       
   379                         textctrl = wx.TextCtrl(self.ParamsEditor, 
       
   380                               size=wx.Size(275, 25), style=wx.TE_READONLY)
       
   381                         if element_infos["value"] is not None:
       
   382                             textctrl.SetValue(element_infos["value"][0])
       
   383                             value_infos = element_infos["value"][1]
       
   384                         else:
       
   385                             value_infos = None
       
   386                         browse_boxsizer.AddWindow(textctrl)
       
   387                         
       
   388                         button = wx.Button(self.ParamsEditor, 
       
   389                               label="...", size=wx.Size(25, 25))
       
   390                         browse_boxsizer.AddWindow(button)
       
   391                         button.Bind(wx.EVT_BUTTON, 
       
   392                                     self.GetBrowseCallBackFunction(element_infos["name"], textctrl, element_infos["type"], 
       
   393                                                                    value_infos, element_path), 
       
   394                                     button)
       
   395                     else:
       
   396                         combobox = wx.ComboBox(self.ParamsEditor, 
       
   397                               size=wx.Size(300, 28), style=wx.CB_READONLY)
       
   398                         boxsizer.AddWindow(combobox)
       
   399                         
       
   400                         if element_infos["use"] == "optional":
       
   401                             combobox.Append("")
       
   402                         if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], types.TupleType):
       
   403                             for choice, xsdclass in element_infos["type"]:
       
   404                                 combobox.Append(choice)
       
   405                             name = element_infos["name"]
       
   406                             value = element_infos["value"]
       
   407                         
       
   408                             staticbox = wx.StaticBox(self.ParamsEditor, 
       
   409                                   label="%s - %s"%(_(name), _(value)), size=wx.Size(10, 0))
       
   410                             staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL)
       
   411                             sizer.AddSizer(staticboxsizer, border=5, flag=wx.GROW|wx.BOTTOM)
       
   412                             self.GenerateSizerElements(staticboxsizer, element_infos["children"], element_path)
       
   413                             callback = self.GetChoiceContentCallBackFunction(combobox, staticboxsizer, element_path)
       
   414                         else:
       
   415                             for choice in element_infos["type"]:
       
   416                                 combobox.Append(choice)
       
   417                             callback = self.GetChoiceCallBackFunction(combobox, element_path)
       
   418                         if element_infos["value"] is None:
       
   419                             combobox.SetStringSelection("")
       
   420                         else:
       
   421                             combobox.SetStringSelection(element_infos["value"])
       
   422                         combobox.Bind(wx.EVT_COMBOBOX, callback, combobox)
       
   423                 
       
   424                 elif isinstance(element_infos["type"], types.DictType):
       
   425                     scmin = -(2**31)
       
   426                     scmax = 2**31-1
       
   427                     if "min" in element_infos["type"]:
       
   428                         scmin = element_infos["type"]["min"]
       
   429                     if "max" in element_infos["type"]:
       
   430                         scmax = element_infos["type"]["max"]
       
   431                     spinctrl = wx.SpinCtrl(self.ParamsEditor, 
       
   432                           size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT)
       
   433                     spinctrl.SetRange(scmin, scmax)
       
   434                     boxsizer.AddWindow(spinctrl)
       
   435                     if element_infos["value"] is not None:
       
   436                         spinctrl.SetValue(element_infos["value"])
       
   437                     spinctrl.Bind(wx.EVT_SPINCTRL, 
       
   438                                   self.GetTextCtrlCallBackFunction(spinctrl, element_path),
       
   439                                   spinctrl)
       
   440                 
       
   441                 else:
       
   442                     if element_infos["type"] == "boolean":
       
   443                         checkbox = wx.CheckBox(self.ParamsEditor, size=wx.Size(17, 25))
       
   444                         boxsizer.AddWindow(checkbox)
       
   445                         if element_infos["value"] is not None:
       
   446                             checkbox.SetValue(element_infos["value"])
       
   447                         checkbox.Bind(wx.EVT_CHECKBOX, 
       
   448                                       self.GetCheckBoxCallBackFunction(checkbox, element_path), 
       
   449                                       checkbox)
       
   450                     
       
   451                     elif element_infos["type"] in ["unsignedLong", "long","integer"]:
       
   452                         if element_infos["type"].startswith("unsigned"):
       
   453                             scmin = 0
       
   454                         else:
       
   455                             scmin = -(2**31)
       
   456                         scmax = 2**31-1
       
   457                         spinctrl = wx.SpinCtrl(self.ParamsEditor, 
       
   458                               size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT)
       
   459                         spinctrl.SetRange(scmin, scmax)
       
   460                         boxsizer.AddWindow(spinctrl)
       
   461                         if element_infos["value"] is not None:
       
   462                             spinctrl.SetValue(element_infos["value"])
       
   463                         spinctrl.Bind(wx.EVT_SPINCTRL, 
       
   464                                       self.GetTextCtrlCallBackFunction(spinctrl, element_path), 
       
   465                                       spinctrl)
       
   466                     
       
   467                     else:
       
   468                         choices = self.ParentWindow.GetConfigEntry(element_path, [""])
       
   469                         textctrl = TextCtrlAutoComplete(name=element_infos["name"], 
       
   470                                                         parent=self.ParamsEditor, 
       
   471                                                         appframe=self, 
       
   472                                                         choices=choices, 
       
   473                                                         element_path=element_path,
       
   474                                                         size=wx.Size(300, 25))
       
   475                         
       
   476                         boxsizer.AddWindow(textctrl)
       
   477                         if element_infos["value"] is not None:
       
   478                             textctrl.ChangeValue(str(element_infos["value"]))
       
   479                         textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, element_path))
       
   480             first = False
       
   481     
       
   482     
       
   483     def GetItemChannelChangedFunction(self, dir):
       
   484         def OnConfNodeTreeItemChannelChanged(event):
       
   485             confnode_IECChannel = self.Controler.BaseParams.getIEC_Channel()
       
   486             res = self.SetConfNodeParamsAttribute("BaseParams.IEC_Channel", confnode_IECChannel + dir)
       
   487             wx.CallAfter(self.RefreshIECChannelControlsState)
       
   488             wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE)
       
   489             wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName())
       
   490             event.Skip()
       
   491         return OnConfNodeTreeItemChannelChanged
       
   492     
       
   493     def SetConfNodeParamsAttribute(self, *args, **kwargs):
       
   494         res, StructChanged = self.Controler.SetParamsAttribute(*args, **kwargs)
       
   495         if StructChanged:
       
   496             wx.CallAfter(self.RefreshConfNodeParamsSizer)
       
   497         wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU)
       
   498         return res
       
   499     
       
   500     def GetButtonCallBackFunction(self, method, push=False):
       
   501         """ Generate the callbackfunc for a given confnode method"""
       
   502         def OnButtonClick(event):
       
   503             # Disable button to prevent re-entrant call 
       
   504             event.GetEventObject().Disable()
       
   505             # Call
       
   506             getattr(self.Controler,method)()
       
   507             # Re-enable button 
       
   508             event.GetEventObject().Enable()
       
   509             
       
   510             if not push:
       
   511                 event.Skip()
       
   512         return OnButtonClick
       
   513     
       
   514     def GetChoiceCallBackFunction(self, choicectrl, path):
       
   515         def OnChoiceChanged(event):
       
   516             res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection())
       
   517             choicectrl.SetStringSelection(res)
       
   518             event.Skip()
       
   519         return OnChoiceChanged
       
   520     
       
   521     def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, path):
       
   522         def OnChoiceContentChanged(event):
       
   523             res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection())
       
   524             wx.CallAfter(self.RefreshConfNodeParamsSizer)
       
   525             event.Skip()
       
   526         return OnChoiceContentChanged
       
   527     
       
   528     def GetTextCtrlCallBackFunction(self, textctrl, path, refresh=False):
       
   529         def OnTextCtrlChanged(event):
       
   530             res = self.SetConfNodeParamsAttribute(path, textctrl.GetValue())
       
   531             if res != textctrl.GetValue():
       
   532                 textctrl.ChangeValue(res)
       
   533             if refresh:
       
   534                 wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE, PAGETITLES)
       
   535                 wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName())
       
   536             event.Skip()
       
   537         return OnTextCtrlChanged
       
   538     
       
   539     def GetCheckBoxCallBackFunction(self, chkbx, path):
       
   540         def OnCheckBoxChanged(event):
       
   541             res = self.SetConfNodeParamsAttribute(path, chkbx.IsChecked())
       
   542             chkbx.SetValue(res)
       
   543             event.Skip()
       
   544         return OnCheckBoxChanged
       
   545     
       
   546     def GetBrowseCallBackFunction(self, name, textctrl, library, value_infos, path):
       
   547         infos = [value_infos]
       
   548         def OnBrowseButton(event):
       
   549             dialog = BrowseValuesLibraryDialog(self, name, library, infos[0])
       
   550             if dialog.ShowModal() == wx.ID_OK:
       
   551                 value, value_infos = self.SetConfNodeParamsAttribute(path, dialog.GetValueInfos())
       
   552                 textctrl.ChangeValue(value)
       
   553                 infos[0] = value_infos
       
   554             dialog.Destroy()
       
   555             event.Skip()
       
   556         return OnBrowseButton
       
   557     
       
   558     def OnWindowResize(self, event):
       
   559         self.ParamsEditor.GetBestSize()
       
   560         xstart, ystart = self.ParamsEditor.GetViewStart()
       
   561         window_size = self.ParamsEditor.GetClientSize()
       
   562         maxx, maxy = self.ParamsEditorSizer.GetMinSize()
       
   563         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
       
   564         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
       
   565         self.ParamsEditor.Scroll(posx, posy)
       
   566         self.ParamsEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
       
   567                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
       
   568         event.Skip()
       
   569     
       
   570     def OnMouseWheel(self, event):
       
   571         if self.ScrollingEnabled:
       
   572             event.Skip()
       
   573