diff -r fc0e7d80494f -r 501cb0bb4c05 controls/DebugVariablePanel/DebugVariableTextViewer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/controls/DebugVariablePanel/DebugVariableTextViewer.py Fri May 31 00:07:21 2013 +0200 @@ -0,0 +1,274 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor +#based on the plcopen standard. +# +#Copyright (C) 2012: Edouard TISSERANT and Laurent BESSARD +# +#See COPYING file for copyrights details. +# +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public +#License as published by the Free Software Foundation; either +#version 2.1 of the License, or (at your option) any later version. +# +#This library is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +#General Public License for more details. +# +#You should have received a copy of the GNU General Public +#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 types import TupleType + +import wx + +from DebugVariableItem import DebugVariableItem +from DebugVariableViewer import DebugVariableViewer +from GraphButton import GraphButton + +#------------------------------------------------------------------------------- +# Debug Variable Text Viewer Drop Target +#------------------------------------------------------------------------------- + +""" +Class that implements a custom drop target class for Debug Variable Text Viewer +""" + +class DebugVariableTextDropTarget(wx.TextDropTarget): + + def __init__(self, parent, window): + """ + Constructor + @param parent: Reference to Debug Variable Text Viewer + @param window: Reference to the Debug Variable Panel + """ + wx.TextDropTarget.__init__(self) + self.ParentControl = parent + self.ParentWindow = window + + def __del__(self): + """ + Destructor + """ + # Remove reference to Debug Variable Text Viewer and Debug Variable + # Panel + self.ParentControl = None + self.ParentWindow = None + + def OnDragOver(self, x, y, d): + """ + Function called when mouse is dragged over Drop Target + @param x: X coordinate of mouse pointer + @param y: Y coordinate of mouse pointer + @param d: Suggested default for return value + """ + # Signal parent that mouse is dragged over + self.ParentControl.OnMouseDragging(x, y) + + return wx.TextDropTarget.OnDragOver(self, x, y, d) + + def OnDropText(self, x, y, data): + """ + Function called when mouse is dragged over Drop Target + @param x: X coordinate of mouse pointer + @param y: Y coordinate of mouse pointer + @param data: Text associated to drag'n drop + """ + message = None + + # Check that data is valid regarding DebugVariablePanel + try: + values = eval(data) + if not isinstance(values, TupleType): + raise + except: + message = _("Invalid value \"%s\" for debug variable") % data + values = None + + # Display message if data is invalid + if message is not None: + wx.CallAfter(self.ShowMessage, message) + + # Data contain a reference to a variable to debug + elif values[1] == "debug": + + # Get Before which Viewer the variable has to be moved or added + # according to the position of mouse in Viewer. + width, height = self.ParentControl.GetSize() + target_idx = self.ParentControl.GetIndex() + if y > height / 2: + target_idx += 1 + + # Drag'n Drop is an internal is an internal move inside Debug + # Variable Panel + if len(values) > 2 and values[2] == "move": + self.ParentWindow.MoveValue(values[0], + target_idx) + + # Drag'n Drop was initiated by another control of Beremiz + else: + self.ParentWindow.InsertValue(values[0], + target_idx, + force=True) + + def OnLeave(self): + """ + Function called when mouse is leave Drop Target + """ + # Signal Debug Variable Panel to reset highlight + self.ParentWindow.ResetHighlight() + + return wx.TextDropTarget.OnLeave(self) + + def ShowMessage(self, message): + """ + Show error message in Error Dialog + @param message: Error message to display + """ + dialog = wx.MessageDialog(self.ParentWindow, + message, + _("Error"), + wx.OK|wx.ICON_ERROR) + dialog.ShowModal() + dialog.Destroy() + + +#------------------------------------------------------------------------------- +# Debug Variable Text Viewer Class +#------------------------------------------------------------------------------- + +""" +Class that implements a Viewer that display variable values as a text +""" + +class DebugVariableTextViewer(DebugVariableViewer, wx.Panel): + + def __init__(self, parent, window, items=[]): + """ + Constructor + @param parent: Parent wx.Window of DebugVariableText + @param window: Reference to the Debug Variable Panel + @param items: List of DebugVariableItem displayed by Viewer + """ + DebugVariableViewer.__init__(self, window, items) + + wx.Panel.__init__(self, parent) + # Set panel background colour + self.SetBackgroundColour(wx.WHITE) + # Define panel drop target + self.SetDropTarget(DebugVariableTextDropTarget(self, window)) + + # Bind events + self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) + self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) + self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter) + self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave) + self.Bind(wx.EVT_SIZE, self.OnResize) + self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) + self.Bind(wx.EVT_PAINT, self.OnPaint) + + # Define panel min size for parent sizer layout + self.SetMinSize(wx.Size(0, 25)) + + # Add buttons to Viewer + for bitmap, callback in [("force", self.OnForceButton), + ("release", self.OnReleaseButton), + ("delete_graph", self.OnCloseButton)]: + self.Buttons.append(GraphButton(0, 0, bitmap, callback)) + + # Hide buttons until mouse enter Viewer + self.ShowButtons(False) + + def RefreshViewer(self): + """ + Method that refresh the content displayed by Viewer + """ + # Create buffered DC for drawing in panel + width, height = self.GetSize() + bitmap = wx.EmptyBitmap(width, height) + dc = wx.BufferedDC(wx.ClientDC(self), bitmap) + dc.Clear() + dc.BeginDrawing() + + # Get Graphics Context for DC, for anti-aliased and transparent + # rendering + gc = wx.GCDC(dc) + + # Get first item + item = self.ItemsDict.values()[0] + + # Get item variable path masked according Debug Variable Panel mask + item_path = item.GetVariable( + self.ParentWindow.GetVariableNameMask()) + + # Draw item variable path at Viewer left side + w, h = gc.GetTextExtent(item_path) + gc.DrawText(item_path, 20, (height - h) / 2) + + # Update 'Release' button state and text color according to item forced + # flag value + item_forced = item.IsForced() + self.Buttons[1].Enable(item_forced) + self.RefreshButtonsPosition() + if item_forced: + gc.SetTextForeground(wx.BLUE) + + # Draw item current value at right side of Viewer + item_value = item.GetValue() + w, h = gc.GetTextExtent(item_value) + gc.DrawText(item_value, width - 40 - w, (height - h) / 2) + + # Draw other Viewer common elements + self.DrawCommonElements(gc) + + gc.EndDrawing() + + def OnLeftDown(self, event): + """ + Function called when mouse left button is pressed + @param event: wx.MouseEvent + """ + # Get first item + item = self.ItemsDict.values()[0] + + # Calculate item path bounding box + width, height = self.GetSize() + item_path = item.GetVariable( + self.ParentWindow.GetVariableNameMask()) + w, h = self.GetTextExtent(item_path) + + # Test if mouse has been pressed in this bounding box. In that case + # start a move drag'n drop of item variable + x, y = event.GetPosition() + item_path_bbox = wx.Rect(20, (height - h) / 2, w, h) + if item_path_bbox.InsideXY(x, y): + data = wx.TextDataObject(str((item.GetVariable(), "debug", "move"))) + dragSource = wx.DropSource(self) + dragSource.SetData(data) + dragSource.DoDragDrop() + + # In other case handle event normally + else: + event.Skip() + + def OnLeftUp(self, event): + """ + Function called when mouse left button is released + @param event: wx.MouseEvent + """ + # Execute callback on button under mouse pointer if it exists + x, y = event.GetPosition() + wx.CallAfter(self.HandleButton, x, y) + event.Skip() + + def OnPaint(self, event): + """ + Function called when redrawing Viewer content is needed + @param event: wx.PaintEvent + """ + self.RefreshViewer() + event.Skip()