dialogs/FBDVariableDialog.py
changeset 409 34c9f624c2fe
child 488 93bf600bae11
equal deleted inserted replaced
408:0e389fa5b160 409:34c9f624c2fe
       
     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 #                          Create New Variable Dialog
       
    31 #-------------------------------------------------------------------------------
       
    32 
       
    33 [ID_FBDVARIABLEDIALOG, ID_FBDVARIABLEDIALOGSPACER, 
       
    34  ID_FBDVARIABLEDIALOGNAME, ID_FBDVARIABLEDIALOGCLASS, 
       
    35  ID_FBDVARIABLEDIALOGPREVIEW, ID_FBDVARIABLEDIALOGEXPRESSION,
       
    36  ID_FBDVARIABLEDIALOGEXECUTIONORDER, ID_FBDVARIABLEDIALOGSTATICTEXT1, 
       
    37  ID_FBDVARIABLEDIALOGSTATICTEXT2, ID_FBDVARIABLEDIALOGSTATICTEXT3, 
       
    38  ID_FBDVARIABLEDIALOGSTATICTEXT4, ID_FBDVARIABLEDIALOGSTATICTEXT5
       
    39 ] = [wx.NewId() for _init_ctrls in range(12)]
       
    40 
       
    41 VARIABLE_CLASSES_DICT = {INPUT : _("Input"),
       
    42                          INOUT : _("InOut"),
       
    43                          OUTPUT : _("Output")}
       
    44 VARIABLE_CLASSES_DICT_REVERSE = dict([(value, key) for key, value in VARIABLE_CLASSES_DICT.iteritems()])
       
    45 
       
    46 class FBDVariableDialog(wx.Dialog):
       
    47     
       
    48     if wx.VERSION < (2, 6, 0):
       
    49         def Bind(self, event, function, id = None):
       
    50             if id is not None:
       
    51                 event(self, id, function)
       
    52             else:
       
    53                 event(self, function)
       
    54     
       
    55     def _init_coll_flexGridSizer1_Items(self, parent):
       
    56         parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
       
    57         parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
       
    58         
       
    59     def _init_coll_flexGridSizer1_Growables(self, parent):
       
    60         parent.AddGrowableCol(0)
       
    61         parent.AddGrowableRow(0)
       
    62     
       
    63     def _init_coll_MainSizer_Items(self, parent):
       
    64         parent.AddSizer(self.TopSizer, 0, border=0, flag=wx.GROW)
       
    65         parent.AddWindow(self.staticText5, 0, border=0, flag=wx.GROW)
       
    66         parent.AddWindow(self.Preview, 0, border=0, flag=wx.GROW)
       
    67         
       
    68     def _init_coll_MainSizer_Growables(self, parent):
       
    69         parent.AddGrowableCol(0)
       
    70         parent.AddGrowableRow(2)
       
    71     
       
    72     def _init_coll_TopSizer_Items(self, parent):
       
    73         parent.AddSizer(self.LeftGridSizer, 1, border=5, flag=wx.GROW|wx.RIGHT)
       
    74         parent.AddSizer(self.RightGridSizer, 1, border=5, flag=wx.GROW|wx.LEFT)
       
    75     
       
    76     def _init_coll_LeftGridSizer_Items(self, parent):
       
    77         parent.AddWindow(self.staticText1, 0, border=0, flag=wx.GROW)
       
    78         parent.AddWindow(self.Class, 0, border=0, flag=wx.GROW)
       
    79         parent.AddWindow(self.staticText2, 0, border=0, flag=wx.GROW)
       
    80         parent.AddWindow(self.Expression, 0, border=0, flag=wx.GROW)
       
    81         parent.AddWindow(self.staticText3, 0, border=0, flag=wx.GROW)
       
    82         parent.AddWindow(self.ExecutionOrder, 0, border=0, flag=wx.GROW)
       
    83         parent.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW)
       
    84     
       
    85     def _init_coll_LeftGridSizer_Growables(self, parent):
       
    86         parent.AddGrowableCol(0)
       
    87         parent.AddGrowableRow(2)
       
    88             
       
    89     def _init_coll_RightGridSizer_Items(self, parent):
       
    90         parent.AddWindow(self.staticText4, 0, border=0, flag=wx.GROW)
       
    91         parent.AddWindow(self.VariableName, 0, border=0, flag=wx.GROW)
       
    92         
       
    93     def _init_coll_RightGridSizer_Growables(self, parent):
       
    94         parent.AddGrowableCol(0)
       
    95         parent.AddGrowableRow(1)
       
    96         
       
    97     def _init_sizers(self):
       
    98         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
       
    99         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=5)
       
   100         self.TopSizer = wx.BoxSizer(wx.HORIZONTAL)
       
   101         self.LeftGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=7, vgap=5)
       
   102         self.RightGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
   103 
       
   104         self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
       
   105         self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1)
       
   106         self._init_coll_MainSizer_Items(self.MainSizer)
       
   107         self._init_coll_MainSizer_Growables(self.MainSizer)
       
   108         self._init_coll_TopSizer_Items(self.TopSizer)
       
   109         self._init_coll_LeftGridSizer_Items(self.LeftGridSizer)
       
   110         self._init_coll_LeftGridSizer_Growables(self.LeftGridSizer)
       
   111         self._init_coll_RightGridSizer_Items(self.RightGridSizer)
       
   112         self._init_coll_RightGridSizer_Growables(self.RightGridSizer)
       
   113         
       
   114         self.SetSizer(self.flexGridSizer1)
       
   115 
       
   116     def _init_ctrls(self, prnt, ctrler):
       
   117         wx.Dialog.__init__(self, id=ID_FBDVARIABLEDIALOG,
       
   118               name='FBDVariableDialog', parent=prnt, pos=wx.Point(376, 223),
       
   119               size=wx.Size(400, 380), style=wx.DEFAULT_DIALOG_STYLE,
       
   120               title=_('Variable Properties'))
       
   121         self.SetClientSize(wx.Size(400, 380))
       
   122 
       
   123         self.staticText1 = wx.StaticText(id=ID_FBDVARIABLEDIALOGSTATICTEXT1,
       
   124               label=_('Class:'), name='staticText1', parent=self,
       
   125               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
       
   126 
       
   127         self.staticText2 = wx.StaticText(id=ID_FBDVARIABLEDIALOGSTATICTEXT2,
       
   128               label=_('Expression:'), name='staticText2', parent=self,
       
   129               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
       
   130 
       
   131         self.staticText3 = wx.StaticText(id=ID_FBDVARIABLEDIALOGSTATICTEXT3,
       
   132               label=_('Execution Order:'), name='staticText3', parent=self,
       
   133               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
       
   134 
       
   135         self.staticText4 = wx.StaticText(id=ID_FBDVARIABLEDIALOGSTATICTEXT4,
       
   136               label=_('Name:'), name='staticText4', parent=self,
       
   137               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
       
   138 
       
   139         self.staticText5 = wx.StaticText(id=ID_FBDVARIABLEDIALOGSTATICTEXT5,
       
   140               label=_('Preview:'), name='staticText5', parent=self,
       
   141               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
       
   142 
       
   143         self.Class = wx.ComboBox(id=ID_FBDVARIABLEDIALOGCLASS,
       
   144               name='Class', parent=self, pos=wx.Point(0, 0),
       
   145               size=wx.Size(0, 28), style=wx.CB_READONLY)
       
   146         self.Bind(wx.EVT_COMBOBOX, self.OnClassChanged, id=ID_FBDVARIABLEDIALOGCLASS)
       
   147         
       
   148         self.VariableName = wx.ListBox(id=ID_FBDVARIABLEDIALOGNAME,
       
   149               name='Name', parent=self, pos=wx.Point(0, 0),
       
   150               size=wx.Size(0, 90), style=wx.LB_SINGLE|wx.LB_SORT)
       
   151         self.Bind(wx.EVT_LISTBOX, self.OnNameChanged, id=ID_FBDVARIABLEDIALOGNAME)
       
   152 
       
   153         self.Expression = wx.TextCtrl(id=ID_FBDVARIABLEDIALOGEXPRESSION,
       
   154               name='Expression', parent=self, pos=wx.Point(0, 0),
       
   155               size=wx.Size(0, 24), style=0)
       
   156         self.Bind(wx.EVT_TEXT, self.OnExpressionChanged, id=ID_FBDVARIABLEDIALOGEXPRESSION)
       
   157 
       
   158         self.ExecutionOrder = wx.SpinCtrl(id=ID_FBDVARIABLEDIALOGEXECUTIONORDER,
       
   159               name='ExecutionOrder', parent=self, pos=wx.Point(0, 0),
       
   160               size=wx.Size(0, 24), style=wx.SP_ARROW_KEYS, min=0)
       
   161         self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged, id=ID_FBDVARIABLEDIALOGEXECUTIONORDER)
       
   162 
       
   163         self.Spacer = wx.Panel(id=ID_FBDVARIABLEDIALOGSPACER,
       
   164               name='Spacer', parent=self, pos=wx.Point(0, 0),
       
   165               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
       
   166 
       
   167         self.Preview = wx.Panel(id=ID_FBDVARIABLEDIALOGPREVIEW,
       
   168               name='Preview', parent=self, pos=wx.Point(0, 0),
       
   169               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
       
   170         self.Preview.SetBackgroundColour(wx.Colour(255,255,255))
       
   171         setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE)
       
   172         setattr(self.Preview, "GetScaling", lambda:None)
       
   173         setattr(self.Preview, "IsOfType", ctrler.IsOfType)
       
   174 
       
   175         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
       
   176         if wx.VERSION >= (2, 5, 0):
       
   177             self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId())
       
   178             self.Preview.Bind(wx.EVT_PAINT, self.OnPaint)
       
   179         else:
       
   180             self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId())
       
   181             wx.EVT_PAINT(self.Preview, self.OnPaint)
       
   182         
       
   183         self._init_sizers()
       
   184 
       
   185     def __init__(self, parent, controler, transition = ""):
       
   186         self._init_ctrls(parent, controler)
       
   187         self.Transition = transition
       
   188         self.Variable = None
       
   189         self.VarList = []
       
   190         self.MinVariableSize = None
       
   191         
       
   192         for choice in VARIABLE_CLASSES_DICT.itervalues():
       
   193             self.Class.Append(choice)
       
   194         self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[INPUT])
       
   195 
       
   196         self.RefreshNameList()
       
   197 
       
   198     def SetPreviewFont(self, font):
       
   199         self.Preview.SetFont(font)
       
   200 
       
   201     def RefreshNameList(self):
       
   202         selected = self.VariableName.GetStringSelection()
       
   203         var_class = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()]
       
   204         self.VariableName.Clear()
       
   205         self.VariableName.Append("")
       
   206         for name, var_type, value_type in self.VarList:
       
   207             if var_type != "Input" or var_class == INPUT:
       
   208                 self.VariableName.Append(name)
       
   209         if selected != "" and self.VariableName.FindString(selected) != wx.NOT_FOUND:
       
   210             self.VariableName.SetStringSelection(selected)
       
   211             self.Expression.Enable(False)
       
   212         else:
       
   213             self.VariableName.SetStringSelection("")
       
   214             self.Expression.Enable(var_class == INPUT)
       
   215         self.VariableName.Enable(self.VariableName.GetCount() > 0)
       
   216             
       
   217     def SetMinVariableSize(self, size):
       
   218         self.MinVariableSize = size
       
   219 
       
   220     def SetVariables(self, vars):
       
   221         self.VarList = vars
       
   222         self.RefreshNameList()
       
   223 
       
   224     def SetValues(self, values):
       
   225         value_type = values.get("type", None)
       
   226         value_name = values.get("name", None)
       
   227         if value_type:
       
   228             self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[value_type])
       
   229             self.RefreshNameList()
       
   230         if value_name:
       
   231             if self.VariableName.FindString(value_name) != wx.NOT_FOUND:
       
   232                 self.VariableName.SetStringSelection(value_name)
       
   233                 self.Expression.Enable(False)
       
   234             else:
       
   235                 self.Expression.SetValue(value_name)
       
   236                 self.VariableName.Enable(False)
       
   237         if "executionOrder" in values:
       
   238             self.ExecutionOrder.SetValue(values["executionOrder"])
       
   239         self.RefreshPreview()
       
   240         
       
   241     def GetValues(self):
       
   242         values = {}
       
   243         values["type"] = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()]
       
   244         expression = self.Expression.GetValue()
       
   245         if self.Expression.IsEnabled() and expression != "":
       
   246             values["name"] = expression
       
   247         else:
       
   248             values["name"] = self.VariableName.GetStringSelection()
       
   249         values["value_type"] = None
       
   250         for var_name, var_type, value_type in self.VarList:
       
   251             if var_name == values["name"]:
       
   252                 values["value_type"] = value_type
       
   253         values["width"], values["height"] = self.Variable.GetSize()
       
   254         values["executionOrder"] = self.ExecutionOrder.GetValue()
       
   255         return values
       
   256 
       
   257     def OnOK(self, event):
       
   258         expression = self.Expression.GetValue()
       
   259         if self.Expression.IsEnabled():
       
   260             value = expression
       
   261         else:
       
   262             value = self.VariableName.GetStringSelection()
       
   263         if value == "":
       
   264             message = wx.MessageDialog(self, _("At least a variable or an expression must be selected!"), _("Error"), wx.OK|wx.ICON_ERROR)
       
   265             message.ShowModal()
       
   266             message.Destroy()
       
   267         elif value.upper() in IEC_KEYWORDS:
       
   268             message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%value, _("Error"), wx.OK|wx.ICON_ERROR)
       
   269             message.ShowModal()
       
   270             message.Destroy()
       
   271         else:
       
   272             self.EndModal(wx.ID_OK)
       
   273 
       
   274     def OnClassChanged(self, event):
       
   275         self.RefreshNameList()
       
   276         self.RefreshPreview()
       
   277         event.Skip()
       
   278 
       
   279     def OnNameChanged(self, event):
       
   280         if self.VariableName.GetStringSelection() != "":
       
   281             self.Expression.Enable(False)
       
   282         elif VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()] == INPUT:
       
   283             self.Expression.Enable(True)
       
   284         self.RefreshPreview()
       
   285         event.Skip()
       
   286     
       
   287     def OnExpressionChanged(self, event):
       
   288         if self.Expression.GetValue() != "":
       
   289             self.VariableName.Enable(False)
       
   290         else:
       
   291             self.VariableName.Enable(True)
       
   292         self.RefreshPreview()
       
   293         event.Skip()
       
   294     
       
   295     def OnExecutionOrderChanged(self, event):
       
   296         self.RefreshPreview()
       
   297         event.Skip()
       
   298     
       
   299     def RefreshPreview(self):
       
   300         dc = wx.ClientDC(self.Preview)
       
   301         dc.SetFont(self.Preview.GetFont())
       
   302         dc.Clear()
       
   303         expression = self.Expression.GetValue()
       
   304         if self.Expression.IsEnabled() and expression != "":
       
   305             name = expression
       
   306         else:
       
   307             name = self.VariableName.GetStringSelection()
       
   308         type = ""
       
   309         for var_name, var_type, value_type in self.VarList:
       
   310             if var_name == name:
       
   311                 type = value_type
       
   312         classtype = VARIABLE_CLASSES_DICT_REVERSE[self.Class.GetStringSelection()]
       
   313         self.Variable = FBD_Variable(self.Preview, classtype, name, type, executionOrder = self.ExecutionOrder.GetValue())
       
   314         width, height = self.MinVariableSize
       
   315         min_width, min_height = self.Variable.GetMinSize()
       
   316         width, height = max(min_width, width), max(min_height, height)
       
   317         self.Variable.SetSize(width, height)
       
   318         clientsize = self.Preview.GetClientSize()
       
   319         x = (clientsize.width - width) / 2
       
   320         y = (clientsize.height - height) / 2
       
   321         self.Variable.SetPosition(x, y)
       
   322         self.Variable.Draw(dc)
       
   323 
       
   324     def OnPaint(self, event):
       
   325         self.RefreshPreview()
       
   326         event.Skip()