def updateVisableRectsAndReturnUpdateRegion(self): """ Updates the self.visibleWidgets list if necessary based on the current scroll position. :return: The update region that would need to be redrawn """ # Determine visible passages updateRect = self.GetUpdateRegion().GetBox() scrollPos = (self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)) if self.visibleWidgets is None or scrollPos != self.lastScrollPos: self.lastScrollPos = scrollPos updateRect = self.GetClientRect() displayArrows = self.app.config.ReadBool('displayArrows') imageArrows = self.app.config.ReadBool('imageArrows') self.visibleWidgets = [ widget for widget in self.widgetDict.itervalues() # It's visible if it's in the client rect, or is being moved. if (widget.dimmed or updateRect.Intersects(widget.getPixelRect()) # It's also visible if an arrow FROM it intersects with the Client Rect or [ w2 for w2 in widget.getConnectedWidgets( displayArrows, imageArrows) if geometry.lineRectIntersection( widget.getConnectorLine(w2, clipped=False), updateRect) ]) ] return updateRect
def paintConnectorTo(self, otherWidget, arrowheads, color, width, gc, updateRect = None): """ Paints a connecting line between this widget and another, with optional arrowheads. You may pass either a wx.GraphicsContext (anti-aliased drawing) or a wx.PaintDC. """ start, end = self.getConnectorLine(otherWidget) # does it actually need to be drawn? if otherWidget == self: return if updateRect and not geometry.lineRectIntersection([start, end], updateRect): return # ok, really draw the line lineWidth = max(self.parent.toPixels((width, 0), scaleOnly = True)[0], 1) gc.SetPen(wx.Pen(color, lineWidth)) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(start[0], start[1], end[0], end[1]) else: gc.DrawLine(start[0], start[1], end[0], end[1]) # arrowheads at end if not arrowheads: return flat = self.app.config.ReadBool('flatDesign') arrowheadLength = max(self.parent.toPixels((PassageWidget.ARROWHEAD_LENGTH, 0), scaleOnly = True)[0], 1) arrowhead = geometry.endPointProjectedFrom((start, end), angle = PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if flat: pass elif isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1]) arrowhead2 = geometry.endPointProjectedFrom((start, end), angle = 0 - PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if flat: gc.SetBrush(wx.Brush(color)) if isinstance(gc, wx.GraphicsContext): gc.DrawLines([wx.Point2D(*arrowhead2), wx.Point2D(*end), wx.Point2D(*arrowhead) ]) else: gc.DrawPolygon([wx.Point(*arrowhead2), wx.Point(*end), wx.Point(*arrowhead)]) elif isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead2[0], arrowhead2[1]) else: gc.DrawLine(end[0], end[1], arrowhead2[0], arrowhead2[1])
def paintConnectorTo(self, otherWidget, arrowheads, gc, updateRect=None): """ Paints a connecting line between this widget and another, with optional arrowheads. You may pass either a wx.GraphicsContext (anti-aliased drawing) or a wx.PaintDC. """ start = self.parent.toPixels(self.getCenter()) end = self.parent.toPixels(otherWidget.getCenter()) start, end = geometry.clipLineByRects([start, end], otherWidget.getPixelRect()) # does it actually need to be drawn? if updateRect and not geometry.lineRectIntersection([start, end], updateRect): return if otherWidget == self: return # ok, really draw the line lineWidth = max( self.parent.toPixels((PassageWidget.CONNECTOR_WIDTH, 0), scaleOnly=True)[0], 1) gc.SetPen(wx.Pen(PassageWidget.CONNECTOR_COLOR, lineWidth)) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(start[0], start[1], end[0], end[1]) else: gc.DrawLine(start[0], start[1], end[0], end[1]) # arrowheads at end if not arrowheads: return arrowheadLength = max( self.parent.toPixels((PassageWidget.ARROWHEAD_LENGTH, 0), scaleOnly=True)[0], 1) arrowhead = geometry.endPointProjectedFrom((start, end), angle = PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1]) arrowhead = geometry.endPointProjectedFrom((start, end), angle = 0 - PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1])
def paintConnectorTo (self, otherWidget, arrowheads, color, gc, updateRect = None): """ Paints a connecting line between this widget and another, with optional arrowheads. You may pass either a wx.GraphicsContext (anti-aliased drawing) or a wx.PaintDC. """ start = self.parent.toPixels(self.getCenter()) end = self.parent.toPixels(otherWidget.getCenter()) start, end = geometry.clipLineByRects([start, end], otherWidget.getPixelRect()) # does it actually need to be drawn? if updateRect and not geometry.lineRectIntersection([start, end], updateRect): return if otherWidget == self: return # ok, really draw the line lineWidth = max(self.parent.toPixels((PassageWidget.CONNECTOR_WIDTH, 0), scaleOnly = True)[0], 1) gc.SetPen(wx.Pen(color, lineWidth)) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(start[0], start[1], end[0], end[1]) else: gc.DrawLine(start[0], start[1], end[0], end[1]) # arrowheads at end if not arrowheads: return arrowheadLength = max(self.parent.toPixels((PassageWidget.ARROWHEAD_LENGTH, 0), scaleOnly = True)[0], 1) arrowhead = geometry.endPointProjectedFrom((start, end), angle = PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1]) arrowhead = geometry.endPointProjectedFrom((start, end), angle = 0 - PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1])
def getConnectorTo(self, otherWidget, arrowheads=False, updateRect=None): # does it actually need to be drawn? if otherWidget == self: return [], [] start, end = self.getConnectorLine(otherWidget) if updateRect and not geometry.lineRectIntersection([start, end], updateRect): return [], [] line = [[start[0], start[1]], [end[0], end[1]]] if not arrowheads: return line, [] else: length = max(self.parent.toPixels((PassageWidget.ARROWHEAD_LENGTH, 0), scaleOnly=True)[0], 1) arrowheadr = geometry.endPointProjectedFrom((start, end), PassageWidget.ARROWHEAD_ANGLE, length) arrowheadl = geometry.endPointProjectedFrom((start, end), 0 - PassageWidget.ARROWHEAD_ANGLE, length) return line, [(arrowheadl, end, arrowheadr)]
def updateVisableRectsAndReturnUpdateRegion(self): """ Updates the self.visibleWidgets list if necessary based on the current scroll position. :return: The update region that would need to be redrawn """ # Determine visible passages updateRect = self.GetUpdateRegion().GetBox() scrollPos = (self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)) if self.visibleWidgets == None or scrollPos != self.lastScrollPos: self.lastScrollPos = scrollPos updateRect = self.GetClientRect() self.visibleWidgets = [widget for widget in self.widgetDict.itervalues() # It's visible if it's in the client rect, or is being moved. if (widget.dimmed or updateRect.Intersects(widget.getPixelRect()) # It's also visible if an arrow FROM it intersects with the Client Rect or [w2 for w2 in widget.getConnectedWidgets() if geometry.lineRectIntersection(w2.getConnectorLine(widget), updateRect)])] return updateRect
def getConnectorTo(self, otherWidget, arrowheads=False, updateRect=None): # does it actually need to be drawn? if otherWidget == self: return [], [] start, end = self.getConnectorLine(otherWidget) if updateRect and not geometry.lineRectIntersection([start, end], updateRect): return [], [] line = [[start[0], start[1]], [end[0], end[1]]] if not arrowheads: return line, [] else: length = max( self.parent.toPixels((PassageWidget.ARROWHEAD_LENGTH, 0), scaleOnly=True)[0], 1) arrowheadr = geometry.endPointProjectedFrom( (start, end), PassageWidget.ARROWHEAD_ANGLE, length) arrowheadl = geometry.endPointProjectedFrom( (start, end), 0 - PassageWidget.ARROWHEAD_ANGLE, length) return line, [(arrowheadl, end, arrowheadr)]
def paintConnectorTo(self, otherWidget, arrowheads, color, width, gc, updateRect = None): """ Paints a connecting line between this widget and another, with optional arrowheads. You may pass either a wx.GraphicsContext (anti-aliased drawing) or a wx.PaintDC. """ start = self.parent.toPixels(self.getCenter()) end = self.parent.toPixels(otherWidget.getCenter()) # Additional tweak to make overlapping arrows more visible length = min(math.sqrt((start[0]-end[0])**2 + (start[1]-end[1])**2)/32, 16) if start[1] != end[1]: start[0] += length * math.copysign(1, start[1] - end[1]); end[0] += length * math.copysign(1, start[1] - end[1]); if start[0] != end[0]: start[1] += length * math.copysign(1, start[0] - end[0]); end[1] += length * math.copysign(1, start[0] - end[0]); # Clip the end of the arrow start, end = geometry.clipLineByRects([start, end], otherWidget.getPixelRect()) # does it actually need to be drawn? if otherWidget == self: return if updateRect and not geometry.lineRectIntersection([start, end], updateRect): return # ok, really draw the line lineWidth = max(self.parent.toPixels((width, 0), scaleOnly = True)[0], 1) gc.SetPen(wx.Pen(color, lineWidth)) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(start[0], start[1], end[0], end[1]) else: gc.DrawLine(start[0], start[1], end[0], end[1]) # arrowheads at end if not arrowheads: return arrowheadLength = max(self.parent.toPixels((PassageWidget.ARROWHEAD_LENGTH, 0), scaleOnly = True)[0], 1) arrowhead = geometry.endPointProjectedFrom((start, end), angle = PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1]) arrowhead = geometry.endPointProjectedFrom((start, end), angle = 0 - PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1])
def paint(self, event): """Paints marquee selection, widget connectors, and widgets onscreen.""" # do NOT call self.DoPrepareDC() no matter what the docs may say # we already take into account our scroll origin in our # toPixels() method # in fast drawing, we ask for a standard paint context # in slow drawing, we ask for a anti-aliased one # # OS X already double buffers drawing for us; if we try to do it # ourselves, performance is horrendous if (sys.platform == 'darwin'): gc = wx.PaintDC(self) else: gc = wx.BufferedPaintDC(self) updateRect = self.GetUpdateRegion().GetBox() # Determine visible passages scrollPos = (self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)) if self.visibleWidgets == None or scrollPos != self.lastScrollPos: self.lastScrollPos = scrollPos updateRect = self.GetClientRect() self.visibleWidgets = [widget for widget in self.widgets # It's visible if it's in the client rect, or is being moved. if (widget.dimmed or updateRect.Intersects(widget.getPixelRect()) # It's also visible if an arrow FROM it intersects with the Client Rect or [w2 for w2 in widget.getConnectedWidgets() if geometry.lineRectIntersection(w2.getConnectorLine(widget), updateRect)])] # background gc.SetBrush(wx.Brush(StoryPanel.FLAT_BG_COLOR if self.app.config.ReadBool('flatDesign') else StoryPanel.BACKGROUND_COLOR )) gc.DrawRectangle(updateRect.x - 1, updateRect.y - 1, updateRect.width + 2, updateRect.height + 2) # connectors arrowheads = (self.scale > StoryPanel.ARROWHEAD_THRESHOLD) for widget in self.visibleWidgets: if not widget.dimmed: widget.paintConnectors(gc, arrowheads, updateRect) for widget in self.visibleWidgets: # Could be "visible" only insofar as its arrow is visible if updateRect.Intersects(widget.getPixelRect()): widget.paint(gc) # marquee selection # with slow drawing, use alpha blending for interior if self.draggingMarquee: if self.app.config.ReadBool('fastStoryPanel'): gc.SetPen(wx.Pen('#ffffff', 1, wx.DOT)) gc.SetBrush(wx.Brush(wx.WHITE, wx.TRANSPARENT)) else: gc = wx.GraphicsContext.Create(gc) marqueeColor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) gc.SetPen(wx.Pen(marqueeColor)) r, g, b = marqueeColor.Get(False) marqueeColor = wx.Colour(r, g, b, StoryPanel.MARQUEE_ALPHA) gc.SetBrush(wx.Brush(marqueeColor)) gc.DrawRectangle(self.dragRect.x, self.dragRect.y, self.dragRect.width, self.dragRect.height)
def paintConnectorTo(self, otherWidget, arrowheads, color, width, gc, updateRect=None): """ Paints a connecting line between this widget and another, with optional arrowheads. You may pass either a wx.GraphicsContext (anti-aliased drawing) or a wx.PaintDC. """ start, end = self.getConnectorLine(otherWidget) # does it actually need to be drawn? if otherWidget == self: return if updateRect and not geometry.lineRectIntersection([start, end], updateRect): return # ok, really draw the line lineWidth = max(self.parent.toPixels((width, 0), scaleOnly=True)[0], 1) gc.SetPen(wx.Pen(color, lineWidth)) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(start[0], start[1], end[0], end[1]) else: gc.DrawLine(start[0], start[1], end[0], end[1]) # arrowheads at end if not arrowheads: return flat = self.app.config.ReadBool('flatDesign') arrowheadLength = max( self.parent.toPixels((PassageWidget.ARROWHEAD_LENGTH, 0), scaleOnly=True)[0], 1) arrowhead = geometry.endPointProjectedFrom((start, end), angle = PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if flat: pass elif isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1]) arrowhead2 = geometry.endPointProjectedFrom((start, end), angle = 0 - PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if flat: gc.SetBrush(wx.Brush(color)) if isinstance(gc, wx.GraphicsContext): gc.DrawLines([ wx.Point2D(*arrowhead2), wx.Point2D(*end), wx.Point2D(*arrowhead) ]) else: gc.DrawPolygon([ wx.Point(*arrowhead2), wx.Point(*end), wx.Point(*arrowhead) ]) elif isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead2[0], arrowhead2[1]) else: gc.DrawLine(end[0], end[1], arrowhead2[0], arrowhead2[1])
def paintConnectorTo(self, otherWidget, arrowheads, color, width, gc, updateRect=None): """ Paints a connecting line between this widget and another, with optional arrowheads. You may pass either a wx.GraphicsContext (anti-aliased drawing) or a wx.PaintDC. """ start = self.parent.toPixels(self.getCenter()) end = self.parent.toPixels(otherWidget.getCenter()) # Additional tweak to make overlapping arrows more visible length = min( math.sqrt((start[0] - end[0])**2 + (start[1] - end[1])**2) / 32, 16) if start[1] != end[1]: start[0] += length * math.copysign(1, start[1] - end[1]) end[0] += length * math.copysign(1, start[1] - end[1]) if start[0] != end[0]: start[1] += length * math.copysign(1, start[0] - end[0]) end[1] += length * math.copysign(1, start[0] - end[0]) # Clip the end of the arrow start, end = geometry.clipLineByRects([start, end], otherWidget.getPixelRect()) # does it actually need to be drawn? if otherWidget == self: return if updateRect and not geometry.lineRectIntersection([start, end], updateRect): return # ok, really draw the line lineWidth = max(self.parent.toPixels((width, 0), scaleOnly=True)[0], 1) gc.SetPen(wx.Pen(color, lineWidth)) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(start[0], start[1], end[0], end[1]) else: gc.DrawLine(start[0], start[1], end[0], end[1]) # arrowheads at end if not arrowheads: return arrowheadLength = max( self.parent.toPixels((PassageWidget.ARROWHEAD_LENGTH, 0), scaleOnly=True)[0], 1) arrowhead = geometry.endPointProjectedFrom((start, end), angle = PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1]) arrowhead = geometry.endPointProjectedFrom((start, end), angle = 0 - PassageWidget.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1])
def paint(self, event): """Paints marquee selection, widget connectors, and widgets onscreen.""" # do NOT call self.DoPrepareDC() no matter what the docs may say # we already take into account our scroll origin in our # toPixels() method # in fast drawing, we ask for a standard paint context # in slow drawing, we ask for a anti-aliased one # # OS X already double buffers drawing for us; if we try to do it # ourselves, performance is horrendous if (sys.platform == 'darwin'): gc = wx.PaintDC(self) else: gc = wx.BufferedPaintDC(self) updateRect = self.GetUpdateRegion().GetBox() # Determine visible passages scrollPos = (self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)) if self.visibleWidgets == None or scrollPos != self.lastScrollPos: self.lastScrollPos = scrollPos updateRect = self.GetClientRect() self.visibleWidgets = [ widget for widget in self.widgets # It's visible if it's in the client rect, or is being moved. if (widget.dimmed or updateRect.Intersects(widget.getPixelRect()) # It's also visible if an arrow FROM it intersects with the Client Rect or [ w2 for w2 in widget.getConnectedWidgets() if geometry.lineRectIntersection( w2.getConnectorLine(widget), updateRect) ]) ] # background gc.SetBrush( wx.Brush(StoryPanel.FLAT_BG_COLOR if self.app.config. ReadBool('flatDesign') else StoryPanel.BACKGROUND_COLOR)) gc.DrawRectangle(updateRect.x - 1, updateRect.y - 1, updateRect.width + 2, updateRect.height + 2) # connectors arrowheads = (self.scale > StoryPanel.ARROWHEAD_THRESHOLD) for widget in self.visibleWidgets: if not widget.dimmed: widget.paintConnectors(gc, arrowheads, updateRect) for widget in self.visibleWidgets: # Could be "visible" only insofar as its arrow is visible if updateRect.Intersects(widget.getPixelRect()): widget.paint(gc) # marquee selection # with slow drawing, use alpha blending for interior if self.draggingMarquee: if self.app.config.ReadBool('fastStoryPanel'): gc.SetPen(wx.Pen('#ffffff', 1, wx.DOT)) gc.SetBrush(wx.Brush(wx.WHITE, wx.TRANSPARENT)) else: gc = wx.GraphicsContext.Create(gc) marqueeColor = wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT) gc.SetPen(wx.Pen(marqueeColor)) r, g, b = marqueeColor.Get(False) marqueeColor = wx.Colour(r, g, b, StoryPanel.MARQUEE_ALPHA) gc.SetBrush(wx.Brush(marqueeColor)) gc.DrawRectangle(self.dragRect.x, self.dragRect.y, self.dragRect.width, self.dragRect.height)
def paint (self, event): """Paints marquee selection, widget connectors, and widgets onscreen.""" # do NOT call self.DoPrepareDC() no matter what the docs may say # we already take into account our scroll origin in our # toPixels() method # in fast drawing, we ask for a standard paint context # in slow drawing, we ask for a anti-aliased one # # OS X already double buffers drawing for us; if we try to do it # ourselves, performance is horrendous if (sys.platform == 'darwin'): gc = wx.PaintDC(self) else: gc = wx.BufferedPaintDC(self) if not self.app.config.ReadBool('fastStoryPanel'): gc = wx.GraphicsContext.Create(gc) # background updateRect = self.GetUpdateRegion().GetBox() gc.SetBrush(wx.Brush(StoryPanel.BACKGROUND_COLOR)) gc.DrawRectangle(updateRect.x - 1, updateRect.y - 1, updateRect.width + 2, updateRect.height + 2) # connectors arrowheadLength = max(self.toPixels((StoryPanel.ARROWHEAD_LENGTH, 0), scaleOnly = True)[0], \ StoryPanel.MIN_ARROWHEAD_LENGTH) gc.SetPen(wx.Pen(StoryPanel.CONNECTOR_COLOR, max(self.toPixels((StoryPanel.CONNECTOR_WIDTH, 0), \ scaleOnly = True)[0], 1))) # cache bad links so we don't have to keep doing worst-case lookups badLinks = [] for widget in self.widgets: if widget.dimmed: continue start = self.toPixels(widget.getCenter()) for link in widget.passage.links(): if link in badLinks: continue otherWidget = self.findWidget(link) if not otherWidget: badLinks.append(link) if otherWidget and not otherWidget.dimmed: # connector line end = self.toPixels(otherWidget.getCenter()) # does it actually need to be drawn? if not geometry.lineRectIntersection([start, end], updateRect): continue # ok, really draw the line if self.scale > StoryPanel.ARROWHEAD_THRESHOLD: start, end = geometry.clipLineByRects([start, end], otherWidget.getPixelRect()) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(start[0], start[1], end[0], end[1]) else: gc.DrawLine(start[0], start[1], end[0], end[1]) # arrowheads at end if self.scale < StoryPanel.ARROWHEAD_THRESHOLD: continue arrowhead = geometry.endPointProjectedFrom((start, end), angle = StoryPanel.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1]) arrowhead = geometry.endPointProjectedFrom((start, end), angle = 0 - StoryPanel.ARROWHEAD_ANGLE, \ distance = arrowheadLength) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(end[0], end[1], arrowhead[0], arrowhead[1]) else: gc.DrawLine(end[0], end[1], arrowhead[0], arrowhead[1]) # widgets for widget in self.widgets: if updateRect.Intersects(widget.getPixelRect()): widget.paint(gc) # marquee selection # with slow drawing, use alpha blending for interior if self.draggingMarquee: if self.app.config.ReadBool('fastStoryPanel'): gc.SetPen(wx.Pen('#ffffff', 1, wx.DOT)) else: marqueeColor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) gc.SetPen(wx.Pen(marqueeColor)) r, g, b = marqueeColor.Get() marqueeColor = wx.Color(r, g, b, StoryPanel.MARQUEE_ALPHA) gc.SetBrush(wx.Brush(marqueeColor)) gc.DrawRectangle(self.dragRect.x, self.dragRect.y, self.dragRect.width, self.dragRect.height)