dialogs/FBDVariableDialog.py
changeset 814 5743cbdff669
child 1182 208103fd9ad0
equal deleted inserted replaced
813:1460273f40ed 814:5743cbdff669
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
       
     5 #based on the plcopen standard. 
       
     6 #
       
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
       
     8 #
       
     9 #See COPYING file for copyrights details.
       
    10 #
       
    11 #This library is free software; you can redistribute it and/or
       
    12 #modify it under the terms of the GNU General Public
       
    13 #License as published by the Free Software Foundation; either
       
    14 #version 2.1 of the License, or (at your option) any later version.
       
    15 #
       
    16 #This library is distributed in the hope that it will be useful,
       
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    19 #General Public License for more details.
       
    20 #
       
    21 #You should have received a copy of the GNU General Public
       
    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
       
    24 
       
    25 import wx
       
    26 
       
    27 from graphics import *
       
    28 
       
    29 #-------------------------------------------------------------------------------
       
    30 #                                    Helpers
       
    31 #-------------------------------------------------------------------------------
       
    32 
       
    33 VARIABLE_CLASSES_DICT = {INPUT : _("Input"),
       
    34                          INOUT : _("InOut"),
       
    35                          OUTPUT : _("Output")}
       
    36 VARIABLE_CLASSES_DICT_REVERSE = dict(
       
    37     [(value, key) for key, value in VARIABLE_CLASSES_DICT.iteritems()])
       
    38 
       
    39 #-------------------------------------------------------------------------------
       
    40 #                          Create New Variable Dialog
       
    41 #-------------------------------------------------------------------------------
       
    42 
       
    43 class FBDVariableDialog(wx.Dialog):
       
    44 
       
    45     def __init__(self, parent, controller, transition = ""):
       
    46         wx.Dialog.__init__(self, parent,
       
    47               size=wx.Size(400, 380), title=_('Variable Properties'))
       
    48         
       
    49         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=4, vgap=10)
       
    50         main_sizer.AddGrowableCol(0)
       
    51         main_sizer.AddGrowableRow(2)
       
    52         
       
    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:'))
       
    63         left_gridsizer.AddWindow(class_label, flag=wx.GROW)
       
    64         
       
    65         self.Class = wx.ComboBox(self, style=wx.CB_READONLY)
       
    66         self.Bind(wx.EVT_COMBOBOX, self.OnClassChanged, self.Class)
       
    67         left_gridsizer.AddWindow(self.Class, flag=wx.GROW)
       
    68         
       
    69         expression_label = wx.StaticText(self, label=_('Expression:'))
       
    70         left_gridsizer.AddWindow(expression_label, flag=wx.GROW)
       
    71         
       
    72         self.Expression = wx.TextCtrl(self)
       
    73         self.Bind(wx.EVT_TEXT, self.OnExpressionChanged, self.Expression)
       
    74         left_gridsizer.AddWindow(self.Expression, flag=wx.GROW)
       
    75         
       
    76         execution_order_label = wx.StaticText(self, label=_('Execution Order:'))
       
    77         left_gridsizer.AddWindow(execution_order_label, flag=wx.GROW)
       
    78         
       
    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)
       
    94         self.Bind(wx.EVT_LISTBOX, self.OnNameChanged, self.VariableName)
       
    95         right_gridsizer.AddWindow(self.VariableName, flag=wx.GROW)
       
    96         
       
    97         preview_label = wx.StaticText(self, label=_('Preview:'))
       
    98         main_sizer.AddWindow(preview_label, border=20,
       
    99               flag=wx.GROW|wx.LEFT|wx.RIGHT)
       
   100         
       
   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)
       
   110         
       
   111         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
       
   112         self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton())
       
   113         main_sizer.AddSizer(button_sizer, border=20, 
       
   114               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
       
   115         
       
   116         self.SetSizer(main_sizer)
       
   117         
       
   118         self.Transition = transition
       
   119         self.Variable = None
       
   120         self.VarList = []
       
   121         self.MinVariableSize = None
       
   122         
       
   123         for choice in VARIABLE_CLASSES_DICT.itervalues():
       
   124             self.Class.Append(choice)
       
   125         self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[INPUT])
       
   126 
       
   127         self.RefreshNameList()
       
   128         self.Class.SetFocus()
       
   129 
       
   130     def SetPreviewFont(self, font):
       
   131         self.Preview.SetFont(font)
       
   132 
       
   133     def RefreshNameList(self):
       
   134         selected = self.VariableName.GetStringSelection()
       
   135         var_class = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()]
       
   136         self.VariableName.Clear()
       
   137         self.VariableName.Append("")
       
   138         for name, var_type, value_type in self.VarList:
       
   139             if var_type != "Input" or var_class == INPUT:
       
   140                 self.VariableName.Append(name)
       
   141         if selected != "" and self.VariableName.FindString(selected) != wx.NOT_FOUND:
       
   142             self.VariableName.SetStringSelection(selected)
       
   143             self.Expression.Enable(False)
       
   144         else:
       
   145             self.VariableName.SetStringSelection("")
       
   146             #self.Expression.Enable(var_class == INPUT)
       
   147         self.VariableName.Enable(self.VariableName.GetCount() > 0)
       
   148             
       
   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         value_type = values.get("type", None)
       
   158         value_name = values.get("name", None)
       
   159         if value_type:
       
   160             self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[value_type])
       
   161             self.RefreshNameList()
       
   162         if value_name:
       
   163             if self.VariableName.FindString(value_name) != wx.NOT_FOUND:
       
   164                 self.VariableName.SetStringSelection(value_name)
       
   165                 self.Expression.Enable(False)
       
   166             else:
       
   167                 self.Expression.SetValue(value_name)
       
   168                 self.VariableName.Enable(False)
       
   169         if "executionOrder" in values:
       
   170             self.ExecutionOrder.SetValue(values["executionOrder"])
       
   171         self.RefreshPreview()
       
   172         
       
   173     def GetValues(self):
       
   174         values = {}
       
   175         values["type"] = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()]
       
   176         expression = self.Expression.GetValue()
       
   177         if self.Expression.IsEnabled() and expression != "":
       
   178             values["name"] = expression
       
   179         else:
       
   180             values["name"] = self.VariableName.GetStringSelection()
       
   181         values["value_type"] = None
       
   182         for var_name, var_type, value_type in self.VarList:
       
   183             if var_name == values["name"]:
       
   184                 values["value_type"] = value_type
       
   185         values["width"], values["height"] = self.Variable.GetSize()
       
   186         values["executionOrder"] = self.ExecutionOrder.GetValue()
       
   187         return values
       
   188 
       
   189     def OnOK(self, event):
       
   190         message = None
       
   191         expression = self.Expression.GetValue()
       
   192         if self.Expression.IsEnabled():
       
   193             value = expression
       
   194         else:
       
   195             value = self.VariableName.GetStringSelection()
       
   196         if value == "":
       
   197             message = _("At least a variable or an expression must be selected!")
       
   198         elif value.upper() in IEC_KEYWORDS:
       
   199             message = _("\"%s\" is a keyword. It can't be used!") % value
       
   200         if message is not None:
       
   201             message = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
       
   202             message.ShowModal()
       
   203             message.Destroy()
       
   204         else:
       
   205             self.EndModal(wx.ID_OK)
       
   206 
       
   207     def OnClassChanged(self, event):
       
   208         self.RefreshNameList()
       
   209         self.RefreshPreview()
       
   210         event.Skip()
       
   211 
       
   212     def OnNameChanged(self, event):
       
   213         if self.VariableName.GetStringSelection() != "":
       
   214             self.Expression.Enable(False)
       
   215         elif VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()] == INPUT:
       
   216             self.Expression.Enable(True)
       
   217         self.RefreshPreview()
       
   218         event.Skip()
       
   219     
       
   220     def OnExpressionChanged(self, event):
       
   221         if self.Expression.GetValue() != "":
       
   222             self.VariableName.Enable(False)
       
   223         else:
       
   224             self.VariableName.Enable(True)
       
   225         self.RefreshPreview()
       
   226         event.Skip()
       
   227     
       
   228     def OnExecutionOrderChanged(self, event):
       
   229         self.RefreshPreview()
       
   230         event.Skip()
       
   231     
       
   232     def RefreshPreview(self):
       
   233         dc = wx.ClientDC(self.Preview)
       
   234         dc.SetFont(self.Preview.GetFont())
       
   235         dc.Clear()
       
   236         expression = self.Expression.GetValue()
       
   237         if self.Expression.IsEnabled() and expression != "":
       
   238             name = expression
       
   239         else:
       
   240             name = self.VariableName.GetStringSelection()
       
   241         type = ""
       
   242         for var_name, var_type, value_type in self.VarList:
       
   243             if var_name == name:
       
   244                 type = value_type
       
   245         classtype = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()]
       
   246         self.Variable = FBD_Variable(self.Preview, classtype, name, type, executionOrder = self.ExecutionOrder.GetValue())
       
   247         width, height = self.MinVariableSize
       
   248         min_width, min_height = self.Variable.GetMinSize()
       
   249         width, height = max(min_width, width), max(min_height, height)
       
   250         self.Variable.SetSize(width, height)
       
   251         clientsize = self.Preview.GetClientSize()
       
   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()