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