diff -r c8e008b8cefe -r 72a826dfcfbb dialogs/FBDVariableDialog.py --- a/dialogs/FBDVariableDialog.py Wed Mar 13 12:34:55 2013 +0900 +++ b/dialogs/FBDVariableDialog.py Wed Jul 31 10:45:07 2013 +0900 @@ -24,12 +24,16 @@ import wx -from graphics import * +from graphics.GraphicCommons import INPUT, INOUT, OUTPUT +from graphics.FBD_Objects import FBD_Variable +from BlockPreviewDialog import BlockPreviewDialog #------------------------------------------------------------------------------- # Helpers #------------------------------------------------------------------------------- +# Dictionaries containing correspondence between variable block class and string +# to be shown in Class combo box in both sense VARIABLE_CLASSES_DICT = {INPUT : _("Input"), INOUT : _("InOut"), OUTPUT : _("Output")} @@ -37,223 +41,250 @@ [(value, key) for key, value in VARIABLE_CLASSES_DICT.iteritems()]) #------------------------------------------------------------------------------- -# Create New Variable Dialog -#------------------------------------------------------------------------------- - -class FBDVariableDialog(wx.Dialog): - - def __init__(self, parent, controller, transition = ""): - wx.Dialog.__init__(self, parent, +# Set Variable Parameters Dialog +#------------------------------------------------------------------------------- + +""" +Class that implements a dialog for defining parameters of a FBD variable graphic +element +""" + +class FBDVariableDialog(BlockPreviewDialog): + + def __init__(self, parent, controller, tagname, exclude_input=False): + """ + Constructor + @param parent: Parent wx.Window of dialog for modal + @param controller: Reference to project controller + @param tagname: Tagname of project POU edited + @param exclude_input: Exclude input from variable class selection + """ + BlockPreviewDialog.__init__(self, parent, controller, tagname, size=wx.Size(400, 380), title=_('Variable Properties')) - main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=4, vgap=10) - main_sizer.AddGrowableCol(0) - main_sizer.AddGrowableRow(2) - - column_sizer = wx.BoxSizer(wx.HORIZONTAL) - main_sizer.AddSizer(column_sizer, border=20, - flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) - - left_gridsizer = wx.FlexGridSizer(cols=1, hgap=0, rows=6, vgap=5) - left_gridsizer.AddGrowableCol(0) - column_sizer.AddSizer(left_gridsizer, 1, border=5, - flag=wx.GROW|wx.RIGHT) - + # Init common sizers + self._init_sizers(4, 2, 4, None, 3, 2) + + # Create label for variable class class_label = wx.StaticText(self, label=_('Class:')) - left_gridsizer.AddWindow(class_label, flag=wx.GROW) - + self.LeftGridSizer.AddWindow(class_label, flag=wx.GROW) + + # Create a combo box for defining variable class self.Class = wx.ComboBox(self, style=wx.CB_READONLY) self.Bind(wx.EVT_COMBOBOX, self.OnClassChanged, self.Class) - left_gridsizer.AddWindow(self.Class, flag=wx.GROW) - - expression_label = wx.StaticText(self, label=_('Expression:')) - left_gridsizer.AddWindow(expression_label, flag=wx.GROW) - + self.LeftGridSizer.AddWindow(self.Class, flag=wx.GROW) + + # Create label for variable execution order + execution_order_label = wx.StaticText(self, + label=_('Execution Order:')) + self.LeftGridSizer.AddWindow(execution_order_label, flag=wx.GROW) + + # Create spin control for defining variable execution order + self.ExecutionOrder = wx.SpinCtrl(self, min=0, style=wx.SP_ARROW_KEYS) + self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged, + self.ExecutionOrder) + self.LeftGridSizer.AddWindow(self.ExecutionOrder, flag=wx.GROW) + + # Create label for variable expression + name_label = wx.StaticText(self, label=_('Expression:')) + self.RightGridSizer.AddWindow(name_label, border=5, + flag=wx.GROW|wx.BOTTOM) + + # Create text control for defining variable expression self.Expression = wx.TextCtrl(self) self.Bind(wx.EVT_TEXT, self.OnExpressionChanged, self.Expression) - left_gridsizer.AddWindow(self.Expression, flag=wx.GROW) - - execution_order_label = wx.StaticText(self, label=_('Execution Order:')) - left_gridsizer.AddWindow(execution_order_label, flag=wx.GROW) - - self.ExecutionOrder = wx.SpinCtrl(self, min=0, style=wx.SP_ARROW_KEYS) - self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged, self.ExecutionOrder) - left_gridsizer.AddWindow(self.ExecutionOrder, flag=wx.GROW) - - right_gridsizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) - right_gridsizer.AddGrowableCol(0) - right_gridsizer.AddGrowableRow(1) - column_sizer.AddSizer(right_gridsizer, 1, border=5, - flag=wx.GROW|wx.LEFT) - - name_label = wx.StaticText(self, label=_('Name:')) - right_gridsizer.AddWindow(name_label, flag=wx.GROW) - - self.VariableName = wx.ListBox(self, size=wx.Size(0, 0), + self.RightGridSizer.AddWindow(self.Expression, flag=wx.GROW) + + # Create a list box to selected variable expression in the list of + # variables defined in POU + self.VariableName = wx.ListBox(self, size=wx.Size(0, 120), style=wx.LB_SINGLE|wx.LB_SORT) self.Bind(wx.EVT_LISTBOX, self.OnNameChanged, self.VariableName) - right_gridsizer.AddWindow(self.VariableName, flag=wx.GROW) - - preview_label = wx.StaticText(self, label=_('Preview:')) - main_sizer.AddWindow(preview_label, border=20, + self.RightGridSizer.AddWindow(self.VariableName, flag=wx.GROW) + + # Add preview panel and associated label to sizers + self.MainSizer.AddWindow(self.PreviewLabel, border=20, flag=wx.GROW|wx.LEFT|wx.RIGHT) - - self.Preview = wx.Panel(self, - style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) - self.Preview.SetBackgroundColour(wx.Colour(255,255,255)) - setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE) - setattr(self.Preview, "GetScaling", lambda:None) - setattr(self.Preview, "IsOfType", controller.IsOfType) - self.Preview.Bind(wx.EVT_PAINT, self.OnPaint) - main_sizer.AddWindow(self.Preview, border=20, + self.MainSizer.AddWindow(self.Preview, border=20, flag=wx.GROW|wx.LEFT|wx.RIGHT) - button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) - self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton()) - main_sizer.AddSizer(button_sizer, border=20, + # Add buttons sizer to sizers + self.MainSizer.AddSizer(self.ButtonSizer, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) - self.SetSizer(main_sizer) - - self.Transition = transition - self.Variable = None - self.VarList = [] - self.MinVariableSize = None - - for choice in VARIABLE_CLASSES_DICT.itervalues(): - self.Class.Append(choice) - self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[INPUT]) - + # Set options that can be selected in class combo box + for var_class, choice in VARIABLE_CLASSES_DICT.iteritems(): + if not exclude_input or var_class != INPUT: + self.Class.Append(choice) + self.Class.SetSelection(0) + + # Extract list of variables defined in POU + self.RefreshVariableList() + + # Refresh values in name list box self.RefreshNameList() + + # Class combo box is default control having keyboard focus self.Class.SetFocus() - def SetPreviewFont(self, font): - self.Preview.SetFont(font) - def RefreshNameList(self): - selected = self.VariableName.GetStringSelection() - var_class = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()] + """ + Called to refresh names in name list box + """ + # Get variable class to select POU variable applicable + var_class = VARIABLE_CLASSES_DICT_REVERSE[ + self.Class.GetStringSelection()] + + # Refresh names in name list box by selecting variables in POU variables + # list that can be applied to variable class self.VariableName.Clear() - self.VariableName.Append("") - for name, var_type, value_type in self.VarList: + for name, (var_type, value_type) in self.VariableList.iteritems(): if var_type != "Input" or var_class == INPUT: self.VariableName.Append(name) - if selected != "" and self.VariableName.FindString(selected) != wx.NOT_FOUND: + + # Get variable expression and select corresponding value in name list + # box if it exists + selected = self.Expression.GetValue() + if (selected != "" and + self.VariableName.FindString(selected) != wx.NOT_FOUND): self.VariableName.SetStringSelection(selected) - self.Expression.Enable(False) else: - self.VariableName.SetStringSelection("") - #self.Expression.Enable(var_class == INPUT) + self.VariableName.SetSelection(wx.NOT_FOUND) + + # Disable name list box if no name present inside self.VariableName.Enable(self.VariableName.GetCount() > 0) - def SetMinVariableSize(self, size): - self.MinVariableSize = size - - def SetVariables(self, vars): - self.VarList = vars - self.RefreshNameList() - def SetValues(self, values): - value_type = values.get("type", None) - value_name = values.get("name", None) - if value_type: - self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[value_type]) + """ + Set default variable parameters + @param values: Variable parameters values + """ + + # Get class parameter value + var_class = values.get("class", None) + if var_class is not None: + # Set class selected in class combo box + self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[var_class]) + # Refresh names in name list box according to var class self.RefreshNameList() - if value_name: - if self.VariableName.FindString(value_name) != wx.NOT_FOUND: - self.VariableName.SetStringSelection(value_name) - self.Expression.Enable(False) - else: - self.Expression.SetValue(value_name) - self.VariableName.Enable(False) - if "executionOrder" in values: - self.ExecutionOrder.SetValue(values["executionOrder"]) + + # For each parameters defined, set corresponding control value + for name, value in values.items(): + + # Parameter is variable expression + if name == "expression": + # Set expression text control value + self.Expression.ChangeValue(value) + # Select corresponding text in name list box if it exists + if self.VariableName.FindString(value) != wx.NOT_FOUND: + self.VariableName.SetStringSelection(value) + else: + self.VariableName.SetSelection(wx.NOT_FOUND) + + # Parameter is variable execution order + elif name == "executionOrder": + self.ExecutionOrder.SetValue(value) + + # Refresh preview panel self.RefreshPreview() def GetValues(self): - values = {} - values["type"] = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()] + """ + Return block parameters defined in dialog + @return: {parameter_name: parameter_value,...} + """ expression = self.Expression.GetValue() - if self.Expression.IsEnabled() and expression != "": - values["name"] = expression - else: - values["name"] = self.VariableName.GetStringSelection() - values["value_type"] = None - for var_name, var_type, value_type in self.VarList: - if var_name == values["name"]: - values["value_type"] = value_type - values["width"], values["height"] = self.Variable.GetSize() - values["executionOrder"] = self.ExecutionOrder.GetValue() + values = { + "class": VARIABLE_CLASSES_DICT_REVERSE[ + self.Class.GetStringSelection()], + "expression": expression, + "var_type": self.VariableList.get(expression, (None, None))[1], + "executionOrder": self.ExecutionOrder.GetValue()} + values["width"], values["height"] = self.Element.GetSize() return values def OnOK(self, event): + """ + Called when dialog OK button is pressed + Test if parameters defined are valid + @param event: wx.Event from OK button + """ message = None - expression = self.Expression.GetValue() - if self.Expression.IsEnabled(): - value = expression - else: - value = self.VariableName.GetStringSelection() + + # Test that an expression have been selected or typed by user + value = self.Expression.GetValue() if value == "": message = _("At least a variable or an expression must be selected!") - elif value.upper() in IEC_KEYWORDS: - message = _("\"%s\" is a keyword. It can't be used!") % value + + # Show error message if an error is detected if message is not None: - message = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR) - message.ShowModal() - message.Destroy() + self.ShowErrorMessage(message) + else: - self.EndModal(wx.ID_OK) + # Call BlockPreviewDialog function + BlockPreviewDialog.OnOK(self, event) def OnClassChanged(self, event): + """ + Called when variable class value changed + @param event: wx.ComboBoxEvent + """ + # Refresh name list box values self.RefreshNameList() + self.RefreshPreview() event.Skip() def OnNameChanged(self, event): - if self.VariableName.GetStringSelection() != "": - self.Expression.Enable(False) - elif VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()] == INPUT: - self.Expression.Enable(True) + """ + Called when name selected in name list box changed + @param event: wx.ListBoxEvent + """ + # Change expression test control value to the value selected in name + # list box if value selected is valid + if self.VariableName.GetSelection() != wx.NOT_FOUND: + self.Expression.ChangeValue(self.VariableName.GetStringSelection()) + self.RefreshPreview() event.Skip() def OnExpressionChanged(self, event): - if self.Expression.GetValue() != "": - self.VariableName.Enable(False) - else: - self.VariableName.Enable(True) + """ + Called when expression text control is changed by user + @param event: wx.ListBoxEvent + """ + # Select the corresponding value in name list box if it exists + self.VariableName.SetSelection( + self.VariableName.FindString(self.Expression.GetValue())) + self.RefreshPreview() event.Skip() def OnExecutionOrderChanged(self, event): + """ + Called when block execution control value changed + @param event: wx.SpinEvent + """ self.RefreshPreview() event.Skip() def RefreshPreview(self): - dc = wx.ClientDC(self.Preview) - dc.SetFont(self.Preview.GetFont()) - dc.Clear() - expression = self.Expression.GetValue() - if self.Expression.IsEnabled() and expression != "": - name = expression - else: - name = self.VariableName.GetStringSelection() - type = "" - for var_name, var_type, value_type in self.VarList: - if var_name == name: - type = value_type - classtype = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()] - self.Variable = FBD_Variable(self.Preview, classtype, name, type, executionOrder = self.ExecutionOrder.GetValue()) - width, height = self.MinVariableSize - min_width, min_height = self.Variable.GetMinSize() - width, height = max(min_width, width), max(min_height, height) - self.Variable.SetSize(width, height) - clientsize = self.Preview.GetClientSize() - x = (clientsize.width - width) / 2 - y = (clientsize.height - height) / 2 - self.Variable.SetPosition(x, y) - self.Variable.Draw(dc) - - def OnPaint(self, event): - self.RefreshPreview() - event.Skip() + """ + Refresh preview panel of graphic element + Override BlockPreviewDialog function + """ + # Get expression value to put in FBD variable element + name = self.Expression.GetValue() + + # Set graphic element displayed, creating a FBD variable element + self.Element = FBD_Variable(self.Preview, + VARIABLE_CLASSES_DICT_REVERSE[ + self.Class.GetStringSelection()], + name, + self.VariableList.get(name, ("", ""))[1], + executionOrder = self.ExecutionOrder.GetValue()) + + # Call BlockPreviewDialog function + BlockPreviewDialog.RefreshPreview(self) + + \ No newline at end of file