controls/VariablePanel.py
changeset 1470 f65ab5ff91d1
parent 1414 8a3998d10b81
child 1416 d4222bad4841
equal deleted inserted replaced
1469:86797748c2a2 1470:f65ab5ff91d1
     1 #!/usr/bin/env python
     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     2 # -*- coding: utf-8 -*-
     3 
     3 
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
     5 #based on the plcopen standard. 
     5 #based on the plcopen standard.
     6 #
     6 #
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     8 #
     8 #
     9 #See COPYING file for copyrights details.
     9 #See COPYING file for copyrights details.
    10 #
    10 #
    28 
    28 
    29 import wx
    29 import wx
    30 import wx.grid
    30 import wx.grid
    31 import wx.lib.buttons
    31 import wx.lib.buttons
    32 
    32 
    33 from plcopen.structures import LOCATIONDATATYPES, TestIdentifier, IEC_KEYWORDS
    33 from plcopen.structures import LOCATIONDATATYPES, TestIdentifier, IEC_KEYWORDS, DefaultType
    34 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD, ERROR_HIGHLIGHT
    34 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD, ERROR_HIGHLIGHT
    35 from dialogs.ArrayTypeDialog import ArrayTypeDialog
    35 from dialogs.ArrayTypeDialog import ArrayTypeDialog
    36 from CustomGrid import CustomGrid
    36 from CustomGrid import CustomGrid
    37 from CustomTable import CustomTable
    37 from CustomTable import CustomTable
    38 from LocationCellEditor import LocationCellEditor
    38 from LocationCellEditor import LocationCellEditor
    41 
    41 
    42 #-------------------------------------------------------------------------------
    42 #-------------------------------------------------------------------------------
    43 #                                 Helpers
    43 #                                 Helpers
    44 #-------------------------------------------------------------------------------
    44 #-------------------------------------------------------------------------------
    45 
    45 
    46 def AppendMenu(parent, help, id, kind, text):
    46 [TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE,
    47     if wx.VERSION >= (2, 6, 0):
       
    48         parent.Append(help=help, id=id, kind=kind, text=text)
       
    49     else:
       
    50         parent.Append(helpString=help, id=id, kind=kind, item=text)
       
    51 
       
    52 [TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE, 
       
    53  POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
    47  POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
    54 ] = range(10)
    48 ] = range(10)
    55 
    49 
    56 def GetVariableTableColnames(location):
    50 def GetVariableTableColnames(location):
    57     _ = lambda x : x
    51     _ = lambda x : x
    71     return options
    65     return options
    72 OPTIONS_DICT = dict([(_(option), option) for option in GetOptions()])
    66 OPTIONS_DICT = dict([(_(option), option) for option in GetOptions()])
    73 
    67 
    74 def GetFilterChoiceTransfer():
    68 def GetFilterChoiceTransfer():
    75     _ = lambda x : x
    69     _ = lambda x : x
    76     return {_("All"): _("All"), _("Interface"): _("Interface"), 
    70     return {_("All"): _("All"), _("Interface"): _("Interface"),
    77             _("   Input"): _("Input"), _("   Output"): _("Output"), _("   InOut"): _("InOut"), 
    71             _("   Input"): _("Input"), _("   Output"): _("Output"), _("   InOut"): _("InOut"),
    78             _("   External"): _("External"), _("Variables"): _("Variables"), _("   Local"): _("Local"),
    72             _("   External"): _("External"), _("Variables"): _("Variables"), _("   Local"): _("Local"),
    79             _("   Temp"): _("Temp"), _("Global"): _("Global")}#, _("Access") : _("Access")}
    73             _("   Temp"): _("Temp"), _("Global"): _("Global")}#, _("Access") : _("Access")}
    80 VARIABLE_CHOICES_DICT = dict([(_(_class), _class) for _class in GetFilterChoiceTransfer().iterkeys()])
    74 VARIABLE_CHOICES_DICT = dict([(_(_class), _class) for _class in GetFilterChoiceTransfer().iterkeys()])
    81 VARIABLE_CLASSES_DICT = dict([(_(_class), _class) for _class in GetFilterChoiceTransfer().itervalues()])
    75 VARIABLE_CLASSES_DICT = dict([(_(_class), _class) for _class in GetFilterChoiceTransfer().itervalues()])
    82 
    76 
    95 #-------------------------------------------------------------------------------
    89 #-------------------------------------------------------------------------------
    96 #                            Variables Panel Table
    90 #                            Variables Panel Table
    97 #-------------------------------------------------------------------------------
    91 #-------------------------------------------------------------------------------
    98 
    92 
    99 class VariableTable(CustomTable):
    93 class VariableTable(CustomTable):
   100     
    94 
   101     """
    95     """
   102     A custom wx.grid.Grid Table using user supplied data
    96     A custom wx.grid.Grid Table using user supplied data
   103     """
    97     """
   104     def __init__(self, parent, data, colnames):
    98     def __init__(self, parent, data, colnames):
   105         # The base class must be initialized *first*
    99         # The base class must be initialized *first*
   106         CustomTable.__init__(self, parent, data, colnames)
   100         CustomTable.__init__(self, parent, data, colnames)
   107         self.old_value = None
   101         self.old_value = None
   108     
   102 
   109     def GetValueByName(self, row, colname):
   103     def GetValueByName(self, row, colname):
   110         if row < self.GetNumberRows():
   104         if row < self.GetNumberRows():
   111             return getattr(self.data[row], colname)
   105             return getattr(self.data[row], colname)
   112 
   106 
   113     def SetValueByName(self, row, colname, value):
   107     def SetValueByName(self, row, colname, value):
   114         if row < self.GetNumberRows():
   108         if row < self.GetNumberRows():
   115             setattr(self.data[row], colname, value)
   109             setattr(self.data[row], colname, value)
   116     
   110 
   117     def GetValue(self, row, col):
   111     def GetValue(self, row, col):
   118         if row < self.GetNumberRows():
   112         if row < self.GetNumberRows():
   119             if col == 0:
   113             if col == 0:
   120                 return self.data[row].Number
   114                 return self.data[row].Number
   121             colname = self.GetColLabelValue(col, False)
   115             colname = self.GetColLabelValue(col, False)
   128             if not isinstance(value, (StringType, UnicodeType)):
   122             if not isinstance(value, (StringType, UnicodeType)):
   129                 value = str(value)
   123                 value = str(value)
   130             if colname in ["Class", "Option"]:
   124             if colname in ["Class", "Option"]:
   131                 return _(value)
   125                 return _(value)
   132             return value
   126             return value
   133     
   127 
   134     def SetValue(self, row, col, value):
   128     def SetValue(self, row, col, value):
   135         if col < len(self.colnames):
   129         if col < len(self.colnames):
   136             colname = self.GetColLabelValue(col, False)
   130             colname = self.GetColLabelValue(col, False)
   137             if colname == "Name":
   131             if colname == "Name":
   138                 self.old_value = getattr(self.data[row], colname)
   132                 self.old_value = getattr(self.data[row], colname)
   207                                 if self.Parent.IsFunctionBlockType(var_type):
   201                                 if self.Parent.IsFunctionBlockType(var_type):
   208                                     excluded.extend(["Local","Temp"])
   202                                     excluded.extend(["Local","Temp"])
   209                                 editor.SetParameters(",".join([_(choice) for choice in self.Parent.ClassList if choice not in excluded]))
   203                                 editor.SetParameters(",".join([_(choice) for choice in self.Parent.ClassList if choice not in excluded]))
   210                     elif colname != "Documentation":
   204                     elif colname != "Documentation":
   211                         grid.SetReadOnly(row, col, True)
   205                         grid.SetReadOnly(row, col, True)
   212                 
   206 
   213                 grid.SetCellEditor(row, col, editor)
   207                 grid.SetCellEditor(row, col, editor)
   214                 grid.SetCellRenderer(row, col, renderer)
   208                 grid.SetCellRenderer(row, col, renderer)
   215                 
   209 
   216                 if colname == "Location" and LOCATION_MODEL.match(self.GetValueByName(row, colname)) is None:
   210                 if colname == "Location" and LOCATION_MODEL.match(self.GetValueByName(row, colname)) is None:
   217                     highlight_colours = ERROR_HIGHLIGHT
   211                     highlight_colours = ERROR_HIGHLIGHT
   218                 else:
   212                 else:
   219                     highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
   213                     highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
   220                 grid.SetCellBackgroundColour(row, col, highlight_colours[0])
   214                 grid.SetCellBackgroundColour(row, col, highlight_colours[0])
   221                 grid.SetCellTextColour(row, col, highlight_colours[1])
   215                 grid.SetCellTextColour(row, col, highlight_colours[1])
   222             self.ResizeRow(grid, row)
   216             self.ResizeRow(grid, row)
   223 
   217 
   224 #-------------------------------------------------------------------------------
   218 #-------------------------------------------------------------------------------
   225 #                         Variable Panel Drop Target
   219 #                         Variable Panel Drop Target
   226 #-------------------------------------------------------------------------------   
   220 #-------------------------------------------------------------------------------
   227 
   221 
   228 class VariableDropTarget(wx.TextDropTarget):
   222 class VariableDropTarget(wx.TextDropTarget):
   229     '''
   223     '''
   230     This allows dragging a variable location from somewhere to the Location
   224     This allows dragging a variable location from somewhere to the Location
   231     column of a variable row.
   225     column of a variable row.
   232     
   226 
   233     The drag source should be a TextDataObject containing a Python tuple like:
   227     The drag source should be a TextDataObject containing a Python tuple like:
   234         ('%ID0.0.0', 'location', 'REAL')
   228         ('%ID0.0.0', 'location', 'REAL')
   235     
   229 
   236     c_ext/CFileEditor.py has an example of this (you can drag a C extension
   230     c_ext/CFileEditor.py has an example of this (you can drag a C extension
   237     variable to the Location column of the variable panel).
   231     variable to the Location column of the variable panel).
   238     '''
   232     '''
   239     def __init__(self, parent):
   233     def __init__(self, parent):
   240         wx.TextDropTarget.__init__(self)
   234         wx.TextDropTarget.__init__(self)
   241         self.ParentWindow = parent
   235         self.ParentWindow = parent
   242     
   236 
   243     def OnDropText(self, x, y, data):
   237     def OnDropText(self, x, y, data):
   244         self.ParentWindow.ParentWindow.Select()
   238         self.ParentWindow.ParentWindow.Select()
   245         x, y = self.ParentWindow.VariablesGrid.CalcUnscrolledPosition(x, y)
   239         x, y = self.ParentWindow.VariablesGrid.CalcUnscrolledPosition(x, y)
   246         col = self.ParentWindow.VariablesGrid.XToCol(x)
   240         col = self.ParentWindow.VariablesGrid.XToCol(x)
   247         row = self.ParentWindow.VariablesGrid.YToRow(y - self.ParentWindow.VariablesGrid.GetColLabelSize())
   241         row = self.ParentWindow.VariablesGrid.YToRow(y - self.ParentWindow.VariablesGrid.GetColLabelSize())
   248         message = None
   242         message = None
   249         element_type = self.ParentWindow.ElementType
   243         element_type = self.ParentWindow.ElementType
   250         try:
   244         try:
   251             values = eval(data)    
   245             values = eval(data)
   252         except:
   246         except:
   253             message = _("Invalid value \"%s\" for variable grid element")%data
   247             message = _("Invalid value \"%s\" for variable grid element")%data
   254             values = None
   248             values = None
   255         if not isinstance(values, TupleType):
   249         if not isinstance(values, TupleType):
   256             message = _("Invalid value \"%s\" for variable grid element")%data
   250             message = _("Invalid value \"%s\" for variable grid element")%data
   265                         message = _("Can only give a location to local or global variables")
   259                         message = _("Can only give a location to local or global variables")
   266                     else:
   260                     else:
   267                         location = values[0]
   261                         location = values[0]
   268                         variable_type = self.ParentWindow.Table.GetValueByName(row, "Type")
   262                         variable_type = self.ParentWindow.Table.GetValueByName(row, "Type")
   269                         base_type = self.ParentWindow.Controler.GetBaseType(variable_type)
   263                         base_type = self.ParentWindow.Controler.GetBaseType(variable_type)
   270                         
   264 
   271                         if values[2] is not None:
   265                         if values[2] is not None:
   272                             base_location_type = self.ParentWindow.Controler.GetBaseType(values[2])
   266                             base_location_type = self.ParentWindow.Controler.GetBaseType(values[2])
   273                             if values[2] != variable_type and base_type != base_location_type:
   267                             if values[2] != variable_type and base_type != base_location_type:
   274                                 message = _("Incompatible data types between \"%s\" and \"%s\"")%(values[2], variable_type)
   268                                 message = _("Incompatible data types between \"%s\" and \"%s\"")%(values[2], variable_type)
   275                         
   269 
   276                         if message is None:
   270                         if message is None:
   277                             if not location.startswith("%"):
   271                             if not location.startswith("%"):
   278                                 if location[0].isdigit() and base_type != "BOOL":
   272                                 if location[0].isdigit() and base_type != "BOOL":
   279                                     message = _("Incompatible size of data between \"%s\" and \"BOOL\"")%location
   273                                     message = _("Incompatible size of data between \"%s\" and \"BOOL\"")%location
   280                                 elif location[0] not in LOCATIONDATATYPES:
   274                                 elif location[0] not in LOCATIONDATATYPES:
   281                                     message = _("Unrecognized data size \"%s\"")%location[0]
   275                                     message = _("Unrecognized data size \"%s\"")%location[0]
   282                                 elif base_type not in LOCATIONDATATYPES[location[0]]:
   276                                 elif base_type not in LOCATIONDATATYPES[location[0]]:
   283                                     message = _("Incompatible size of data between \"%s\" and \"%s\"")%(location, variable_type)
   277                                     message = _("Incompatible size of data between \"%s\" and \"%s\"")%(location, variable_type)
   284                                 else:
   278                                 else:
   285                                     dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow.ParentWindow, 
   279                                     dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow.ParentWindow,
   286                                           _("Select a variable class:"), _("Variable class"), 
   280                                           _("Select a variable class:"), _("Variable class"),
   287                                           ["Input", "Output", "Memory"], 
   281                                           ["Input", "Output", "Memory"],
   288                                           wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   282                                           wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   289                                     if dialog.ShowModal() == wx.ID_OK:
   283                                     if dialog.ShowModal() == wx.ID_OK:
   290                                         selected = dialog.GetSelection()
   284                                         selected = dialog.GetSelection()
   291                                     else:
   285                                     else:
   292                                         selected = None
   286                                         selected = None
   297                                         location = "%I" + location
   291                                         location = "%I" + location
   298                                     elif selected == 1:
   292                                     elif selected == 1:
   299                                         location = "%Q" + location
   293                                         location = "%Q" + location
   300                                     else:
   294                                     else:
   301                                         location = "%M" + location
   295                                         location = "%M" + location
   302                                         
   296 
   303                             if message is None:
   297                             if message is None:
   304                                 self.ParentWindow.Table.SetValue(row, col, location)
   298                                 self.ParentWindow.Table.SetValue(row, col, location)
   305                                 self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid)
   299                                 self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid)
   306                                 self.ParentWindow.SaveValues()
   300                                 self.ParentWindow.SaveValues()
   307                 elif colname == "Initial Value" and values[1] == "Constant":
   301                 elif colname == "Initial Value" and values[1] == "Constant":
   309                         message = _("Can't set an initial value to a function block instance")
   303                         message = _("Can't set an initial value to a function block instance")
   310                     else:
   304                     else:
   311                         self.ParentWindow.Table.SetValue(row, col, values[0])
   305                         self.ParentWindow.Table.SetValue(row, col, values[0])
   312                         self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid)
   306                         self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid)
   313                         self.ParentWindow.SaveValues()
   307                         self.ParentWindow.SaveValues()
   314             elif (element_type not in ["config", "resource", "function"] and values[1] == "Global" and 
   308             elif (element_type not in ["config", "resource", "function"] and values[1] == "Global" and
   315                   self.ParentWindow.Filter in ["All", "Interface", "External"] or
   309                   self.ParentWindow.Filter in ["All", "Interface", "External"] or
   316                   element_type != "function" and values[1] == "location"):
   310                   element_type != "function" and values[1] == "location"):
   317                 if values[1] == "location":
   311                 if values[1] == "location":
   318                     var_name = values[3]
   312                     var_name = values[3]
   319                 else:
   313                 else:
   320                     var_name = values[0]
   314                     var_name = values[0]
   321                 tagname = self.ParentWindow.GetTagName()
   315                 tagname = self.ParentWindow.GetTagName()
   322                 if var_name.upper() in [name.upper() 
   316                 if var_name.upper() in [name.upper()
   323                         for name in self.ParentWindow.Controler.\
   317                         for name in self.ParentWindow.Controler.\
   324                             GetProjectPouNames(self.ParentWindow.Debug)]:
   318                             GetProjectPouNames(self.ParentWindow.Debug)]:
   325                     message = _("\"%s\" pou already exists!")%var_name
   319                     message = _("\"%s\" pou already exists!")%var_name
   326                 elif not var_name.upper() in [name.upper() 
   320                 elif not var_name.upper() in [name.upper()
   327                         for name in self.ParentWindow.Controler.\
   321                         for name in self.ParentWindow.Controler.\
   328                             GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
   322                             GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
   329                     var_infos = self.ParentWindow.DefaultValue.copy()
   323                     var_infos = self.ParentWindow.DefaultValue.copy()
   330                     var_infos.Name = var_name
   324                     var_infos.Name = var_name
   331                     var_infos.Type = values[2]
   325                     var_infos.Type = values[2]
   332                     if values[1] == "location":
   326                     if values[1] == "location":
   333                         location = values[0]
   327                         location = values[0]
   334                         if not location.startswith("%"):
   328                         if not location.startswith("%"):
   335                             dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow.ParentWindow, 
   329                             dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow.ParentWindow,
   336                                   _("Select a variable class:"), _("Variable class"), 
   330                                   _("Select a variable class:"), _("Variable class"),
   337                                   ["Input", "Output", "Memory"], 
   331                                   ["Input", "Output", "Memory"],
   338                                   wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   332                                   wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   339                             if dialog.ShowModal() == wx.ID_OK:
   333                             if dialog.ShowModal() == wx.ID_OK:
   340                                 selected = dialog.GetSelection()
   334                                 selected = dialog.GetSelection()
   341                             else:
   335                             else:
   342                                 selected = None
   336                                 selected = None
   352                         if element_type == "functionBlock":
   346                         if element_type == "functionBlock":
   353                             configs = self.ParentWindow.Controler.GetProjectConfigNames(
   347                             configs = self.ParentWindow.Controler.GetProjectConfigNames(
   354                                                                 self.ParentWindow.Debug)
   348                                                                 self.ParentWindow.Debug)
   355                             if len(configs) == 0:
   349                             if len(configs) == 0:
   356                                 return
   350                                 return
   357                             if not var_name.upper() in [name.upper() 
   351                             if not var_name.upper() in [name.upper()
   358                                 for name in self.ParentWindow.Controler.\
   352                                 for name in self.ParentWindow.Controler.\
   359                                     GetConfigurationVariableNames(configs[0])]:
   353                                     GetConfigurationVariableNames(configs[0])]:
   360                                 self.ParentWindow.Controler.AddConfigurationGlobalVar(
   354                                 self.ParentWindow.Controler.AddConfigurationGlobalVar(
   361                                     configs[0], values[2], var_name, location, "")
   355                                     configs[0], values[2], var_name, location, "")
   362                             var_infos.Class = "External"
   356                             var_infos.Class = "External"
   370                         var_infos.Class = "External"
   364                         var_infos.Class = "External"
   371                     var_infos.Number = len(self.ParentWindow.Values)
   365                     var_infos.Number = len(self.ParentWindow.Values)
   372                     self.ParentWindow.Values.append(var_infos)
   366                     self.ParentWindow.Values.append(var_infos)
   373                     self.ParentWindow.SaveValues()
   367                     self.ParentWindow.SaveValues()
   374                     self.ParentWindow.RefreshValues()
   368                     self.ParentWindow.RefreshValues()
   375         
   369 
   376         if message is not None:
   370         if message is not None:
   377             wx.CallAfter(self.ShowMessage, message)
   371             wx.CallAfter(self.ShowMessage, message)
   378     
   372 
   379     def ShowMessage(self, message):
   373     def ShowMessage(self, message):
   380         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
   374         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
   381         message.ShowModal()
   375         message.ShowModal()
   382         message.Destroy()
   376         message.Destroy()
   383 
   377 
   384 #-------------------------------------------------------------------------------
   378 #-------------------------------------------------------------------------------
   385 #                               Variable Panel
   379 #                               Variable Panel
   386 #-------------------------------------------------------------------------------   
   380 #-------------------------------------------------------------------------------
   387 
   381 
   388 class VariablePanel(wx.Panel):
   382 class VariablePanel(wx.Panel):
   389     
   383 
   390     def __init__(self, parent, window, controler, element_type, debug=False):
   384     def __init__(self, parent, window, controler, element_type, debug=False):
   391         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
   385         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
   392         
   386 
   393         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=0)
   387         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=0)
   394         self.MainSizer.AddGrowableCol(0)
   388         self.MainSizer.AddGrowableCol(0)
   395         self.MainSizer.AddGrowableRow(1)
   389         self.MainSizer.AddGrowableRow(1)
   396         
   390 
   397         controls_sizer = wx.FlexGridSizer(cols=10, hgap=5, rows=1, vgap=5)
   391         controls_sizer = wx.FlexGridSizer(cols=10, hgap=5, rows=1, vgap=5)
   398         controls_sizer.AddGrowableCol(5)
   392         controls_sizer.AddGrowableCol(5)
   399         controls_sizer.AddGrowableRow(0)
   393         controls_sizer.AddGrowableRow(0)
   400         self.MainSizer.AddSizer(controls_sizer, border=5, flag=wx.GROW|wx.ALL)
   394         self.MainSizer.AddSizer(controls_sizer, border=5, flag=wx.GROW|wx.ALL)
   401         
   395 
   402         self.ReturnTypeLabel = wx.StaticText(self, label=_('Return Type:'))
   396         self.ReturnTypeLabel = wx.StaticText(self, label=_('Return Type:'))
   403         controls_sizer.AddWindow(self.ReturnTypeLabel, flag=wx.ALIGN_CENTER_VERTICAL)
   397         controls_sizer.AddWindow(self.ReturnTypeLabel, flag=wx.ALIGN_CENTER_VERTICAL)
   404         
   398 
   405         self.ReturnType = wx.ComboBox(self,
   399         self.ReturnType = wx.ComboBox(self,
   406               size=wx.Size(145, -1), style=wx.CB_READONLY)
   400               size=wx.Size(145, -1), style=wx.CB_READONLY)
   407         self.Bind(wx.EVT_COMBOBOX, self.OnReturnTypeChanged, self.ReturnType)
   401         self.Bind(wx.EVT_COMBOBOX, self.OnReturnTypeChanged, self.ReturnType)
   408         controls_sizer.AddWindow(self.ReturnType)
   402         controls_sizer.AddWindow(self.ReturnType)
   409         
   403 
   410         self.DescriptionLabel = wx.StaticText(self, label=_('Description:'))
   404         self.DescriptionLabel = wx.StaticText(self, label=_('Description:'))
   411         controls_sizer.AddWindow(self.DescriptionLabel, flag=wx.ALIGN_CENTER_VERTICAL)
   405         controls_sizer.AddWindow(self.DescriptionLabel, flag=wx.ALIGN_CENTER_VERTICAL)
   412         
   406 
   413         self.Description = wx.TextCtrl(self,
   407         self.Description = wx.TextCtrl(self,
   414               size=wx.Size(250, -1), style=wx.TE_PROCESS_ENTER)
   408               size=wx.Size(250, -1), style=wx.TE_PROCESS_ENTER)
   415         self.Bind(wx.EVT_TEXT_ENTER, self.OnDescriptionChanged, self.Description)
   409         self.Bind(wx.EVT_TEXT_ENTER, self.OnDescriptionChanged, self.Description)
   416         self.Description.Bind(wx.EVT_KILL_FOCUS, self.OnDescriptionChanged)
   410         self.Description.Bind(wx.EVT_KILL_FOCUS, self.OnDescriptionChanged)
   417         controls_sizer.AddWindow(self.Description) 
   411         controls_sizer.AddWindow(self.Description)
   418         
   412 
   419         class_filter_label = wx.StaticText(self, label=_('Class Filter:'))
   413         class_filter_label = wx.StaticText(self, label=_('Class Filter:'))
   420         controls_sizer.AddWindow(class_filter_label, flag=wx.ALIGN_CENTER_VERTICAL)
   414         controls_sizer.AddWindow(class_filter_label, flag=wx.ALIGN_CENTER_VERTICAL)
   421         
   415 
   422         self.ClassFilter = wx.ComboBox(self, 
   416         self.ClassFilter = wx.ComboBox(self,
   423               size=wx.Size(145, -1), style=wx.CB_READONLY)
   417               size=wx.Size(145, -1), style=wx.CB_READONLY)
   424         self.Bind(wx.EVT_COMBOBOX, self.OnClassFilter, self.ClassFilter)
   418         self.Bind(wx.EVT_COMBOBOX, self.OnClassFilter, self.ClassFilter)
   425         controls_sizer.AddWindow(self.ClassFilter)
   419         controls_sizer.AddWindow(self.ClassFilter)
   426         
   420 
   427         for name, bitmap, help in [
   421         for name, bitmap, help in [
   428                 ("AddButton", "add_element", _("Add variable")),
   422                 ("AddButton", "add_element", _("Add variable")),
   429                 ("DeleteButton", "remove_element", _("Remove variable")),
   423                 ("DeleteButton", "remove_element", _("Remove variable")),
   430                 ("UpButton", "up", _("Move variable up")),
   424                 ("UpButton", "up", _("Move variable up")),
   431                 ("DownButton", "down", _("Move variable down"))]:
   425                 ("DownButton", "down", _("Move variable down"))]:
   432             button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), 
   426             button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap),
   433                   size=wx.Size(28, 28), style=wx.NO_BORDER)
   427                   size=wx.Size(28, 28), style=wx.NO_BORDER)
   434             button.SetToolTipString(help)
   428             button.SetToolTipString(help)
   435             setattr(self, name, button)
   429             setattr(self, name, button)
   436             controls_sizer.AddWindow(button)
   430             controls_sizer.AddWindow(button)
   437         
   431 
   438         self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL)
   432         self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL)
   439         self.VariablesGrid.SetDropTarget(VariableDropTarget(self))
   433         self.VariablesGrid.SetDropTarget(VariableDropTarget(self))
   440         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, 
   434         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
   441               self.OnVariablesGridCellChange)
   435               self.OnVariablesGridCellChange)
   442         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, 
   436         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK,
   443               self.OnVariablesGridCellLeftClick)
   437               self.OnVariablesGridCellLeftClick)
   444         self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, 
   438         self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN,
   445               self.OnVariablesGridEditorShown)
   439               self.OnVariablesGridEditorShown)
   446         self.MainSizer.AddWindow(self.VariablesGrid, flag=wx.GROW)
   440         self.MainSizer.AddWindow(self.VariablesGrid, flag=wx.GROW)
   447         
   441 
   448         self.SetSizer(self.MainSizer)
   442         self.SetSizer(self.MainSizer)
   449         
   443 
   450         self.ParentWindow = window
   444         self.ParentWindow = window
   451         self.Controler = controler
   445         self.Controler = controler
   452         self.ElementType = element_type
   446         self.ElementType = element_type
   453         self.Debug = debug
   447         self.Debug = debug
   454         
   448 
   455         self.RefreshHighlightsTimer = wx.Timer(self, -1)
   449         self.RefreshHighlightsTimer = wx.Timer(self, -1)
   456         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, 
   450         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer,
   457               self.RefreshHighlightsTimer)
   451               self.RefreshHighlightsTimer)
   458         
   452 
   459         self.Filter = "All"
   453         self.Filter = "All"
   460         self.FilterChoices = []
   454         self.FilterChoices = []
   461         self.FilterChoiceTransfer = GetFilterChoiceTransfer()
   455         self.FilterChoiceTransfer = GetFilterChoiceTransfer()
   462         
   456 
   463         self.DefaultValue = _VariableInfos("", "", "", "", "", True, "", "INT", ([], []), 0)
   457         self.DefaultValue = _VariableInfos("", "", "", "", "", True, "", DefaultType, ([], []), 0)
   464         
   458 
   465         if element_type in ["config", "resource"]:
   459         if element_type in ["config", "resource"]:
   466             self.DefaultTypes = {"All" : "Global"}
   460             self.DefaultTypes = {"All" : "Global"}
   467         else:
   461         else:
   468             self.DefaultTypes = {"All" : "Local", "Interface" : "Input", "Variables" : "Local"}
   462             self.DefaultTypes = {"All" : "Local", "Interface" : "Input", "Variables" : "Local"}
   469 
   463 
   479                                         "Interface", "   Input", "   Output", "   InOut", "   External",
   473                                         "Interface", "   Input", "   Output", "   InOut", "   External",
   480                                         "Variables", "   Local", "   Temp"]#,"Access"]
   474                                         "Variables", "   Local", "   Temp"]#,"Access"]
   481 
   475 
   482             # these condense the ColAlignements list
   476             # these condense the ColAlignements list
   483             l = wx.ALIGN_LEFT
   477             l = wx.ALIGN_LEFT
   484             c = wx.ALIGN_CENTER 
   478             c = wx.ALIGN_CENTER
   485 
   479 
   486             #                      Num  Name    Class   Type    Loc     Init    Option   Doc
   480             #                      Num  Name    Class   Type    Loc     Init    Option   Doc
   487             self.ColSizes       = [40,  80,     70,     80,     80,     80,     100,     80]
   481             self.ColSizes       = [40,  80,     70,     80,     80,     80,     100,     80]
   488             self.ColAlignements = [c,   l,      l,      l,      l,      l,      l,       l]
   482             self.ColAlignements = [c,   l,      l,      l,      l,      l,      l,       l]
   489 
   483 
   500                                         "Interface", "   Input", "   Output", "   InOut", "   External",
   494                                         "Interface", "   Input", "   Output", "   InOut", "   External",
   501                                         "Variables", "   Local", "   Temp"]
   495                                         "Variables", "   Local", "   Temp"]
   502 
   496 
   503             # these condense the ColAlignements list
   497             # these condense the ColAlignements list
   504             l = wx.ALIGN_LEFT
   498             l = wx.ALIGN_LEFT
   505             c = wx.ALIGN_CENTER 
   499             c = wx.ALIGN_CENTER
   506 
   500 
   507             #                      Num  Name    Class   Type    Init    Option   Doc
   501             #                      Num  Name    Class   Type    Init    Option   Doc
   508             self.ColSizes       = [40,  80,     70,     80,     80,     100,     160]
   502             self.ColSizes       = [40,  80,     70,     80,     80,     100,     160]
   509             self.ColAlignements = [c,   l,      l,      l,      l,      l,       l]
   503             self.ColAlignements = [c,   l,      l,      l,      l,      l,       l]
   510             
   504 
   511         self.ElementType = element_type
   505         self.ElementType = element_type
   512         self.BodyType = None
   506         self.BodyType = None
   513         
   507 
   514         for choice in self.FilterChoices:
   508         for choice in self.FilterChoices:
   515             self.ClassFilter.Append(_(choice))
   509             self.ClassFilter.Append(_(choice))
   516 
   510 
   517         reverse_transfer = {}
   511         reverse_transfer = {}
   518         for filter, choice in self.FilterChoiceTransfer.items():
   512         for filter, choice in self.FilterChoiceTransfer.items():
   524         self.VariablesGrid.SetButtons({"Add": self.AddButton,
   518         self.VariablesGrid.SetButtons({"Add": self.AddButton,
   525                                        "Delete": self.DeleteButton,
   519                                        "Delete": self.DeleteButton,
   526                                        "Up": self.UpButton,
   520                                        "Up": self.UpButton,
   527                                        "Down": self.DownButton})
   521                                        "Down": self.DownButton})
   528         self.VariablesGrid.SetEditable(not self.Debug)
   522         self.VariablesGrid.SetEditable(not self.Debug)
   529         
   523 
   530         def _AddVariable(new_row):
   524         def _AddVariable(new_row):
   531             if new_row > 0:
   525             if new_row > 0:
   532                 row_content = self.Values[new_row - 1].copy()
   526                 row_content = self.Values[new_row - 1].copy()
   533                 
   527 
   534                 result = VARIABLE_NAME_SUFFIX_MODEL.search(row_content.Name)
   528                 result = VARIABLE_NAME_SUFFIX_MODEL.search(row_content.Name)
   535                 if result is not None:
   529                 if result is not None:
   536                     name = row_content.Name[:result.start(1)]
   530                     name = row_content.Name[:result.start(1)]
   537                     suffix = result.group(1)
   531                     suffix = result.group(1)
   538                     if suffix != "":
   532                     if suffix != "":
   544                     start_idx = 0
   538                     start_idx = 0
   545             else:
   539             else:
   546                 row_content = None
   540                 row_content = None
   547                 start_idx = 0
   541                 start_idx = 0
   548                 name = "LocalVar"
   542                 name = "LocalVar"
   549                 
   543 
   550             if row_content is not None and row_content.Edit: 
   544             if row_content is not None and row_content.Edit:
   551                 row_content = self.Values[new_row - 1].copy()
   545                 row_content = self.Values[new_row - 1].copy()
   552             else:
   546             else:
   553                 row_content = self.DefaultValue.copy()
   547                 row_content = self.DefaultValue.copy()
   554                 if self.Filter in self.DefaultTypes:
   548                 if self.Filter in self.DefaultTypes:
   555                     row_content.Class = self.DefaultTypes[self.Filter]
   549                     row_content.Class = self.DefaultTypes[self.Filter]
   556                 else:
   550                 else:
   557                     row_content.Class = self.Filter
   551                     row_content.Class = self.Filter
   558             
   552 
   559             row_content.Name = self.Controler.GenerateNewName(
   553             row_content.Name = self.Controler.GenerateNewName(
   560                     self.TagName, None, name + "%d", start_idx)
   554                     self.TagName, None, name + "%d", start_idx)
   561             
   555 
   562             if self.Filter == "All" and len(self.Values) > 0:
   556             if self.Filter == "All" and len(self.Values) > 0:
   563                 self.Values.insert(new_row, row_content)
   557                 self.Values.insert(new_row, row_content)
   564             else:
   558             else:
   565                 self.Values.append(row_content)
   559                 self.Values.append(row_content)
   566                 new_row = self.Table.GetNumberRows()
   560                 new_row = self.Table.GetNumberRows()
   567             self.SaveValues()
   561             self.SaveValues()
   568             self.RefreshValues()
   562             self.RefreshValues()
   569             return new_row
   563             return new_row
   570         setattr(self.VariablesGrid, "_AddRow", _AddVariable)
   564         setattr(self.VariablesGrid, "_AddRow", _AddVariable)
   571         
   565 
   572         def _DeleteVariable(row):
   566         def _DeleteVariable(row):
   573             if self.Table.GetValueByName(row, "Edit"):
   567             if self.Table.GetValueByName(row, "Edit"):
   574                 self.Values.remove(self.Table.GetRow(row))
   568                 self.Values.remove(self.Table.GetRow(row))
   575                 self.SaveValues()
   569                 self.SaveValues()
   576                 if self.ElementType == "resource":
   570                 if self.ElementType == "resource":
   577                     self.ParentWindow.RefreshView(variablepanel = False)
   571                     self.ParentWindow.RefreshView(variablepanel = False)
   578                 self.RefreshValues()
   572                 self.RefreshValues()
   579         setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
   573         setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
   580             
   574 
   581         def _MoveVariable(row, move):
   575         def _MoveVariable(row, move):
   582             if self.Filter == "All":
   576             if self.Filter == "All":
   583                 new_row = max(0, min(row + move, len(self.Values) - 1))
   577                 new_row = max(0, min(row + move, len(self.Values) - 1))
   584                 if new_row != row:
   578                 if new_row != row:
   585                     self.Values.insert(new_row, self.Values.pop(row))
   579                     self.Values.insert(new_row, self.Values.pop(row))
   586                     self.SaveValues()
   580                     self.SaveValues()
   587                     self.RefreshValues()
   581                     self.RefreshValues()
   588                 return new_row
   582                 return new_row
   589             return row
   583             return row
   590         setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
   584         setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
   591         
   585 
   592         def _RefreshButtons():
   586         def _RefreshButtons():
   593             if self:
   587             if self:
   594                 table_length = len(self.Table.data)
   588                 table_length = len(self.Table.data)
   595                 row_class = None
   589                 row_class = None
   596                 row_edit = True
   590                 row_edit = True
   601                 self.AddButton.Enable(not self.Debug)
   595                 self.AddButton.Enable(not self.Debug)
   602                 self.DeleteButton.Enable(not self.Debug and (table_length > 0 and row_edit))
   596                 self.DeleteButton.Enable(not self.Debug and (table_length > 0 and row_edit))
   603                 self.UpButton.Enable(not self.Debug and (table_length > 0 and row > 0 and self.Filter == "All"))
   597                 self.UpButton.Enable(not self.Debug and (table_length > 0 and row > 0 and self.Filter == "All"))
   604                 self.DownButton.Enable(not self.Debug and (table_length > 0 and row < table_length - 1 and self.Filter == "All"))
   598                 self.DownButton.Enable(not self.Debug and (table_length > 0 and row < table_length - 1 and self.Filter == "All"))
   605         setattr(self.VariablesGrid, "RefreshButtons", _RefreshButtons)
   599         setattr(self.VariablesGrid, "RefreshButtons", _RefreshButtons)
   606         
   600 
   607         self.VariablesGrid.SetRowLabelSize(0)
   601         self.VariablesGrid.SetRowLabelSize(0)
   608         for col in range(self.Table.GetNumberCols()):
   602         for col in range(self.Table.GetNumberCols()):
   609             attr = wx.grid.GridCellAttr()
   603             attr = wx.grid.GridCellAttr()
   610             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
   604             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
   611             self.VariablesGrid.SetColAttr(col, attr)
   605             self.VariablesGrid.SetColAttr(col, attr)
   612             self.VariablesGrid.SetColMinimalWidth(col, self.ColSizes[col])
   606             self.VariablesGrid.SetColMinimalWidth(col, self.ColSizes[col])
   613             self.VariablesGrid.AutoSizeColumn(col, False)
   607             self.VariablesGrid.AutoSizeColumn(col, False)
   614     
   608 
   615     def __del__(self):
   609     def __del__(self):
   616         self.RefreshHighlightsTimer.Stop()
   610         self.RefreshHighlightsTimer.Stop()
   617     
   611 
   618     def SetTagName(self, tagname):
   612     def SetTagName(self, tagname):
   619         self.TagName = tagname
   613         self.TagName = tagname
   620         self.BodyType = self.Controler.GetEditedElementBodyType(self.TagName)
   614         self.BodyType = self.Controler.GetEditedElementBodyType(self.TagName)
   621     
   615 
   622     def GetTagName(self):
   616     def GetTagName(self):
   623         return self.TagName
   617         return self.TagName
   624     
   618 
   625     def IsFunctionBlockType(self, name):
   619     def IsFunctionBlockType(self, name):
   626         if (isinstance(name, TupleType) or 
   620         if (isinstance(name, TupleType) or
   627             self.ElementType != "function" and self.BodyType in ["ST", "IL"]):
   621             self.ElementType != "function" and self.BodyType in ["ST", "IL"]):
   628             return False
   622             return False
   629         else:
   623         else:
   630             return self.Controler.GetBlockType(name, debug=self.Debug) is not None
   624             return self.Controler.GetBlockType(name, debug=self.Debug) is not None
   631     
   625 
   632     def RefreshView(self):
   626     def RefreshView(self):
   633         self.PouNames = self.Controler.GetProjectPouNames(self.Debug)
   627         self.PouNames = self.Controler.GetProjectPouNames(self.Debug)
   634         returnType = None
   628         returnType = None
   635         description = None
   629         description = None
   636         
   630 
   637         words = self.TagName.split("::")
   631         words = self.TagName.split("::")
   638         if self.ElementType == "config":
   632         if self.ElementType == "config":
   639             self.Values = self.Controler.GetConfigurationGlobalVars(words[1], self.Debug)
   633             self.Values = self.Controler.GetConfigurationGlobalVars(words[1], self.Debug)
   640         elif self.ElementType == "resource":
   634         elif self.ElementType == "resource":
   641             self.Values = self.Controler.GetConfigurationResourceGlobalVars(words[1], words[2], self.Debug)
   635             self.Values = self.Controler.GetConfigurationResourceGlobalVars(words[1], words[2], self.Debug)
   645                 for data_type in self.Controler.GetDataTypes(self.TagName, debug=self.Debug):
   639                 for data_type in self.Controler.GetDataTypes(self.TagName, debug=self.Debug):
   646                     self.ReturnType.Append(data_type)
   640                     self.ReturnType.Append(data_type)
   647                 returnType = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, debug=self.Debug)
   641                 returnType = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, debug=self.Debug)
   648             description = self.Controler.GetPouDescription(words[1])
   642             description = self.Controler.GetPouDescription(words[1])
   649             self.Values = self.Controler.GetEditedElementInterfaceVars(self.TagName, debug=self.Debug)
   643             self.Values = self.Controler.GetEditedElementInterfaceVars(self.TagName, debug=self.Debug)
   650         
   644 
   651         if returnType is not None:
   645         if returnType is not None:
   652             self.ReturnType.SetStringSelection(returnType)
   646             self.ReturnType.SetStringSelection(returnType)
   653             self.ReturnType.Enable(not self.Debug)
   647             self.ReturnType.Enable(not self.Debug)
   654             self.ReturnTypeLabel.Show()
   648             self.ReturnTypeLabel.Show()
   655             self.ReturnType.Show()
   649             self.ReturnType.Show()
   656         else:
   650         else:
   657             self.ReturnType.Enable(False)
   651             self.ReturnType.Enable(False)
   658             self.ReturnTypeLabel.Hide()
   652             self.ReturnTypeLabel.Hide()
   659             self.ReturnType.Hide()
   653             self.ReturnType.Hide()
   660         
   654 
   661         if description is not None:
   655         if description is not None:
   662             self.Description.SetValue(description)
   656             self.Description.SetValue(description)
   663             self.Description.Enable(not self.Debug)
   657             self.Description.Enable(not self.Debug)
   664             self.DescriptionLabel.Show()
   658             self.DescriptionLabel.Show()
   665             self.Description.Show()
   659             self.Description.Show()
   666         else:
   660         else:
   667             self.Description.Enable(False)
   661             self.Description.Enable(False)
   668             self.DescriptionLabel.Hide()
   662             self.DescriptionLabel.Hide()
   669             self.Description.Hide()
   663             self.Description.Hide()
   670         
   664 
   671         self.RefreshValues()
   665         self.RefreshValues()
   672         self.VariablesGrid.RefreshButtons()
   666         self.VariablesGrid.RefreshButtons()
   673         self.MainSizer.Layout()
   667         self.MainSizer.Layout()
   674     
   668 
   675     def OnReturnTypeChanged(self, event):
   669     def OnReturnTypeChanged(self, event):
   676         words = self.TagName.split("::")
   670         words = self.TagName.split("::")
   677         self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
   671         self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
   678         self.Controler.BufferProject()
   672         self.Controler.BufferProject()
   679         self.ParentWindow.RefreshView(variablepanel = False)
   673         self.ParentWindow.RefreshView(variablepanel = False)
   680         self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   674         self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   681         event.Skip()
   675         event.Skip()
   682     
   676 
   683     def OnDescriptionChanged(self, event):
   677     def OnDescriptionChanged(self, event):
   684         words = self.TagName.split("::")
   678         words = self.TagName.split("::")
   685         old_description = self.Controler.GetPouDescription(words[1])
   679         old_description = self.Controler.GetPouDescription(words[1])
   686         new_description = self.Description.GetValue()
   680         new_description = self.Description.GetValue()
   687         if new_description != old_description:
   681         if new_description != old_description:
   688             self.Controler.SetPouDescription(words[1], new_description)
   682             self.Controler.SetPouDescription(words[1], new_description)
   689             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   683             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   690         event.Skip()
   684         event.Skip()
   691     
   685 
   692     def OnClassFilter(self, event):
   686     def OnClassFilter(self, event):
   693         self.Filter = self.FilterChoiceTransfer[VARIABLE_CHOICES_DICT[self.ClassFilter.GetStringSelection()]]
   687         self.Filter = self.FilterChoiceTransfer[VARIABLE_CHOICES_DICT[self.ClassFilter.GetStringSelection()]]
   694         self.RefreshTypeList()
   688         self.RefreshTypeList()
   695         self.RefreshValues()
   689         self.RefreshValues()
   696         self.VariablesGrid.RefreshButtons()
   690         self.VariablesGrid.RefreshButtons()
   709     def OnVariablesGridCellChange(self, event):
   703     def OnVariablesGridCellChange(self, event):
   710         row, col = event.GetRow(), event.GetCol()
   704         row, col = event.GetRow(), event.GetCol()
   711         colname = self.Table.GetColLabelValue(col, False)
   705         colname = self.Table.GetColLabelValue(col, False)
   712         value = self.Table.GetValue(row, col)
   706         value = self.Table.GetValue(row, col)
   713         message = None
   707         message = None
   714         
   708 
   715         if colname == "Name" and value != "":
   709         if colname == "Name" and value != "":
   716             if not TestIdentifier(value):
   710             if not TestIdentifier(value):
   717                 message = _("\"%s\" is not a valid identifier!") % value
   711                 message = _("\"%s\" is not a valid identifier!") % value
   718             elif value.upper() in IEC_KEYWORDS:
   712             elif value.upper() in IEC_KEYWORDS:
   719                 message = _("\"%s\" is a keyword. It can't be used!") % value
   713                 message = _("\"%s\" is a keyword. It can't be used!") % value
   733             self.SaveValues()
   727             self.SaveValues()
   734             if colname == "Class":
   728             if colname == "Class":
   735                 wx.CallAfter(self.ParentWindow.RefreshView, False)
   729                 wx.CallAfter(self.ParentWindow.RefreshView, False)
   736             elif colname == "Location":
   730             elif colname == "Location":
   737                 wx.CallAfter(self.ParentWindow.RefreshView)
   731                 wx.CallAfter(self.ParentWindow.RefreshView)
   738             
   732 
   739         if message is not None:
   733         if message is not None:
   740             dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
   734             dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
   741             dialog.ShowModal()
   735             dialog.ShowModal()
   742             dialog.Destroy()
   736             dialog.Destroy()
   743             event.Veto()
   737             event.Veto()
   744         else:
   738         else:
   745             event.Skip()
   739             event.Skip()
   746     
   740 
   747     def OnVariablesGridEditorShown(self, event):
   741     def BuildStdIECTypesMenu(self,type_menu):
   748         row, col = event.GetRow(), event.GetCol() 
       
   749 
       
   750         label_value = self.Table.GetColLabelValue(col, False)
       
   751         if label_value == "Type":
       
   752             type_menu = wx.Menu(title='')   # the root menu
       
   753 
       
   754             # build a submenu containing standard IEC types
   742             # build a submenu containing standard IEC types
   755             base_menu = wx.Menu(title='')
   743             base_menu = wx.Menu(title='')
   756             for base_type in self.Controler.GetBaseTypes():
   744             for base_type in self.Controler.GetBaseTypes():
   757                 new_id = wx.NewId()
   745                 new_id = wx.NewId()
   758                 AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
   746                 base_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
   759                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
   747                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
   760 
   748 
   761             type_menu.AppendMenu(wx.NewId(), _("Base Types"), base_menu)
   749             type_menu.AppendMenu(wx.NewId(), _("Base Types"), base_menu)
   762 
   750 
       
   751     def BuildUserTypesMenu(self,type_menu):
   763             # build a submenu containing user-defined types
   752             # build a submenu containing user-defined types
   764             datatype_menu = wx.Menu(title='')
   753             datatype_menu = wx.Menu(title='')
   765             datatypes = self.Controler.GetDataTypes(basetypes = False, confnodetypes = False)
   754             datatypes = self.Controler.GetDataTypes(basetypes = False, confnodetypes = False)
   766             for datatype in datatypes:
   755             for datatype in datatypes:
   767                 new_id = wx.NewId()
   756                 new_id = wx.NewId()
   768                 AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   757                 datatype_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   769                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   758                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   770 
   759 
   771             type_menu.AppendMenu(wx.NewId(), _("User Data Types"), datatype_menu)
   760             type_menu.AppendMenu(wx.NewId(), _("User Data Types"), datatype_menu)
   772             
   761 
   773             for category in self.Controler.GetConfNodeDataTypes():
   762     def BuildLibsTypesMenu(self, type_menu):
   774                
   763         for category in self.Controler.GetConfNodeDataTypes():
   775                if len(category["list"]) > 0:
   764             if len(category["list"]) > 0:
   776                    # build a submenu containing confnode types
   765                 # build a submenu containing confnode types
   777                    confnode_datatype_menu = wx.Menu(title='')
   766                 confnode_datatype_menu = wx.Menu(title='')
   778                    for datatype in category["list"]:
   767                 for datatype in category["list"]:
   779                        new_id = wx.NewId()
   768                     new_id = wx.NewId()
   780                        AppendMenu(confnode_datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   769                     confnode_datatype_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   781                        self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   770                     self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   782                    
   771 
   783                    type_menu.AppendMenu(wx.NewId(), category["name"], confnode_datatype_menu)
   772                 type_menu.AppendMenu(wx.NewId(), category["name"], confnode_datatype_menu)
   784 
   773 
   785             # build a submenu containing function block types
   774     def BuildProjectTypesMenu(self, type_menu, classtype):
   786             bodytype = self.Controler.GetEditedElementBodyType(self.TagName)
   775         # build a submenu containing function block types
   787             pouname, poutype = self.Controler.GetEditedElementType(self.TagName)
   776         bodytype = self.Controler.GetEditedElementBodyType(self.TagName)
       
   777         pouname, poutype = self.Controler.GetEditedElementType(self.TagName)
       
   778         if classtype in ["Input", "Output", "InOut", "External", "Global"] or \
       
   779         poutype != "function" and bodytype in ["ST", "IL"]:
       
   780             functionblock_menu = wx.Menu(title='')
       
   781             fbtypes = self.Controler.GetFunctionBlockTypes(self.TagName)
       
   782             for functionblock_type in fbtypes:
       
   783                 new_id = wx.NewId()
       
   784                 functionblock_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=functionblock_type)
       
   785                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(functionblock_type), id=new_id)
       
   786 
       
   787             type_menu.AppendMenu(wx.NewId(), _("Function Block Types"), functionblock_menu)
       
   788 
       
   789     def BuildArrayTypesMenu(self, type_menu):
       
   790         new_id = wx.NewId()
       
   791         type_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Array"))
       
   792         self.Bind(wx.EVT_MENU, self.VariableArrayTypeFunction, id=new_id)
       
   793 
       
   794     def OnVariablesGridEditorShown(self, event):
       
   795         row, col = event.GetRow(), event.GetCol()
       
   796 
       
   797         label_value = self.Table.GetColLabelValue(col, False)
       
   798         if label_value == "Type":
   788             classtype = self.Table.GetValueByName(row, "Class")
   799             classtype = self.Table.GetValueByName(row, "Class")
   789             
   800             type_menu = wx.Menu(title='')   # the root menu
   790             new_id = wx.NewId()
   801 
   791             AppendMenu(type_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Array"))
   802             self.BuildStdIECTypesMenu(type_menu)
   792             self.Bind(wx.EVT_MENU, self.VariableArrayTypeFunction, id=new_id)
   803 
   793             
   804             self.BuildUserTypesMenu(type_menu)
   794             if classtype in ["Input", "Output", "InOut", "External", "Global"] or \
   805 
   795             poutype != "function" and bodytype in ["ST", "IL"]:
   806             self.BuildLibsTypesMenu(type_menu)
   796                 functionblock_menu = wx.Menu(title='')
   807 
   797                 fbtypes = self.Controler.GetFunctionBlockTypes(self.TagName)
   808             self.BuildProjectTypesMenu(type_menu,classtype)
   798                 for functionblock_type in fbtypes:
   809 
   799                     new_id = wx.NewId()
   810             self.BuildArrayTypesMenu(type_menu)
   800                     AppendMenu(functionblock_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=functionblock_type)
       
   801                     self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(functionblock_type), id=new_id)
       
   802 
       
   803                 type_menu.AppendMenu(wx.NewId(), _("Function Block Types"), functionblock_menu)
       
   804 
   811 
   805             rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
   812             rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
   806             corner_x = rect.x + rect.width
   813             corner_x = rect.x + rect.width
   807             corner_y = rect.y + self.VariablesGrid.GetColLabelSize()
   814             corner_y = rect.y + self.VariablesGrid.GetColLabelSize()
   808 
   815 
   810             self.VariablesGrid.PopupMenuXY(type_menu, corner_x, corner_y)
   817             self.VariablesGrid.PopupMenuXY(type_menu, corner_x, corner_y)
   811             type_menu.Destroy()
   818             type_menu.Destroy()
   812             event.Veto()
   819             event.Veto()
   813         else:
   820         else:
   814             event.Skip()
   821             event.Skip()
   815     
   822 
   816     def GetVariableTypeFunction(self, base_type):
   823     def GetVariableTypeFunction(self, base_type):
   817         def VariableTypeFunction(event):
   824         def VariableTypeFunction(event):
   818             row = self.VariablesGrid.GetGridCursorRow()
   825             row = self.VariablesGrid.GetGridCursorRow()
   819             self.Table.SetValueByName(row, "Type", base_type)
   826             self.Table.SetValueByName(row, "Type", base_type)
   820             self.Table.ResetView(self.VariablesGrid)
   827             self.Table.ResetView(self.VariablesGrid)
   821             self.SaveValues(False)
   828             self.SaveValues(False)
   822             self.ParentWindow.RefreshView(variablepanel = False)
   829             self.ParentWindow.RefreshView(variablepanel = False)
   823             self.Controler.BufferProject()
   830             self.Controler.BufferProject()
   824             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   831             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   825         return VariableTypeFunction
   832         return VariableTypeFunction
   826     
   833 
   827     def VariableArrayTypeFunction(self, event):
   834     def VariableArrayTypeFunction(self, event):
   828         row = self.VariablesGrid.GetGridCursorRow()
   835         row = self.VariablesGrid.GetGridCursorRow()
   829         dialog = ArrayTypeDialog(self, 
   836         dialog = ArrayTypeDialog(self,
   830                                  self.Controler.GetDataTypes(self.TagName), 
   837                                  self.Controler.GetDataTypes(self.TagName),
   831                                  self.Table.GetValueByName(row, "Type"))
   838                                  self.Table.GetValueByName(row, "Type"))
   832         if dialog.ShowModal() == wx.ID_OK:
   839         if dialog.ShowModal() == wx.ID_OK:
   833             self.Table.SetValueByName(row, "Type", dialog.GetValue())
   840             self.Table.SetValueByName(row, "Type", dialog.GetValue())
   834             self.Table.ResetView(self.VariablesGrid)
   841             self.Table.ResetView(self.VariablesGrid)
   835             self.SaveValues(False)
   842             self.SaveValues(False)
   836             self.ParentWindow.RefreshView(variablepanel = False)
   843             self.ParentWindow.RefreshView(variablepanel = False)
   837             self.Controler.BufferProject()
   844             self.Controler.BufferProject()
   838             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   845             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   839         dialog.Destroy()
   846         dialog.Destroy()
   840     
   847 
   841     def OnVariablesGridCellLeftClick(self, event):
   848     def OnVariablesGridCellLeftClick(self, event):
   842         row = event.GetRow()
   849         row = event.GetRow()
   843         if not self.Debug and (event.GetCol() == 0 and self.Table.GetValueByName(row, "Edit")):
   850         if not self.Debug and (event.GetCol() == 0 and self.Table.GetValueByName(row, "Edit")):
   844             var_name = self.Table.GetValueByName(row, "Name")
   851             var_name = self.Table.GetValueByName(row, "Name")
   845             var_class = self.Table.GetValueByName(row, "Class")
   852             var_class = self.Table.GetValueByName(row, "Class")
   847             data = wx.TextDataObject(str((var_name, var_class, var_type, self.TagName)))
   854             data = wx.TextDataObject(str((var_name, var_class, var_type, self.TagName)))
   848             dragSource = wx.DropSource(self.VariablesGrid)
   855             dragSource = wx.DropSource(self.VariablesGrid)
   849             dragSource.SetData(data)
   856             dragSource.SetData(data)
   850             dragSource.DoDragDrop()
   857             dragSource.DoDragDrop()
   851         event.Skip()
   858         event.Skip()
   852     
   859 
   853     def RefreshValues(self):
   860     def RefreshValues(self):
   854         data = []
   861         data = []
   855         for num, variable in enumerate(self.Values):
   862         for num, variable in enumerate(self.Values):
   856             if variable.Class in self.ClassList:
   863             if variable.Class in self.ClassList:
   857                 variable.Number = num + 1
   864                 variable.Number = num + 1
   858                 data.append(variable)
   865                 data.append(variable)
   859         self.Table.SetData(data)
   866         self.Table.SetData(data)
   860         self.Table.ResetView(self.VariablesGrid)
   867         self.Table.ResetView(self.VariablesGrid)
   861             
   868 
   862     def SaveValues(self, buffer = True):
   869     def SaveValues(self, buffer = True):
   863         words = self.TagName.split("::")
   870         words = self.TagName.split("::")
   864         if self.ElementType == "config":
   871         if self.ElementType == "config":
   865             self.Controler.SetConfigurationGlobalVars(words[1], self.Values)
   872             self.Controler.SetConfigurationGlobalVars(words[1], self.Values)
   866         elif self.ElementType == "resource":
   873         elif self.ElementType == "resource":
   869             if self.ReturnType.IsEnabled():
   876             if self.ReturnType.IsEnabled():
   870                 self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
   877                 self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
   871             self.Controler.SetPouInterfaceVars(words[1], self.Values)
   878             self.Controler.SetPouInterfaceVars(words[1], self.Values)
   872         if buffer:
   879         if buffer:
   873             self.Controler.BufferProject()
   880             self.Controler.BufferProject()
   874             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)            
   881             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   875 
   882 
   876 #-------------------------------------------------------------------------------
   883 #-------------------------------------------------------------------------------
   877 #                        Highlights showing functions
   884 #                        Highlights showing functions
   878 #-------------------------------------------------------------------------------
   885 #-------------------------------------------------------------------------------
   879 
   886