dialogs/FBDBlockDialog.py
changeset 814 5743cbdff669
child 1230 5a4c5724788e
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 from controls.LibraryPanel import LibraryPanel
       
    29 
       
    30 #-------------------------------------------------------------------------------
       
    31 #                          Create New Block Dialog
       
    32 #-------------------------------------------------------------------------------
       
    33 
       
    34 class FBDBlockDialog(wx.Dialog):
       
    35     
       
    36     def __init__(self, parent, controller):
       
    37         wx.Dialog.__init__(self, parent,
       
    38               size=wx.Size(600, 450), title=_('Block Properties'))
       
    39         
       
    40         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=4, vgap=10)
       
    41         main_sizer.AddGrowableCol(0)
       
    42         main_sizer.AddGrowableRow(0)
       
    43         
       
    44         column_sizer = wx.BoxSizer(wx.HORIZONTAL)
       
    45         main_sizer.AddSizer(column_sizer, border=20, 
       
    46               flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
       
    47         
       
    48         type_staticbox = wx.StaticBox(self, label=_('Type:'))
       
    49         left_staticboxsizer = wx.StaticBoxSizer(type_staticbox, wx.VERTICAL)
       
    50         column_sizer.AddSizer(left_staticboxsizer, 1, border=5, 
       
    51               flag=wx.GROW|wx.RIGHT)
       
    52         
       
    53         self.LibraryPanel = LibraryPanel(self)
       
    54         self.LibraryPanel.SetController(controller)
       
    55         setattr(self.LibraryPanel, "_OnTreeItemSelected", 
       
    56               self.OnLibraryTreeItemSelected)
       
    57         left_staticboxsizer.AddWindow(self.LibraryPanel, 1, border=5, 
       
    58               flag=wx.GROW|wx.TOP)
       
    59         
       
    60         right_gridsizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=5)
       
    61         right_gridsizer.AddGrowableCol(0)
       
    62         right_gridsizer.AddGrowableRow(2)
       
    63         column_sizer.AddSizer(right_gridsizer, 1, border=5, 
       
    64               flag=wx.GROW|wx.LEFT)
       
    65         
       
    66         top_right_gridsizer = wx.FlexGridSizer(cols=2, hgap=0, rows=4, vgap=5)
       
    67         top_right_gridsizer.AddGrowableCol(1)
       
    68         right_gridsizer.AddSizer(top_right_gridsizer, flag=wx.GROW)
       
    69         
       
    70         name_label = wx.StaticText(self, label=_('Name:'))
       
    71         top_right_gridsizer.AddWindow(name_label, 
       
    72               flag=wx.ALIGN_CENTER_VERTICAL)
       
    73         
       
    74         self.BlockName = wx.TextCtrl(self)
       
    75         self.Bind(wx.EVT_TEXT, self.OnNameChanged, self.BlockName)
       
    76         top_right_gridsizer.AddWindow(self.BlockName, flag=wx.GROW)
       
    77         
       
    78         inputs_label = wx.StaticText(self, label=_('Inputs:'))
       
    79         top_right_gridsizer.AddWindow(inputs_label, 
       
    80               flag=wx.ALIGN_CENTER_VERTICAL)
       
    81         
       
    82         self.Inputs = wx.SpinCtrl(self, min=2, max=20,
       
    83               style=wx.SP_ARROW_KEYS)
       
    84         self.Bind(wx.EVT_SPINCTRL, self.OnInputsChanged, self.Inputs)
       
    85         top_right_gridsizer.AddWindow(self.Inputs, flag=wx.GROW)
       
    86         
       
    87         execution_order_label = wx.StaticText(self, label=_('Execution Order:'))
       
    88         top_right_gridsizer.AddWindow(execution_order_label, 
       
    89               flag=wx.ALIGN_CENTER_VERTICAL)
       
    90         
       
    91         self.ExecutionOrder = wx.SpinCtrl(self, min=0, style=wx.SP_ARROW_KEYS)
       
    92         self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged, self.ExecutionOrder)
       
    93         top_right_gridsizer.AddWindow(self.ExecutionOrder, flag=wx.GROW)
       
    94                 
       
    95         execution_control_label = wx.StaticText(self, label=_('Execution Control:'))
       
    96         top_right_gridsizer.AddWindow(execution_control_label, 
       
    97               flag=wx.ALIGN_CENTER_VERTICAL)
       
    98         
       
    99         self.ExecutionControl = wx.CheckBox(self)
       
   100         self.Bind(wx.EVT_CHECKBOX, self.OnExecutionOrderChanged, self.ExecutionControl)
       
   101         top_right_gridsizer.AddWindow(self.ExecutionControl, flag=wx.GROW)
       
   102         
       
   103         preview_label = wx.StaticText(self, label=_('Preview:'))
       
   104         right_gridsizer.AddWindow(preview_label, flag=wx.GROW)
       
   105 
       
   106         self.Preview = wx.Panel(self,
       
   107               style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
       
   108         self.Preview.SetBackgroundColour(wx.Colour(255,255,255))
       
   109         setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE)
       
   110         setattr(self.Preview, "GetScaling", lambda:None)
       
   111         setattr(self.Preview, "GetBlockType", controller.GetBlockType)
       
   112         setattr(self.Preview, "IsOfType", controller.IsOfType)
       
   113         self.Preview.Bind(wx.EVT_PAINT, self.OnPaint)
       
   114         right_gridsizer.AddWindow(self.Preview, flag=wx.GROW)
       
   115         
       
   116         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
       
   117         self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton())
       
   118         main_sizer.AddSizer(button_sizer, border=20, 
       
   119               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
       
   120         
       
   121         self.SetSizer(main_sizer)
       
   122         
       
   123         self.Controller = controller
       
   124         
       
   125         self.BlockName.SetValue("")
       
   126         self.BlockName.Enable(False)
       
   127         self.Inputs.Enable(False)
       
   128         self.Block = None
       
   129         self.MinBlockSize = None
       
   130         self.First = True
       
   131         
       
   132         self.PouNames = []
       
   133         self.PouElementNames = []
       
   134         
       
   135         self.LibraryPanel.SetFocus()
       
   136     
       
   137     def __del__(self):
       
   138         self.Controller = None
       
   139     
       
   140     def SetBlockList(self, blocklist):
       
   141         self.LibraryPanel.SetBlockList(blocklist)
       
   142     
       
   143     def SetPreviewFont(self, font):
       
   144         self.Preview.SetFont(font)
       
   145     
       
   146     def OnOK(self, event):
       
   147         message = None
       
   148         selected = self.LibraryPanel.GetSelectedBlock()
       
   149         block_name = self.BlockName.GetValue()
       
   150         name_enabled = self.BlockName.IsEnabled()
       
   151         if selected is None:
       
   152             message = _("Form isn't complete. Valid block type must be selected!")
       
   153         elif name_enabled and block_name == "":
       
   154             message = _("Form isn't complete. Name must be filled!")
       
   155         elif name_enabled and not TestIdentifier(block_name):
       
   156             message = _("\"%s\" is not a valid identifier!") % block_name
       
   157         elif name_enabled and block_name.upper() in IEC_KEYWORDS:
       
   158             message = _("\"%s\" is a keyword. It can't be used!") % block_name
       
   159         elif name_enabled and block_name.upper() in self.PouNames:
       
   160             message = _("\"%s\" pou already exists!") % block_name
       
   161         elif name_enabled and block_name.upper() in self.PouElementNames:
       
   162             message = _("\"%s\" element for this pou already exists!") % block_name
       
   163         if message is not None:
       
   164             dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
       
   165             dialog.ShowModal()
       
   166             dialog.Destroy()
       
   167         else:
       
   168             self.EndModal(wx.ID_OK)
       
   169 
       
   170     def SetMinBlockSize(self, size):
       
   171         self.MinBlockSize = size
       
   172 
       
   173     def SetPouNames(self, pou_names):
       
   174         self.PouNames = [pou_name.upper() for pou_name in pou_names]
       
   175         
       
   176     def SetPouElementNames(self, element_names):
       
   177         self.PouElementNames = [element_name.upper() for element_name in element_names]
       
   178         
       
   179     def SetValues(self, values):
       
   180         blocktype = values.get("type", None)
       
   181         if blocktype is not None:
       
   182             self.LibraryPanel.SelectTreeItem(blocktype, values.get("inputs", None))
       
   183         for name, value in values.items():
       
   184             if name == "name":
       
   185                 self.BlockName.SetValue(value)
       
   186             elif name == "extension":
       
   187                 self.Inputs.SetValue(value)
       
   188             elif name == "executionOrder":
       
   189                 self.ExecutionOrder.SetValue(value)
       
   190             elif name == "executionControl":
       
   191                    self.ExecutionControl.SetValue(value)
       
   192         self.RefreshPreview()
       
   193 
       
   194     def GetValues(self):
       
   195         values = self.LibraryPanel.GetSelectedBlock()
       
   196         if self.BlockName.IsEnabled() and self.BlockName.GetValue() != "":
       
   197             values["name"] = self.BlockName.GetValue()
       
   198         values["width"], values["height"] = self.Block.GetSize()
       
   199         values["extension"] = self.Inputs.GetValue()
       
   200         values["executionOrder"] = self.ExecutionOrder.GetValue()
       
   201         values["executionControl"] = self.ExecutionControl.GetValue()
       
   202         return values
       
   203 
       
   204     def OnLibraryTreeItemSelected(self, event):
       
   205         values = self.LibraryPanel.GetSelectedBlock()
       
   206         if values is not None:
       
   207             blocktype = self.Controller.GetBlockType(values["type"], values["inputs"])
       
   208         else:
       
   209             blocktype = None
       
   210         if blocktype is not None:
       
   211             self.Inputs.SetValue(len(blocktype["inputs"]))
       
   212             self.Inputs.Enable(blocktype["extensible"])
       
   213             self.BlockName.Enable(blocktype["type"] != "function")
       
   214             wx.CallAfter(self.RefreshPreview)
       
   215         else:
       
   216             self.BlockName.Enable(False)
       
   217             self.Inputs.Enable(False)
       
   218             self.Inputs.SetValue(2)
       
   219             wx.CallAfter(self.ErasePreview)
       
   220     
       
   221     def OnNameChanged(self, event):
       
   222         if self.BlockName.IsEnabled():
       
   223             self.RefreshPreview()
       
   224         event.Skip()
       
   225     
       
   226     def OnInputsChanged(self, event):
       
   227         if self.Inputs.IsEnabled():
       
   228             self.RefreshPreview()
       
   229         event.Skip()
       
   230     
       
   231     def OnExecutionOrderChanged(self, event):
       
   232         self.RefreshPreview()
       
   233         event.Skip()
       
   234     
       
   235     def OnExecutionControlChanged(self, event):
       
   236         self.RefreshPreview()
       
   237         event.Skip()
       
   238     
       
   239     def ErasePreview(self):
       
   240         dc = wx.ClientDC(self.Preview)
       
   241         dc.Clear()
       
   242         self.Block = None
       
   243         
       
   244     def RefreshPreview(self):
       
   245         dc = wx.ClientDC(self.Preview)
       
   246         dc.SetFont(self.Preview.GetFont())
       
   247         dc.Clear()
       
   248         values = self.LibraryPanel.GetSelectedBlock()
       
   249         if values is not None:
       
   250             if self.BlockName.IsEnabled():
       
   251                 blockname = self.BlockName.GetValue()
       
   252             else:
       
   253                 blockname = ""
       
   254             self.Block = FBD_Block(self.Preview, values["type"], 
       
   255                     blockname, 
       
   256                     extension = self.Inputs.GetValue(), 
       
   257                     inputs = values["inputs"], 
       
   258                     executionControl = self.ExecutionControl.GetValue(), 
       
   259                     executionOrder = self.ExecutionOrder.GetValue())
       
   260             width, height = self.MinBlockSize
       
   261             min_width, min_height = self.Block.GetMinSize()
       
   262             width, height = max(min_width, width), max(min_height, height)
       
   263             self.Block.SetSize(width, height)
       
   264             clientsize = self.Preview.GetClientSize()
       
   265             x = (clientsize.width - width) / 2
       
   266             y = (clientsize.height - height) / 2
       
   267             self.Block.SetPosition(x, y)
       
   268             self.Block.Draw(dc)
       
   269         else:
       
   270             self.Block = None        
       
   271 
       
   272     def OnPaint(self, event):
       
   273         if self.Block is not None:
       
   274             self.RefreshPreview()
       
   275         event.Skip()