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