controls/PouInstanceVariablesPanel.py
changeset 814 5743cbdff669
child 821 3667bb14aeca
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) 2012: 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 import wx.lib.buttons
       
    27 import wx.lib.agw.customtreectrl as CT
       
    28 
       
    29 from PLCControler import ITEMS_VARIABLE, ITEM_CONFIGURATION, ITEM_RESOURCE, ITEM_POU
       
    30 from util.BitmapLibrary import GetBitmap
       
    31 
       
    32 class PouInstanceVariablesPanel(wx.Panel):
       
    33     
       
    34     def __init__(self, parent, window, controller, debug):
       
    35         wx.Panel.__init__(self, name='PouInstanceTreePanel', 
       
    36                 parent=parent, pos=wx.Point(0, 0), 
       
    37                 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
       
    38         
       
    39         self.ParentButton = wx.lib.buttons.GenBitmapButton(self,
       
    40               bitmap=GetBitmap("top"), size=wx.Size(28, 28), style=wx.NO_BORDER)
       
    41         self.ParentButton.SetToolTipString(_("Parent instance"))
       
    42         self.Bind(wx.EVT_BUTTON, self.OnParentButtonClick, 
       
    43                 self.ParentButton)
       
    44         
       
    45         self.InstanceChoice = wx.ComboBox(self, style=wx.CB_READONLY)
       
    46         self.Bind(wx.EVT_COMBOBOX, self.OnInstanceChoiceChanged,
       
    47                 self.InstanceChoice)
       
    48         self.InstanceChoice.Bind(wx.EVT_LEFT_DOWN, self.OnInstanceChoiceLeftDown)
       
    49         
       
    50         self.DebugButton = wx.lib.buttons.GenBitmapButton(self, 
       
    51               bitmap=GetBitmap("debug_instance"), size=wx.Size(28, 28), style=wx.NO_BORDER)
       
    52         self.ParentButton.SetToolTipString(_("Debug instance"))
       
    53         self.Bind(wx.EVT_BUTTON, self.OnDebugButtonClick, 
       
    54                 self.DebugButton)
       
    55         
       
    56         self.VariablesList = CT.CustomTreeCtrl(self,
       
    57               style=wx.SUNKEN_BORDER,
       
    58               agwStyle=CT.TR_NO_BUTTONS|
       
    59                        CT.TR_SINGLE|
       
    60                        CT.TR_HAS_VARIABLE_ROW_HEIGHT|
       
    61                        CT.TR_HIDE_ROOT|
       
    62                        CT.TR_NO_LINES|
       
    63                        getattr(CT, "TR_ALIGN_WINDOWS_RIGHT", CT.TR_ALIGN_WINDOWS))
       
    64         self.VariablesList.SetIndent(0)
       
    65         self.VariablesList.SetSpacing(5)
       
    66         self.VariablesList.DoSelectItem = lambda *x,**y:True
       
    67         self.VariablesList.Bind(CT.EVT_TREE_ITEM_ACTIVATED,
       
    68                 self.OnVariablesListItemActivated)
       
    69         self.VariablesList.Bind(wx.EVT_LEFT_DOWN, self.OnVariablesListLeftDown)
       
    70         
       
    71         buttons_sizer = wx.FlexGridSizer(cols=3, hgap=0, rows=1, vgap=0)
       
    72         buttons_sizer.AddWindow(self.ParentButton)
       
    73         buttons_sizer.AddWindow(self.InstanceChoice, flag=wx.GROW)
       
    74         buttons_sizer.AddWindow(self.DebugButton)
       
    75         buttons_sizer.AddGrowableCol(1)
       
    76         buttons_sizer.AddGrowableRow(0)
       
    77         
       
    78         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
       
    79         main_sizer.AddSizer(buttons_sizer, flag=wx.GROW)
       
    80         main_sizer.AddWindow(self.VariablesList, flag=wx.GROW)
       
    81         main_sizer.AddGrowableCol(0)
       
    82         main_sizer.AddGrowableRow(1)
       
    83         
       
    84         self.SetSizer(main_sizer)
       
    85         
       
    86         self.ParentWindow = window
       
    87         self.Controller = controller
       
    88         self.Debug = debug
       
    89         if not self.Debug:
       
    90             self.DebugButton.Hide()
       
    91         
       
    92         self.PouTagName = None
       
    93         self.PouInfos = None
       
    94         self.PouInstance = None
       
    95         
       
    96     def __del__(self):
       
    97         self.Controller = None
       
    98     
       
    99     def SetTreeImageList(self, tree_image_list):
       
   100         self.VariablesList.SetImageList(tree_image_list)
       
   101     
       
   102     def SetController(self, controller):
       
   103         self.Controller = controller
       
   104     
       
   105         self.RefreshView()
       
   106     
       
   107     def SetPouType(self, tagname, pou_instance=None):
       
   108         self.PouTagName = tagname
       
   109         if pou_instance is not None:
       
   110             self.PouInstance = pou_instance
       
   111         
       
   112         self.RefreshView()
       
   113     
       
   114     def ResetView(self):
       
   115         self.Controller = None
       
   116         
       
   117         self.PouTagName = None
       
   118         self.PouInfos = None
       
   119         self.PouInstance = None
       
   120         
       
   121         self.RefreshView()
       
   122     
       
   123     def RefreshView(self):
       
   124         self.VariablesList.DeleteAllItems()
       
   125         self.InstanceChoice.Clear()
       
   126         self.InstanceChoice.SetValue("")
       
   127         
       
   128         if self.Controller is not None and self.PouTagName is not None:
       
   129             self.PouInfos = self.Controller.GetPouVariables(self.PouTagName, self.Debug)
       
   130         else:
       
   131             self.PouInfos = None
       
   132         if self.PouInfos is not None:
       
   133             root = self.VariablesList.AddRoot("")
       
   134             for var_infos in self.PouInfos["variables"]:
       
   135                 if var_infos.get("type", None) is not None:
       
   136                     text = "%(name)s (%(type)s)" % var_infos
       
   137                 else:
       
   138                     text = var_infos["name"]
       
   139                 
       
   140                 panel = wx.Panel(self.VariablesList)
       
   141                     
       
   142                 buttons = []
       
   143                 if var_infos["class"] in ITEMS_VARIABLE:
       
   144                     if (var_infos["debug"] and self.Debug and
       
   145                         (self.Controller.IsOfType(var_infos["type"], "ANY_NUM", True) or
       
   146                          self.Controller.IsOfType(var_infos["type"], "ANY_BIT", True))):
       
   147                         graph_button = wx.lib.buttons.GenBitmapButton(panel, 
       
   148                               bitmap=GetBitmap("instance_graph"), 
       
   149                               size=wx.Size(28, 28), style=wx.NO_BORDER)
       
   150                         self.Bind(wx.EVT_BUTTON, self.GenGraphButtonCallback(var_infos), graph_button)
       
   151                         buttons.append(graph_button)
       
   152                 elif var_infos["edit"]:
       
   153                     edit_button = wx.lib.buttons.GenBitmapButton(panel, 
       
   154                           bitmap=GetBitmap("edit"), 
       
   155                           size=wx.Size(28, 28), style=wx.NO_BORDER)
       
   156                     self.Bind(wx.EVT_BUTTON, self.GenEditButtonCallback(var_infos), edit_button)
       
   157                     buttons.append(edit_button)
       
   158                 
       
   159                 if var_infos["debug"] and self.Debug:
       
   160                     debug_button = wx.lib.buttons.GenBitmapButton(panel, 
       
   161                           bitmap=GetBitmap("debug_instance"), 
       
   162                           size=wx.Size(28, 28), style=wx.NO_BORDER)
       
   163                     self.Bind(wx.EVT_BUTTON, self.GenDebugButtonCallback(var_infos), debug_button)
       
   164                     buttons.append(debug_button)
       
   165                 
       
   166                 button_num = len(buttons)
       
   167                 if button_num > 0:
       
   168                     panel.SetSize(wx.Size(button_num * 32, 28))
       
   169                     panel.SetBackgroundColour(self.VariablesList.GetBackgroundColour())
       
   170                     panel_sizer = wx.BoxSizer(wx.HORIZONTAL)
       
   171                     panel.SetSizer(panel_sizer)
       
   172                     
       
   173                     for button in buttons:
       
   174                         panel_sizer.AddWindow(button, 0, border=4, flag=wx.LEFT)
       
   175                     panel_sizer.Layout()
       
   176                     
       
   177                 else:
       
   178                     panel.Destroy()
       
   179                     panel = None
       
   180                 
       
   181                 item = self.VariablesList.AppendItem(root, text, wnd=panel)
       
   182                 self.VariablesList.SetItemImage(item, self.ParentWindow.GetTreeImage(var_infos["class"]))
       
   183                 self.VariablesList.SetPyData(item, var_infos)
       
   184             
       
   185             instances = self.Controller.SearchPouInstances(self.PouTagName, self.Debug)
       
   186             for instance in instances:
       
   187                 self.InstanceChoice.Append(instance)
       
   188             if len(instances) == 1:
       
   189                 self.PouInstance = instances[0]
       
   190             if self.PouInfos["class"] in [ITEM_CONFIGURATION, ITEM_RESOURCE]:
       
   191                 self.PouInstance = None
       
   192                 self.InstanceChoice.SetSelection(0)
       
   193             elif self.PouInstance in instances:
       
   194                 self.InstanceChoice.SetStringSelection(self.PouInstance)
       
   195             else:
       
   196                 self.PouInstance = None
       
   197                 self.InstanceChoice.SetValue(_("Select an instance"))
       
   198         
       
   199         self.RefreshButtons()
       
   200         
       
   201     def RefreshButtons(self):
       
   202         enabled = self.InstanceChoice.GetSelection() != -1
       
   203         self.ParentButton.Enable(enabled and self.PouInfos["class"] != ITEM_CONFIGURATION)
       
   204         self.DebugButton.Enable(enabled and self.PouInfos["debug"] and self.Debug)
       
   205         
       
   206         root = self.VariablesList.GetRootItem()
       
   207         if root is not None and root.IsOk():
       
   208             item, item_cookie = self.VariablesList.GetFirstChild(root)
       
   209             while item is not None and item.IsOk():
       
   210                 panel = self.VariablesList.GetItemWindow(item)
       
   211                 if panel is not None:
       
   212                     for child in panel.GetChildren():
       
   213                         if child.GetName() != "edit":
       
   214                             child.Enable(enabled)
       
   215                 item, item_cookie = self.VariablesList.GetNextChild(root, item_cookie)
       
   216     
       
   217     def GenEditButtonCallback(self, infos):
       
   218         def EditButtonCallback(event):
       
   219             var_class = infos["class"]
       
   220             if var_class == ITEM_RESOURCE:
       
   221                 tagname = self.Controller.ComputeConfigurationResourceName(
       
   222                     self.InstanceChoice.GetStringSelection(), 
       
   223                     infos["name"])
       
   224             else:
       
   225                 var_class = ITEM_POU
       
   226                 tagname = self.Controller.ComputePouName(infos["type"])
       
   227             self.ParentWindow.EditProjectElement(var_class, tagname)
       
   228             event.Skip()
       
   229         return EditButtonCallback
       
   230     
       
   231     def GenDebugButtonCallback(self, infos):
       
   232         def DebugButtonCallback(event):
       
   233             if self.InstanceChoice.GetSelection() != -1:
       
   234                 var_class = infos["class"]
       
   235                 var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), 
       
   236                                       infos["name"])
       
   237                 if var_class in ITEMS_VARIABLE:
       
   238                     self.ParentWindow.AddDebugVariable(var_path, force=True)
       
   239                 else:
       
   240                     self.ParentWindow.OpenDebugViewer(
       
   241                         infos["class"],
       
   242                         var_path,
       
   243                         self.Controller.ComputePouName(infos["type"]))
       
   244             event.Skip()
       
   245         return DebugButtonCallback
       
   246     
       
   247     def GenGraphButtonCallback(self, infos):
       
   248         def GraphButtonCallback(event):
       
   249             if self.InstanceChoice.GetSelection() != -1:
       
   250                 if infos["class"] in ITEMS_VARIABLE:
       
   251                     var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), 
       
   252                                           infos["name"])
       
   253                     self.ParentWindow.OpenGraphicViewer(var_path)
       
   254             event.Skip()
       
   255         return GraphButtonCallback
       
   256     
       
   257     def ShowInstanceChoicePopup(self):
       
   258         self.InstanceChoice.SetFocusFromKbd()
       
   259         size = self.InstanceChoice.GetSize()
       
   260         event = wx.MouseEvent(wx.EVT_LEFT_DOWN._getEvtType())
       
   261         event.m_x = size.width / 2
       
   262         event.m_y = size.height / 2
       
   263         event.SetEventObject(self.InstanceChoice)
       
   264         #event = wx.KeyEvent(wx.EVT_KEY_DOWN._getEvtType())
       
   265         #event.m_keyCode = wx.WXK_SPACE
       
   266         self.InstanceChoice.GetEventHandler().ProcessEvent(event)
       
   267     
       
   268     def OnParentButtonClick(self, event):
       
   269         if self.InstanceChoice.GetSelection() != -1:
       
   270             parent_path = self.InstanceChoice.GetStringSelection().rsplit(".", 1)[0]
       
   271             tagname = self.Controller.GetPouInstanceTagName(parent_path, self.Debug)
       
   272             if tagname is not None:
       
   273                 wx.CallAfter(self.SetPouType, tagname, parent_path)
       
   274                 wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, tagname)
       
   275         event.Skip()
       
   276         
       
   277     def OnInstanceChoiceChanged(self, event):
       
   278         self.RefreshButtons()
       
   279         event.Skip()
       
   280         
       
   281     def OnDebugButtonClick(self, event):
       
   282         if self.InstanceChoice.GetSelection() != -1:
       
   283             self.ParentWindow.OpenDebugViewer(
       
   284                 self.PouInfos["class"],
       
   285                 self.InstanceChoice.GetStringSelection(),
       
   286                 self.PouTagName)
       
   287         event.Skip()
       
   288         
       
   289     def OnVariablesListItemActivated(self, event):
       
   290         if self.InstanceChoice.GetSelection() != -1:
       
   291             instance_path = self.InstanceChoice.GetStringSelection()
       
   292             selected_item = event.GetItem()
       
   293             if selected_item is not None and selected_item.IsOk():
       
   294                 item_infos = self.VariablesList.GetPyData(selected_item)
       
   295                 if item_infos is not None and item_infos["class"] not in ITEMS_VARIABLE:
       
   296                     if item_infos["class"] == ITEM_RESOURCE:
       
   297                         tagname = self.Controller.ComputeConfigurationResourceName(
       
   298                                        instance_path, 
       
   299                                        item_infos["name"])
       
   300                     else:
       
   301                         tagname = self.Controller.ComputePouName(item_infos["type"])
       
   302                     item_path = "%s.%s" % (instance_path, item_infos["name"])
       
   303                     wx.CallAfter(self.SetPouType, tagname, item_path)
       
   304                     wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, tagname)
       
   305         event.Skip()
       
   306     
       
   307     def OnVariablesListLeftDown(self, event):
       
   308         if self.InstanceChoice.GetSelection() == -1:
       
   309             wx.CallAfter(self.ShowInstanceChoicePopup)
       
   310         event.Skip()
       
   311         
       
   312     def OnInstanceChoiceLeftDown(self, event):
       
   313         event.Skip()