diff -r 72a826dfcfbb -r 02fe382c4511 controls/PouInstanceVariablesPanel.py --- a/controls/PouInstanceVariablesPanel.py Wed Jul 31 10:45:07 2013 +0900 +++ b/controls/PouInstanceVariablesPanel.py Mon Nov 18 12:12:31 2013 +0900 @@ -22,22 +22,98 @@ #License along with this library; if not, write to the Free Software #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +from collections import namedtuple + import wx +import wx.lib.agw.customtreectrl as CT import wx.lib.buttons -import wx.lib.agw.customtreectrl as CT - -try: - import matplotlib - matplotlib.use('WX') - USE_MPL = True -except: - USE_MPL = False + +# Customize CustomTreeItem for adding icon on item right +CT.GenericTreeItem._rightimages = [] + +def SetRightImages(self, images): + self._rightimages = images +CT.GenericTreeItem.SetRightImages = SetRightImages + +def GetRightImages(self): + return self._rightimages +CT.GenericTreeItem.GetRightImages = GetRightImages + + +class CustomTreeCtrlWithRightImage(CT.CustomTreeCtrl): + + def SetRightImageList(self, imageList): + self._imageListRight = imageList + + def GetLineHeight(self, item): + height = CT.CustomTreeCtrl.GetLineHeight(self, item) + rightimages = item.GetRightImages() + if len(rightimages) > 0: + r_image_w, r_image_h = self._imageListRight.GetSize(rightimages[0]) + return max(height, r_image_h + 8) + return height + + def GetItemRightImagesBBox(self, item): + rightimages = item.GetRightImages() + if len(rightimages) > 0: + w, h = self.GetClientSize() + total_h = self.GetLineHeight(item) + r_image_w, r_image_h = self._imageListRight.GetSize(rightimages[0]) + + bbox_width = (r_image_w + 4) * len(rightimages) + 4 + bbox_height = r_image_h + 8 + bbox_x = w - bbox_width + bbox_y = item.GetY() + ((total_h > r_image_h) and [(total_h-r_image_h)/2] or [0])[0] + + return wx.Rect(bbox_x, bbox_y, bbox_width, bbox_height) + + return None + + def IsOverItemRightImage(self, item, point): + rightimages = item.GetRightImages() + if len(rightimages) > 0: + point = self.CalcUnscrolledPosition(point) + r_image_w, r_image_h = self._imageListRight.GetSize(rightimages[0]) + images_bbx = self.GetItemRightImagesBBox(item) + + rect = wx.Rect(images_bbx.x + 4, images_bbx.y + 4, + r_image_w, r_image_h) + for r_image in rightimages: + if rect.Inside(point): + return r_image + rect.x += r_image_w + 4 + + return None + + def PaintItem(self, item, dc, level, align): + CT.CustomTreeCtrl.PaintItem(self, item, dc, level, align) + + rightimages = item.GetRightImages() + if len(rightimages) > 0: + images_bbx = self.GetItemRightImagesBBox(item) + r_image_w, r_image_h = self._imageListRight.GetSize(rightimages[0]) + + dc.SetBrush(wx.WHITE_BRUSH) + dc.SetPen(wx.TRANSPARENT_PEN) + + bg_width = (r_image_w + 4) * len(rightimages) + 4 + bg_height = r_image_h + 8 + dc.DrawRectangle(images_bbx.x, images_bbx.y, + images_bbx.width, images_bbx.height) + x_pos = images_bbx.x + 4 + for r_image in rightimages: + self._imageListRight.Draw( + r_image, dc, x_pos, images_bbx.y + 4, + wx.IMAGELIST_DRAW_TRANSPARENT) + x_pos += r_image_w + 4 + +_ButtonCallbacks = namedtuple("ButtonCallbacks", ["leftdown", "dclick"]) from PLCControler import ITEMS_VARIABLE, ITEM_CONFIGURATION, ITEM_RESOURCE, ITEM_POU, ITEM_TRANSITION, ITEM_ACTION from util.BitmapLibrary import GetBitmap class PouInstanceVariablesPanel(wx.Panel): - + def __init__(self, parent, window, controller, debug): wx.Panel.__init__(self, name='PouInstanceTreePanel', parent=parent, pos=wx.Point(0, 0), @@ -59,7 +135,7 @@ self.Bind(wx.EVT_BUTTON, self.OnDebugButtonClick, self.DebugButton) - self.VariablesList = CT.CustomTreeCtrl(self, + self.VariablesList = CustomTreeCtrlWithRightImage(self, style=wx.SUNKEN_BORDER, agwStyle=CT.TR_NO_BUTTONS| CT.TR_SINGLE| @@ -75,6 +151,17 @@ self.VariablesList.Bind(wx.EVT_LEFT_DOWN, self.OnVariablesListLeftDown) self.VariablesList.Bind(wx.EVT_KEY_DOWN, self.OnVariablesListKeyDown) + self.TreeRightImageList = wx.ImageList(24, 24) + self.EditImage = self.TreeRightImageList.Add(GetBitmap("edit")) + self.DebugInstanceImage = self.TreeRightImageList.Add(GetBitmap("debug_instance")) + self.VariablesList.SetRightImageList(self.TreeRightImageList) + + self.ButtonCallBacks = { + self.EditImage: _ButtonCallbacks( + self.EditButtonCallback, None), + self.DebugInstanceImage: _ButtonCallbacks( + self.DebugButtonCallback, self.DebugButtonDClickCallback)} + buttons_sizer = wx.FlexGridSizer(cols=3, hgap=0, rows=1, vgap=0) buttons_sizer.AddWindow(self.ParentButton) buttons_sizer.AddWindow(self.InstanceChoice, flag=wx.GROW) @@ -147,56 +234,22 @@ self.PouInfos = None if self.PouInfos is not None: root = self.VariablesList.AddRoot("") - for var_infos in self.PouInfos["variables"]: - if var_infos.get("type", None) is not None: - text = "%(name)s (%(type)s)" % var_infos + for var_infos in self.PouInfos.variables: + if var_infos.type is not None: + text = "%s (%s)" % (var_infos.name, var_infos.type) else: - text = var_infos["name"] - - panel = wx.Panel(self.VariablesList) - - buttons = [] - if var_infos["class"] in ITEMS_VARIABLE: - if (not USE_MPL and var_infos["debug"] and self.Debug and - (self.Controller.IsOfType(var_infos["type"], "ANY_NUM", True) or - self.Controller.IsOfType(var_infos["type"], "ANY_BIT", True))): - graph_button = wx.lib.buttons.GenBitmapButton(panel, - bitmap=GetBitmap("instance_graph"), - size=wx.Size(28, 28), style=wx.NO_BORDER) - self.Bind(wx.EVT_BUTTON, self.GenGraphButtonCallback(var_infos), graph_button) - buttons.append(graph_button) - elif var_infos["edit"]: - edit_button = wx.lib.buttons.GenBitmapButton(panel, - bitmap=GetBitmap("edit"), - size=wx.Size(28, 28), style=wx.NO_BORDER) - self.Bind(wx.EVT_BUTTON, self.GenEditButtonCallback(var_infos), edit_button) - buttons.append(edit_button) - - if var_infos["debug"] and self.Debug: - debug_button = wx.lib.buttons.GenBitmapButton(panel, - bitmap=GetBitmap("debug_instance"), - size=wx.Size(28, 28), style=wx.NO_BORDER) - self.Bind(wx.EVT_BUTTON, self.GenDebugButtonCallback(var_infos), debug_button) - debug_button.Bind(wx.EVT_LEFT_DCLICK, self.GenDebugButtonDClickCallback(var_infos)) - buttons.append(debug_button) - - button_num = len(buttons) - if button_num > 0: - panel.SetSize(wx.Size(button_num * 32, 28)) - panel.SetBackgroundColour(self.VariablesList.GetBackgroundColour()) - panel_sizer = wx.BoxSizer(wx.HORIZONTAL) - panel.SetSizer(panel_sizer) - - for button in buttons: - panel_sizer.AddWindow(button, 0, border=4, flag=wx.LEFT) - panel_sizer.Layout() - - else: - panel.Destroy() - panel = None - - item = self.VariablesList.AppendItem(root, text, wnd=panel) - self.VariablesList.SetItemImage(item, self.ParentWindow.GetTreeImage(var_infos["class"])) + text = var_infos.name + + right_images = [] + if var_infos.edit: + right_images.append(self.EditImage) + + if var_infos.debug and self.Debug: + right_images.append(self.DebugInstanceImage) + + item = self.VariablesList.AppendItem(root, text) + item.SetRightImages(right_images) + self.VariablesList.SetItemImage(item, self.ParentWindow.GetTreeImage(var_infos.var_class)) self.VariablesList.SetPyData(item, var_infos) self.RefreshInstanceChoice() @@ -213,7 +266,7 @@ self.InstanceChoice.Append(instance) if len(instances) == 1: self.PouInstance = instances[0] - if self.PouInfos["class"] in [ITEM_CONFIGURATION, ITEM_RESOURCE]: + if self.PouInfos.var_class in [ITEM_CONFIGURATION, ITEM_RESOURCE]: self.PouInstance = None self.InstanceChoice.SetSelection(0) elif self.PouInstance in instances: @@ -224,8 +277,8 @@ def RefreshButtons(self): enabled = self.InstanceChoice.GetSelection() != -1 - self.ParentButton.Enable(enabled and self.PouInfos["class"] != ITEM_CONFIGURATION) - self.DebugButton.Enable(enabled and self.PouInfos["debug"] and self.Debug) + self.ParentButton.Enable(enabled and self.PouInfos.var_class != ITEM_CONFIGURATION) + self.DebugButton.Enable(enabled and self.PouInfos.debug and self.Debug) root = self.VariablesList.GetRootItem() if root is not None and root.IsOk(): @@ -238,79 +291,60 @@ child.Enable(enabled) item, item_cookie = self.VariablesList.GetNextChild(root, item_cookie) - def GenEditButtonCallback(self, infos): - def EditButtonCallback(event): - var_class = infos["class"] - if var_class == ITEM_RESOURCE: - tagname = self.Controller.ComputeConfigurationResourceName( - self.InstanceChoice.GetStringSelection(), - infos["name"]) + def EditButtonCallback(self, infos): + var_class = infos.var_class + if var_class == ITEM_RESOURCE: + tagname = self.Controller.ComputeConfigurationResourceName( + self.InstanceChoice.GetStringSelection(), + infos.name) + elif var_class == ITEM_TRANSITION: + tagname = self.Controller.ComputePouTransitionName( + self.PouTagName.split("::")[1], + infos.name) + elif var_class == ITEM_ACTION: + tagname = self.Controller.ComputePouActionName( + self.PouTagName.split("::")[1], + infos.name) + else: + var_class = ITEM_POU + tagname = self.Controller.ComputePouName(infos.type) + self.ParentWindow.EditProjectElement(var_class, tagname) + + def DebugButtonCallback(self, infos): + if self.InstanceChoice.GetSelection() != -1: + var_class = infos.var_class + var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), + infos.name) + if var_class in ITEMS_VARIABLE: + self.ParentWindow.AddDebugVariable(var_path, force=True) elif var_class == ITEM_TRANSITION: - tagname = self.Controller.ComputePouTransitionName( - self.PouTagName.split("::")[1], - infos["name"]) + self.ParentWindow.OpenDebugViewer( + var_class, + var_path, + self.Controller.ComputePouTransitionName( + self.PouTagName.split("::")[1], + infos.name)) elif var_class == ITEM_ACTION: - tagname = self.Controller.ComputePouActionName( - self.PouTagName.split("::")[1], - infos["name"]) + self.ParentWindow.OpenDebugViewer( + var_class, + var_path, + self.Controller.ComputePouActionName( + self.PouTagName.split("::")[1], + infos.name)) else: - var_class = ITEM_POU - tagname = self.Controller.ComputePouName(infos["type"]) - self.ParentWindow.EditProjectElement(var_class, tagname) - event.Skip() - return EditButtonCallback - - def GenDebugButtonCallback(self, infos): - def DebugButtonCallback(event): - if self.InstanceChoice.GetSelection() != -1: - var_class = infos["class"] - var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), - infos["name"]) - if var_class in ITEMS_VARIABLE: - self.ParentWindow.AddDebugVariable(var_path, force=True) - elif var_class == ITEM_TRANSITION: - self.ParentWindow.OpenDebugViewer( - var_class, - var_path, - self.Controller.ComputePouTransitionName( - self.PouTagName.split("::")[1], - infos["name"])) - elif var_class == ITEM_ACTION: - self.ParentWindow.OpenDebugViewer( - var_class, - var_path, - self.Controller.ComputePouActionName( - self.PouTagName.split("::")[1], - infos["name"])) - else: - self.ParentWindow.OpenDebugViewer( - var_class, - var_path, - self.Controller.ComputePouName(infos["type"])) - event.Skip() - return DebugButtonCallback - - def GenDebugButtonDClickCallback(self, infos): - def DebugButtonDClickCallback(event): - if self.InstanceChoice.GetSelection() != -1: - if infos["class"] in ITEMS_VARIABLE: - self.ParentWindow.AddDebugVariable( - "%s.%s" % (self.InstanceChoice.GetStringSelection(), - infos["name"]), - force=True, - graph=True) - event.Skip() - return DebugButtonDClickCallback - - def GenGraphButtonCallback(self, infos): - def GraphButtonCallback(event): - if self.InstanceChoice.GetSelection() != -1: - if infos["class"] in ITEMS_VARIABLE: - var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), - infos["name"]) - self.ParentWindow.OpenDebugViewer(infos["class"], var_path, infos["type"]) - event.Skip() - return GraphButtonCallback + self.ParentWindow.OpenDebugViewer( + var_class, + var_path, + self.Controller.ComputePouName(infos.type)) + + def DebugButtonDClickCallback(self, infos): + if self.InstanceChoice.GetSelection() != -1: + if infos.var_class in ITEMS_VARIABLE: + self.ParentWindow.AddDebugVariable( + "%s.%s" % (self.InstanceChoice.GetStringSelection(), + infos.name), + force=True, + graph=True) def ShowInstanceChoicePopup(self): self.InstanceChoice.SetFocusFromKbd() @@ -339,33 +373,42 @@ def OnDebugButtonClick(self, event): if self.InstanceChoice.GetSelection() != -1: self.ParentWindow.OpenDebugViewer( - self.PouInfos["class"], + self.PouInfos.var_class, self.InstanceChoice.GetStringSelection(), self.PouTagName) event.Skip() - + def OnVariablesListItemActivated(self, event): selected_item = event.GetItem() if selected_item is not None and selected_item.IsOk(): item_infos = self.VariablesList.GetPyData(selected_item) - if item_infos is not None and item_infos["class"] not in ITEMS_VARIABLE: - instance_path = self.InstanceChoice.GetStringSelection() - if item_infos["class"] == ITEM_RESOURCE: - if instance_path != "": - tagname = self.Controller.ComputeConfigurationResourceName( - instance_path, - item_infos["name"]) + if item_infos is not None: + + item_button = self.VariablesList.IsOverItemRightImage( + selected_item, event.GetPoint()) + if item_button is not None: + callback = self.ButtonCallBacks[item_button].dclick + if callback is not None: + callback(item_infos) + + elif item_infos.var_class not in ITEMS_VARIABLE: + instance_path = self.InstanceChoice.GetStringSelection() + if item_infos.var_class == ITEM_RESOURCE: + if instance_path != "": + tagname = self.Controller.ComputeConfigurationResourceName( + instance_path, + item_infos.name) + else: + tagname = None else: - tagname = None - else: - tagname = self.Controller.ComputePouName(item_infos["type"]) - if tagname is not None: - if instance_path != "": - item_path = "%s.%s" % (instance_path, item_infos["name"]) - else: - item_path = None - self.SetPouType(tagname, item_path) - self.ParentWindow.SelectProjectTreeItem(tagname) + tagname = self.Controller.ComputePouName(item_infos.type) + if tagname is not None: + if instance_path != "": + item_path = "%s.%s" % (instance_path, item_infos.name) + else: + item_path = None + self.SetPouType(tagname, item_path) + self.ParentWindow.SelectProjectTreeItem(tagname) event.Skip() def OnVariablesListLeftDown(self, event): @@ -374,16 +417,26 @@ else: instance_path = self.InstanceChoice.GetStringSelection() item, flags = self.VariablesList.HitTest(event.GetPosition()) - if item is not None and flags & CT.TREE_HITTEST_ONITEMLABEL: + if item is not None: item_infos = self.VariablesList.GetPyData(item) - if item_infos is not None and item_infos["class"] in ITEMS_VARIABLE: - self.ParentWindow.EnsureTabVisible( - self.ParentWindow.DebugVariablePanel) - item_path = "%s.%s" % (instance_path, item_infos["name"]) - data = wx.TextDataObject(str((item_path, "debug"))) - dragSource = wx.DropSource(self.VariablesList) - dragSource.SetData(data) - dragSource.DoDragDrop() + if item_infos is not None: + + item_button = self.VariablesList.IsOverItemRightImage( + item, event.GetPosition()) + if item_button is not None: + callback = self.ButtonCallBacks[item_button].leftdown + if callback is not None: + callback(item_infos) + + elif (flags & CT.TREE_HITTEST_ONITEMLABEL and + item_infos.var_class in ITEMS_VARIABLE): + self.ParentWindow.EnsureTabVisible( + self.ParentWindow.DebugVariablePanel) + item_path = "%s.%s" % (instance_path, item_infos.name) + data = wx.TextDataObject(str((item_path, "debug"))) + dragSource = wx.DropSource(self.VariablesList) + dragSource.SetData(data) + dragSource.DoDragDrop() event.Skip() def OnVariablesListKeyDown(self, event):