dialogs/FBDVariableDialog.py
branch1.1 Korean release
changeset 1280 72a826dfcfbb
parent 1259 8350222a81c3
child 1571 486f94a8032c
equal deleted inserted replaced
977:c8e008b8cefe 1280:72a826dfcfbb
    22 #License along with this library; if not, write to the Free Software
    22 #License along with this library; if not, write to the Free Software
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24 
    24 
    25 import wx
    25 import wx
    26 
    26 
    27 from graphics import *
    27 from graphics.GraphicCommons import INPUT, INOUT, OUTPUT
       
    28 from graphics.FBD_Objects import FBD_Variable
       
    29 from BlockPreviewDialog import BlockPreviewDialog
    28 
    30 
    29 #-------------------------------------------------------------------------------
    31 #-------------------------------------------------------------------------------
    30 #                                    Helpers
    32 #                                    Helpers
    31 #-------------------------------------------------------------------------------
    33 #-------------------------------------------------------------------------------
    32 
    34 
       
    35 # Dictionaries containing correspondence between variable block class and string
       
    36 # to be shown in Class combo box in both sense
    33 VARIABLE_CLASSES_DICT = {INPUT : _("Input"),
    37 VARIABLE_CLASSES_DICT = {INPUT : _("Input"),
    34                          INOUT : _("InOut"),
    38                          INOUT : _("InOut"),
    35                          OUTPUT : _("Output")}
    39                          OUTPUT : _("Output")}
    36 VARIABLE_CLASSES_DICT_REVERSE = dict(
    40 VARIABLE_CLASSES_DICT_REVERSE = dict(
    37     [(value, key) for key, value in VARIABLE_CLASSES_DICT.iteritems()])
    41     [(value, key) for key, value in VARIABLE_CLASSES_DICT.iteritems()])
    38 
    42 
    39 #-------------------------------------------------------------------------------
    43 #-------------------------------------------------------------------------------
    40 #                          Create New Variable Dialog
    44 #                        Set Variable Parameters Dialog
    41 #-------------------------------------------------------------------------------
    45 #-------------------------------------------------------------------------------
    42 
    46 
    43 class FBDVariableDialog(wx.Dialog):
    47 """
    44 
    48 Class that implements a dialog for defining parameters of a FBD variable graphic
    45     def __init__(self, parent, controller, transition = ""):
    49 element
    46         wx.Dialog.__init__(self, parent,
    50 """
       
    51 
       
    52 class FBDVariableDialog(BlockPreviewDialog):
       
    53 
       
    54     def __init__(self, parent, controller, tagname, exclude_input=False):
       
    55         """
       
    56         Constructor
       
    57         @param parent: Parent wx.Window of dialog for modal
       
    58         @param controller: Reference to project controller
       
    59         @param tagname: Tagname of project POU edited
       
    60         @param exclude_input: Exclude input from variable class selection
       
    61         """
       
    62         BlockPreviewDialog.__init__(self, parent, controller, tagname,
    47               size=wx.Size(400, 380), title=_('Variable Properties'))
    63               size=wx.Size(400, 380), title=_('Variable Properties'))
    48         
    64         
    49         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=4, vgap=10)
    65         # Init common sizers
    50         main_sizer.AddGrowableCol(0)
    66         self._init_sizers(4, 2, 4, None, 3, 2)
    51         main_sizer.AddGrowableRow(2)
    67         
    52         
    68         # Create label for variable class
    53         column_sizer = wx.BoxSizer(wx.HORIZONTAL)
       
    54         main_sizer.AddSizer(column_sizer, border=20, 
       
    55               flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
       
    56         
       
    57         left_gridsizer = wx.FlexGridSizer(cols=1, hgap=0, rows=6, vgap=5)
       
    58         left_gridsizer.AddGrowableCol(0)
       
    59         column_sizer.AddSizer(left_gridsizer, 1, border=5, 
       
    60               flag=wx.GROW|wx.RIGHT)
       
    61         
       
    62         class_label = wx.StaticText(self, label=_('Class:'))
    69         class_label = wx.StaticText(self, label=_('Class:'))
    63         left_gridsizer.AddWindow(class_label, flag=wx.GROW)
    70         self.LeftGridSizer.AddWindow(class_label, flag=wx.GROW)
    64         
    71         
       
    72         # Create a combo box for defining variable class
    65         self.Class = wx.ComboBox(self, style=wx.CB_READONLY)
    73         self.Class = wx.ComboBox(self, style=wx.CB_READONLY)
    66         self.Bind(wx.EVT_COMBOBOX, self.OnClassChanged, self.Class)
    74         self.Bind(wx.EVT_COMBOBOX, self.OnClassChanged, self.Class)
    67         left_gridsizer.AddWindow(self.Class, flag=wx.GROW)
    75         self.LeftGridSizer.AddWindow(self.Class, flag=wx.GROW)
    68         
    76         
    69         expression_label = wx.StaticText(self, label=_('Expression:'))
    77         # Create label for variable execution order
    70         left_gridsizer.AddWindow(expression_label, flag=wx.GROW)
    78         execution_order_label = wx.StaticText(self, 
    71         
    79               label=_('Execution Order:'))
       
    80         self.LeftGridSizer.AddWindow(execution_order_label, flag=wx.GROW)
       
    81         
       
    82         # Create spin control for defining variable execution order
       
    83         self.ExecutionOrder = wx.SpinCtrl(self, min=0, style=wx.SP_ARROW_KEYS)
       
    84         self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged, 
       
    85                   self.ExecutionOrder)
       
    86         self.LeftGridSizer.AddWindow(self.ExecutionOrder, flag=wx.GROW)
       
    87         
       
    88         # Create label for variable expression
       
    89         name_label = wx.StaticText(self, label=_('Expression:'))
       
    90         self.RightGridSizer.AddWindow(name_label, border=5, 
       
    91               flag=wx.GROW|wx.BOTTOM)
       
    92         
       
    93         # Create text control for defining variable expression
    72         self.Expression = wx.TextCtrl(self)
    94         self.Expression = wx.TextCtrl(self)
    73         self.Bind(wx.EVT_TEXT, self.OnExpressionChanged, self.Expression)
    95         self.Bind(wx.EVT_TEXT, self.OnExpressionChanged, self.Expression)
    74         left_gridsizer.AddWindow(self.Expression, flag=wx.GROW)
    96         self.RightGridSizer.AddWindow(self.Expression, flag=wx.GROW)
    75         
    97         
    76         execution_order_label = wx.StaticText(self, label=_('Execution Order:'))
    98         # Create a list box to selected variable expression in the list of
    77         left_gridsizer.AddWindow(execution_order_label, flag=wx.GROW)
    99         # variables defined in POU
    78         
   100         self.VariableName = wx.ListBox(self, size=wx.Size(0, 120), 
    79         self.ExecutionOrder = wx.SpinCtrl(self, min=0, style=wx.SP_ARROW_KEYS)
       
    80         self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged, self.ExecutionOrder)
       
    81         left_gridsizer.AddWindow(self.ExecutionOrder, flag=wx.GROW)
       
    82         
       
    83         right_gridsizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
    84         right_gridsizer.AddGrowableCol(0)
       
    85         right_gridsizer.AddGrowableRow(1)
       
    86         column_sizer.AddSizer(right_gridsizer, 1, border=5, 
       
    87               flag=wx.GROW|wx.LEFT)
       
    88         
       
    89         name_label = wx.StaticText(self, label=_('Name:'))
       
    90         right_gridsizer.AddWindow(name_label, flag=wx.GROW)
       
    91         
       
    92         self.VariableName = wx.ListBox(self, size=wx.Size(0, 0), 
       
    93               style=wx.LB_SINGLE|wx.LB_SORT)
   101               style=wx.LB_SINGLE|wx.LB_SORT)
    94         self.Bind(wx.EVT_LISTBOX, self.OnNameChanged, self.VariableName)
   102         self.Bind(wx.EVT_LISTBOX, self.OnNameChanged, self.VariableName)
    95         right_gridsizer.AddWindow(self.VariableName, flag=wx.GROW)
   103         self.RightGridSizer.AddWindow(self.VariableName, flag=wx.GROW)
    96         
   104         
    97         preview_label = wx.StaticText(self, label=_('Preview:'))
   105         # Add preview panel and associated label to sizers
    98         main_sizer.AddWindow(preview_label, border=20,
   106         self.MainSizer.AddWindow(self.PreviewLabel, border=20,
    99               flag=wx.GROW|wx.LEFT|wx.RIGHT)
   107               flag=wx.GROW|wx.LEFT|wx.RIGHT)
   100         
   108         self.MainSizer.AddWindow(self.Preview, border=20,
   101         self.Preview = wx.Panel(self, 
       
   102               style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
       
   103         self.Preview.SetBackgroundColour(wx.Colour(255,255,255))
       
   104         setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE)
       
   105         setattr(self.Preview, "GetScaling", lambda:None)
       
   106         setattr(self.Preview, "IsOfType", controller.IsOfType)
       
   107         self.Preview.Bind(wx.EVT_PAINT, self.OnPaint)
       
   108         main_sizer.AddWindow(self.Preview, border=20,
       
   109               flag=wx.GROW|wx.LEFT|wx.RIGHT)
   109               flag=wx.GROW|wx.LEFT|wx.RIGHT)
   110         
   110         
   111         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
   111         # Add buttons sizer to sizers
   112         self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton())
   112         self.MainSizer.AddSizer(self.ButtonSizer, border=20, 
   113         main_sizer.AddSizer(button_sizer, border=20, 
       
   114               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
   113               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
   115         
   114         
   116         self.SetSizer(main_sizer)
   115         # Set options that can be selected in class combo box
   117         
   116         for var_class, choice in VARIABLE_CLASSES_DICT.iteritems():
   118         self.Transition = transition
   117             if not exclude_input or var_class != INPUT:
   119         self.Variable = None
   118                 self.Class.Append(choice)
   120         self.VarList = []
   119         self.Class.SetSelection(0)
   121         self.MinVariableSize = None
   120         
   122         
   121         # Extract list of variables defined in POU
   123         for choice in VARIABLE_CLASSES_DICT.itervalues():
   122         self.RefreshVariableList()
   124             self.Class.Append(choice)
   123         
   125         self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[INPUT])
   124         # Refresh values in name list box
   126 
       
   127         self.RefreshNameList()
   125         self.RefreshNameList()
       
   126         
       
   127         # Class combo box is default control having keyboard focus
   128         self.Class.SetFocus()
   128         self.Class.SetFocus()
   129 
   129 
   130     def SetPreviewFont(self, font):
       
   131         self.Preview.SetFont(font)
       
   132 
       
   133     def RefreshNameList(self):
   130     def RefreshNameList(self):
   134         selected = self.VariableName.GetStringSelection()
   131         """
   135         var_class = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()]
   132         Called to refresh names in name list box
       
   133         """
       
   134         # Get variable class to select POU variable applicable
       
   135         var_class = VARIABLE_CLASSES_DICT_REVERSE[
       
   136                             self.Class.GetStringSelection()]
       
   137         
       
   138         # Refresh names in name list box by selecting variables in POU variables
       
   139         # list that can be applied to variable class
   136         self.VariableName.Clear()
   140         self.VariableName.Clear()
   137         self.VariableName.Append("")
   141         for name, (var_type, value_type) in self.VariableList.iteritems():
   138         for name, var_type, value_type in self.VarList:
       
   139             if var_type != "Input" or var_class == INPUT:
   142             if var_type != "Input" or var_class == INPUT:
   140                 self.VariableName.Append(name)
   143                 self.VariableName.Append(name)
   141         if selected != "" and self.VariableName.FindString(selected) != wx.NOT_FOUND:
   144         
       
   145         # Get variable expression and select corresponding value in name list
       
   146         # box if it exists
       
   147         selected = self.Expression.GetValue()
       
   148         if (selected != "" and 
       
   149             self.VariableName.FindString(selected) != wx.NOT_FOUND):
   142             self.VariableName.SetStringSelection(selected)
   150             self.VariableName.SetStringSelection(selected)
   143             self.Expression.Enable(False)
       
   144         else:
   151         else:
   145             self.VariableName.SetStringSelection("")
   152             self.VariableName.SetSelection(wx.NOT_FOUND)
   146             #self.Expression.Enable(var_class == INPUT)
   153         
       
   154         # Disable name list box if no name present inside
   147         self.VariableName.Enable(self.VariableName.GetCount() > 0)
   155         self.VariableName.Enable(self.VariableName.GetCount() > 0)
   148             
   156             
   149     def SetMinVariableSize(self, size):
       
   150         self.MinVariableSize = size
       
   151 
       
   152     def SetVariables(self, vars):
       
   153         self.VarList = vars
       
   154         self.RefreshNameList()
       
   155 
       
   156     def SetValues(self, values):
   157     def SetValues(self, values):
   157         value_type = values.get("type", None)
   158         """
   158         value_name = values.get("name", None)
   159         Set default variable parameters
   159         if value_type:
   160         @param values: Variable parameters values
   160             self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[value_type])
   161         """
       
   162         
       
   163         # Get class parameter value
       
   164         var_class = values.get("class", None)
       
   165         if var_class is not None:
       
   166             # Set class selected in class combo box
       
   167             self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[var_class])
       
   168             # Refresh names in name list box according to var class
   161             self.RefreshNameList()
   169             self.RefreshNameList()
   162         if value_name:
   170         
   163             if self.VariableName.FindString(value_name) != wx.NOT_FOUND:
   171         # For each parameters defined, set corresponding control value
   164                 self.VariableName.SetStringSelection(value_name)
   172         for name, value in values.items():
   165                 self.Expression.Enable(False)
   173             
   166             else:
   174             # Parameter is variable expression
   167                 self.Expression.SetValue(value_name)
   175             if name == "expression":
   168                 self.VariableName.Enable(False)
   176                 # Set expression text control value
   169         if "executionOrder" in values:
   177                 self.Expression.ChangeValue(value)
   170             self.ExecutionOrder.SetValue(values["executionOrder"])
   178                 # Select corresponding text in name list box if it exists
       
   179                 if self.VariableName.FindString(value) != wx.NOT_FOUND:
       
   180                     self.VariableName.SetStringSelection(value)
       
   181                 else:
       
   182                     self.VariableName.SetSelection(wx.NOT_FOUND)
       
   183             
       
   184             # Parameter is variable execution order
       
   185             elif name == "executionOrder":
       
   186                 self.ExecutionOrder.SetValue(value)
       
   187         
       
   188         # Refresh preview panel
   171         self.RefreshPreview()
   189         self.RefreshPreview()
   172         
   190         
   173     def GetValues(self):
   191     def GetValues(self):
   174         values = {}
   192         """
   175         values["type"] = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()]
   193         Return block parameters defined in dialog
       
   194         @return: {parameter_name: parameter_value,...}
       
   195         """
   176         expression = self.Expression.GetValue()
   196         expression = self.Expression.GetValue()
   177         if self.Expression.IsEnabled() and expression != "":
   197         values = {
   178             values["name"] = expression
   198             "class": VARIABLE_CLASSES_DICT_REVERSE[
   179         else:
   199                         self.Class.GetStringSelection()],
   180             values["name"] = self.VariableName.GetStringSelection()
   200             "expression": expression,
   181         values["value_type"] = None
   201             "var_type": self.VariableList.get(expression, (None, None))[1],
   182         for var_name, var_type, value_type in self.VarList:
   202             "executionOrder": self.ExecutionOrder.GetValue()}
   183             if var_name == values["name"]:
   203         values["width"], values["height"] = self.Element.GetSize()
   184                 values["value_type"] = value_type
       
   185         values["width"], values["height"] = self.Variable.GetSize()
       
   186         values["executionOrder"] = self.ExecutionOrder.GetValue()
       
   187         return values
   204         return values
   188 
   205 
   189     def OnOK(self, event):
   206     def OnOK(self, event):
       
   207         """
       
   208         Called when dialog OK button is pressed
       
   209         Test if parameters defined are valid
       
   210         @param event: wx.Event from OK button
       
   211         """
   190         message = None
   212         message = None
   191         expression = self.Expression.GetValue()
   213         
   192         if self.Expression.IsEnabled():
   214         # Test that an expression have been selected or typed by user
   193             value = expression
   215         value = self.Expression.GetValue()
   194         else:
       
   195             value = self.VariableName.GetStringSelection()
       
   196         if value == "":
   216         if value == "":
   197             message = _("At least a variable or an expression must be selected!")
   217             message = _("At least a variable or an expression must be selected!")
   198         elif value.upper() in IEC_KEYWORDS:
   218         
   199             message = _("\"%s\" is a keyword. It can't be used!") % value
   219         # Show error message if an error is detected
   200         if message is not None:
   220         if message is not None:
   201             message = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
   221             self.ShowErrorMessage(message)
   202             message.ShowModal()
   222         
   203             message.Destroy()
       
   204         else:
   223         else:
   205             self.EndModal(wx.ID_OK)
   224             # Call BlockPreviewDialog function
       
   225             BlockPreviewDialog.OnOK(self, event)
   206 
   226 
   207     def OnClassChanged(self, event):
   227     def OnClassChanged(self, event):
       
   228         """
       
   229         Called when variable class value changed
       
   230         @param event: wx.ComboBoxEvent
       
   231         """
       
   232         # Refresh name list box values
   208         self.RefreshNameList()
   233         self.RefreshNameList()
       
   234         
   209         self.RefreshPreview()
   235         self.RefreshPreview()
   210         event.Skip()
   236         event.Skip()
   211 
   237 
   212     def OnNameChanged(self, event):
   238     def OnNameChanged(self, event):
   213         if self.VariableName.GetStringSelection() != "":
   239         """
   214             self.Expression.Enable(False)
   240         Called when name selected in name list box changed
   215         elif VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()] == INPUT:
   241         @param event: wx.ListBoxEvent
   216             self.Expression.Enable(True)
   242         """
       
   243         # Change expression test control value to the value selected in name
       
   244         # list box if value selected is valid
       
   245         if self.VariableName.GetSelection() != wx.NOT_FOUND:
       
   246             self.Expression.ChangeValue(self.VariableName.GetStringSelection())
       
   247         
   217         self.RefreshPreview()
   248         self.RefreshPreview()
   218         event.Skip()
   249         event.Skip()
   219     
   250     
   220     def OnExpressionChanged(self, event):
   251     def OnExpressionChanged(self, event):
   221         if self.Expression.GetValue() != "":
   252         """
   222             self.VariableName.Enable(False)
   253         Called when expression text control is changed by user
   223         else:
   254         @param event: wx.ListBoxEvent
   224             self.VariableName.Enable(True)
   255         """
       
   256         # Select the corresponding value in name list box if it exists
       
   257         self.VariableName.SetSelection(
       
   258             self.VariableName.FindString(self.Expression.GetValue()))
       
   259         
   225         self.RefreshPreview()
   260         self.RefreshPreview()
   226         event.Skip()
   261         event.Skip()
   227     
   262     
   228     def OnExecutionOrderChanged(self, event):
   263     def OnExecutionOrderChanged(self, event):
       
   264         """
       
   265         Called when block execution control value changed
       
   266         @param event: wx.SpinEvent
       
   267         """
   229         self.RefreshPreview()
   268         self.RefreshPreview()
   230         event.Skip()
   269         event.Skip()
   231     
   270     
   232     def RefreshPreview(self):
   271     def RefreshPreview(self):
   233         dc = wx.ClientDC(self.Preview)
   272         """
   234         dc.SetFont(self.Preview.GetFont())
   273         Refresh preview panel of graphic element
   235         dc.Clear()
   274         Override BlockPreviewDialog function
   236         expression = self.Expression.GetValue()
   275         """
   237         if self.Expression.IsEnabled() and expression != "":
   276         # Get expression value to put in FBD variable element
   238             name = expression
   277         name = self.Expression.GetValue()
   239         else:
   278         
   240             name = self.VariableName.GetStringSelection()
   279         # Set graphic element displayed, creating a FBD variable element
   241         type = ""
   280         self.Element = FBD_Variable(self.Preview, 
   242         for var_name, var_type, value_type in self.VarList:
   281                     VARIABLE_CLASSES_DICT_REVERSE[
   243             if var_name == name:
   282                         self.Class.GetStringSelection()], 
   244                 type = value_type
   283                     name, 
   245         classtype = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()]
   284                     self.VariableList.get(name, ("", ""))[1], 
   246         self.Variable = FBD_Variable(self.Preview, classtype, name, type, executionOrder = self.ExecutionOrder.GetValue())
   285                     executionOrder = self.ExecutionOrder.GetValue())
   247         width, height = self.MinVariableSize
   286         
   248         min_width, min_height = self.Variable.GetMinSize()
   287         # Call BlockPreviewDialog function
   249         width, height = max(min_width, width), max(min_height, height)
   288         BlockPreviewDialog.RefreshPreview(self)
   250         self.Variable.SetSize(width, height)
   289         
   251         clientsize = self.Preview.GetClientSize()
   290         
   252         x = (clientsize.width - width) / 2
       
   253         y = (clientsize.height - height) / 2
       
   254         self.Variable.SetPosition(x, y)
       
   255         self.Variable.Draw(dc)
       
   256 
       
   257     def OnPaint(self, event):
       
   258         self.RefreshPreview()
       
   259         event.Skip()