# HG changeset patch # User greg # Date 1243696522 -7200 # Node ID 62570186dad4d064fea531759de4de129b8514dc # Parent 072f9f8306593d84d3b4b50c754e043018778929 Adding support for synchronize refreshing with tick and limit it to a defined period diff -r 072f9f830659 -r 62570186dad4 GraphicViewer.py --- a/GraphicViewer.py Thu May 28 08:10:18 2009 +0200 +++ b/GraphicViewer.py Sat May 30 17:15:22 2009 +0200 @@ -24,6 +24,7 @@ import wx import wx.lib.plot as plot +from graphics.GraphicCommons import DebugViewer colours = ['blue', 'red', 'green', 'yellow', 'orange', 'purple', 'brown', 'cyan', @@ -44,7 +45,7 @@ ID_GRAPHICVIEWERSTATICTEXT1, ID_GRAPHICVIEWERSTATICTEXT2, ] = [wx.NewId() for _init_ctrls in range(8)] -class GraphicViewer(wx.Panel): +class GraphicViewer(wx.Panel, DebugViewer): def _init_coll_MainGridSizer_Items(self, parent): # generated method, don't edit @@ -145,7 +146,8 @@ def __init__(self, parent, window, controler, instancepath = ""): self._init_ctrls(parent) - + DebugViewer.__init__(self, controler, True, False) + self.ParentWindow = window self.Controler = controler self.InstancePath = instancepath @@ -154,35 +156,41 @@ self.CurrentValue = 0 self.CurrentRange = 25 - self.Controler.SubscribeDebugIECVariable(self.InstancePath.upper(), self) + self.AddDataConsumer(self.InstancePath.upper(), self) def __del__(self): - self.Controler.UnsubscribeDebugIECVariable(self.InstancePath.upper(), self) + DebugViewer.__del__(self) + self.RemoveDataConsumer(self) def ResetView(self): self.Datas = [] self.CurrentValue = 0 self.RefreshView() - def RefreshView(self): - var_name = self.InstancePath.split(".")[-1] - - self.VariableGraphic = plot.PolyLine(self.Datas[self.CurrentValue:self.CurrentValue + self.CurrentRange], - legend=var_name, colour=colours[0]) - self.GraphicsObject = plot.PlotGraphics([self.VariableGraphic], "%s Graphics" % var_name, "Tick", "Values") - datas_length = len(self.Datas) - if datas_length > 1: - start = self.Datas[self.CurrentValue][0] - if self.CurrentValue + self.CurrentRange > datas_length: - end = start + (self.Datas[datas_length - 1][0] - start) * self.CurrentRange / (datas_length - self.CurrentValue - 1) + def RefreshNewData(self): + self.RefreshView(False) + + def RefreshView(self, force=True): + self.Freeze() + if force or self.CurrentValue + self.CurrentRange == len(self.Datas) or self.CurrentValue + len(self.Datas) < self.CurrentRange: + var_name = self.InstancePath.split(".")[-1] + + self.VariableGraphic = plot.PolyLine(self.Datas[self.CurrentValue:self.CurrentValue + self.CurrentRange], + legend=var_name, colour=colours[0]) + self.GraphicsObject = plot.PlotGraphics([self.VariableGraphic], "%s Graphics" % var_name, "Tick", "Values") + datas_length = len(self.Datas) + if datas_length > 1: + start = self.Datas[self.CurrentValue][0] + if self.CurrentValue + self.CurrentRange > datas_length: + end = start + (self.Datas[datas_length - 1][0] - start) * self.CurrentRange / (datas_length - self.CurrentValue - 1) + else: + end = self.Datas[self.CurrentValue + self.CurrentRange - 1][0] else: - end = self.Datas[self.CurrentValue + self.CurrentRange - 1][0] - else: - start = 0. - end = 25. - self.Canvas.Draw(self.GraphicsObject, xAxis=(start, end)) - + start = 0. + end = 25. + self.Canvas.Draw(self.GraphicsObject, xAxis=(start, end)) self.RefreshScrollBar() + self.Thaw() def SetMode(self, mode): pass @@ -205,17 +213,12 @@ def SelectAll(self): pass - def AddPoint(self, tick, value): - if self: - self.Datas.append((float(tick), {True:1., False:0.}.get(value, float(value)))) - if self.CurrentValue + self.CurrentRange == len(self.Datas) - 1: - self.CurrentValue += 1 - self.RefreshView() - elif len(self.Datas) < self.CurrentValue + self.CurrentRange: - self.RefreshView() - else: - self.RefreshScrollBar() - + def NewValue(self, tick, value): + self.Datas.append((float(tick), {True:1., False:0.}.get(value, float(value)))) + if self.CurrentValue + self.CurrentRange == len(self.Datas) - 1: + self.CurrentValue += 1 + self.NewDataAvailable() + def RefreshScrollBar(self): self.CanvasPosition.SetScrollbar(self.CurrentValue, self.CurrentRange, len(self.Datas), self.CurrentRange) diff -r 072f9f830659 -r 62570186dad4 PLCOpenEditor.py --- a/PLCOpenEditor.py Thu May 28 08:10:18 2009 +0200 +++ b/PLCOpenEditor.py Sat May 30 17:15:22 2009 +0200 @@ -1295,6 +1295,8 @@ if selected != -1: window = self.TabsOpened.GetPage(selected) window.SetScale(idx) + window.RefreshVisibleElements() + window.RefreshScrollBars() event.Skip() return ZoomFunction @@ -4534,9 +4536,10 @@ # Variables Editor Panel #------------------------------------------------------------------------------- -class VariableTableItem: +class VariableTableItem(DebugDataConsumer): def __init__(self, parent, variable, value): + DebugDataConsumer.__init__(self) self.Parent = parent self.Variable = variable self.Value = value @@ -4553,12 +4556,12 @@ return self.Variable def SetValue(self, value): - if self.Parent and self.Value != value: + if self.Value != value: self.Value = value - self.Parent.RefreshGrid() + self.Parent.NewDataAvailable() def GetValue(self): - return self.Value + return self.Value class DebugVariableTable(wx.grid.PyGridTableBase): @@ -4716,10 +4719,10 @@ [ID_DEBUGVARIABLEPANEL, ID_DEBUGVARIABLEPANELVARIABLESGRID, ID_DEBUGVARIABLEPANELUPBUTTON, ID_DEBUGVARIABLEPANELDOWNBUTTON, - ID_DEBUGVARIABLEPANELDELETEBUTTON, + ID_DEBUGVARIABLEPANELDELETEBUTTON, ] = [wx.NewId() for _init_ctrls in range(5)] -class DebugVariablePanel(wx.Panel): +class DebugVariablePanel(wx.Panel, DebugViewer): if wx.VERSION < (2, 6, 0): def Bind(self, event, function, id = None): @@ -4786,9 +4789,10 @@ def __init__(self, parent, controler): self._init_ctrls(parent) + DebugViewer.__init__(self, controler, True) self.Controler = controler - self.Table = DebugVariableTable(self, [], ["Variable", "Value"]) + self.Table = DebugVariableTable(self, [], ["Variable", "Value"]) self.VariablesGrid.SetTable(self.Table) self.VariablesGrid.SetRowLabelSize(0) @@ -4797,20 +4801,21 @@ attr.SetAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTER) self.VariablesGrid.SetColAttr(col, attr) self.VariablesGrid.SetColSize(col, 100) - + self.Table.ResetView(self.VariablesGrid) - def __del__(self): - for item in self.Table.GetData(): - self.Controler.UnsubscribeDebugIECVariable(item.GetVariable().upper(), item) + def RefreshNewData(self): + self.RefreshGrid() def RefreshGrid(self): + self.Freeze() self.Table.ResetView(self.VariablesGrid) + self.Thaw() def OnDeleteButton(self, event): idx = self.VariablesGrid.GetGridCursorRow() item = self.Table.GetItem(idx) - self.Controler.UnsubscribeDebugIECVariable(item.GetVariable().upper(), item) + self.RemoveDataConsumer(item) self.Table.RemoveItem(idx) self.RefreshGrid() event.Skip() @@ -4828,7 +4833,7 @@ if iec_path == item.GetVariable(): return item = VariableTableItem(self, iec_path, "") - result = self.Controler.SubscribeDebugIECVariable(iec_path.upper(), item) + result = self.AddDataConsumer(iec_path.upper(), item) if result is not None: self.Table.InsertItem(idx, item) self.RefreshGrid() diff -r 072f9f830659 -r 62570186dad4 Viewer.py --- a/Viewer.py Thu May 28 08:10:18 2009 +0200 +++ b/Viewer.py Sat May 30 17:15:22 2009 +0200 @@ -234,7 +234,7 @@ manipulating graphic elements """ -class Viewer(wx.ScrolledWindow): +class Viewer(wx.ScrolledWindow, DebugViewer): if wx.VERSION < (2, 6, 0): def Bind(self, event, function, id = None): @@ -344,6 +344,7 @@ def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""): wx.ScrolledWindow.__init__(self, parent, pos=wx.Point(0, 0), size=wx.Size(0, 0), style=wx.HSCROLL | wx.VSCROLL | wx.ALWAYS_SHOW_SB) + DebugViewer.__init__(self, controler, debug) self._init_menus() # Adding a rubberband to Viewer self.rubberBand = RubberBand(drawingSurface=self) @@ -359,7 +360,6 @@ self.current_id = 0 self.TagName = tagname self.Errors = [] - self.Debug = debug self.InstancePath = instancepath self.StartMousePos = None self.StartScreenPos = None @@ -378,6 +378,8 @@ if not self.Debug: self.SetDropTarget(ViewerDropTarget(self)) + self.NewDataRefreshRect = None + dc = wx.ClientDC(self) font = wx.Font(faces["size"], wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["mono"]) dc.SetFont(font) @@ -388,6 +390,8 @@ 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.SetScale(len(ZOOM_FACTORS) / 2) @@ -442,6 +446,7 @@ # Destructor def __del__(self): + DebugViewer.__del__(self) self.Flush() self.ResetView() @@ -467,10 +472,12 @@ dc.SetUserScale(self.ViewScale[0], self.ViewScale[1]) return dc + def GetMiniTextExtent(self, text): + return self.MiniTextDC.GetTextExtent(text) + def GetMiniFont(self): - font = self.GetFont() - return wx.Font(font.GetPointSize() * 0.75, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["helv"]) - + return self.MiniTextDC.GetFont() + #------------------------------------------------------------------------------- # Element management functions #------------------------------------------------------------------------------- @@ -549,7 +556,7 @@ 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(element, (LD_Contact, LD_Coil)): + 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()) @@ -574,8 +581,7 @@ self.HighlightedElement = None def Flush(self): - for element, iec_path in self.Subscribed.iteritems(): - self.Controler.UnsubscribeDebugIECVariable(iec_path, element) + self.DeleteDataConsumers() for block in self.Blocks: block.Flush() @@ -643,6 +649,18 @@ # Refresh functions #------------------------------------------------------------------------------- + def UpdateRefreshRect(self, refresh_rect): + if self.NewDataRefreshRect is None: + self.NewDataRefreshRect = refresh_rect + else: + self.NewDataRefreshRect.Union(refresh_rect) + + def RefreshNewData(self): + if self.NewDataRefreshRect is not None: + refresh_rect, self.NewDataRefreshRect = self.NewDataRefreshRect, None + self.RefreshRect(self.GetScrolledRect(refresh_rect), False) + DebugViewer.RefreshNewData(self) + def ResetBuffer(self): pass @@ -679,15 +697,11 @@ 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) - if self.Controler.SubscribeDebugIECVariable(iec_path.upper(), wire) is not None: - self.Subscribed[wire] = iec_path.upper() - else: + if self.AddDataConsumer(iec_path.upper(), wire) is None: wire.SetValue("undefined") elif isinstance(block, FBD_Variable): iec_path = "%s.%s"%(self.InstancePath, block.GetName()) - if self.Controler.SubscribeDebugIECVariable(iec_path.upper(), wire) is not None: - self.Subscribed[wire] = iec_path.upper() - else: + if self.AddDataConsumer(iec_path.upper(), wire) is None: wire.SetValue("undefined") elif isinstance(block, FBD_Connector): wire.SetValue("undefined") @@ -697,10 +711,8 @@ block.SpreadCurrent() iec_path = self.GetElementIECPath(block) if iec_path is not None: - result = self.Controler.SubscribeDebugIECVariable(iec_path.upper(), block) - if result is not None: - self.Subscribed[block] = iec_path.upper() - + self.AddDataConsumer(iec_path.upper(), block) + self.RefreshVisibleElements() self.ShowErrors() self.Refresh(False) @@ -2687,7 +2699,7 @@ names.update(dict([(varname.upper(), True) for varname in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)])) format = "Block%d" elif isinstance(element, SFC_Step): - names.update(dict([block.GetName().upper() for block in self.Blocks if isinstance(block, SFC_Step)])) + names.update(dict([(block.GetName().upper(), True) for block in self.Blocks if isinstance(block, SFC_Step)])) format = "Step%d" i = 1 while names.get((format%i).upper(), False): diff -r 072f9f830659 -r 62570186dad4 graphics/GraphicCommons.py --- a/graphics/GraphicCommons.py Thu May 28 08:10:18 2009 +0200 +++ b/graphics/GraphicCommons.py Sat May 30 17:15:22 2009 +0200 @@ -23,6 +23,7 @@ #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import wx +import time from math import * from types import * @@ -188,6 +189,98 @@ #------------------------------------------------------------------------------- +# Debug Data Consumer Class +#------------------------------------------------------------------------------- + +class DebugDataConsumer: + + def __init__(self): + self.LastValue = None + self.Value = None + self.Inhibited = False + + def Inhibit(self, inhibit): + self.Inhibited = inhibit + if inhibit and self.LastValue is not None: + self.SetValue(self.LastValue) + self.LastValue = None + + def NewValue(self, tick, value): + if self.Inhibited: + self.LastValue = value + else: + self.SetValue(value) + + def SetValue(self, value): + self.Value = value + +#------------------------------------------------------------------------------- +# Debug Viewer Class +#------------------------------------------------------------------------------- + +REFRESH_PERIOD = 0.1 + +class DebugViewer: + + def __init__(self, producer, debug, register_tick=True): + self.DataProducer = producer + self.Debug = debug + + self.DataConsumers = {} + + self.LastRefreshTime = time.time() + + if register_tick: + self.DataProducer.SubscribeDebugIECVariable("__tick__", self) + + self.RefreshTimer = wx.Timer(self, -1) + self.Bind(wx.EVT_TIMER, self.OnRefreshTimer, self.RefreshTimer) + + def __del__(self): + self.DataProducer.UnsubscribeDebugIECVariable("__tick__", self) + self.DeleteDataConsumers() + self.RefreshTimer.Stop() + + def Inhibit(self, inhibit): + for consumer, iec_path in self.DataConsumers.iteritems(): + consumer.Inhibit(inhibit) + + def AddDataConsumer(self, iec_path, consumer): + result = self.DataProducer.SubscribeDebugIECVariable(iec_path, consumer) is not None + if result is not None and consumer != self: + self.DataConsumers[consumer] = iec_path + return result + + def RemoveDataConsumer(self, consumer): + iec_path = self.DataConsumers.pop(consumer, None) + if iec_path is not None: + self.DataProducer.UnsubscribeDebugIECVariable(iec_path, consumer) + + def DeleteDataConsumers(self): + for consumer, iec_path in self.DataConsumers.iteritems(): + self.DataProducer.UnsubscribeDebugIECVariable(iec_path, consumer) + self.DataConsumers = {} + + def OnRefreshTimer(self, event): + self.RefreshNewData() + event.Skip() + + def NewDataAvailable(self): + self.Inhibit(True) + current_time = time.time() + if current_time - self.LastRefreshTime > REFRESH_PERIOD: + self.LastRefreshTime = current_time + wx.CallAfter(self.RefreshViewOnNewData) + + def RefreshViewOnNewData(self): + if self: + self.RefreshNewData() + self.RefreshTimer.Start(int(REFRESH_PERIOD * 1000), oneShot=True) + + def RefreshNewData(self): + self.Inhibit(False) + +#------------------------------------------------------------------------------- # Viewer Rubberband #------------------------------------------------------------------------------- @@ -293,7 +386,7 @@ self.currentBox.height) #------------------------------------------------------------------------------- -# Viewer Rubberband +# Viewer ToolTip #------------------------------------------------------------------------------- """ @@ -312,10 +405,14 @@ def SetTip(self, tip): self.Tip = tip - dc = wx.ClientDC(self) - w, h = dc.GetTextExtent(tip) - self.SetSize(wx.Size(w + 4, h + 4)) - self.Refresh() + wx.CallAfter(self.RefreshTip) + + def RefreshTip(self): + if self: + dc = wx.ClientDC(self) + w, h = dc.GetTextExtent(self.Tip) + self.SetSize(wx.Size(w + 4, h + 4)) + self.Refresh() def OnPaint(self, event): dc = wx.AutoBufferedPaintDC(self) @@ -1433,11 +1530,12 @@ Class that implements a wire for connecting two blocks """ -class Wire(Graphic_Element): +class Wire(Graphic_Element, DebugDataConsumer): # Create a new wire def __init__(self, parent, start = None, end = None): Graphic_Element.__init__(self, parent) + DebugDataConsumer.__init__(self) self.StartPoint = start self.EndPoint = end self.StartConnected = None @@ -1451,14 +1549,12 @@ self.Segments = [] self.SelectedSegment = None self.Valid = True - self.Value = None self.ValueSize = None self.ComputedValue = None self.OverStart = False self.OverEnd = False self.ComputingType = False self.ToolTip = None - self.Font = parent.GetMiniFont() def Flush(self): self.StartConnected = None @@ -1492,7 +1588,6 @@ rect = rect.Union(self.EndConnected.GetRedrawRect(movex, movey)) if self.ValueSize is not None: width, height = self.ValueSize - width, height = self.ValueSize if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4: x = self.Points[0].x + width * self.StartPoint[1][0] / 2 y = self.Points[0].y + (height * self.StartPoint[1][1] - 1) / 2 @@ -1624,7 +1719,7 @@ return False def SetValue(self, value): - if self.Value != value and self.Parent: + if self.Value != value: self.Value = value if value is not None and not isinstance(value, BooleanType): if isinstance(value, StringType): @@ -1636,16 +1731,14 @@ if len(self.ComputedValue) > 4: self.ComputedValue = self.ComputedValue[:4] + "..." if isinstance(self.ComputedValue, StringType): - dc = wx.ClientDC(self.Parent) - dc.SetFont(self.Font) - self.ValueSize = dc.GetTextExtent(self.ComputedValue) + self.ValueSize = self.Parent.GetMiniTextExtent(self.ComputedValue) else: self.ValueSize = None if self.StartConnected: self.StartConnected.RefreshValue() if self.EndConnected: self.EndConnected.RefreshValue() - self.Refresh() + self.Parent.UpdateRefreshRect(self.GetRedrawRect()) if isinstance(value, BooleanType) and self.StartConnected is not None: block = self.StartConnected.GetParentBlock() block.SpreadCurrent() @@ -2514,7 +2607,7 @@ if self.SelectedSegment == len(self.Segments) - 1: dc.DrawPoint(self.Points[-1].x, self.Points[-1].y) if self.Value is not None and not isinstance(self.Value, BooleanType) and self.Value != "undefined": - dc.SetFont(self.Font) + dc.SetFont(self.Parent.GetMiniFont()) dc.SetTextForeground(wx.NamedColour("purple")) width, height = self.ValueSize if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4: diff -r 072f9f830659 -r 62570186dad4 graphics/LD_Objects.py --- a/graphics/LD_Objects.py Thu May 28 08:10:18 2009 +0200 +++ b/graphics/LD_Objects.py Sat May 30 17:15:22 2009 +0200 @@ -379,11 +379,12 @@ Class that implements the graphic representation of a contact """ -class LD_Contact(Graphic_Element): +class LD_Contact(Graphic_Element, DebugDataConsumer): # Create a new contact def __init__(self, parent, type, name, id = None): Graphic_Element.__init__(self, parent) + DebugDataConsumer.__init__(self) self.Type = type self.Name = name self.Id = id @@ -392,7 +393,6 @@ # Create an input and output connector self.Input = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] / 2 + 1), WEST) self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] / 2 + 1), EAST) - self.Value = None self.PreviousValue = False self.PreviousSpreading = False self.RefreshNameSize() @@ -410,7 +410,7 @@ self.PreviousValue = self.Value self.Value = value if self.Value != self.PreviousValue: - self.Refresh() + self.Parent.UpdateRefreshRect(self.GetRedrawRect()) self.SpreadCurrent() def SpreadCurrent(self): @@ -717,7 +717,7 @@ elif not self.Value and self.PreviousValue: self.Output.SpreadCurrent(False) if self.Value != self.PreviousValue: - self.Refresh() + self.Parent.UpdateRefreshRect(self.GetRedrawRect()) # Make a clone of this LD_Coil def Clone(self, parent, id = None, pos = None): diff -r 072f9f830659 -r 62570186dad4 graphics/SFC_Objects.py --- a/graphics/SFC_Objects.py Thu May 28 08:10:18 2009 +0200 +++ b/graphics/SFC_Objects.py Sat May 30 17:15:22 2009 +0200 @@ -41,11 +41,12 @@ Class that implements the graphic representation of a step """ -class SFC_Step(Graphic_Element): +class SFC_Step(Graphic_Element, DebugDataConsumer): # Create a new step def __init__(self, parent, name, initial = False, id = None): Graphic_Element.__init__(self, parent) + DebugDataConsumer.__init__(self) self.SetName(name) self.Initial = initial self.Id = id @@ -58,7 +59,6 @@ self.Input = None self.Output = None self.Action = None - self.Value = None self.PreviousValue = None self.PreviousSpreading = False @@ -77,7 +77,7 @@ self.PreviousValue = self.Value self.Value = value if self.Value != self.PreviousValue: - self.Refresh() + self.Parent.UpdateRefreshRect(self.GetRedrawRect()) self.SpreadCurrent() def SpreadCurrent(self): @@ -547,11 +547,12 @@ Class that implements the graphic representation of a transition """ -class SFC_Transition(Graphic_Element): +class SFC_Transition(Graphic_Element, DebugDataConsumer): # Create a new transition def __init__(self, parent, type = "reference", condition = None, priority = 0, id = None): Graphic_Element.__init__(self, parent) + DebugDataConsumer.__init__(self) self.Type = None self.Id = id self.Priority = 0 @@ -562,7 +563,6 @@ self.SetType(type, condition) self.SetPriority(priority) self.Errors = {} - self.Value = None self.PreviousValue = None self.PreviousSpreading = False @@ -581,7 +581,7 @@ self.PreviousValue = self.Value self.Value = value if self.Value != self.PreviousValue: - self.Refresh() + self.Parent.UpdateRefreshRect(self.GetRedrawRect()) self.SpreadCurrent() def SpreadCurrent(self): @@ -1029,11 +1029,11 @@ else: self.Value = False if self.Value and not self.PreviousValue: - self.Refresh() + self.Parent.UpdateRefreshRect(self.GetRedrawRect()) for output in self.Outputs: output.SpreadCurrent(True) elif not self.Value and self.PreviousValue: - self.Refresh() + self.Parent.UpdateRefreshRect(self.GetRedrawRect()) for output in self.Outputs: output.SpreadCurrent(False) @@ -1469,7 +1469,7 @@ self.PreviousValue = self.Value self.Value = self.Input.ReceivingCurrent() if self.Value != self.PreviousValue: - self.Refresh() + self.Parent.UpdateRefreshRect(self.GetRedrawRect()) # Make a clone of this SFC_Jump def Clone(self, parent, id = None, pos = None): @@ -1714,7 +1714,7 @@ self.PreviousValue = self.Value self.Value = self.Input.ReceivingCurrent() if self.Value != self.PreviousValue: - self.Refresh() + self.Parent.UpdateRefreshRect(self.GetRedrawRect()) # Make a clone of this SFC_ActionBlock def Clone(self, parent, id = None, pos = None):