Adding support for drag'n dropping variable from global defined in configurations and resources to POU variable panel or body editor for declaring external variables
Adding support for drag'n dropping located variables from topology panel to configurations and resources variable panel for declaring global located variables
#!/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) 2007: 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
import math
from types import TupleType
from threading import Lock
import wx
from plcopen.structures import *
from PLCControler import ITEM_POU
from dialogs import *
from graphics import *
from controls import EditorPanel
SCROLLBAR_UNIT = 10
WINDOW_BORDER = 10
SCROLL_ZONE = 10
CURSORS = None
def ResetCursors():
global CURSORS
if CURSORS == None:
CURSORS = [wx.NullCursor,
wx.StockCursor(wx.CURSOR_HAND),
wx.StockCursor(wx.CURSOR_SIZENWSE),
wx.StockCursor(wx.CURSOR_SIZENESW),
wx.StockCursor(wx.CURSOR_SIZEWE),
wx.StockCursor(wx.CURSOR_SIZENS)]
def AppendMenu(parent, help, id, kind, text):
if wx.VERSION >= (2, 6, 0):
parent.Append(help=help, id=id, kind=kind, text=text)
else:
parent.Append(helpString=help, id=id, kind=kind, item=text)
if wx.Platform == '__WXMSW__':
faces = { 'times': 'Times New Roman',
'mono' : 'Courier New',
'helv' : 'Arial',
'other': 'Comic Sans MS',
'size' : 10,
}
else:
faces = { 'times': 'Times',
'mono' : 'Courier',
'helv' : 'Helvetica',
'other': 'new century schoolbook',
'size' : 12,
}
ZOOM_FACTORS = [math.sqrt(2) ** x for x in xrange(-6, 7)]
def GetVariableCreationFunction(variable_type):
def variableCreationFunction(viewer, id, specific_values):
return FBD_Variable(viewer, variable_type,
specific_values["name"],
specific_values["value_type"],
id,
specific_values["executionOrder"])
return variableCreationFunction
def GetConnectorCreationFunction(connector_type):
def connectorCreationFunction(viewer, id, specific_values):
return FBD_Connector(viewer, connector_type,
specific_values["name"], id)
return connectorCreationFunction
def commentCreationFunction(viewer, id, specific_values):
return Comment(viewer, specific_values["content"], id)
def GetPowerRailCreationFunction(powerrail_type):
def powerRailCreationFunction(viewer, id, specific_values):
return LD_PowerRail(viewer, powerrail_type, id,
specific_values["connectors"])
return powerRailCreationFunction
CONTACT_TYPES = {(True, "none"): CONTACT_REVERSE,
(False, "rising"): CONTACT_RISING,
(False, "falling"): CONTACT_FALLING}
def contactCreationFunction(viewer, id, specific_values):
contact_type = CONTACT_TYPES.get((specific_values.get("negated", False),
specific_values.get("edge", "none")),
CONTACT_NORMAL)
return LD_Contact(viewer, contact_type, specific_values["name"], id)
COIL_TYPES = {(True, "none", "none"): COIL_REVERSE,
(False, "none", "set"): COIL_SET,
(False, "none", "reset"): COIL_RESET,
(False, "rising", "none"): COIL_RISING,
(False, "falling", "none"): COIL_FALLING}
def coilCreationFunction(viewer, id, specific_values):
coil_type = COIL_TYPES.get((specific_values.get("negated", False),
specific_values.get("edge", "none"),
specific_values.get("storage", "none")),
COIL_NORMAL)
return LD_Coil(viewer, coil_type, specific_values["name"], id)
def stepCreationFunction(viewer, id, specific_values):
step = SFC_Step(viewer, specific_values["name"],
specific_values.get("initial", False), id)
if specific_values.get("action", None):
step.AddAction()
connector = step.GetActionConnector()
connector.SetPosition(wx.Point(*specific_values["action"]["position"]))
return step
def transitionCreationFunction(viewer, id, specific_values):
transition = SFC_Transition(viewer, specific_values["condition_type"],
specific_values.get("condition", None),
specific_values["priority"], id)
return transition
def GetDivergenceCreationFunction(divergence_type):
def divergenceCreationFunction(viewer, id, specific_values):
return SFC_Divergence(viewer, divergence_type,
specific_values["connectors"], id)
return divergenceCreationFunction
def jumpCreationFunction(viewer, id, specific_values):
return SFC_Jump(viewer, specific_values["target"], id)
def actionBlockCreationFunction(viewer, id, specific_values):
return SFC_ActionBlock(viewer, specific_values["actions"], id)
ElementCreationFunctions = {
"input": GetVariableCreationFunction(INPUT),
"output": GetVariableCreationFunction(OUTPUT),
"inout": GetVariableCreationFunction(INOUT),
"connector": GetConnectorCreationFunction(CONNECTOR),
"continuation": GetConnectorCreationFunction(CONTINUATION),
"comment": commentCreationFunction,
"leftPowerRail": GetPowerRailCreationFunction(LEFTRAIL),
"rightPowerRail": GetPowerRailCreationFunction(RIGHTRAIL),
"contact": contactCreationFunction,
"coil": coilCreationFunction,
"step": stepCreationFunction,
"transition": transitionCreationFunction,
"selectionDivergence": GetDivergenceCreationFunction(SELECTION_DIVERGENCE),
"selectionConvergence": GetDivergenceCreationFunction(SELECTION_CONVERGENCE),
"simultaneousDivergence": GetDivergenceCreationFunction(SIMULTANEOUS_DIVERGENCE),
"simultaneousConvergence": GetDivergenceCreationFunction(SIMULTANEOUS_CONVERGENCE),
"jump": jumpCreationFunction,
"actionBlock": actionBlockCreationFunction,
}
#-------------------------------------------------------------------------------
# Graphic elements Viewer base class
#-------------------------------------------------------------------------------
# ID Constants for alignment menu items
[ID_VIEWERALIGNMENTMENUITEMS0, ID_VIEWERALIGNMENTMENUITEMS1,
ID_VIEWERALIGNMENTMENUITEMS2, ID_VIEWERALIGNMENTMENUITEMS4,
ID_VIEWERALIGNMENTMENUITEMS5, ID_VIEWERALIGNMENTMENUITEMS6,
] = [wx.NewId() for _init_coll_AlignmentMenu_Items in range(6)]
# ID Constants for contextual menu items
[ID_VIEWERCONTEXTUALMENUITEMS0, ID_VIEWERCONTEXTUALMENUITEMS1,
ID_VIEWERCONTEXTUALMENUITEMS2, ID_VIEWERCONTEXTUALMENUITEMS3,
ID_VIEWERCONTEXTUALMENUITEMS5, ID_VIEWERCONTEXTUALMENUITEMS6,
ID_VIEWERCONTEXTUALMENUITEMS8, ID_VIEWERCONTEXTUALMENUITEMS9,
ID_VIEWERCONTEXTUALMENUITEMS11, ID_VIEWERCONTEXTUALMENUITEMS12,
ID_VIEWERCONTEXTUALMENUITEMS14, ID_VIEWERCONTEXTUALMENUITEMS16,
ID_VIEWERCONTEXTUALMENUITEMS17,
] = [wx.NewId() for _init_coll_ContextualMenu_Items in range(13)]
class ViewerDropTarget(wx.TextDropTarget):
def __init__(self, parent):
wx.TextDropTarget.__init__(self)
self.ParentWindow = parent
def OnDropText(self, x, y, data):
tagname = self.ParentWindow.GetTagName()
pou_name, pou_type = self.ParentWindow.Controler.GetEditedElementType(tagname, self.ParentWindow.Debug)
x, y = self.ParentWindow.CalcUnscrolledPosition(x, y)
x = int(x / self.ParentWindow.ViewScale[0])
y = int(y / self.ParentWindow.ViewScale[1])
scaling = self.ParentWindow.Scaling
message = None
try:
values = eval(data)
except:
message = _("Invalid value \"%s\" for viewer block")%data
values = None
if not isinstance(values, TupleType):
message = _("Invalid value \"%s\" for viewer block")%data
values = None
if values is not None:
if values[1] == "debug":
pass
elif values[1] == "program":
message = _("Programs can't be used by other POUs!")
elif values[1] in ["function", "functionBlock"]:
words = tagname.split("::")
if pou_name == values[0]:
message = _("\"%s\" can't use itself!")%pou_name
elif pou_type == "function" and values[1] != "function":
message = _("Function Blocks can't be used in Functions!")
elif words[0] == "T" and values[1] != "function":
message = _("Function Blocks can't be used in Transitions!")
elif self.ParentWindow.Controler.PouIsUsedBy(pou_name, values[0], self.ParentWindow.Debug):
message = _("\"%s\" is already used by \"%s\"!")%(pou_name, values[0])
else:
blockname = values[2]
if len(values) > 3:
blockinputs = values[3]
else:
blockinputs = None
if values[1] != "function" and blockname == "":
dialog = wx.TextEntryDialog(self.ParentWindow.ParentWindow, "Block name", "Please enter a block name", "", wx.OK|wx.CANCEL|wx.CENTRE)
if dialog.ShowModal() == wx.ID_OK:
blockname = dialog.GetValue()
else:
return
dialog.Destroy()
if blockname.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames(self.ParentWindow.Debug)]:
message = _("\"%s\" pou already exists!")%blockname
elif blockname.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
message = _("\"%s\" element for this pou already exists!")%blockname
else:
id = self.ParentWindow.GetNewId()
block = FBD_Block(self.ParentWindow, values[0], blockname, id, inputs = blockinputs)
width, height = block.GetMinSize()
if scaling is not None:
x = round(float(x) / float(scaling[0])) * scaling[0]
y = round(float(y) / float(scaling[1])) * scaling[1]
width = round(float(width) / float(scaling[0]) + 0.5) * scaling[0]
height = round(float(height) / float(scaling[1]) + 0.5) * scaling[1]
block.SetPosition(x, y)
block.SetSize(width, height)
self.ParentWindow.AddBlock(block)
self.ParentWindow.Controler.AddEditedElementBlock(tagname, id, values[0], blockname)
self.ParentWindow.RefreshBlockModel(block)
self.ParentWindow.RefreshBuffer()
self.ParentWindow.RefreshScrollBars()
self.ParentWindow.RefreshVisibleElements()
self.ParentWindow.RefreshVariablePanel()
self.ParentWindow.Refresh(False)
elif values[1] == "location":
if len(values) > 2 and pou_type == "program":
var_name = values[3]
if var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames(self.ParentWindow.Debug)]:
message = _("\"%s\" pou already exists!")%var_name
else:
if values[0][1] == "Q":
var_class = OUTPUT
else:
var_class = INPUT
if values[2] is not None:
var_type = values[2]
else:
var_type = LOCATIONDATATYPES.get(values[0][2], ["BOOL"])[0]
if not var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
self.ParentWindow.Controler.AddEditedElementPouVar(tagname, var_type, var_name, values[0], values[4])
self.ParentWindow.RefreshVariablePanel()
self.ParentWindow.AddVariableBlock(x, y, scaling, var_class, var_name, var_type)
elif values[1] == "Global":
var_name = values[0]
if var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames(self.ParentWindow.Debug)]:
message = _("\"%s\" pou already exists!")%var_name
else:
if not var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
self.ParentWindow.Controler.AddEditedElementPouExternalVar(tagname, values[2], var_name)
self.ParentWindow.RefreshVariablePanel()
self.ParentWindow.AddVariableBlock(x, y, scaling, INPUT, var_name, values[2])
elif values[3] == tagname:
if values[1] == "Output":
var_class = OUTPUT
elif values[1] == "InOut":
var_class = INPUT
else:
var_class = INPUT
tree = dict([(var["Name"], var["Tree"]) for var in self.ParentWindow.Controler.GetEditedElementInterfaceVars(tagname, self.ParentWindow.Debug)]).get(values[0], None)
if tree is not None:
if len(tree[0]) > 0:
menu = wx.Menu(title='')
self.GenerateTreeMenu(x, y, scaling, menu, "", var_class, [(values[0], values[2], tree)])
self.ParentWindow.PopupMenuXY(menu)
else:
self.ParentWindow.AddVariableBlock(x, y, scaling, var_class, values[0], values[2])
else:
message = _("Unknown variable \"%s\" for this POU!") % values[0]
else:
message = _("Variable don't belong to this POU!")
if message is not None:
wx.CallAfter(self.ShowMessage, message)
def GenerateTreeMenu(self, x, y, scaling, menu, base_path, var_class, tree):
for child_name, child_type, (child_tree, child_dimensions) in tree:
if base_path:
child_path = "%s.%s" % (base_path, child_name)
else:
child_path = child_name
if len(child_dimensions) > 0:
child_path += "[%s]" % ",".join([str(dimension[0]) for dimension in child_dimensions])
child_name += "[]"
new_id = wx.NewId()
AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=child_name)
self.ParentWindow.Bind(wx.EVT_MENU, self.GetAddVariableBlockFunction(x, y, scaling, var_class, child_path, child_type), id=new_id)
if len(child_tree) > 0:
new_id = wx.NewId()
child_menu = wx.Menu(title='')
self.GenerateTreeMenu(x, y, scaling, child_menu, child_path, var_class, child_tree)
menu.AppendMenu(new_id, "%s." % child_name, child_menu)
def GetAddVariableBlockFunction(self, x, y, scaling, var_class, var_name, var_type):
def AddVariableFunction(event):
self.ParentWindow.AddVariableBlock(x, y, scaling, var_class, var_name, var_type)
return AddVariableFunction
def ShowMessage(self, message):
message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
message.ShowModal()
message.Destroy()
"""
Class that implements a Viewer based on a wx.ScrolledWindow for drawing and
manipulating graphic elements
"""
class Viewer(EditorPanel, DebugViewer):
if wx.VERSION < (2, 6, 0):
def Bind(self, event, function, id = None):
if id is not None:
event(self, id, function)
else:
event(self, function)
# Create Alignment Menu items
def _init_coll_AlignmentMenu_Items(self, parent):
# Create menu items
AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS0,
kind=wx.ITEM_NORMAL, text=_(u'Left'))
AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS1,
kind=wx.ITEM_NORMAL, text=_(u'Center'))
AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS2,
kind=wx.ITEM_NORMAL, text=_(u'Right'))
parent.AppendSeparator()
AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS4,
kind=wx.ITEM_NORMAL, text=_(u'Top'))
AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS5,
kind=wx.ITEM_NORMAL, text=_(u'Middle'))
AppendMenu(parent, help='', id=ID_VIEWERALIGNMENTMENUITEMS6,
kind=wx.ITEM_NORMAL, text=_(u'Bottom'))
# Link menu event to corresponding called functions
self.Bind(wx.EVT_MENU, self.OnAlignLeftMenu,
id=ID_VIEWERALIGNMENTMENUITEMS0)
self.Bind(wx.EVT_MENU, self.OnAlignCenterMenu,
id=ID_VIEWERALIGNMENTMENUITEMS1)
self.Bind(wx.EVT_MENU, self.OnAlignRightMenu,
id=ID_VIEWERALIGNMENTMENUITEMS2)
self.Bind(wx.EVT_MENU, self.OnAlignTopMenu,
id=ID_VIEWERALIGNMENTMENUITEMS4)
self.Bind(wx.EVT_MENU, self.OnAlignMiddleMenu,
id=ID_VIEWERALIGNMENTMENUITEMS5)
self.Bind(wx.EVT_MENU, self.OnAlignBottomMenu,
id=ID_VIEWERALIGNMENTMENUITEMS6)
# Create Contextual Menu items
def _init_coll_ContextualMenu_Items(self, parent):
# Create menu items
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS0,
kind=wx.ITEM_RADIO, text=_(u'No Modifier'))
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS1,
kind=wx.ITEM_RADIO, text=_(u'Negated'))
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS2,
kind=wx.ITEM_RADIO, text=_(u'Rising Edge'))
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS3,
kind=wx.ITEM_RADIO, text=_(u'Falling Edge'))
parent.AppendSeparator()
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS5,
kind=wx.ITEM_NORMAL, text=_(u'Add Wire Segment'))
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS6,
kind=wx.ITEM_NORMAL, text=_(u'Delete Wire Segment'))
parent.AppendSeparator()
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS8,
kind=wx.ITEM_NORMAL, text=_(u'Add Divergence Branch'))
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS9,
kind=wx.ITEM_NORMAL, text=_(u'Delete Divergence Branch'))
parent.AppendSeparator()
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS11,
kind=wx.ITEM_NORMAL, text=_(u'Clear Execution Order'))
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS12,
kind=wx.ITEM_NORMAL, text=_(u'Reset Execution Order'))
parent.AppendSeparator()
parent.AppendMenu(ID_VIEWERCONTEXTUALMENUITEMS14, _("Alignment"), self.AlignmentMenu)
parent.AppendSeparator()
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS16,
kind=wx.ITEM_NORMAL, text=_(u'Edit Block'))
AppendMenu(parent, help='', id=ID_VIEWERCONTEXTUALMENUITEMS17,
kind=wx.ITEM_NORMAL, text=_(u'Delete'))
# Link menu event to corresponding called functions
self.Bind(wx.EVT_MENU, self.OnNoModifierMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS0)
self.Bind(wx.EVT_MENU, self.OnNegatedMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS1)
self.Bind(wx.EVT_MENU, self.OnRisingEdgeMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS2)
self.Bind(wx.EVT_MENU, self.OnFallingEdgeMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS3)
self.Bind(wx.EVT_MENU, self.OnAddSegmentMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS5)
self.Bind(wx.EVT_MENU, self.OnDeleteSegmentMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS6)
self.Bind(wx.EVT_MENU, self.OnAddBranchMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS8)
self.Bind(wx.EVT_MENU, self.OnDeleteBranchMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS9)
self.Bind(wx.EVT_MENU, self.OnClearExecutionOrderMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS11)
self.Bind(wx.EVT_MENU, self.OnResetExecutionOrderMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS12)
self.Bind(wx.EVT_MENU, self.OnEditBlockMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS16)
self.Bind(wx.EVT_MENU, self.OnDeleteMenu,
id=ID_VIEWERCONTEXTUALMENUITEMS17)
# Create and initialize Contextual Menu
def _init_menus(self):
self.AlignmentMenu = wx.Menu(title='')
self.ContextualMenu = wx.Menu(title='')
self._init_coll_AlignmentMenu_Items(self.AlignmentMenu)
self._init_coll_ContextualMenu_Items(self.ContextualMenu)
def _init_Editor(self, prnt):
self.Editor = wx.ScrolledWindow(prnt, name="Viewer",
pos=wx.Point(0, 0), size=wx.Size(0, 0),
style=wx.HSCROLL | wx.VSCROLL | wx.ALWAYS_SHOW_SB)
# Create a new Viewer
def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""):
self.VARIABLE_PANEL_TYPE = controler.GetPouType(tagname.split("::")[1])
EditorPanel.__init__(self, parent, tagname, window, controler, debug)
DebugViewer.__init__(self, controler, debug)
self._init_menus()
# Adding a rubberband to Viewer
self.rubberBand = RubberBand(viewer=self)
self.Editor.SetBackgroundColour(wx.Colour(255,255,255))
self.Editor.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.ResetView()
self.Scaling = None
self.DrawGrid = True
self.GridBrush = wx.TRANSPARENT_BRUSH
self.PageSize = None
self.PagePen = wx.TRANSPARENT_PEN
self.DrawingWire = False
self.current_id = 0
self.TagName = tagname
self.Highlights = []
self.InstancePath = instancepath
self.StartMousePos = None
self.StartScreenPos = None
# Initialize Cursors
ResetCursors()
self.CurrentCursor = 0
# Initialize Block, Wire and Comment numbers
self.wire_id = 0
# Initialize Viewer mode to Selection mode
self.Mode = MODE_SELECTION
self.SavedMode = False
self.CurrentLanguage = "FBD"
if not self.Debug:
self.Editor.SetDropTarget(ViewerDropTarget(self))
self.NewDataRefreshRect = None
self.NewDataRefreshRect_lock = Lock()
dc = wx.ClientDC(self.Editor)
font = wx.Font(faces["size"], wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["mono"])
dc.SetFont(font)
width, height = dc.GetTextExtent("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
while width > 260:
faces["size"] -= 1
font = wx.Font(faces["size"], wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["mono"])
dc.SetFont(font)
width, height = dc.GetTextExtent("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
self.SetFont(font)
self.MiniTextDC = wx.MemoryDC()
self.MiniTextDC.SetFont(wx.Font(faces["size"] * 0.75, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["helv"]))
self.CurrentScale = None
self.SetScale(len(ZOOM_FACTORS) / 2, False)
self.RefreshHighlightsTimer = wx.Timer(self, -1)
self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
self.ResetView()
# Link Viewer event to corresponding methods
self.Editor.Bind(wx.EVT_PAINT, self.OnPaint)
self.Editor.Bind(wx.EVT_LEFT_DOWN, self.OnViewerLeftDown)
self.Editor.Bind(wx.EVT_LEFT_UP, self.OnViewerLeftUp)
self.Editor.Bind(wx.EVT_LEFT_DCLICK, self.OnViewerLeftDClick)
self.Editor.Bind(wx.EVT_RIGHT_DOWN, self.OnViewerRightDown)
self.Editor.Bind(wx.EVT_RIGHT_UP, self.OnViewerRightUp)
self.Editor.Bind(wx.EVT_MIDDLE_DOWN, self.OnViewerMiddleDown)
self.Editor.Bind(wx.EVT_MIDDLE_UP, self.OnViewerMiddleUp)
self.Editor.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveViewer)
self.Editor.Bind(wx.EVT_MOTION, self.OnViewerMotion)
self.Editor.Bind(wx.EVT_CHAR, self.OnChar)
self.Editor.Bind(wx.EVT_SCROLLWIN, self.OnScrollWindow)
self.Editor.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.OnScrollStop)
self.Editor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheelWindow)
self.Editor.Bind(wx.EVT_SIZE, self.OnMoveWindow)
def __del__(self):
DebugViewer.__del__(self)
self.RefreshHighlightsTimer.Stop()
def SetCurrentCursor(self, cursor):
if self.Mode != MODE_MOTION:
global CURSORS
if self.CurrentCursor != cursor:
self.CurrentCursor = cursor
self.Editor.SetCursor(CURSORS[cursor])
def GetScrolledRect(self, rect):
rect.x, rect.y = self.Editor.CalcScrolledPosition(int(rect.x * self.ViewScale[0]),
int(rect.y * self.ViewScale[1]))
rect.width = int(rect.width * self.ViewScale[0]) + 2
rect.height = int(rect.height * self.ViewScale[1]) + 2
return rect
def GetTitle(self):
if self.Debug:
if len(self.InstancePath) > 15:
return "..." + self.InstancePath[-12:]
return self.InstancePath
return EditorPanel.GetTitle(self)
def GetScaling(self):
return self.Scaling
def GetInstancePath(self):
return self.InstancePath
def IsViewing(self, tagname):
if self.Debug:
return self.InstancePath == tagname
return EditorPanel.IsViewing(self, tagname)
# Returns a new id
def GetNewId(self):
self.current_id += 1
return self.current_id
# Destructor
def __del__(self):
DebugViewer.__del__(self)
self.Flush()
self.ResetView()
def SetScale(self, scale_number, refresh=True, mouse_event=None):
new_scale = max(0, min(scale_number, len(ZOOM_FACTORS) - 1))
if self.CurrentScale != new_scale:
if refresh:
dc = self.GetLogicalDC()
self.CurrentScale = new_scale
self.ViewScale = (ZOOM_FACTORS[self.CurrentScale], ZOOM_FACTORS[self.CurrentScale])
if refresh:
self.Editor.Freeze()
if mouse_event is None:
client_size = self.Editor.GetClientSize()
mouse_pos = wx.Point(client_size[0] / 2, client_size[1] / 2)
mouse_event = wx.MouseEvent(wx.EVT_MOUSEWHEEL.typeId)
mouse_event.m_x = mouse_pos.x
mouse_event.m_y = mouse_pos.y
else:
mouse_pos = mouse_event.GetPosition()
pos = mouse_event.GetLogicalPosition(dc)
xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL)
ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL)
scrollx = max(0, round(pos.x * self.ViewScale[0] - mouse_pos.x) / SCROLLBAR_UNIT)
scrolly = max(0, round(pos.y * self.ViewScale[1] - mouse_pos.y) / SCROLLBAR_UNIT)
if scrollx > xmax or scrolly > ymax:
self.RefreshScrollBars(max(0, scrollx - xmax), max(0, scrolly - ymax))
self.Scroll(scrollx, scrolly)
else:
self.Scroll(scrollx, scrolly)
self.RefreshScrollBars()
self.RefreshScaling(refresh)
self.Editor.Thaw()
def GetScale(self):
return self.CurrentScale
def GetLogicalDC(self, buffered=False):
if buffered:
bitmap = wx.EmptyBitmap(*self.Editor.GetClientSize())
dc = wx.MemoryDC(bitmap)
else:
dc = wx.ClientDC(self.Editor)
dc.SetFont(self.GetFont())
if wx.VERSION >= (2, 6, 0):
self.Editor.DoPrepareDC(dc)
else:
self.Editor.PrepareDC(dc)
dc.SetUserScale(self.ViewScale[0], self.ViewScale[1])
return dc
def RefreshRect(self, rect, eraseBackground=True):
self.Editor.RefreshRect(rect, eraseBackground)
def Scroll(self, x, y):
self.Editor.Scroll(x, y)
def GetScrollPos(self, orientation):
return self.Editor.GetScrollPos(orientation)
def GetScrollRange(self, orientation):
return self.Editor.GetScrollRange(orientation)
def GetScrollThumb(self, orientation):
return self.Editor.GetScrollThumb(orientation)
def CalcUnscrolledPosition(self, x, y):
return self.Editor.CalcUnscrolledPosition(x, y)
def GetViewStart(self):
return self.Editor.GetViewStart()
def GetTextExtent(self, text):
return self.Editor.GetTextExtent(text)
def GetFont(self):
return self.Editor.GetFont()
def GetMiniTextExtent(self, text):
return self.MiniTextDC.GetTextExtent(text)
def GetMiniFont(self):
return self.MiniTextDC.GetFont()
#-------------------------------------------------------------------------------
# Element management functions
#-------------------------------------------------------------------------------
def AddBlock(self, block):
self.Blocks[block.GetId()] = block
def AddWire(self, wire):
self.wire_id += 1
self.Wires[wire] = self.wire_id
def AddComment(self, comment):
self.Comments[comment.GetId()] = comment
def IsBlock(self, block):
return self.Blocks.get(block.GetId(), False)
def IsWire(self, wire):
return self.Wires.get(wire, False)
def IsComment(self, comment):
return self.Comments.get(comment.GetId(), False)
def RemoveBlock(self, block):
self.Blocks.pop(block.GetId())
def RemoveWire(self, wire):
self.Wires.pop(wire)
def RemoveComment(self, comment):
self.Comments.pop(comment.GetId())
def GetElements(self, sort_blocks=False, sort_wires=False, sort_comments=False):
blocks = self.Blocks.values()
wires = self.Wires.keys()
comments = self.Comments.values()
if sort_blocks:
blocks.sort(lambda x, y: cmp(x.GetId(), y.GetId()))
if sort_wires:
wires.sort(lambda x, y: cmp(self.Wires[x], self.Wires[y]))
if sort_comments:
comments.sort(lambda x, y: cmp(x.GetId(), y.GetId()))
return blocks + wires + comments
def GetConnectorByName(self, name):
for block in self.Blocks.itervalues():
if isinstance(block, FBD_Connector) and\
block.GetType() == CONNECTOR and\
block.GetName() == name:
return block
return None
def RefreshVisibleElements(self, xp = None, yp = None):
x, y = self.Editor.CalcUnscrolledPosition(0, 0)
if xp is not None:
x = xp * self.Editor.GetScrollPixelsPerUnit()[0]
if yp is not None:
y = yp * self.Editor.GetScrollPixelsPerUnit()[1]
width, height = self.Editor.GetClientSize()
screen = wx.Rect(int(x / self.ViewScale[0]), int(y / self.ViewScale[1]),
int(width / self.ViewScale[0]), int(height / self.ViewScale[1]))
for comment in self.Comments.itervalues():
comment.TestVisible(screen)
for wire in self.Wires.iterkeys():
wire.TestVisible(screen)
for block in self.Blocks.itervalues():
block.TestVisible(screen)
def GetElementIECPath(self, element):
iec_path = None
if isinstance(element, Wire) and element.EndConnected is not None:
block = element.EndConnected.GetParentBlock()
if isinstance(block, FBD_Block):
blockname = block.GetName()
connectorname = element.EndConnected.GetName()
if blockname != "":
iec_path = "%s.%s.%s"%(self.InstancePath, blockname, connectorname)
else:
if connectorname == "":
iec_path = "%s.%s%d"%(self.InstancePath, block.GetType(), block.GetId())
else:
iec_path = "%s.%s%d_%s"%(self.InstancePath, block.GetType(), block.GetId(), connectorname)
elif isinstance(block, FBD_Variable):
iec_path = "%s.%s"%(self.InstancePath, block.GetName())
elif isinstance(block, FBD_Connector):
connection = self.GetConnectorByName(block.GetName())
if connection is not None:
connector = connection.GetConnector()
if len(connector.Wires) == 1:
iec_path = self.GetElementIECPath(connector.Wires[0][0])
elif isinstance(element, LD_Contact):
iec_path = "%s.%s"%(self.InstancePath, element.GetName())
elif isinstance(element, SFC_Step):
iec_path = "%s.%s.X"%(self.InstancePath, element.GetName())
elif isinstance(element, SFC_Transition):
connectors = element.GetConnectors()
previous_steps = self.GetPreviousSteps(connectors["inputs"])
next_steps = self.GetNextSteps(connectors["outputs"])
iec_path = "%s.%s->%s"%(self.InstancePath, ",".join(previous_steps), ",".join(next_steps))
return iec_path
#-------------------------------------------------------------------------------
# Reset functions
#-------------------------------------------------------------------------------
# Resets Viewer lists
def ResetView(self):
self.Blocks = {}
self.Wires = {}
self.Comments = {}
self.Subscribed = {}
self.SelectedElement = None
self.HighlightedElement = None
def Flush(self):
self.DeleteDataConsumers()
for block in self.Blocks.itervalues():
block.Flush()
# Remove all elements
def CleanView(self):
for block in self.Blocks.itervalues():
block.Clean()
self.ResetView()
# Changes Viewer mode
def SetMode(self, mode):
if self.Mode != mode or mode == MODE_SELECTION:
if self.Mode == MODE_MOTION:
wx.CallAfter(self.Editor.SetCursor, wx.NullCursor)
self.Mode = mode
self.SavedMode = False
else:
self.SavedMode = True
# Reset selection
if self.Mode != MODE_SELECTION and self.SelectedElement:
self.SelectedElement.SetSelected(False)
self.SelectedElement = None
if self.Mode == MODE_MOTION:
wx.CallAfter(self.Editor.SetCursor, wx.StockCursor(wx.CURSOR_HAND))
self.SavedMode = True
# Return current drawing mode
def GetDrawingMode(self):
return self.ParentWindow.GetDrawingMode()
# Buffer the last model state
def RefreshBuffer(self):
self.Controler.BufferProject()
self.ParentWindow.RefreshTitle()
self.ParentWindow.RefreshFileMenu()
self.ParentWindow.RefreshEditMenu()
def GetBufferState(self):
if not self.Debug:
return self.Controler.GetBufferState()
return False, False
def Undo(self):
if not self.Debug:
self.Controler.LoadPrevious()
self.ParentWindow.CloseTabsWithoutModel()
self.ParentWindow.RefreshEditor()
def Redo(self):
if not self.Debug:
self.Controler.LoadNext()
self.ParentWindow.CloseTabsWithoutModel()
self.ParentWindow.RefreshEditor()
def HasNoModel(self):
if not self.Debug:
return self.Controler.GetEditedElement(self.TagName) is None
return False
# Refresh the current scaling
def RefreshScaling(self, refresh=True):
properties = self.Controler.GetProjectProperties(self.Debug)
scaling = properties["scaling"][self.CurrentLanguage]
if scaling[0] != 0 and scaling[1] != 0:
self.Scaling = scaling
if self.DrawGrid:
width = max(2, int(scaling[0] * self.ViewScale[0]))
height = max(2, int(scaling[1] * self.ViewScale[1]))
bitmap = wx.EmptyBitmap(width, height)
dc = wx.MemoryDC(bitmap)
dc.SetBackground(wx.Brush(self.Editor.GetBackgroundColour()))
dc.Clear()
dc.SetPen(MiterPen(wx.Colour(180, 180, 180)))
dc.DrawPoint(0, 0)
self.GridBrush = wx.BrushFromBitmap(bitmap)
else:
self.GridBrush = wx.TRANSPARENT_BRUSH
else:
self.Scaling = None
self.GridBrush = wx.TRANSPARENT_BRUSH
page_size = properties["pageSize"]
if page_size != (0, 0):
self.PageSize = map(int, page_size)
self.PagePen = MiterPen(wx.Colour(180, 180, 180))
else:
self.PageSize = None
self.PagePen = wx.TRANSPARENT_PEN
if refresh:
self.RefreshVisibleElements()
self.Refresh(False)
#-------------------------------------------------------------------------------
# Refresh functions
#-------------------------------------------------------------------------------
def UpdateRefreshRect(self, refresh_rect):
self.NewDataRefreshRect_lock.acquire()
if self.NewDataRefreshRect is None:
self.NewDataRefreshRect = refresh_rect
else:
self.NewDataRefreshRect.Union(refresh_rect)
self.NewDataRefreshRect_lock.release()
def RefreshNewData(self):
if self.NewDataRefreshRect is not None:
self.NewDataRefreshRect_lock.acquire()
refresh_rect, self.NewDataRefreshRect = self.NewDataRefreshRect, None
self.NewDataRefreshRect_lock.release()
self.RefreshRect(self.GetScrolledRect(refresh_rect), False)
else:
DebugViewer.RefreshNewData(self)
# Refresh Viewer elements
def RefreshView(self, variablepanel=True, selection=None):
EditorPanel.RefreshView(self, variablepanel)
self.Inhibit(True)
self.current_id = 0
# Start by reseting Viewer
self.Flush()
self.ResetView()
instance = {}
# List of ids of already loaded blocks
ids = []
# Load Blocks until they are all loaded
while instance is not None:
instance = self.Controler.GetEditedElementInstanceInfos(self.TagName, exclude = ids, debug = self.Debug)
if instance is not None:
self.loadInstance(instance, ids, selection)
self.RefreshScrollBars()
for wire in self.Wires:
if not wire.IsConnectedCompatible():
wire.SetValid(False)
if self.Debug:
iec_path = self.GetElementIECPath(wire)
if iec_path is None:
block = wire.EndConnected.GetParentBlock()
if isinstance(block, LD_PowerRail):
wire.SetValue(True)
elif self.AddDataConsumer(iec_path.upper(), wire) is None:
wire.SetValue("undefined")
if self.Debug:
for block in self.Blocks.itervalues():
block.SpreadCurrent()
iec_path = self.GetElementIECPath(block)
if iec_path is not None:
self.AddDataConsumer(iec_path.upper(), block)
self.Inhibit(False)
self.RefreshVisibleElements()
self.ShowHighlights()
self.Refresh(False)
def GetPreviousSteps(self, connectors):
steps = []
for connector in connectors:
for wire, handle in connector.GetWires():
previous = wire.GetOtherConnected(connector).GetParentBlock()
if isinstance(previous, SFC_Step):
steps.append(previous.GetName())
elif isinstance(previous, SFC_Divergence) and previous.GetType() in [SIMULTANEOUS_CONVERGENCE, SELECTION_DIVERGENCE]:
connectors = previous.GetConnectors()
steps.extend(self.GetPreviousSteps(connectors["inputs"]))
return steps
def GetNextSteps(self, connectors):
steps = []
for connector in connectors:
for wire, handle in connector.GetWires():
next = wire.GetOtherConnected(connector).GetParentBlock()
if isinstance(next, SFC_Step):
steps.append(next.GetName())
elif isinstance(next, SFC_Jump):
steps.append(next.GetTarget())
elif isinstance(next, SFC_Divergence) and next.GetType() in [SIMULTANEOUS_DIVERGENCE, SELECTION_CONVERGENCE]:
connectors = next.GetConnectors()
steps.extend(self.GetNextSteps(connectors["outputs"]))
return steps
def GetMaxSize(self):
maxx = maxy = 0
for element in self.GetElements():
bbox = element.GetBoundingBox()
maxx = max(maxx, bbox.x + bbox.width)
maxy = max(maxy, bbox.y + bbox.height)
return maxx, maxy
def RefreshScrollBars(self, width_incr=0, height_incr=0):
xstart, ystart = self.GetViewStart()
window_size = self.Editor.GetClientSize()
maxx, maxy = self.GetMaxSize()
maxx = max(maxx + WINDOW_BORDER, (xstart * SCROLLBAR_UNIT + window_size[0]) / self.ViewScale[0])
maxy = max(maxy + WINDOW_BORDER, (ystart * SCROLLBAR_UNIT + window_size[1]) / self.ViewScale[1])
if self.rubberBand.IsShown():
extent = self.rubberBand.GetCurrentExtent()
maxx = max(maxx, extent.x + extent.width)
maxy = max(maxy, extent.y + extent.height)
maxx = int(maxx * self.ViewScale[0])
maxy = int(maxy * self.ViewScale[1])
self.Editor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
round(maxx / SCROLLBAR_UNIT) + width_incr, round(maxy / SCROLLBAR_UNIT) + height_incr,
xstart, ystart, True)
def SelectInGroup(self, element):
element.SetSelected(True)
if self.SelectedElement is None:
self.SelectedElement = element
elif isinstance(self.SelectedElement, Graphic_Group):
self.SelectedElement.SelectElement(element)
else:
group = Graphic_Group(self)
group.SelectElement(self.SelectedElement)
group.SelectElement(element)
self.SelectedElement = group
# Load instance from given informations
def loadInstance(self, instance, ids, selection):
ids.append(instance["id"])
self.current_id = max(self.current_id, instance["id"])
creation_function = ElementCreationFunctions.get(instance["type"], None)
connectors = {"inputs" : [], "outputs" : []}
specific_values = instance["specific_values"]
if creation_function is not None:
element = creation_function(self, instance["id"], specific_values)
if isinstance(element, SFC_Step):
if len(instance["inputs"]) > 0:
element.AddInput()
else:
element.RemoveInput()
if len(instance["outputs"]) > 0:
element.AddOutput()
if isinstance(element, SFC_Transition) and specific_values["condition_type"] == "connection":
connector = element.GetConditionConnector()
self.CreateWires(connector, id, specific_values["connection"]["links"], ids, selection)
else:
executionControl = False
for input in instance["inputs"]:
if input["negated"]:
connectors["inputs"].append((input["name"], None, "negated"))
elif input["edge"]:
connectors["inputs"].append((input["name"], None, input["edge"]))
else:
connectors["inputs"].append((input["name"], None, "none"))
for output in instance["outputs"]:
if output["negated"]:
connectors["outputs"].append((output["name"], None, "negated"))
elif output["edge"]:
connectors["outputs"].append((output["name"], None, output["edge"]))
else:
connectors["outputs"].append((output["name"], None, "none"))
if len(connectors["inputs"]) > 0 and connectors["inputs"][0][0] == "EN":
connectors["inputs"].pop(0)
executionControl = True
if len(connectors["outputs"]) > 0 and connectors["outputs"][0][0] == "ENO":
connectors["outputs"].pop(0)
executionControl = True
if specific_values["name"] is None:
specific_values["name"] = ""
element = FBD_Block(self, instance["type"], specific_values["name"],
instance["id"], len(connectors["inputs"]),
connectors=connectors, executionControl=executionControl,
executionOrder=specific_values["executionOrder"])
element.SetPosition(instance["x"], instance["y"])
element.SetSize(instance["width"], instance["height"])
if isinstance(element, Comment):
self.AddComment(element)
else:
self.AddBlock(element)
connectors = element.GetConnectors()
for i, input_connector in enumerate(instance["inputs"]):
if i < len(connectors["inputs"]):
connector = connectors["inputs"][i]
connector.SetPosition(wx.Point(*input_connector["position"]))
if input_connector.get("negated", False):
connector.SetNegated(True)
if input_connector.get("edge", "none") != "none":
connector.SetEdge(input_connector["edge"])
self.CreateWires(connector, instance["id"], input_connector["links"], ids, selection)
for i, output_connector in enumerate(instance["outputs"]):
if i < len(connectors["outputs"]):
connector = connectors["outputs"][i]
if output_connector.get("negated", False):
connector.SetNegated(True)
if output_connector.get("edge", "none") != "none":
connector.SetEdge(output_connector["edge"])
connector.SetPosition(wx.Point(*output_connector["position"]))
if selection is not None and selection[0].get(instance["id"], False):
self.SelectInGroup(element)
def CreateWires(self, start_connector, id, links, ids, selection=None):
for link in links:
refLocalId = link["refLocalId"]
if refLocalId is not None:
if refLocalId not in ids:
new_instance = self.Controler.GetEditedElementInstanceInfos(self.TagName, refLocalId, debug = self.Debug)
if new_instance is not None:
self.loadInstance(new_instance, ids, selection)
connected = self.FindElementById(refLocalId)
if connected is not None:
points = link["points"]
end_connector = connected.GetConnector(wx.Point(points[-1][0], points[-1][1]), link["formalParameter"])
if end_connector is not None:
wire = Wire(self)
wire.SetPoints(points)
start_connector.Connect((wire, 0), False)
end_connector.Connect((wire, -1), False)
wire.ConnectStartPoint(None, start_connector)
wire.ConnectEndPoint(None, end_connector)
self.AddWire(wire)
if selection is not None and (\
selection[1].get((id, refLocalId), False) or \
selection[1].get((refLocalId, id), False)):
self.SelectInGroup(wire)
def IsOfType(self, type, reference):
return self.Controler.IsOfType(type, reference, self.Debug)
def IsEndType(self, type):
return self.Controler.IsEndType(type)
def GetBlockType(self, type, inputs = None):
return self.Controler.GetBlockType(type, inputs, self.Debug)
#-------------------------------------------------------------------------------
# Search Element functions
#-------------------------------------------------------------------------------
def FindBlock(self, event):
dc = self.GetLogicalDC()
pos = event.GetLogicalPosition(dc)
for block in self.Blocks.itervalues():
if block.HitTest(pos) or block.TestHandle(event) != (0, 0):
return block
return None
def FindWire(self, event):
dc = self.GetLogicalDC()
pos = event.GetLogicalPosition(dc)
for wire in self.Wires:
if wire.HitTest(pos) or wire.TestHandle(event) != (0, 0):
return wire
return None
def FindElement(self, event, exclude_group = False):
dc = self.GetLogicalDC()
pos = event.GetLogicalPosition(dc)
if self.SelectedElement and not (exclude_group and isinstance(self.SelectedElement, Graphic_Group)):
if self.SelectedElement.HitTest(pos) or self.SelectedElement.TestHandle(event) != (0, 0):
return self.SelectedElement
for element in self.GetElements():
if element.HitTest(pos) or element.TestHandle(event) != (0, 0):
return element
return None
def FindBlockConnector(self, pos, direction = None, exclude = None):
for block in self.Blocks.itervalues():
result = block.TestConnector(pos, direction, exclude)
if result:
return result
return None
def FindElementById(self, id):
block = self.Blocks.get(id, None)
if block is not None:
return block
comment = self.Comments.get(id, None)
if comment is not None:
return comment
return None
def SearchElements(self, bbox):
elements = []
for element in self.GetElements():
if element.IsInSelection(bbox):
elements.append(element)
return elements
def SelectAll(self):
if self.SelectedElement is not None:
self.SelectedElement.SetSelected(False)
self.SelectedElement = Graphic_Group(self)
for element in self.GetElements():
self.SelectedElement.SelectElement(element)
self.SelectedElement.SetSelected(True)
#-------------------------------------------------------------------------------
# Popup menu functions
#-------------------------------------------------------------------------------
def GetForceVariableMenuFunction(self, iec_path, element):
iec_type = self.GetDataType(iec_path)
def ForceVariableFunction(event):
if iec_type is not None:
dialog = ForceVariableDialog(self.ParentWindow, iec_type, str(element.GetValue()))
if dialog.ShowModal() == wx.ID_OK:
self.ParentWindow.AddDebugVariable(iec_path)
self.ForceDataValue(iec_path, dialog.GetValue())
return ForceVariableFunction
def GetReleaseVariableMenuFunction(self, iec_path):
def ReleaseVariableFunction(event):
self.ReleaseDataValue(iec_path)
return ReleaseVariableFunction
def PopupForceMenu(self):
iec_path = self.GetElementIECPath(self.SelectedElement)
if iec_path is not None:
menu = wx.Menu(title='')
new_id = wx.NewId()
AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Force value"))
self.Bind(wx.EVT_MENU, self.GetForceVariableMenuFunction(iec_path.upper(), self.SelectedElement), id=new_id)
new_id = wx.NewId()
AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Release value"))
self.Bind(wx.EVT_MENU, self.GetReleaseVariableMenuFunction(iec_path.upper()), id=new_id)
if self.SelectedElement.IsForced():
menu.Enable(new_id, True)
else:
menu.Enable(new_id, False)
self.Editor.PopupMenu(menu)
def PopupBlockMenu(self, connector = None):
if connector is not None and connector.IsCompatible("BOOL"):
type = self.Controler.GetEditedElementType(self.TagName, self.Debug)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, True)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, True)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, type != "function")
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, type != "function")
else:
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS5, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS6, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS8, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS9, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, self.SelectedElement.GetType() in self.Controler.GetProjectPouNames(self.Debug))
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
if connector is not None:
if connector.IsNegated():
self.ContextualMenu.Check(ID_VIEWERCONTEXTUALMENUITEMS1, True)
elif connector.GetEdge() == "rising":
self.ContextualMenu.Check(ID_VIEWERCONTEXTUALMENUITEMS2, True)
elif connector.GetEdge() == "falling":
self.ContextualMenu.Check(ID_VIEWERCONTEXTUALMENUITEMS3, True)
else:
self.ContextualMenu.Check(ID_VIEWERCONTEXTUALMENUITEMS0, True)
self.Editor.PopupMenu(self.ContextualMenu)
def PopupWireMenu(self, delete=True):
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS5, True)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS6, delete)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS8, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS9, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
self.Editor.PopupMenu(self.ContextualMenu)
def PopupDivergenceMenu(self, connector):
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS5, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS6, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS8, True)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS9, connector)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
self.Editor.PopupMenu(self.ContextualMenu)
def PopupGroupMenu(self):
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS5, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS6, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS8, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS9, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, True)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
self.Editor.PopupMenu(self.ContextualMenu)
def PopupDefaultMenu(self, block = True):
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS1, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS2, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS3, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS5, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS6, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS8, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS9, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, block)
self.Editor.PopupMenu(self.ContextualMenu)
#-------------------------------------------------------------------------------
# Menu items functions
#-------------------------------------------------------------------------------
def OnAlignLeftMenu(self, event):
if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
self.SelectedElement.AlignElements(ALIGN_LEFT, None)
self.RefreshBuffer()
self.Refresh(False)
def OnAlignCenterMenu(self, event):
if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
self.SelectedElement.AlignElements(ALIGN_CENTER, None)
self.RefreshBuffer()
self.Refresh(False)
def OnAlignRightMenu(self, event):
if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
self.SelectedElement.AlignElements(ALIGN_RIGHT, None)
self.RefreshBuffer()
self.Refresh(False)
def OnAlignTopMenu(self, event):
if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
self.SelectedElement.AlignElements(None, ALIGN_TOP)
self.RefreshBuffer()
self.Refresh(False)
def OnAlignMiddleMenu(self, event):
if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
self.SelectedElement.AlignElements(None, ALIGN_MIDDLE)
self.RefreshBuffer()
self.Refresh(False)
def OnAlignBottomMenu(self, event):
if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
self.SelectedElement.AlignElements(None, ALIGN_BOTTOM)
self.RefreshBuffer()
self.Refresh(False)
def OnNoModifierMenu(self, event):
if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
self.SelectedElement.SetConnectorNegated(False)
self.SelectedElement.Refresh()
self.RefreshBuffer()
def OnNegatedMenu(self, event):
if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
self.SelectedElement.SetConnectorNegated(True)
self.SelectedElement.Refresh()
self.RefreshBuffer()
def OnRisingEdgeMenu(self, event):
if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
self.SelectedElement.SetConnectorEdge("rising")
self.SelectedElement.Refresh()
self.RefreshBuffer()
def OnFallingEdgeMenu(self, event):
if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
self.SelectedElement.SetConnectorEdge("falling")
self.SelectedElement.Refresh()
self.RefreshBuffer()
def OnAddSegmentMenu(self, event):
if self.SelectedElement is not None and self.IsWire(self.SelectedElement):
self.SelectedElement.AddSegment()
self.SelectedElement.Refresh()
def OnDeleteSegmentMenu(self, event):
if self.SelectedElement is not None and self.IsWire(self.SelectedElement):
self.SelectedElement.DeleteSegment()
self.SelectedElement.Refresh()
def OnAddBranchMenu(self, event):
if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
self.AddDivergenceBranch(self.SelectedElement)
def OnDeleteBranchMenu(self, event):
if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
self.RemoveDivergenceBranch(self.SelectedElement)
def OnEditBlockMenu(self, event):
if self.SelectedElement is not None:
self.ParentWindow.EditProjectElement(ITEM_POU, "P::%s"%self.SelectedElement.GetType())
def OnDeleteMenu(self, event):
if self.SelectedElement is not None:
self.SelectedElement.Delete()
self.SelectedElement = None
self.RefreshBuffer()
self.Refresh(False)
def OnClearExecutionOrderMenu(self, event):
self.Controler.ClearEditedElementExecutionOrder(self.TagName)
self.RefreshBuffer()
self.RefreshView()
def OnResetExecutionOrderMenu(self, event):
self.Controler.ResetEditedElementExecutionOrder(self.TagName)
self.RefreshBuffer()
self.RefreshView()
#-------------------------------------------------------------------------------
# Mouse event functions
#-------------------------------------------------------------------------------
def OnViewerLeftDown(self, event):
if self.Mode == MODE_SELECTION:
dc = self.GetLogicalDC()
pos = event.GetLogicalPosition(dc)
if event.ShiftDown() and not event.ControlDown() and self.SelectedElement is not None:
element = self.FindElement(event, True)
if element is not None:
if isinstance(self.SelectedElement, Graphic_Group):
self.SelectedElement.SetSelected(False)
self.SelectedElement.SelectElement(element)
elif self.SelectedElement is not None:
group = Graphic_Group(self)
group.SelectElement(self.SelectedElement)
group.SelectElement(element)
self.SelectedElement = group
elements = self.SelectedElement.GetElements()
if len(elements) == 0:
self.SelectedElement = element
elif len(elements) == 1:
self.SelectedElement = elements[0]
self.SelectedElement.SetSelected(True)
else:
element = self.FindElement(event)
if not self.Debug and (element is None or element.TestHandle(event) == (0, 0)):
connector = self.FindBlockConnector(pos)
else:
connector = None
if not self.Debug and self.DrawingWire:
self.DrawingWire = False
if self.SelectedElement is not None:
if element is None or element.TestHandle(event) == (0, 0):
connector = self.FindBlockConnector(pos, self.SelectedElement.GetConnectionDirection())
if connector is not None:
event.Dragging = lambda : True
self.SelectedElement.OnMotion(event, dc, self.Scaling)
if self.SelectedElement.EndConnected is not None:
self.SelectedElement.ResetPoints()
self.SelectedElement.GeneratePoints()
self.SelectedElement.RefreshModel()
self.SelectedElement.SetSelected(True)
element = self.SelectedElement
self.RefreshBuffer()
else:
rect = self.SelectedElement.GetRedrawRect()
self.SelectedElement.Delete()
self.SelectedElement = None
element = None
self.RefreshRect(self.GetScrolledRect(rect), False)
elif not self.Debug and connector is not None:
self.DrawingWire = True
scaled_pos = GetScaledEventPosition(event, dc, self.Scaling)
if (connector.GetDirection() == EAST):
wire = Wire(self, [wx.Point(pos.x, pos.y), EAST], [wx.Point(scaled_pos.x, scaled_pos.y), WEST])
else:
wire = Wire(self, [wx.Point(pos.x, pos.y), WEST], [wx.Point(scaled_pos.x, scaled_pos.y), EAST])
wire.oldPos = scaled_pos
wire.Handle = (HANDLE_POINT, 0)
wire.ProcessDragging(0, 0, event, None)
wire.Handle = (HANDLE_POINT, 1)
self.AddWire(wire)
if self.SelectedElement is not None:
self.SelectedElement.SetSelected(False)
self.SelectedElement = wire
self.RefreshVisibleElements()
self.SelectedElement.Refresh()
else:
if self.SelectedElement is not None and self.SelectedElement != element:
self.SelectedElement.SetSelected(False)
self.SelectedElement = None
if element is not None:
self.SelectedElement = element
if self.Debug:
self.StartMousePos = event.GetPosition()
Graphic_Element.OnLeftDown(self.SelectedElement, event, dc, self.Scaling)
else:
self.SelectedElement.OnLeftDown(event, dc, self.Scaling)
self.SelectedElement.Refresh()
else:
self.rubberBand.Reset()
self.rubberBand.OnLeftDown(event, dc, self.Scaling)
elif self.Mode in [MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT,
MODE_CONTACT, MODE_COIL, MODE_POWERRAIL, MODE_INITIALSTEP,
MODE_STEP, MODE_TRANSITION, MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION]:
self.rubberBand.Reset()
self.rubberBand.OnLeftDown(event, self.GetLogicalDC(), self.Scaling)
elif self.Mode == MODE_MOTION:
self.StartMousePos = event.GetPosition()
self.StartScreenPos = self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)
event.Skip()
def OnViewerLeftUp(self, event):
self.StartMousePos = None
if self.rubberBand.IsShown():
if self.Mode == MODE_SELECTION:
elements = self.SearchElements(self.rubberBand.GetCurrentExtent())
self.rubberBand.OnLeftUp(event, self.GetLogicalDC(), self.Scaling)
if len(elements) == 1:
self.SelectedElement = elements[0]
self.SelectedElement.SetSelected(True)
elif len(elements) > 1:
self.SelectedElement = Graphic_Group(self)
self.SelectedElement.SetElements(elements)
self.SelectedElement.SetSelected(True)
else:
bbox = self.rubberBand.GetCurrentExtent()
self.rubberBand.OnLeftUp(event, self.GetLogicalDC(), self.Scaling)
if self.Mode == MODE_BLOCK:
wx.CallAfter(self.AddNewBlock, bbox)
elif self.Mode == MODE_VARIABLE:
wx.CallAfter(self.AddNewVariable, bbox)
elif self.Mode == MODE_CONNECTION:
wx.CallAfter(self.AddNewConnection, bbox)
elif self.Mode == MODE_COMMENT:
wx.CallAfter(self.AddNewComment, bbox)
elif self.Mode == MODE_CONTACT:
wx.CallAfter(self.AddNewContact, bbox)
elif self.Mode == MODE_COIL:
wx.CallAfter(self.AddNewCoil, bbox)
elif self.Mode == MODE_POWERRAIL:
wx.CallAfter(self.AddNewPowerRail, bbox)
elif self.Mode == MODE_INITIALSTEP:
wx.CallAfter(self.AddNewStep, bbox, True)
elif self.Mode == MODE_STEP:
wx.CallAfter(self.AddNewStep, bbox, False)
elif self.Mode == MODE_TRANSITION:
wx.CallAfter(self.AddNewTransition, bbox)
elif self.Mode == MODE_DIVERGENCE:
wx.CallAfter(self.AddNewDivergence, bbox)
elif self.Mode == MODE_JUMP:
wx.CallAfter(self.AddNewJump, bbox)
elif self.Mode == MODE_ACTION:
wx.CallAfter(self.AddNewActionBlock, bbox)
elif self.Mode == MODE_SELECTION and self.SelectedElement is not None:
dc = self.GetLogicalDC()
if not self.Debug and self.DrawingWire:
pos = event.GetLogicalPosition(dc)
connector = self.FindBlockConnector(pos, self.SelectedElement.GetConnectionDirection())
if self.SelectedElement.EndConnected is not None:
self.DrawingWire = False
self.SelectedElement.StartConnected.HighlightParentBlock(False)
self.SelectedElement.EndConnected.HighlightParentBlock(False)
self.SelectedElement.ResetPoints()
self.SelectedElement.OnMotion(event, dc, self.Scaling)
self.SelectedElement.GeneratePoints()
self.SelectedElement.RefreshModel()
if self.HighlightedElement is not None:
self.HighlightedElement.SetHighlighted(False)
self.HighlightedElement = None
self.SelectedElement.SetHighlighted(True)
self.HighlightedElement = self.SelectedElement
self.SelectedElement.SetSelected(True)
self.RefreshBuffer()
elif connector is None or self.SelectedElement.GetDragging():
self.DrawingWire = False
rect = self.SelectedElement.GetRedrawRect()
self.SelectedElement.Delete()
self.SelectedElement = None
self.RefreshRect(self.GetScrolledRect(rect), False)
else:
if self.Debug:
Graphic_Element.OnLeftUp(self.SelectedElement, event, dc, self.Scaling)
else:
self.SelectedElement.OnLeftUp(event, dc, self.Scaling)
wx.CallAfter(self.SetCurrentCursor, 0)
elif self.Mode == MODE_MOTION:
self.StartMousePos = None
self.StartScreenPos = None
if self.Mode != MODE_SELECTION and not self.SavedMode:
wx.CallAfter(self.ParentWindow.ResetCurrentMode)
event.Skip()
def OnViewerMiddleDown(self, event):
self.StartMousePos = event.GetPosition()
self.StartScreenPos = self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)
event.Skip()
def OnViewerMiddleUp(self, event):
self.StartMousePos = None
self.StartScreenPos = None
event.Skip()
def OnViewerRightDown(self, event):
if self.Mode == MODE_SELECTION:
element = self.FindElement(event)
if self.SelectedElement is not None and self.SelectedElement != element:
self.SelectedElement.SetSelected(False)
self.SelectedElement = None
if element:
self.SelectedElement = element
if self.Debug:
Graphic_Element.OnRightDown(self.SelectedElement, event, self.GetLogicalDC(), self.Scaling)
else:
self.SelectedElement.OnRightDown(event, self.GetLogicalDC(), self.Scaling)
self.SelectedElement.Refresh()
event.Skip()
def OnViewerRightUp(self, event):
if self.SelectedElement is not None:
if self.Debug:
Graphic_Element.OnRightUp(self.SelectedElement, event, self.GetLogicalDC(), self.Scaling)
else:
self.SelectedElement.OnRightUp(event, self.GetLogicalDC(), self.Scaling)
wx.CallAfter(self.SetCurrentCursor, 0)
elif not self.Debug:
self.PopupDefaultMenu(False)
event.Skip()
def OnViewerLeftDClick(self, event):
if self.Mode == MODE_SELECTION and self.SelectedElement is not None:
if self.Debug:
iec_path = self.GetElementIECPath(self.SelectedElement)
if iec_path is not None:
if isinstance(self.SelectedElement, Wire):
if self.SelectedElement.EndConnected is not None:
var_type = self.SelectedElement.EndConnected.GetType()
if self.Controler.IsOfType(var_type, "ANY_NUM", self.Debug) or\
self.Controler.IsOfType(var_type, "ANY_BIT", self.Debug):
self.ParentWindow.OpenGraphicViewer(iec_path)
else:
self.ParentWindow.OpenGraphicViewer(iec_path)
elif event.ControlDown() and not event.ShiftDown():
if self.IsBlock(self.SelectedElement) and self.SelectedElement.GetType() in self.Controler.GetProjectPouNames(self.Debug):
self.ParentWindow.EditProjectElement(ITEM_POU, self.Controler.ComputePouName(self.SelectedElement.GetType()))
else:
self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling)
elif event.ControlDown() and event.ShiftDown():
movex, movey = self.SelectedElement.AdjustToScaling(self.Scaling)
self.SelectedElement.RefreshModel()
self.RefreshBuffer()
if movex != 0 or movey != 0:
self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False)
else:
self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling)
event.Skip()
def OnViewerMotion(self, event):
refresh = False
dc = self.GetLogicalDC()
pos = GetScaledEventPosition(event, dc, self.Scaling)
if event.MiddleIsDown() or self.Mode == MODE_MOTION:
if self.StartMousePos is not None and self.StartScreenPos is not None:
new_pos = event.GetPosition()
xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL)
ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL)
scrollx = max(0, self.StartScreenPos[0] - (new_pos[0] - self.StartMousePos[0]) / SCROLLBAR_UNIT)
scrolly = max(0, self.StartScreenPos[1] - (new_pos[1] - self.StartMousePos[1]) / SCROLLBAR_UNIT)
if scrollx > xmax or scrolly > ymax:
self.RefreshScrollBars(max(0, scrollx - xmax), max(0, scrolly - ymax))
self.Scroll(scrollx, scrolly)
else:
self.Scroll(scrollx, scrolly)
self.RefreshScrollBars()
self.RefreshVisibleElements()
else:
if not event.Dragging():
if self.Debug:
tooltip_pos = self.Editor.ClientToScreen(event.GetPosition())
tooltip_pos.x += 10
tooltip_pos.y += 10
highlighted = self.FindElement(event)
if self.HighlightedElement is not None and self.HighlightedElement != highlighted:
if self.Debug and isinstance(self.HighlightedElement, Wire):
self.HighlightedElement.ClearToolTip()
self.HighlightedElement.SetHighlighted(False)
self.HighlightedElement = None
if highlighted is not None and self.HighlightedElement != highlighted:
if self.Debug and isinstance(highlighted, Wire):
highlighted.CreateToolTip(tooltip_pos)
highlighted.SetHighlighted(True)
elif self.Debug and highlighted is not None and isinstance(highlighted, Wire):
highlighted.MoveToolTip(tooltip_pos)
self.HighlightedElement = highlighted
if self.rubberBand.IsShown():
self.rubberBand.OnMotion(event, dc, self.Scaling)
elif not self.Debug and self.Mode == MODE_SELECTION and self.SelectedElement is not None:
if self.DrawingWire:
connector = self.FindBlockConnector(pos, self.SelectedElement.GetConnectionDirection(), self.SelectedElement.EndConnected)
if not connector or self.SelectedElement.EndConnected == None:
self.SelectedElement.ResetPoints()
movex, movey = self.SelectedElement.OnMotion(event, dc, self.Scaling)
self.SelectedElement.GeneratePoints()
if movex != 0 or movey != 0:
self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False)
else:
movex, movey = self.SelectedElement.OnMotion(event, dc, self.Scaling)
if movex != 0 or movey != 0:
self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False)
elif self.Debug and self.StartMousePos is not None and event.Dragging():
pos = event.GetPosition()
if abs(self.StartMousePos.x - pos.x) > 5 or abs(self.StartMousePos.y - pos.y) > 5:
iec_path = self.GetElementIECPath(self.SelectedElement)
if iec_path is not None:
self.StartMousePos = None
if self.HighlightedElement is not None:
if isinstance(self.HighlightedElement, Wire):
self.HighlightedElement.ClearToolTip()
self.HighlightedElement.SetHighlighted(False)
self.HighlightedElement = None
data = wx.TextDataObject(str((iec_path, "debug")))
dragSource = wx.DropSource(self.Editor)
dragSource.SetData(data)
dragSource.DoDragDrop()
self.UpdateScrollPos(event)
event.Skip()
def OnLeaveViewer(self, event):
if self.StartScreenPos is None:
self.StartMousePos = None
if self.SelectedElement is not None and self.SelectedElement.GetDragging():
event.Skip()
elif self.HighlightedElement is not None:
if isinstance(self.HighlightedElement, Wire):
self.HighlightedElement.ClearToolTip()
self.HighlightedElement.SetHighlighted(False)
self.HighlightedElement = None
event.Skip()
def UpdateScrollPos(self, event):
if (event.Dragging() and self.SelectedElement is not None) or self.rubberBand.IsShown():
position = event.GetPosition()
move_window = wx.Point()
window_size = self.Editor.GetClientSize()
xstart, ystart = self.GetViewStart()
if position.x < SCROLL_ZONE and xstart > 0:
move_window.x = -1
elif position.x > window_size[0] - SCROLL_ZONE:
move_window.x = 1
if position.y < SCROLL_ZONE and ystart > 0:
move_window.y = -1
elif position.y > window_size[1] - SCROLL_ZONE:
move_window.y = 1
if move_window.x != 0 or move_window.y != 0:
self.RefreshVisibleElements(xp = xstart + move_window.x, yp = ystart + move_window.y)
self.Scroll(xstart + move_window.x, ystart + move_window.y)
self.RefreshScrollBars(move_window.x, move_window.y)
#-------------------------------------------------------------------------------
# Keyboard event functions
#-------------------------------------------------------------------------------
def OnChar(self, event):
xpos, ypos = self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)
xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL)
ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL)
keycode = event.GetKeyCode()
if self.Scaling is not None:
scaling = self.Scaling
else:
scaling = (8, 8)
if not self.Debug and keycode == wx.WXK_DELETE and self.SelectedElement is not None:
rect = self.SelectedElement.GetRedrawRect(1, 1)
self.SelectedElement.Delete()
self.SelectedElement = None
self.RefreshBuffer()
self.RefreshScrollBars()
wx.CallAfter(self.SetCurrentCursor, 0)
self.RefreshRect(self.GetScrolledRect(rect), False)
elif not self.Debug and keycode == wx.WXK_RETURN and self.SelectedElement is not None:
self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling)
elif keycode == wx.WXK_LEFT:
if event.ControlDown() and event.ShiftDown():
self.Scroll(0, ypos)
self.RefreshVisibleElements()
elif event.ControlDown():
self.Scroll(xpos - 1, ypos)
self.RefreshScrollBars()
self.RefreshVisibleElements()
elif not self.Debug and self.SelectedElement is not None:
self.SelectedElement.Move(-scaling[0], 0)
self.SelectedElement.RefreshModel()
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(-scaling[0], 0)), False)
elif keycode == wx.WXK_RIGHT:
if event.ControlDown() and event.ShiftDown():
self.Scroll(xmax, ypos)
self.RefreshVisibleElements()
elif event.ControlDown():
self.RefreshScrollBars(width_incr=max(0, xpos + 1 - xmax))
self.Scroll(xpos + 1, ypos)
self.RefreshVisibleElements()
elif not self.Debug and self.SelectedElement is not None:
self.SelectedElement.Move(scaling[0], 0)
self.SelectedElement.RefreshModel()
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(scaling[0], 0)), False)
elif keycode == wx.WXK_UP:
if event.ControlDown() and event.ShiftDown():
self.Scroll(xpos, 0)
self.RefreshVisibleElements()
elif event.ControlDown():
self.Scroll(xpos, ypos - 1)
self.RefreshScrollBars()
self.RefreshVisibleElements()
elif not self.Debug and self.SelectedElement is not None:
self.SelectedElement.Move(0, -scaling[1])
self.SelectedElement.RefreshModel()
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(0, -scaling[1])), False)
elif keycode == wx.WXK_DOWN:
if event.ControlDown() and event.ShiftDown():
self.Scroll(xpos, ymax)
self.RefreshVisibleElements()
elif event.ControlDown():
self.RefreshScrollBars(height_incr=max(0, ypos + 1 - ymax))
self.Scroll(xpos, ypos + 1)
self.RefreshVisibleElements()
elif not self.Debug and self.SelectedElement is not None:
self.SelectedElement.Move(0, scaling[1])
self.SelectedElement.RefreshModel()
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(0, scaling[1])), False)
elif not self.Debug and keycode == wx.WXK_SPACE and self.SelectedElement is not None and self.SelectedElement.Dragging:
if self.IsBlock(self.SelectedElement) or self.IsComment(self.SelectedElement):
block = self.CopyBlock(self.SelectedElement, wx.Point(*self.SelectedElement.GetPosition()))
event = wx.MouseEvent()
event.m_x, event.m_y = self.Editor.ScreenToClient(wx.GetMousePosition())
dc = self.GetLogicalDC()
self.SelectedElement.OnLeftUp(event, dc, self.Scaling)
self.SelectedElement.SetSelected(False)
block.OnLeftDown(event, dc, self.Scaling)
self.SelectedElement = block
self.SelectedElement.SetSelected(True)
self.RefreshVariablePanel()
self.RefreshVisibleElements()
else:
event.Skip()
elif keycode == ord("+"):
self.SetScale(self.CurrentScale + 1)
self.ParentWindow.RefreshDisplayMenu()
elif keycode == ord("-"):
self.SetScale(self.CurrentScale - 1)
self.ParentWindow.RefreshDisplayMenu()
else:
event.Skip()
#-------------------------------------------------------------------------------
# Model adding functions from Drop Target
#-------------------------------------------------------------------------------
def AddVariableBlock(self, x, y, scaling, var_class, var_name, var_type):
id = self.GetNewId()
variable = FBD_Variable(self, var_class, var_name, var_type, id)
width, height = variable.GetMinSize()
if scaling is not None:
x = round(float(x) / float(scaling[0])) * scaling[0]
y = round(float(y) / float(scaling[1])) * scaling[1]
width = round(float(width) / float(scaling[0]) + 0.5) * scaling[0]
height = round(float(height) / float(scaling[1]) + 0.5) * scaling[1]
variable.SetPosition(x, y)
variable.SetSize(width, height)
self.AddBlock(variable)
self.Controler.AddEditedElementVariable(self.GetTagName(), id, var_class)
self.RefreshVariableModel(variable)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
self.Refresh(False)
#-------------------------------------------------------------------------------
# Model adding functions
#-------------------------------------------------------------------------------
def GetScaledSize(self, width, height):
if self.Scaling is not None:
width = round(float(width) / float(self.Scaling[0]) + 0.4) * self.Scaling[0]
height = round(float(height) / float(self.Scaling[1]) + 0.4) * self.Scaling[1]
return width, height
def AddNewBlock(self, bbox):
dialog = FBDBlockDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetBlockList(self.Controler.GetBlockTypes(self.TagName, self.Debug))
dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
dialog.SetPouElementNames(self.Controler.GetEditedElementVariables(self.TagName, self.Debug))
dialog.SetMinBlockSize((bbox.width, bbox.height))
if dialog.ShowModal() == wx.ID_OK:
id = self.GetNewId()
values = dialog.GetValues()
values.setdefault("name", "")
block = FBD_Block(self, values["type"], values["name"], id,
values["extension"], values["inputs"],
executionControl = values["executionControl"],
executionOrder = values["executionOrder"])
block.SetPosition(bbox.x, bbox.y)
block.SetSize(*self.GetScaledSize(values["width"], values["height"]))
self.AddBlock(block)
self.Controler.AddEditedElementBlock(self.TagName, id, values["type"], values.get("name", None))
self.RefreshBlockModel(block)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
self.RefreshVariablePanel()
self.ParentWindow.RefreshInstancesTree()
block.Refresh()
dialog.Destroy()
def AddNewVariable(self, bbox):
words = self.TagName.split("::")
if words[0] == "T":
dialog = FBDVariableDialog(self.ParentWindow, self.Controler, words[2])
else:
dialog = FBDVariableDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinVariableSize((bbox.width, bbox.height))
varlist = []
vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
if vars:
for var in vars:
if var["Edit"]:
varlist.append((var["Name"], var["Class"], var["Type"]))
returntype = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug)
if returntype:
varlist.append((self.Controler.GetEditedElementName(self.TagName), "Output", returntype))
dialog.SetVariables(varlist)
if dialog.ShowModal() == wx.ID_OK:
id = self.GetNewId()
values = dialog.GetValues()
variable = FBD_Variable(self, values["type"], values["name"], values["value_type"], id)
variable.SetPosition(bbox.x, bbox.y)
variable.SetSize(*self.GetScaledSize(values["width"], values["height"]))
self.AddBlock(variable)
self.Controler.AddEditedElementVariable(self.TagName, id, values["type"])
self.RefreshVariableModel(variable)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
variable.Refresh()
dialog.Destroy()
def AddNewConnection(self, bbox):
dialog = ConnectionDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
dialog.SetPouElementNames(self.Controler.GetEditedElementVariables(self.TagName, self.Debug))
dialog.SetMinConnectionSize((bbox.width, bbox.height))
if dialog.ShowModal() == wx.ID_OK:
id = self.GetNewId()
values = dialog.GetValues()
connection = FBD_Connector(self, values["type"], values["name"], id)
connection.SetPosition(bbox.x, bbox.y)
connection.SetSize(*self.GetScaledSize(values["width"], values["height"]))
self.AddBlock(connection)
self.Controler.AddEditedElementConnection(self.TagName, id, values["type"])
self.RefreshConnectionModel(connection)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
connection.Refresh()
dialog.Destroy()
def AddNewComment(self, bbox):
if wx.VERSION >= (2, 5, 0):
dialog = wx.TextEntryDialog(self.ParentWindow, _("Edit comment"), _("Please enter comment text"), "", wx.OK|wx.CANCEL|wx.TE_MULTILINE)
else:
dialog = wx.TextEntryDialog(self.ParentWindow, _("Edit comment"), _("Please enter comment text"), "", wx.OK|wx.CANCEL)
dialog.SetClientSize(wx.Size(400, 200))
if dialog.ShowModal() == wx.ID_OK:
value = dialog.GetValue()
id = self.GetNewId()
comment = Comment(self, value, id)
comment.SetPosition(bbox.x, bbox.y)
min_width, min_height = comment.GetMinSize()
comment.SetSize(*self.GetScaledSize(max(min_width,bbox.width),max(min_height,bbox.height)))
self.AddComment(comment)
self.Controler.AddEditedElementComment(self.TagName, id)
self.RefreshCommentModel(comment)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
comment.Refresh()
dialog.Destroy()
def AddNewContact(self, bbox):
dialog = LDElementDialog(self.ParentWindow, self.Controler, "contact")
dialog.SetPreviewFont(self.GetFont())
varlist = []
vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
if vars:
for var in vars:
if var["Type"] == "BOOL":
varlist.append(var["Name"])
dialog.SetVariables(varlist)
dialog.SetValues({"name":"","type":CONTACT_NORMAL})
dialog.SetElementSize((bbox.width, bbox.height))
if dialog.ShowModal() == wx.ID_OK:
id = self.GetNewId()
values = dialog.GetValues()
contact = LD_Contact(self, values["type"], values["name"], id)
contact.SetPosition(bbox.x, bbox.y)
contact.SetSize(*self.GetScaledSize(values["width"], values["height"]))
self.AddBlock(contact)
self.Controler.AddEditedElementContact(self.TagName, id)
self.RefreshContactModel(contact)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
contact.Refresh()
dialog.Destroy()
def AddNewCoil(self, bbox):
dialog = LDElementDialog(self.ParentWindow, self.Controler, "coil")
dialog.SetPreviewFont(self.GetFont())
varlist = []
vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
if vars:
for var in vars:
if var["Class"] != "Input" and var["Type"] == "BOOL":
varlist.append(var["Name"])
returntype = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug)
if returntype == "BOOL":
varlist.append(self.Controler.GetEditedElementName(self.TagName))
dialog.SetVariables(varlist)
dialog.SetValues({"name":"","type":COIL_NORMAL})
dialog.SetElementSize((bbox.width, bbox.height))
if dialog.ShowModal() == wx.ID_OK:
id = self.GetNewId()
values = dialog.GetValues()
coil = LD_Coil(self, values["type"], values["name"], id)
coil.SetPosition(bbox.x, bbox.y)
coil.SetSize(*self.GetScaledSize(values["width"], values["height"]))
self.AddBlock(coil)
self.Controler.AddEditedElementCoil(self.TagName, id)
self.RefreshCoilModel(coil)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
coil.Refresh()
dialog.Destroy()
def AddNewPowerRail(self, bbox):
dialog = LDPowerRailDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinSize((bbox.width, bbox.height))
if dialog.ShowModal() == wx.ID_OK:
id = self.GetNewId()
values = dialog.GetValues()
powerrail = LD_PowerRail(self, values["type"], id, values["number"])
powerrail.SetPosition(bbox.x, bbox.y)
powerrail.SetSize(*self.GetScaledSize(values["width"], values["height"]))
self.AddBlock(powerrail)
self.Controler.AddEditedElementPowerRail(self.TagName, id, values["type"])
self.RefreshPowerRailModel(powerrail)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
powerrail.Refresh()
dialog.Destroy()
def AddNewStep(self, bbox, initial = False):
dialog = SFCStepDialog(self.ParentWindow, self.Controler, initial)
dialog.SetPreviewFont(self.GetFont())
dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
dialog.SetVariables(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
dialog.SetStepNames([block.GetName() for block in self.Blocks.itervalues() if isinstance(block, SFC_Step)])
dialog.SetMinStepSize((bbox.width, bbox.height))
if dialog.ShowModal() == wx.ID_OK:
id = self.GetNewId()
values = dialog.GetValues()
step = SFC_Step(self, values["name"], initial, id)
if values["input"]:
step.AddInput()
else:
step.RemoveInput()
if values["output"]:
step.AddOutput()
else:
step.RemoveOutput()
if values["action"]:
step.AddAction()
else:
step.RemoveAction()
step.SetPosition(bbox.x, bbox.y)
min_width, min_height = step.GetMinSize()
step.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
self.AddBlock(step)
self.Controler.AddEditedElementStep(self.TagName, id)
self.RefreshStepModel(step)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
step.Refresh()
dialog.Destroy()
def AddNewTransition(self, bbox):
dialog = SFCTransitionDialog(self.ParentWindow, self.Controler, self.GetDrawingMode() == FREEDRAWING_MODE)
dialog.SetPreviewFont(self.GetFont())
dialog.SetTransitions(self.Controler.GetEditedElementTransitions(self.TagName, self.Debug))
if dialog.ShowModal() == wx.ID_OK:
id = self.GetNewId()
values = dialog.GetValues()
transition = SFC_Transition(self, values["type"], values["value"], values["priority"], id)
transition.SetPosition(bbox.x, bbox.y)
min_width, min_height = transition.GetMinSize()
transition.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
self.AddBlock(transition)
self.Controler.AddEditedElementTransition(self.TagName, id)
self.RefreshTransitionModel(transition)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
transition.Refresh()
dialog.Destroy()
def AddNewDivergence(self, bbox):
dialog = SFCDivergenceDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinSize((bbox.width, bbox.height))
if dialog.ShowModal() == wx.ID_OK:
id = self.GetNewId()
values = dialog.GetValues()
divergence = SFC_Divergence(self, values["type"], values["number"], id)
divergence.SetPosition(bbox.x, bbox.y)
min_width, min_height = divergence.GetMinSize(True)
divergence.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
self.AddBlock(divergence)
self.Controler.AddEditedElementDivergence(self.TagName, id, values["type"])
self.RefreshDivergenceModel(divergence)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
divergence.Refresh()
dialog.Destroy()
def AddNewJump(self, bbox):
choices = []
for block in self.Blocks.itervalues():
if isinstance(block, SFC_Step):
choices.append(block.GetName())
dialog = wx.SingleChoiceDialog(self.ParentWindow, _("Add a new jump"), _("Please choose a target"), choices, wx.OK|wx.CANCEL)
if dialog.ShowModal() == wx.ID_OK:
id = self.GetNewId()
value = dialog.GetStringSelection()
jump = SFC_Jump(self, value, id)
jump.SetPosition(bbox.x, bbox.y)
min_width, min_height = jump.GetMinSize()
jump.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
self.AddBlock(jump)
self.Controler.AddEditedElementJump(self.TagName, id)
self.RefreshJumpModel(jump)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
jump.Refresh()
dialog.Destroy()
def AddNewActionBlock(self, bbox):
dialog = ActionBlockDialog(self.ParentWindow)
dialog.SetQualifierList(self.Controler.GetQualifierTypes())
dialog.SetActionList(self.Controler.GetEditedElementActions(self.TagName, self.Debug))
dialog.SetVariableList(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
if dialog.ShowModal() == wx.ID_OK:
actions = dialog.GetValues()
id = self.GetNewId()
actionblock = SFC_ActionBlock(self, actions, id)
actionblock.SetPosition(bbox.x, bbox.y)
min_width, min_height = actionblock.GetMinSize()
actionblock.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
self.AddBlock(actionblock)
self.Controler.AddEditedElementActionBlock(self.TagName, id)
self.RefreshActionBlockModel(actionblock)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
actionblock.Refresh()
dialog.Destroy()
#-------------------------------------------------------------------------------
# Edit element content functions
#-------------------------------------------------------------------------------
def EditBlockContent(self, block):
dialog = FBDBlockDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetBlockList(self.Controler.GetBlockTypes(self.TagName, self.Debug))
dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
variable_names = self.Controler.GetEditedElementVariables(self.TagName, self.Debug)
if block.GetName() != "":
variable_names.remove(block.GetName())
dialog.SetPouElementNames(variable_names)
dialog.SetMinBlockSize(block.GetSize())
old_values = {"name" : block.GetName(),
"type" : block.GetType(),
"extension" : block.GetExtension(),
"inputs" : block.GetInputTypes(),
"executionControl" : block.GetExecutionControl(),
"executionOrder" : block.GetExecutionOrder()}
dialog.SetValues(old_values)
if dialog.ShowModal() == wx.ID_OK:
new_values = dialog.GetValues()
rect = block.GetRedrawRect(1, 1)
if "name" in new_values:
block.SetName(new_values["name"])
else:
block.SetName("")
block.SetSize(*self.GetScaledSize(new_values["width"], new_values["height"]))
block.SetType(new_values["type"], new_values["extension"], executionControl = new_values["executionControl"])
block.SetExecutionOrder(new_values["executionOrder"])
rect = rect.Union(block.GetRedrawRect())
self.RefreshBlockModel(block)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
self.RefreshVariablePanel()
self.ParentWindow.RefreshInstancesTree()
if old_values["executionOrder"] != new_values["executionOrder"]:
self.RefreshView()
else:
block.Refresh(rect)
dialog.Destroy()
def EditVariableContent(self, variable):
words = self.TagName.split("::")
if words[0] == "T":
dialog = FBDVariableDialog(self.ParentWindow, self.Controler, words[2])
else:
dialog = FBDVariableDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinVariableSize(variable.GetSize())
varlist = []
vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
if vars:
for var in vars:
if var["Edit"]:
varlist.append((var["Name"], var["Class"], var["Type"]))
returntype = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug)
if returntype:
varlist.append((self.Controler.GetEditedElementName(self.TagName), "Output", returntype))
dialog.SetVariables(varlist)
old_values = {"name" : variable.GetName(), "type" : variable.GetType(),
"executionOrder" : variable.GetExecutionOrder()}
dialog.SetValues(old_values)
if dialog.ShowModal() == wx.ID_OK:
new_values = dialog.GetValues()
rect = variable.GetRedrawRect(1, 1)
variable.SetName(new_values["name"])
variable.SetType(new_values["type"], new_values["value_type"])
variable.SetSize(*self.GetScaledSize(new_values["width"], new_values["height"]))
variable.SetExecutionOrder(new_values["executionOrder"])
rect = rect.Union(variable.GetRedrawRect())
if old_values["type"] != new_values["type"]:
id = variable.GetId()
self.Controler.RemoveEditedElementInstance(self.TagName, id)
self.Controler.AddEditedElementVariable(self.TagName, id, new_values["type"])
self.RefreshVariableModel(variable)
if old_values["executionOrder"] != new_values["executionOrder"]:
self.RefreshView()
self.RefreshBuffer()
self.RefreshVisibleElements()
self.RefreshScrollBars()
variable.Refresh(rect)
dialog.Destroy()
def EditConnectionContent(self, connection):
dialog = ConnectionDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
dialog.SetPouElementNames(self.Controler.GetEditedElementVariables(self.TagName, self.Debug))
dialog.SetMinConnectionSize(connection.GetSize())
values = {"name" : connection.GetName(), "type" : connection.GetType()}
dialog.SetValues(values)
if dialog.ShowModal() == wx.ID_OK:
old_type = connection.GetType()
values = dialog.GetValues()
rect = connection.GetRedrawRect(1, 1)
connection.SetName(values["name"])
connection.SetType(values["type"])
connection.SetSize(*self.GetScaledSize(values["width"], values["height"]))
rect = rect.Union(connection.GetRedrawRect())
if old_type != values["type"]:
id = connection.GetId()
self.Controler.RemoveEditedElementInstance(self.TagName, id)
self.Controler.AddEditedElementConnection(self.TagName, id, values["type"])
self.RefreshConnectionModel(connection)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
connection.Refresh(rect)
dialog.Destroy()
def EditContactContent(self, contact):
dialog = LDElementDialog(self.ParentWindow, self.Controler, "contact")
dialog.SetPreviewFont(self.GetFont())
varlist = []
vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
if vars:
for var in vars:
if var["Type"] == "BOOL":
varlist.append(var["Name"])
dialog.SetVariables(varlist)
values = {"name" : contact.GetName(), "type" : contact.GetType()}
dialog.SetValues(values)
dialog.SetElementSize(contact.GetSize())
if dialog.ShowModal() == wx.ID_OK:
values = dialog.GetValues()
rect = contact.GetRedrawRect(1, 1)
contact.SetName(values["name"])
contact.SetType(values["type"])
contact.SetSize(*self.GetScaledSize(values["width"], values["height"]))
rect = rect.Union(contact.GetRedrawRect())
self.RefreshContactModel(contact)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
contact.Refresh(rect)
dialog.Destroy()
def EditCoilContent(self, coil):
dialog = LDElementDialog(self.ParentWindow, self.Controler, "coil")
dialog.SetPreviewFont(self.GetFont())
varlist = []
vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
if vars:
for var in vars:
if var["Class"] != "Input" and var["Type"] == "BOOL":
varlist.append(var["Name"])
returntype = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug)
if returntype == "BOOL":
varlist.append(self.Controler.GetEditedElementName(self.TagName))
dialog.SetVariables(varlist)
values = {"name" : coil.GetName(), "type" : coil.GetType()}
dialog.SetValues(values)
dialog.SetElementSize(coil.GetSize())
if dialog.ShowModal() == wx.ID_OK:
values = dialog.GetValues()
rect = coil.GetRedrawRect(1, 1)
coil.SetName(values["name"])
coil.SetType(values["type"])
coil.SetSize(*self.GetScaledSize(values["width"], values["height"]))
rect = rect.Union(coil.GetRedrawRect())
self.RefreshCoilModel(coil)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
coil.Refresh(rect)
dialog.Destroy()
def EditPowerRailContent(self, powerrail):
connectors = powerrail.GetConnectors()
type = powerrail.GetType()
if type == LEFTRAIL:
pin_number = len(connectors["outputs"])
else:
pin_number = len(connectors["inputs"])
dialog = LDPowerRailDialog(self.ParentWindow, self.Controler, type, pin_number)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinSize(powerrail.GetSize())
if dialog.ShowModal() == wx.ID_OK:
old_type = powerrail.GetType()
values = dialog.GetValues()
rect = powerrail.GetRedrawRect(1, 1)
powerrail.SetType(values["type"], values["number"])
powerrail.SetSize(*self.GetScaledSize(values["width"], values["height"]))
rect = rect.Union(powerrail.GetRedrawRect())
if old_type != values["type"]:
id = powerrail.GetId()
self.Controler.RemoveEditedElementInstance(self.TagName, id)
self.Controler.AddEditedElementPowerRail(self.TagName, id, values["type"])
self.RefreshPowerRailModel(powerrail)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
powerrail.Refresh(rect)
dialog.Destroy()
def EditStepContent(self, step):
dialog = SFCStepDialog(self.ParentWindow, self.Controler, step.GetInitial())
dialog.SetPreviewFont(self.GetFont())
dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
dialog.SetVariables(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
dialog.SetStepNames([block.GetName() for block in self.Blocks.itervalues() if isinstance(block, SFC_Step) and block.GetName() != step.GetName()])
dialog.SetMinStepSize(step.GetSize())
values = {"name" : step.GetName()}
connectors = step.GetConnectors()
values["input"] = len(connectors["inputs"]) > 0
values["output"] = len(connectors["outputs"]) > 0
values["action"] = step.GetActionConnector() != None
dialog.SetValues(values)
if dialog.ShowModal() == wx.ID_OK:
values = dialog.GetValues()
rect = step.GetRedrawRect(1, 1)
step.SetName(values["name"])
if values["input"]:
step.AddInput()
else:
step.RemoveInput()
if values["output"]:
step.AddOutput()
else:
step.RemoveOutput()
if values["action"]:
step.AddAction()
else:
step.RemoveAction()
step.UpdateSize(*self.GetScaledSize(values["width"], values["height"]))
rect = rect.Union(step.GetRedrawRect())
self.RefreshStepModel(step)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
step.Refresh(rect)
def EditTransitionContent(self, transition):
dialog = SFCTransitionDialog(self.ParentWindow, self.Controler, self.GetDrawingMode() == FREEDRAWING_MODE)
dialog.SetPreviewFont(self.GetFont())
dialog.SetTransitions(self.Controler.GetEditedElementTransitions(self.TagName, self.Debug))
dialog.SetValues({"type":transition.GetType(),"value":transition.GetCondition(), "priority":transition.GetPriority()})
dialog.SetElementSize(transition.GetSize())
if dialog.ShowModal() == wx.ID_OK:
values = dialog.GetValues()
rect = transition.GetRedrawRect(1, 1)
transition.SetType(values["type"],values["value"])
transition.SetPriority(values["priority"])
rect = rect.Union(transition.GetRedrawRect())
self.RefreshTransitionModel(transition)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
transition.Refresh(rect)
dialog.Destroy()
def EditJumpContent(self, jump):
choices = []
for block in self.Blocks.itervalues():
if isinstance(block, SFC_Step):
choices.append(block.GetName())
dialog = wx.SingleChoiceDialog(self.ParentWindow, _("Edit jump target"), _("Please choose a target"), choices, wx.OK|wx.CANCEL)
dialog.SetSelection(choices.index(jump.GetTarget()))
if dialog.ShowModal() == wx.ID_OK:
value = dialog.GetStringSelection()
rect = jump.GetRedrawRect(1, 1)
jump.SetTarget(value)
rect = rect.Union(jump.GetRedrawRect())
self.RefreshJumpModel(jump)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
jump.Refresh(rect)
dialog.Destroy()
def EditActionBlockContent(self, actionblock):
dialog = ActionBlockDialog(self.ParentWindow)
dialog.SetQualifierList(self.Controler.GetQualifierTypes())
dialog.SetActionList(self.Controler.GetEditedElementActions(self.TagName, self.Debug))
dialog.SetVariableList(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
dialog.SetValues(actionblock.GetActions())
if dialog.ShowModal() == wx.ID_OK:
actions = dialog.GetValues()
rect = actionblock.GetRedrawRect(1, 1)
actionblock.SetActions(actions)
actionblock.SetSize(*self.GetScaledSize(*actionblock.GetSize()))
rect = rect.Union(actionblock.GetRedrawRect())
self.RefreshActionBlockModel(actionblock)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
actionblock.Refresh(rect)
dialog.Destroy()
def EditCommentContent(self, comment):
if wx.VERSION >= (2, 5, 0):
dialog = wx.TextEntryDialog(self.ParentWindow, _("Edit comment"), _("Please enter comment text"), comment.GetContent(), wx.OK|wx.CANCEL|wx.TE_MULTILINE)
else:
dialog = wx.TextEntryDialog(self.ParentWindow, _("Edit comment"), _("Please enter comment text"), comment.GetContent(), wx.OK|wx.CANCEL)
dialog.SetClientSize(wx.Size(400, 200))
if dialog.ShowModal() == wx.ID_OK:
value = dialog.GetValue()
rect = comment.GetRedrawRect(1, 1)
comment.SetContent(value)
comment.SetSize(*self.GetScaledSize(*comment.GetSize()))
rect = rect.Union(comment.GetRedrawRect())
self.RefreshCommentModel(comment)
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVisibleElements()
comment.Refresh(rect)
dialog.Destroy()
#-------------------------------------------------------------------------------
# Model update functions
#-------------------------------------------------------------------------------
def RefreshBlockModel(self, block):
blockid = block.GetId()
infos = {}
infos["type"] = block.GetType()
infos["name"] = block.GetName()
if self.CurrentLanguage == "FBD":
infos["executionOrder"] = block.GetExecutionOrder()
infos["x"], infos["y"] = block.GetPosition()
infos["width"], infos["height"] = block.GetSize()
infos["connectors"] = block.GetConnectors()
self.Controler.SetEditedElementBlockInfos(self.TagName, blockid, infos)
def RefreshVariableModel(self, variable):
variableid = variable.GetId()
infos = {}
infos["name"] = variable.GetName()
if self.CurrentLanguage == "FBD":
infos["executionOrder"] = variable.GetExecutionOrder()
infos["x"], infos["y"] = variable.GetPosition()
infos["width"], infos["height"] = variable.GetSize()
infos["connectors"] = variable.GetConnectors()
self.Controler.SetEditedElementVariableInfos(self.TagName, variableid, infos)
def RefreshConnectionModel(self, connection):
connectionid = connection.GetId()
infos = {}
infos["name"] = connection.GetName()
infos["x"], infos["y"] = connection.GetPosition()
infos["width"], infos["height"] = connection.GetSize()
infos["connector"] = connection.GetConnector()
self.Controler.SetEditedElementConnectionInfos(self.TagName, connectionid, infos)
def RefreshCommentModel(self, comment):
commentid = comment.GetId()
infos = {}
infos["content"] = comment.GetContent()
infos["x"], infos["y"] = comment.GetPosition()
infos["width"], infos["height"] = comment.GetSize()
self.Controler.SetEditedElementCommentInfos(self.TagName, commentid, infos)
def RefreshPowerRailModel(self, powerrail):
powerrailid = powerrail.GetId()
infos = {}
infos["x"], infos["y"] = powerrail.GetPosition()
infos["width"], infos["height"] = powerrail.GetSize()
infos["connectors"] = powerrail.GetConnectors()
self.Controler.SetEditedElementPowerRailInfos(self.TagName, powerrailid, infos)
def RefreshContactModel(self, contact):
contactid = contact.GetId()
infos = {}
infos["name"] = contact.GetName()
infos["type"] = contact.GetType()
infos["x"], infos["y"] = contact.GetPosition()
infos["width"], infos["height"] = contact.GetSize()
infos["connectors"] = contact.GetConnectors()
self.Controler.SetEditedElementContactInfos(self.TagName, contactid, infos)
def RefreshCoilModel(self, coil):
coilid = coil.GetId()
infos = {}
infos["name"] = coil.GetName()
infos["type"] = coil.GetType()
infos["x"], infos["y"] = coil.GetPosition()
infos["width"], infos["height"] = coil.GetSize()
infos["connectors"] = coil.GetConnectors()
self.Controler.SetEditedElementCoilInfos(self.TagName, coilid, infos)
def RefreshStepModel(self, step):
stepid = step.GetId()
infos = {}
infos["name"] = step.GetName()
infos["initial"] = step.GetInitial()
infos["x"], infos["y"] = step.GetPosition()
infos["width"], infos["height"] = step.GetSize()
infos["connectors"] = step.GetConnectors()
infos["action"] = step.GetActionConnector()
self.Controler.SetEditedElementStepInfos(self.TagName, stepid, infos)
def RefreshTransitionModel(self, transition):
transitionid = transition.GetId()
infos = {}
infos["type"] = transition.GetType()
infos["priority"] = transition.GetPriority()
infos["condition"] = transition.GetCondition()
infos["x"], infos["y"] = transition.GetPosition()
infos["width"], infos["height"] = transition.GetSize()
infos["connectors"] = transition.GetConnectors()
infos["connection"] = transition.GetConditionConnector()
self.Controler.SetEditedElementTransitionInfos(self.TagName, transitionid, infos)
def RefreshDivergenceModel(self, divergence):
divergenceid = divergence.GetId()
infos = {}
infos["x"], infos["y"] = divergence.GetPosition()
infos["width"], infos["height"] = divergence.GetSize()
infos["connectors"] = divergence.GetConnectors()
self.Controler.SetEditedElementDivergenceInfos(self.TagName, divergenceid, infos)
def RefreshJumpModel(self, jump):
jumpid = jump.GetId()
infos = {}
infos["target"] = jump.GetTarget()
infos["x"], infos["y"] = jump.GetPosition()
infos["width"], infos["height"] = jump.GetSize()
infos["connector"] = jump.GetConnector()
self.Controler.SetEditedElementJumpInfos(self.TagName, jumpid, infos)
def RefreshActionBlockModel(self, actionblock):
actionblockid = actionblock.GetId()
infos = {}
infos["actions"] = actionblock.GetActions()
infos["x"], infos["y"] = actionblock.GetPosition()
infos["width"], infos["height"] = actionblock.GetSize()
infos["connector"] = actionblock.GetConnector()
self.Controler.SetEditedElementActionBlockInfos(self.TagName, actionblockid, infos)
#-------------------------------------------------------------------------------
# Model delete functions
#-------------------------------------------------------------------------------
def DeleteBlock(self, block):
elements = []
for output in block.GetConnectors()["outputs"]:
for element in output.GetConnectedBlocks():
if element not in elements:
elements.append(element)
block.Clean()
self.RemoveBlock(block)
self.Controler.RemoveEditedElementInstance(self.TagName, block.GetId())
for element in elements:
element.RefreshModel()
wx.CallAfter(self.RefreshVariablePanel)
wx.CallAfter(self.ParentWindow.RefreshInstancesTree)
def DeleteVariable(self, variable):
connectors = variable.GetConnectors()
if len(connectors["outputs"]) > 0:
elements = connectors["outputs"][0].GetConnectedBlocks()
else:
elements = []
variable.Clean()
self.RemoveBlock(variable)
self.Controler.RemoveEditedElementInstance(self.TagName, variable.GetId())
for element in elements:
element.RefreshModel()
def DeleteConnection(self, connection):
if connection.GetType() == CONTINUATION:
elements = connection.GetConnector().GetConnectedBlocks()
else:
elements = []
connection.Clean()
self.RemoveBlock(connection)
self.Controler.RemoveEditedElementInstance(self.TagName, connection.GetId())
for element in elements:
element.RefreshModel()
def DeleteComment(self, comment):
self.RemoveComment(comment)
self.Controler.RemoveEditedElementInstance(self.TagName, comment.GetId())
def DeleteWire(self, wire):
if wire in self.Wires:
connected = wire.GetConnected()
wire.Clean()
self.RemoveWire(wire)
for connector in connected:
connector.RefreshParentBlock()
def DeleteContact(self, contact):
connectors = contact.GetConnectors()
elements = connectors["outputs"][0].GetConnectedBlocks()
contact.Clean()
self.RemoveBlock(contact)
self.Controler.RemoveEditedElementInstance(self.TagName, contact.GetId())
for element in elements:
element.RefreshModel()
def DeleteCoil(self, coil):
connectors = coil.GetConnectors()
elements = connectors["outputs"][0].GetConnectedBlocks()
coil.Clean()
self.RemoveBlock(coil)
self.Controler.RemoveEditedElementInstance(self.TagName, coil.GetId())
for element in elements:
element.RefreshModel()
def DeletePowerRail(self, powerrail):
elements = []
if powerrail.GetType() == LEFTRAIL:
connectors = powerrail.GetConnectors()
for connector in connectors["outputs"]:
for element in connector.GetConnectedBlocks():
if element not in elements:
elements.append(element)
powerrail.Clean()
self.RemoveBlock(powerrail)
self.Controler.RemoveEditedElementInstance(self.TagName, powerrail.GetId())
for element in elements:
element.RefreshModel()
def DeleteStep(self, step):
elements = []
connectors = step.GetConnectors()
action_connector = step.GetActionConnector()
if len(connectors["outputs"]) > 0:
for element in connectors["outputs"][0].GetConnectedBlocks():
if element not in elements:
elements.append(element)
if action_connector is not None:
for element in action_connector.GetConnectedBlocks():
if element not in elements:
elements.append(element)
step.Clean()
self.RemoveBlock(step)
self.Controler.RemoveEditedElementInstance(self.TagName, step.GetId())
for element in elements:
element.RefreshModel()
def DeleteTransition(self, transition):
elements = []
connectors = transition.GetConnectors()
for element in connectors["outputs"][0].GetConnectedBlocks():
if element not in elements:
elements.append(element)
transition.Clean()
self.RemoveBlock(transition)
self.Controler.RemoveEditedElementInstance(self.TagName, transition.GetId())
for element in elements:
element.RefreshModel()
def DeleteDivergence(self, divergence):
elements = []
connectors = divergence.GetConnectors()
for output in connectors["outputs"]:
for element in output.GetConnectedBlocks():
if element not in elements:
elements.append(element)
divergence.Clean()
self.RemoveBlock(divergence)
self.Controler.RemoveEditedElementInstance(self.TagName, divergence.GetId())
for element in elements:
element.RefreshModel()
def DeleteJump(self, jump):
jump.Clean()
self.RemoveBlock(jump)
self.Controler.RemoveEditedElementInstance(self.TagName, jump.GetId())
def DeleteActionBlock(self, actionblock):
actionblock.Clean()
self.RemoveBlock(actionblock)
self.Controler.RemoveEditedElementInstance(self.TagName, actionblock.GetId())
#-------------------------------------------------------------------------------
# Editing functions
#-------------------------------------------------------------------------------
def Cut(self):
if not self.Debug and (self.IsBlock(self.SelectedElement) or self.IsComment(self.SelectedElement) or isinstance(self.SelectedElement, Graphic_Group)):
blocks, wires = self.SelectedElement.GetDefinition()
text = self.Controler.GetEditedElementInstancesCopy(self.TagName, blocks, wires, self.Debug)
self.ParentWindow.SetCopyBuffer(text)
rect = self.SelectedElement.GetRedrawRect(1, 1)
self.SelectedElement.Delete()
self.SelectedElement = None
self.RefreshBuffer()
self.RefreshScrollBars()
self.RefreshVariablePanel()
self.ParentWindow.RefreshInstancesTree()
self.RefreshRect(self.GetScrolledRect(rect), False)
def Copy(self):
if not self.Debug and (self.IsBlock(self.SelectedElement) or self.IsComment(self.SelectedElement) or isinstance(self.SelectedElement, Graphic_Group)):
blocks, wires = self.SelectedElement.GetDefinition()
text = self.Controler.GetEditedElementInstancesCopy(self.TagName, blocks, wires, self.Debug)
self.ParentWindow.SetCopyBuffer(text)
def Paste(self):
if not self.Debug:
element = self.ParentWindow.GetCopyBuffer()
mouse_pos = self.Editor.ScreenToClient(wx.GetMousePosition())
middle = wx.Rect(0, 0, *self.Editor.GetClientSize()).InsideXY(mouse_pos.x, mouse_pos.y)
if middle:
x, y = self.CalcUnscrolledPosition(mouse_pos.x, mouse_pos.y)
else:
x, y = self.CalcUnscrolledPosition(0, 0)
new_pos = [int(x / self.ViewScale[0]), int(y / self.ViewScale[1])]
result = self.Controler.PasteEditedElementInstances(self.TagName, element, new_pos, middle, self.Debug)
if not isinstance(result, (StringType, UnicodeType)):
self.RefreshBuffer()
self.RefreshView(selection=result)
self.RefreshVariablePanel()
self.ParentWindow.RefreshInstancesTree()
else:
message = wx.MessageDialog(self.Editor, result, "Error", wx.OK|wx.ICON_ERROR)
message.ShowModal()
message.Destroy()
def CanAddElement(self, block):
if isinstance(block, Graphic_Group):
return block.CanAddBlocks(self)
elif self.CurrentLanguage == "SFC":
return True
elif self.CurrentLanguage == "LD" and not isinstance(block, (SFC_Step, SFC_Transition, SFC_Divergence, SFC_Jump, SFC_ActionBlock)):
return True
elif self.CurrentLanguage == "FBD" and isinstance(block, (FBD_Block, FBD_Variable, FBD_Connector, Comment)):
return True
return False
def GenerateNewName(self, element, exclude={}):
if isinstance(element, SFC_Step):
format = "Step%d"
else:
format = "Block%d"
return self.Controler.GenerateNewName(self.TagName, element.GetName(), format, exclude, self.Debug)
def IsNamedElement(self, element):
return isinstance(element, FBD_Block) and element.GetName() != "" or isinstance(element, SFC_Step)
def CopyBlock(self, element, pos):
id = self.GetNewId()
if isinstance(element, Graphic_Group):
block = element.Clone(self, pos=pos)
else:
if self.IsNamedElement(element):
name = self.GenerateNewName(element)
block = element.Clone(self, id, name, pos)
else:
name = None
block = element.Clone(self, id, pos=pos)
self.AddBlockInModel(block)
return block
def AddBlockInModel(self, block):
if isinstance(block, Comment):
self.AddComment(block)
self.Controler.AddEditedElementComment(self.TagName, block.GetId())
self.RefreshCommentModel(block)
else:
self.AddBlock(block)
if isinstance(block, FBD_Block):
self.Controler.AddEditedElementBlock(self.TagName, block.GetId(), block.GetType(), block.GetName())
self.RefreshBlockModel(block)
elif isinstance(block, FBD_Variable):
self.Controler.AddEditedElementVariable(self.TagName, block.GetId(), block.GetType())
self.RefreshVariableModel(block)
elif isinstance(block, FBD_Connector):
self.Controler.AddEditedElementConnection(self.TagName, block.GetId(), block.GetType())
self.RefreshConnectionModel(block)
elif isinstance(block, LD_Contact):
self.Controler.AddEditedElementContact(self.TagName, block.GetId())
self.RefreshContactModel(block)
elif isinstance(block, LD_Coil):
self.Controler.AddEditedElementCoil(self.TagName, block.GetId())
self.RefreshCoilModel(block)
elif isinstance(block, LD_PowerRail):
self.Controler.AddEditedElementPowerRail(self.TagName, block.GetId(), block.GetType())
self.RefreshPowerRailModel(block)
elif isinstance(block, SFC_Step):
self.Controler.AddEditedElementStep(self.TagName, block.GetId())
self.RefreshStepModel(block)
elif isinstance(block, SFC_Transition):
self.Controler.AddEditedElementTransition(self.TagName, block.GetId())
self.RefreshTransitionModel(block)
elif isinstance(block, SFC_Divergence):
self.Controler.AddEditedElementDivergence(self.TagName, block.GetId(), block.GetType())
self.RefreshDivergenceModel(block)
elif isinstance(block, SFC_Jump):
self.Controler.AddEditedElementJump(self.TagName, block.GetId())
self.RefreshJumpModel(block)
elif isinstance(block, SFC_ActionBlock):
self.Controler.AddEditedElementActionBlock(self.TagName, block.GetId())
self.RefreshActionBlockModel(block)
#-------------------------------------------------------------------------------
# Highlights showing functions
#-------------------------------------------------------------------------------
def OnRefreshHighlightsTimer(self, event):
self.RefreshView()
event.Skip()
def ClearHighlights(self, highlight_type=None):
if highlight_type is None:
self.Highlights = []
else:
self.Highlights = [(infos, start, end, highlight) for (infos, start, end, highlight) in self.Highlights if highlight != highlight_type]
self.RefreshView()
def AddHighlight(self, infos, start, end, highlight_type):
self.Highlights.append((infos, start, end, highlight_type))
self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
def ShowHighlights(self):
for infos, start, end, highlight_type in self.Highlights:
if infos[0] in ["comment", "io_variable", "block", "connector", "coil", "contact", "step", "transition", "jump", "action_block"]:
block = self.FindElementById(infos[1])
if block is not None:
block.AddHighlight(infos[2:], start, end, highlight_type)
#-------------------------------------------------------------------------------
# Drawing functions
#-------------------------------------------------------------------------------
def OnScrollWindow(self, event):
if event.GetOrientation() == wx.HORIZONTAL:
self.RefreshVisibleElements(xp = event.GetPosition())
else:
self.RefreshVisibleElements(yp = event.GetPosition())
event.Skip()
def OnScrollStop(self, event):
self.RefreshScrollBars()
event.Skip()
def OnMouseWheelWindow(self, event):
if self.StartMousePos is None or self.StartScreenPos is None:
rotation = event.GetWheelRotation() / event.GetWheelDelta()
if event.ShiftDown():
x, y = self.GetViewStart()
xp = max(0, min(x - rotation * 3, self.Editor.GetVirtualSize()[0] / self.Editor.GetScrollPixelsPerUnit()[0]))
self.RefreshVisibleElements(xp = xp)
self.Scroll(xp, y)
elif event.ControlDown():
dc = self.GetLogicalDC()
self.SetScale(self.CurrentScale + rotation, mouse_event = event)
self.ParentWindow.RefreshDisplayMenu()
else:
x, y = self.GetViewStart()
yp = max(0, min(y - rotation * 3, self.Editor.GetVirtualSize()[1] / self.Editor.GetScrollPixelsPerUnit()[1]))
self.RefreshVisibleElements(yp = yp)
self.Scroll(x, yp)
def OnMoveWindow(self, event):
self.Editor.GetBestSize()
self.RefreshScrollBars()
self.RefreshVisibleElements()
event.Skip()
def DoDrawing(self, dc, printing = False):
if printing:
if getattr(dc, "printing", False):
font = wx.Font(self.GetFont().GetPointSize(), wx.MODERN, wx.NORMAL, wx.NORMAL)
dc.SetFont(font)
else:
dc.SetFont(self.GetFont())
else:
dc.SetBackground(wx.Brush(self.Editor.GetBackgroundColour()))
dc.Clear()
dc.BeginDrawing()
if self.Scaling is not None and self.DrawGrid and not printing:
dc.SetPen(wx.TRANSPARENT_PEN)
dc.SetBrush(self.GridBrush)
xstart, ystart = self.GetViewStart()
window_size = self.Editor.GetClientSize()
width, height = self.Editor.GetVirtualSize()
width = int(max(width, xstart * SCROLLBAR_UNIT + window_size[0]) / self.ViewScale[0])
height = int(max(height, ystart * SCROLLBAR_UNIT + window_size[1]) / self.ViewScale[1])
dc.DrawRectangle(1, 1, width, height)
if self.PageSize is not None and not printing:
dc.SetPen(self.PagePen)
xstart, ystart = self.GetViewStart()
window_size = self.Editor.GetClientSize()
for x in xrange(self.PageSize[0] - (xstart * SCROLLBAR_UNIT) % self.PageSize[0], int(window_size[0] / self.ViewScale[0]), self.PageSize[0]):
dc.DrawLine(xstart * SCROLLBAR_UNIT + x + 1, int(ystart * SCROLLBAR_UNIT / self.ViewScale[0]),
xstart * SCROLLBAR_UNIT + x + 1, int((ystart * SCROLLBAR_UNIT + window_size[1]) / self.ViewScale[0]))
for y in xrange(self.PageSize[1] - (ystart * SCROLLBAR_UNIT) % self.PageSize[1], int(window_size[1] / self.ViewScale[1]), self.PageSize[1]):
dc.DrawLine(int(xstart * SCROLLBAR_UNIT / self.ViewScale[0]), ystart * SCROLLBAR_UNIT + y + 1,
int((xstart * SCROLLBAR_UNIT + window_size[0]) / self.ViewScale[1]), ystart * SCROLLBAR_UNIT + y + 1)
# Draw all elements
for comment in self.Comments.itervalues():
if comment != self.SelectedElement and (comment.IsVisible() or printing):
comment.Draw(dc)
for wire in self.Wires.iterkeys():
if wire != self.SelectedElement and (wire.IsVisible() or printing):
if not self.Debug or wire.GetValue() != True:
wire.Draw(dc)
if self.Debug:
for wire in self.Wires.iterkeys():
if wire != self.SelectedElement and (wire.IsVisible() or printing) and wire.GetValue() == True:
wire.Draw(dc)
for block in self.Blocks.itervalues():
if block != self.SelectedElement and (block.IsVisible() or printing):
block.Draw(dc)
if self.SelectedElement is not None and (self.SelectedElement.IsVisible() or printing):
self.SelectedElement.Draw(dc)
if not printing:
if self.Debug:
xstart, ystart = self.GetViewStart()
dc.DrawText(_("Debug: %s") % self.InstancePath, 2, 2)
if self.rubberBand.IsShown():
self.rubberBand.Draw(dc)
dc.EndDrawing()
def OnPaint(self, event):
dc = self.GetLogicalDC(True)
self.DoDrawing(dc)
wx.BufferedPaintDC(self.Editor, dc.GetAsBitmap())
if self.Debug:
DebugViewer.RefreshNewData(self)
event.Skip()