X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ec873c943d71f0d5f13e3398557071448cda6c23..a4027e74873007e3430af3bd77019bcab76f6c04:/wxPython/wx/lib/ogl/_lines.py?ds=inline diff --git a/wxPython/wx/lib/ogl/_lines.py b/wxPython/wx/lib/ogl/_lines.py deleted file mode 100644 index 77ce392cac..0000000000 --- a/wxPython/wx/lib/ogl/_lines.py +++ /dev/null @@ -1,1527 +0,0 @@ -# -*- coding: iso-8859-1 -*- -#---------------------------------------------------------------------------- -# Name: lines.py -# Purpose: LineShape class -# -# Author: Pierre Hjälm (from C++ original by Julian Smart) -# -# Created: 2004-05-08 -# RCS-ID: $Id$ -# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart -# Licence: wxWindows license -#---------------------------------------------------------------------------- - -import sys -import math - -from _basic import Shape, ShapeRegion, ShapeTextLine, ControlPoint, RectangleShape -from _oglmisc import * - -# Line alignment flags -# Vertical by default -LINE_ALIGNMENT_HORIZ = 1 -LINE_ALIGNMENT_VERT = 0 -LINE_ALIGNMENT_TO_NEXT_HANDLE = 2 -LINE_ALIGNMENT_NONE = 0 - - - -class LineControlPoint(ControlPoint): - def __init__(self, theCanvas = None, object = None, size = 0.0, x = 0.0, y = 0.0, the_type = 0): - ControlPoint.__init__(self, theCanvas, object, size, x, y, the_type) - self._xpos = x - self._ypos = y - self._type = the_type - self._point = None - self._originalPos = None - - def OnDraw(self, dc): - RectangleShape.OnDraw(self, dc) - - # Implement movement of Line point - def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0): - self._shape.GetEventHandler().OnSizingDragLeft(self, draw, x, y, keys, attachment) - - def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0): - self._shape.GetEventHandler().OnSizingBeginDragLeft(self, x, y, keys, attachment) - - def OnEndDragLeft(self, x, y, keys = 0, attachment = 0): - self._shape.GetEventHandler().OnSizingEndDragLeft(self, x, y, keys, attachment) - - - -class ArrowHead(object): - def __init__(self, type = 0, end = 0, size = 0.0, dist = 0.0, name = "", mf = None, arrowId = -1): - if isinstance(type, ArrowHead): - pass - else: - self._arrowType = type - self._arrowEnd = end - self._arrowSize = size - self._xOffset = dist - self._yOffset = 0.0 - self._spacing = 5.0 - - self._arrowName = name - self._metaFile = mf - self._id = arrowId - if self._id == -1: - self._id = wx.NewId() - - def _GetType(self): - return self._arrowType - - def GetPosition(self): - return self._arrowEnd - - def SetPosition(self, pos): - self._arrowEnd = pos - - def GetXOffset(self): - return self._xOffset - - def GetYOffset(self): - return self._yOffset - - def GetSpacing(self): - return self._spacing - - def GetSize(self): - return self._arrowSize - - def SetSize(self, size): - self._arrowSize = size - if self._arrowType == ARROW_METAFILE and self._metaFile: - oldWidth = self._metaFile._width - if oldWidth == 0: - return - - scale = float(size) / oldWidth - if scale != 1: - self._metaFile.Scale(scale, scale) - - def GetName(self): - return self._arrowName - - def SetXOffset(self, x): - self._xOffset = x - - def SetYOffset(self, y): - self._yOffset = y - - def GetMetaFile(self): - return self._metaFile - - def GetId(self): - return self._id - - def GetArrowEnd(self): - return self._arrowEnd - - def GetArrowSize(self): - return self._arrowSize - - def SetSpacing(self, sp): - self._spacing = sp - - - -class LabelShape(RectangleShape): - def __init__(self, parent, region, w, h): - RectangleShape.__init__(self, w, h) - self._lineShape = parent - self._shapeRegion = region - self.SetPen(wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)) - - def OnDraw(self, dc): - if self._lineShape and not self._lineShape.GetDrawHandles(): - return - - x1 = self._xpos - self._width / 2.0 - y1 = self._ypos - self._height / 2.0 - - if self._pen: - if self._pen.GetWidth() == 0: - dc.SetPen(wx.Pen(wx.WHITE, 1, wx.TRANSPARENT)) - else: - dc.SetPen(self._pen) - dc.SetBrush(wx.TRANSPARENT_BRUSH) - - if self._cornerRadius > 0: - dc.DrawRoundedRectangle(x1, y1, self._width, self._height, self._cornerRadius) - else: - dc.DrawRectangle(x1, y1, self._width, self._height) - - def OnDrawContents(self, dc): - pass - - def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0): - RectangleShape.OnDragLeft(self, draw, x, y, keys, attachment) - - def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0): - RectangleShape.OnBeginDragLeft(self, x, y, keys, attachment) - - def OnEndDragLeft(self, x, y, keys = 0, attachment = 0): - RectangleShape.OnEndDragLeft(self, x, y, keys, attachment) - - def OnMovePre(self, dc, x, y, old_x, old_y, display): - return self._lineShape.OnLabelMovePre(dc, self, x, y, old_x, old_y, display) - - # Divert left and right clicks to line object - def OnLeftClick(self, x, y, keys = 0, attachment = 0): - self._lineShape.GetEventHandler().OnLeftClick(x, y, keys, attachment) - - def OnRightClick(self, x, y, keys = 0, attachment = 0): - self._lineShape.GetEventHandler().OnRightClick(x, y, keys, attachment) - - - -class LineShape(Shape): - """LineShape may be attached to two nodes; - it may be segmented, in which case a control point is drawn for each joint. - - A wxLineShape may have arrows at the beginning, end and centre. - - Derived from: - Shape - """ - def __init__(self): - Shape.__init__(self) - - self._sensitivity = OP_CLICK_LEFT | OP_CLICK_RIGHT - self._draggable = False - self._attachmentTo = 0 - self._attachmentFrom = 0 - self._from = None - self._to = None - self._erasing = False - self._arrowSpacing = 5.0 - self._ignoreArrowOffsets = False - self._isSpline = False - self._maintainStraightLines = False - self._alignmentStart = 0 - self._alignmentEnd = 0 - - self._lineControlPoints = None - - # Clear any existing regions (created in an earlier constructor) - # and make the three line regions. - self.ClearRegions() - for name in ["Middle","Start","End"]: - newRegion = ShapeRegion() - newRegion.SetName(name) - newRegion.SetSize(150, 50) - self._regions.append(newRegion) - - self._labelObjects = [None, None, None] - self._lineOrientations = [] - self._lineControlPoints = [] - self._arcArrows = [] - - def GetFrom(self): - """Return the 'from' object.""" - return self._from - - def GetTo(self): - """Return the 'to' object.""" - return self._to - - def GetAttachmentFrom(self): - """Return the attachment point on the 'from' node.""" - return self._attachmentFrom - - def GetAttachmentTo(self): - """Return the attachment point on the 'to' node.""" - return self._attachmentTo - - def GetLineControlPoints(self): - return self._lineControlPoints - - def SetSpline(self, spline): - """Specifies whether a spline is to be drawn through the control points.""" - self._isSpline = spline - - def IsSpline(self): - """TRUE if a spline is drawn through the control points.""" - return self._isSpline - - def SetAttachmentFrom(self, attach): - """Set the 'from' shape attachment.""" - self._attachmentFrom = attach - - def SetAttachmentTo(self, attach): - """Set the 'to' shape attachment.""" - self._attachmentTo = attach - - # This is really to distinguish between lines and other images. - # For lines, want to pass drag to canvas, since lines tend to prevent - # dragging on a canvas (they get in the way.) - def Draggable(self): - return False - - def SetIgnoreOffsets(self, ignore): - """Set whether to ignore offsets from the end of the line when drawing.""" - self._ignoreArrowOffsets = ignore - - def GetArrows(self): - return self._arcArrows - - def GetAlignmentStart(self): - return self._alignmentStart - - def GetAlignmentEnd(self): - return self._alignmentEnd - - def IsEnd(self, nodeObject): - """TRUE if shape is at the end of the line.""" - return self._to == nodeObject - - def MakeLineControlPoints(self, n): - """Make a given number of control points (minimum of two).""" - self._lineControlPoints = [] - - for _ in range(n): - point = wx.RealPoint(-999, -999) - self._lineControlPoints.append(point) - - # pi: added _initialised to keep track of when we have set - # the middle points to something other than (-999, -999) - self._initialised = False - - def InsertLineControlPoint(self, dc = None, point = None): - """Insert a control point at an optional given position.""" - if dc: - self.Erase(dc) - - if point: - line_x, line_y = point - else: - last_point = self._lineControlPoints[-1] - second_last_point = self._lineControlPoints[-2] - - line_x = (last_point[0] + second_last_point[0]) / 2.0 - line_y = (last_point[1] + second_last_point[1]) / 2.0 - - point = wx.RealPoint(line_x, line_y) - self._lineControlPoints.insert(len(self._lineControlPoints)-1, point) - - def DeleteLineControlPoint(self): - """Delete an arbitary point on the line.""" - if len(self._lineControlPoints) < 3: - return False - - del self._lineControlPoints[-2] - return True - - def Initialise(self): - """Initialise the line object.""" - if self._lineControlPoints: - # Just move the first and last control points - first_point = self._lineControlPoints[0] - last_point = self._lineControlPoints[-1] - - # If any of the line points are at -999, we must - # initialize them by placing them half way between the first - # and the last. - - for i in range(1,len(self._lineControlPoints)): - point = self._lineControlPoints[i] - if point[0] == -999: - if first_point[0] < last_point[0]: - x1 = first_point[0] - x2 = last_point[0] - else: - x2 = first_point[0] - x1 = last_point[0] - if first_point[1] < last_point[1]: - y1 = first_point[1] - y2 = last_point[1] - else: - y2 = first_point[1] - y1 = last_point[1] - self._lineControlPoints[i] = wx.RealPoint((x2 - x1) / 2.0 + x1, (y2 - y1) / 2.0 + y1) - self._initialised = True - - def FormatText(self, dc, s, i): - """Format a text string according to the region size, adding - strings with positions to region text list. - """ - self.ClearText(i) - - if len(self._regions) == 0 or i >= len(self._regions): - return - - region = self._regions[i] - region.SetText(s) - dc.SetFont(region.GetFont()) - - w, h = region.GetSize() - # Initialize the size if zero - if (w == 0 or h == 0) and s: - w, h = 100, 50 - region.SetSize(w, h) - - string_list = FormatText(dc, s, w - 5, h - 5, region.GetFormatMode()) - for s in string_list: - line = ShapeTextLine(0.0, 0.0, s) - region.GetFormattedText().append(line) - - actualW = w - actualH = h - if region.GetFormatMode() & FORMAT_SIZE_TO_CONTENTS: - actualW, actualH = GetCentredTextExtent(dc, region.GetFormattedText(), self._xpos, self._ypos, w, h) - if actualW != w or actualH != h: - xx, yy = self.GetLabelPosition(i) - self.EraseRegion(dc, region, xx, yy) - if len(self._labelObjects) < i: - self._labelObjects[i].Select(False, dc) - self._labelObjects[i].Erase(dc) - self._labelObjects[i].SetSize(actualW, actualH) - - region.SetSize(actualW, actualH) - - if len(self._labelObjects) < i: - self._labelObjects[i].Select(True, dc) - self._labelObjects[i].Draw(dc) - - CentreText(dc, region.GetFormattedText(), self._xpos, self._ypos, actualW, actualH, region.GetFormatMode()) - self._formatted = True - - def DrawRegion(self, dc, region, x, y): - """Format one region at this position.""" - if self.GetDisableLabel(): - return - - w, h = region.GetSize() - - # Get offset from x, y - xx, yy = region.GetPosition() - - xp = xx + x - yp = yy + y - - # First, clear a rectangle for the text IF there is any - if len(region.GetFormattedText()): - dc.SetPen(self.GetBackgroundPen()) - dc.SetBrush(self.GetBackgroundBrush()) - - # Now draw the text - if region.GetFont(): - dc.SetFont(region.GetFont()) - dc.DrawRectangle(xp - w / 2.0, yp - h / 2.0, w, h) - - if self._pen: - dc.SetPen(self._pen) - dc.SetTextForeground(region.GetActualColourObject()) - - DrawFormattedText(dc, region.GetFormattedText(), xp, yp, w, h, region.GetFormatMode()) - - def EraseRegion(self, dc, region, x, y): - """Erase one region at this position.""" - if self.GetDisableLabel(): - return - - w, h = region.GetSize() - - # Get offset from x, y - xx, yy = region.GetPosition() - - xp = xx + x - yp = yy + y - - if region.GetFormattedText(): - dc.SetPen(self.GetBackgroundPen()) - dc.SetBrush(self.GetBackgroundBrush()) - - dc.DrawRectangle(xp - w / 2.0, yp - h / 2.0, w, h) - - def GetLabelPosition(self, position): - """Get the reference point for a label. - - Region x and y are offsets from this. - position is 0 (middle), 1 (start), 2 (end). - """ - if position == 0: - # Want to take the middle section for the label - half_way = int(len(self._lineControlPoints) / 2.0) - - # Find middle of this line - point = self._lineControlPoints[half_way - 1] - next_point = self._lineControlPoints[half_way] - - dx = next_point[0] - point[0] - dy = next_point[1] - point[1] - - return point[0] + dx / 2.0, point[1] + dy / 2.0 - elif position == 1: - return self._lineControlPoints[0][0], self._lineControlPoints[0][1] - elif position == 2: - return self._lineControlPoints[-1][0], self._lineControlPoints[-1][1] - - def Straighten(self, dc = None): - """Straighten verticals and horizontals.""" - if len(self._lineControlPoints) < 3: - return - - if dc: - self.Erase(dc) - - GraphicsStraightenLine(self._lineControlPoints[-1], self._lineControlPoints[-2]) - - for i in range(len(self._lineControlPoints) - 2): - GraphicsStraightenLine(self._lineControlPoints[i], self._lineControlPoints[i + 1]) - - if dc: - self.Draw(dc) - - def Unlink(self): - """Unlink the line from the nodes at either end.""" - if self._to: - self._to.GetLines().remove(self) - if self._from: - self._from.GetLines().remove(self) - self._to = None - self._from = None - for i in range(3): - if self._labelObjects[i]: - self._labelObjects[i].Select(False) - self._labelObjects[i].RemoveFromCanvas(self._canvas) - self.ClearArrowsAtPosition(-1) - - def SetEnds(self, x1, y1, x2, y2): - """Set the end positions of the line.""" - self._lineControlPoints[0] = wx.RealPoint(x1, y1) - self._lineControlPoints[-1] = wx.RealPoint(x2, y2) - - # Find centre point - self._xpos = (x1 + x2) / 2.0 - self._ypos = (y1 + y2) / 2.0 - - # Get absolute positions of ends - def GetEnds(self): - """Get the visible endpoints of the lines for drawing between two objects.""" - first_point = self._lineControlPoints[0] - last_point = self._lineControlPoints[-1] - - return first_point[0], first_point[1], last_point[0], last_point[1] - - def SetAttachments(self, from_attach, to_attach): - """Specify which object attachment points should be used at each end - of the line. - """ - self._attachmentFrom = from_attach - self._attachmentTo = to_attach - - def HitTest(self, x, y): - if not self._lineControlPoints: - return False - - # Look at label regions in case mouse is over a label - inLabelRegion = False - for i in range(3): - if self._regions[i]: - region = self._regions[i] - if len(region._formattedText): - xp, yp = self.GetLabelPosition(i) - # Offset region from default label position - cx, cy = region.GetPosition() - cw, ch = region.GetSize() - cx += xp - cy += yp - - rLeft = cx - cw / 2.0 - rTop = cy - ch / 2.0 - rRight = cx + cw / 2.0 - rBottom = cy + ch / 2.0 - if x > rLeft and x < rRight and y > rTop and y < rBottom: - inLabelRegion = True - break - - for i in range(len(self._lineControlPoints) - 1): - point1 = self._lineControlPoints[i] - point2 = self._lineControlPoints[i + 1] - - # For inaccurate mousing allow 8 pixel corridor - extra = 4 - - dx = point2[0] - point1[0] - dy = point2[1] - point1[1] - - seg_len = math.sqrt(dx * dx + dy * dy) - if dy == 0 and dx == 0: - continue - distance_from_seg = seg_len * float((x - point1[0]) * dy - (y - point1[1]) * dx) / (dy * dy + dx * dx) - distance_from_prev = seg_len * float((y - point1[1]) * dy + (x - point1[0]) * dx) / (dy * dy + dx * dx) - - if abs(distance_from_seg) < extra and distance_from_prev >= 0 and distance_from_prev <= seg_len or inLabelRegion: - return 0, distance_from_seg - - return False - - def DrawArrows(self, dc): - """Draw all arrows.""" - # Distance along line of each arrow: space them out evenly - startArrowPos = 0.0 - endArrowPos = 0.0 - middleArrowPos = 0.0 - - for arrow in self._arcArrows: - ah = arrow.GetArrowEnd() - if ah == ARROW_POSITION_START: - if arrow.GetXOffset() and not self._ignoreArrowOffsets: - # If specified, x offset is proportional to line length - self.DrawArrow(dc, arrow, arrow.GetXOffset(), True) - else: - self.DrawArrow(dc, arrow, startArrowPos, False) - startArrowPos += arrow.GetSize() + arrow.GetSpacing() - elif ah == ARROW_POSITION_END: - if arrow.GetXOffset() and not self._ignoreArrowOffsets: - self.DrawArrow(dc, arrow, arrow.GetXOffset(), True) - else: - self.DrawArrow(dc, arrow, endArrowPos, False) - endArrowPos += arrow.GetSize() + arrow.GetSpacing() - elif ah == ARROW_POSITION_MIDDLE: - arrow.SetXOffset(middleArrowPos) - if arrow.GetXOffset() and not self._ignoreArrowOffsets: - self.DrawArrow(dc, arrow, arrow.GetXOffset(), True) - else: - self.DrawArrow(dc, arrow, middleArrowPos, False) - middleArrowPos += arrow.GetSize() + arrow.GetSpacing() - - def DrawArrow(self, dc, arrow, XOffset, proportionalOffset): - """Draw the given arrowhead (or annotation).""" - first_line_point = self._lineControlPoints[0] - second_line_point = self._lineControlPoints[1] - - last_line_point = self._lineControlPoints[-1] - second_last_line_point = self._lineControlPoints[-2] - - # Position of start point of line, at the end of which we draw the arrow - startPositionX, startPositionY = 0.0, 0.0 - - ap = arrow.GetPosition() - if ap == ARROW_POSITION_START: - # If we're using a proportional offset, calculate just where this - # will be on the line. - realOffset = XOffset - if proportionalOffset: - totalLength = math.sqrt((second_line_point[0] - first_line_point[0]) * (second_line_point[0] - first_line_point[0]) + (second_line_point[1] - first_line_point[1]) * (second_line_point[1] - first_line_point[1])) - realOffset = XOffset * totalLength - - positionOnLineX, positionOnLineY = GetPointOnLine(second_line_point[0], second_line_point[1], first_line_point[0], first_line_point[1], realOffset) - - startPositionX = second_line_point[0] - startPositionY = second_line_point[1] - elif ap == ARROW_POSITION_END: - # If we're using a proportional offset, calculate just where this - # will be on the line. - realOffset = XOffset - if proportionalOffset: - totalLength = math.sqrt((second_last_line_point[0] - last_line_point[0]) * (second_last_line_point[0] - last_line_point[0]) + (second_last_line_point[1] - last_line_point[1]) * (second_last_line_point[1] - last_line_point[1])); - realOffset = XOffset * totalLength - - positionOnLineX, positionOnLineY = GetPointOnLine(second_last_line_point[0], second_last_line_point[1], last_line_point[0], last_line_point[1], realOffset) - - startPositionX = second_last_line_point[0] - startPositionY = second_last_line_point[1] - elif ap == ARROW_POSITION_MIDDLE: - # Choose a point half way between the last and penultimate points - x = (last_line_point[0] + second_last_line_point[0]) / 2.0 - y = (last_line_point[1] + second_last_line_point[1]) / 2.0 - - # If we're using a proportional offset, calculate just where this - # will be on the line. - realOffset = XOffset - if proportionalOffset: - totalLength = math.sqrt((second_last_line_point[0] - x) * (second_last_line_point[0] - x) + (second_last_line_point[1] - y) * (second_last_line_point[1] - y)); - realOffset = XOffset * totalLength - - positionOnLineX, positionOnLineY = GetPointOnLine(second_last_line_point[0], second_last_line_point[1], x, y, realOffset) - startPositionX = second_last_line_point[0] - startPositionY = second_last_line_point[1] - - # Add yOffset to arrow, if any - - # The translation that the y offset may give - deltaX = 0.0 - deltaY = 0.0 - if arrow.GetYOffset and not self._ignoreArrowOffsets: - # |(x4, y4) - # |d - # | - # (x1, y1)--------------(x3, y3)------------------(x2, y2) - # x4 = x3 - d * math.sin(theta) - # y4 = y3 + d * math.cos(theta) - # - # Where theta = math.tan(-1) of (y3-y1) / (x3-x1) - x1 = startPositionX - y1 = startPositionY - x3 = float(positionOnLineX) - y3 = float(positionOnLineY) - d = -arrow.GetYOffset() # Negate so +offset is above line - - if x3 == x1: - theta = math.pi / 2.0 - else: - theta = math.atan((y3 - y1) / (x3 - x1)) - - x4 = x3 - d * math.sin(theta) - y4 = y3 + d * math.cos(theta) - - deltaX = x4 - positionOnLineX - deltaY = y4 - positionOnLineY - - at = arrow._GetType() - if at == ARROW_ARROW: - arrowLength = arrow.GetSize() - arrowWidth = arrowLength / 3.0 - - tip_x, tip_y, side1_x, side1_y, side2_x, side2_y = GetArrowPoints(startPositionX + deltaX, startPositionY + deltaY, positionOnLineX + deltaX, positionOnLineY + deltaY, arrowLength, arrowWidth) - - points = [[tip_x, tip_y], - [side1_x, side1_y], - [side2_x, side2_y], - [tip_x, tip_y]] - - dc.SetPen(self._pen) - dc.SetBrush(self._brush) - dc.DrawPolygon(points) - elif at in [ARROW_HOLLOW_CIRCLE, ARROW_FILLED_CIRCLE]: - # Find point on line of centre of circle, which is a radius away - # from the end position - diameter = arrow.GetSize() - x, y = GetPointOnLine(startPositionX + deltaX, startPositionY + deltaY, - positionOnLineX + deltaX, positionOnLineY + deltaY, - diameter / 2.0) - x1 = x - diameter / 2.0 - y1 = y - diameter / 2.0 - dc.SetPen(self._pen) - if arrow._GetType() == ARROW_HOLLOW_CIRCLE: - dc.SetBrush(self.GetBackgroundBrush()) - else: - dc.SetBrush(self._brush) - - dc.DrawEllipse(x1, y1, diameter, diameter) - elif at == ARROW_SINGLE_OBLIQUE: - pass - elif at == ARROW_METAFILE: - if arrow.GetMetaFile(): - # Find point on line of centre of object, which is a half-width away - # from the end position - # - # width - # <-- start pos <-----><-- positionOnLineX - # _____ - # --------------| x | <-- e.g. rectangular arrowhead - # ----- - # - x, y = GetPointOnLine(startPositionX, startPositionY, - positionOnLineX, positionOnLineY, - arrow.GetMetaFile()._width / 2.0) - # Calculate theta for rotating the metafile. - # - # | - # | o(x2, y2) 'o' represents the arrowhead. - # | / - # | / - # | /theta - # | /(x1, y1) - # |______________________ - # - theta = 0.0 - x1 = startPositionX - y1 = startPositionY - x2 = float(positionOnLineX) - y2 = float(positionOnLineY) - - if x1 == x2 and y1 == y2: - theta = 0.0 - elif x1 == x2 and y1 > y2: - theta = 3.0 * math.pi / 2.0 - elif x1 == x2 and y2 > y1: - theta = math.pi / 2.0 - elif x2 > x1 and y2 >= y1: - theta = math.atan((y2 - y1) / (x2 - x1)) - elif x2 < x1: - theta = math.pi + math.atan((y2 - y1) / (x2 - x1)) - elif x2 > x1 and y2 < y1: - theta = 2 * math.pi + math.atan((y2 - y1) / (x2 - x1)) - else: - raise "Unknown arrowhead rotation case" - - # Rotate about the centre of the object, then place - # the object on the line. - if arrow.GetMetaFile().GetRotateable(): - arrow.GetMetaFile().Rotate(0.0, 0.0, theta) - - if self._erasing: - # If erasing, just draw a rectangle - minX, minY, maxX, maxY = arrow.GetMetaFile().GetBounds() - # Make erasing rectangle slightly bigger or you get droppings - extraPixels = 4 - dc.DrawRectangle(deltaX + x + minX - extraPixels / 2.0, deltaY + y + minY - extraPixels / 2.0, maxX - minX + extraPixels, maxY - minY + extraPixels) - else: - arrow.GetMetaFile().Draw(dc, x + deltaX, y + deltaY) - - def OnErase(self, dc): - old_pen = self._pen - old_brush = self._brush - - bg_pen = self.GetBackgroundPen() - bg_brush = self.GetBackgroundBrush() - self.SetPen(bg_pen) - self.SetBrush(bg_brush) - - bound_x, bound_y = self.GetBoundingBoxMax() - if self._font: - dc.SetFont(self._font) - - # Undraw text regions - for i in range(3): - if self._regions[i]: - x, y = self.GetLabelPosition(i) - self.EraseRegion(dc, self._regions[i], x, y) - - # Undraw line - dc.SetPen(self.GetBackgroundPen()) - dc.SetBrush(self.GetBackgroundBrush()) - - # Drawing over the line only seems to work if the line has a thickness - # of 1. - if old_pen and old_pen.GetWidth() > 1: - dc.DrawRectangle(self._xpos - bound_x / 2.0 - 2, self._ypos - bound_y / 2.0 - 2, - bound_x + 4, bound_y + 4) - else: - self._erasing = True - self.GetEventHandler().OnDraw(dc) - self.GetEventHandler().OnEraseControlPoints(dc) - self._erasing = False - - if old_pen: - self.SetPen(old_pen) - if old_brush: - self.SetBrush(old_brush) - - def GetBoundingBoxMin(self): - x1, y1 = 10000, 10000 - x2, y2 = -10000, -10000 - - for point in self._lineControlPoints: - if point[0] < x1: - x1 = point[0] - if point[1] < y1: - y1 = point[1] - if point[0] > x2: - x2 = point[0] - if point[1] > y2: - y2 = point[1] - - return x2 - x1, y2 - y1 - - # For a node image of interest, finds the position of this arc - # amongst all the arcs which are attached to THIS SIDE of the node image, - # and the number of same. - def FindNth(self, image, incoming): - """Find the position of the line on the given object. - - Specify whether incoming or outgoing lines are being considered - with incoming. - """ - n = -1 - num = 0 - - if image == self._to: - this_attachment = self._attachmentTo - else: - this_attachment = self._attachmentFrom - - # Find number of lines going into / out of this particular attachment point - for line in image.GetLines(): - if line._from == image: - # This is the nth line attached to 'image' - if line == self and not incoming: - n = num - - # Increment num count if this is the same side (attachment number) - if line._attachmentFrom == this_attachment: - num += 1 - - if line._to == image: - # This is the nth line attached to 'image' - if line == self and incoming: - n = num - - # Increment num count if this is the same side (attachment number) - if line._attachmentTo == this_attachment: - num += 1 - - return n, num - - def OnDrawOutline(self, dc, x, y, w, h): - old_pen = self._pen - old_brush = self._brush - - dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT) - self.SetPen(dottedPen) - self.SetBrush(wx.TRANSPARENT_BRUSH) - - self.GetEventHandler().OnDraw(dc) - - if old_pen: - self.SetPen(old_pen) - else: - self.SetPen(None) - if old_brush: - self.SetBrush(old_brush) - else: - self.SetBrush(None) - - def OnMovePre(self, dc, x, y, old_x, old_y, display = True): - x_offset = x - old_x - y_offset = y - old_y - - if self._lineControlPoints and not (x_offset == 0 and y_offset == 0): - for point in self._lineControlPoints: - point[0] += x_offset - point[1] += y_offset - - # Move temporary label rectangles if necessary - for i in range(3): - if self._labelObjects[i]: - self._labelObjects[i].Erase(dc) - xp, yp = self.GetLabelPosition(i) - if i < len(self._regions): - xr, yr = self._regions[i].GetPosition() - else: - xr, yr = 0, 0 - self._labelObjects[i].Move(dc, xp + xr, yp + yr) - return True - - def OnMoveLink(self, dc, moveControlPoints = True): - """Called when a connected object has moved, to move the link to - correct position - """ - if not self._from or not self._to: - return - - # Do each end - nothing in the middle. User has to move other points - # manually if necessary - end_x, end_y, other_end_x, other_end_y = self.FindLineEndPoints() - - oldX, oldY = self._xpos, self._ypos - - # pi: The first time we go through FindLineEndPoints we can't - # use the middle points (since they don't have sane values), - # so we just do what we do for a normal line. Then we call - # Initialise to set the middle points, and then FindLineEndPoints - # again, but this time (and from now on) we use the middle - # points to calculate the end points. - # This was buggy in the C++ version too. - - self.SetEnds(end_x, end_y, other_end_x, other_end_y) - - if len(self._lineControlPoints) > 2: - self.Initialise() - - # Do a second time, because one may depend on the other - end_x, end_y, other_end_x, other_end_y = self.FindLineEndPoints() - self.SetEnds(end_x, end_y, other_end_x, other_end_y) - - # Try to move control points with the arc - x_offset = self._xpos - oldX - y_offset = self._ypos - oldY - - # Only move control points if it's a self link. And only works - # if attachment mode is ON - if self._from == self._to and self._from.GetAttachmentMode() != ATTACHMENT_MODE_NONE and moveControlPoints and self._lineControlPoints and not (x_offset == 0 and y_offset == 0): - for point in self._lineControlPoints[1:-1]: - point[0] += x_offset - point[1] += y_offset - - self.Move(dc, self._xpos, self._ypos) - - def FindLineEndPoints(self): - """Finds the x, y points at the two ends of the line. - - This function can be used by e.g. line-routing routines to - get the actual points on the two node images where the lines will be - drawn to / from. - """ - if not self._from or not self._to: - return - - # Do each end - nothing in the middle. User has to move other points - # manually if necessary. - second_point = self._lineControlPoints[1] - second_last_point = self._lineControlPoints[-2] - - # pi: If we have a segmented line and this is the first time, - # do this as a straight line. - if len(self._lineControlPoints) > 2 and self._initialised: - if self._from.GetAttachmentMode() != ATTACHMENT_MODE_NONE: - nth, no_arcs = self.FindNth(self._from, False) # Not incoming - end_x, end_y = self._from.GetAttachmentPosition(self._attachmentFrom, nth, no_arcs, self) - else: - end_x, end_y = self._from.GetPerimeterPoint(self._from.GetX(), self._from.GetY(), second_point[0], second_point[1]) - - if self._to.GetAttachmentMode() != ATTACHMENT_MODE_NONE: - nth, no_arch = self.FindNth(self._to, True) # Incoming - other_end_x, other_end_y = self._to.GetAttachmentPosition(self._attachmentTo, nth, no_arch, self) - else: - other_end_x, other_end_y = self._to.GetPerimeterPoint(self._to.GetX(), self._to.GetY(), second_last_point[0], second_last_point[1]) - else: - fromX = self._from.GetX() - fromY = self._from.GetY() - toX = self._to.GetX() - toY = self._to.GetY() - - if self._from.GetAttachmentMode() != ATTACHMENT_MODE_NONE: - nth, no_arcs = self.FindNth(self._from, False) - end_x, end_y = self._from.GetAttachmentPosition(self._attachmentFrom, nth, no_arcs, self) - fromX = end_x - fromY = end_y - - if self._to.GetAttachmentMode() != ATTACHMENT_MODE_NONE: - nth, no_arcs = self.FindNth(self._to, True) - other_end_x, other_end_y = self._to.GetAttachmentPosition(self._attachmentTo, nth, no_arcs, self) - toX = other_end_x - toY = other_end_y - - if self._from.GetAttachmentMode() == ATTACHMENT_MODE_NONE: - end_x, end_y = self._from.GetPerimeterPoint(self._from.GetX(), self._from.GetY(), toX, toY) - - if self._to.GetAttachmentMode() == ATTACHMENT_MODE_NONE: - other_end_x, other_end_y = self._to.GetPerimeterPoint(self._to.GetX(), self._to.GetY(), fromX, fromY) - - return end_x, end_y, other_end_x, other_end_y - - - def OnDraw(self, dc): - if not self._lineControlPoints: - return - - if self._pen: - dc.SetPen(self._pen) - if self._brush: - dc.SetBrush(self._brush) - - points = [] - for point in self._lineControlPoints: - points.append(wx.Point(point[0], point[1])) - - if self._isSpline: - dc.DrawSpline(points) - else: - dc.DrawLines(points) - - if sys.platform[:3] == "win": - # For some reason, last point isn't drawn under Windows - pt = points[-1] - dc.DrawPoint(pt[0], pt[1]) - - # Problem with pen - if not a solid pen, does strange things - # to the arrowhead. So make (get) a new pen that's solid. - if self._pen and self._pen.GetStyle() != wx.SOLID: - solid_pen = wx.Pen(self._pen.GetColour(), 1, wx.SOLID) - if solid_pen: - dc.SetPen(solid_pen) - - self.DrawArrows(dc) - - def OnDrawControlPoints(self, dc): - if not self._drawHandles: - return - - # Draw temporary label rectangles if necessary - for i in range(3): - if self._labelObjects[i]: - self._labelObjects[i].Draw(dc) - - Shape.OnDrawControlPoints(self, dc) - - def OnEraseControlPoints(self, dc): - # Erase temporary label rectangles if necessary - - for i in range(3): - if self._labelObjects[i]: - self._labelObjects[i].Erase(dc) - - Shape.OnEraseControlPoints(self, dc) - - def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0): - pass - - def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0): - pass - - def OnEndDragLeft(self, x, y, keys = 0, attachment = 0): - pass - - def OnDrawContents(self, dc): - if self.GetDisableLabel(): - return - - for i in range(3): - if self._regions[i]: - x, y = self.GetLabelPosition(i) - self.DrawRegion(dc, self._regions[i], x, y) - - def SetTo(self, object): - """Set the 'to' object for the line.""" - self._to = object - - def SetFrom(self, object): - """Set the 'from' object for the line.""" - self._from = object - - def MakeControlPoints(self): - """Make handle control points.""" - if self._canvas and self._lineControlPoints: - first = self._lineControlPoints[0] - last = self._lineControlPoints[-1] - - control = LineControlPoint(self._canvas, self, CONTROL_POINT_SIZE, first[0], first[1], CONTROL_POINT_ENDPOINT_FROM) - control._point = first - self._canvas.AddShape(control) - self._controlPoints.append(control) - - for point in self._lineControlPoints[1:-1]: - control = LineControlPoint(self._canvas, self, CONTROL_POINT_SIZE, point[0], point[1], CONTROL_POINT_LINE) - control._point = point - self._canvas.AddShape(control) - self._controlPoints.append(control) - - control = LineControlPoint(self._canvas, self, CONTROL_POINT_SIZE, last[0], last[1], CONTROL_POINT_ENDPOINT_TO) - control._point = last - self._canvas.AddShape(control) - self._controlPoints.append(control) - - def ResetControlPoints(self): - if self._canvas and self._lineControlPoints and self._controlPoints: - for i in range(min(len(self._controlPoints), len(self._lineControlPoints))): - point = self._lineControlPoints[i] - control = self._controlPoints[i] - control.SetX(point[0]) - control.SetY(point[1]) - - # Override select, to create / delete temporary label-moving objects - def Select(self, select, dc = None): - Shape.Select(self, select, dc) - if select: - for i in range(3): - if self._regions[i]: - region = self._regions[i] - if region._formattedText: - w, h = region.GetSize() - x, y = region.GetPosition() - xx, yy = self.GetLabelPosition(i) - - if self._labelObjects[i]: - self._labelObjects[i].Select(False) - self._labelObjects[i].RemoveFromCanvas(self._canvas) - - self._labelObjects[i] = self.OnCreateLabelShape(self, region, w, h) - self._labelObjects[i].AddToCanvas(self._canvas) - self._labelObjects[i].Show(True) - if dc: - self._labelObjects[i].Move(dc, x + xx, y + yy) - self._labelObjects[i].Select(True, dc) - else: - for i in range(3): - if self._labelObjects[i]: - self._labelObjects[i].Select(False, dc) - self._labelObjects[i].Erase(dc) - self._labelObjects[i].RemoveFromCanvas(self._canvas) - self._labelObjects[i] = None - - # Control points ('handles') redirect control to the actual shape, to - # make it easier to override sizing behaviour. - def OnSizingDragLeft(self, pt, draw, x, y, keys = 0, attachment = 0): - dc = wx.ClientDC(self.GetCanvas()) - self.GetCanvas().PrepareDC(dc) - - dc.SetLogicalFunction(OGLRBLF) - - dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT) - dc.SetPen(dottedPen) - dc.SetBrush(wx.TRANSPARENT_BRUSH) - - if pt._type == CONTROL_POINT_LINE: - x, y = self._canvas.Snap(x, y) - - pt.SetX(x) - pt.SetY(y) - pt._point[0] = x - pt._point[1] = y - - old_pen = self.GetPen() - old_brush = self.GetBrush() - - self.SetPen(dottedPen) - self.SetBrush(wx.TRANSPARENT_BRUSH) - - self.GetEventHandler().OnMoveLink(dc, False) - - self.SetPen(old_pen) - self.SetBrush(old_brush) - - def OnSizingBeginDragLeft(self, pt, x, y, keys = 0, attachment = 0): - dc = wx.ClientDC(self.GetCanvas()) - self.GetCanvas().PrepareDC(dc) - - if pt._type == CONTROL_POINT_LINE: - pt._originalPos = pt._point - x, y = self._canvas.Snap(x, y) - - self.Erase(dc) - - # Redraw start and end objects because we've left holes - # when erasing the line - self.GetFrom().OnDraw(dc) - self.GetFrom().OnDrawContents(dc) - self.GetTo().OnDraw(dc) - self.GetTo().OnDrawContents(dc) - - self.SetDisableLabel(True) - dc.SetLogicalFunction(OGLRBLF) - - pt._xpos = x - pt._ypos = y - pt._point[0] = x - pt._point[1] = y - - old_pen = self.GetPen() - old_brush = self.GetBrush() - - dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT) - self.SetPen(dottedPen) - self.SetBrush(wx.TRANSPARENT_BRUSH) - - self.GetEventHandler().OnMoveLink(dc, False) - - self.SetPen(old_pen) - self.SetBrush(old_brush) - - if pt._type == CONTROL_POINT_ENDPOINT_FROM or pt._type == CONTROL_POINT_ENDPOINT_TO: - self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_BULLSEYE)) - pt._oldCursor = wx.STANDARD_CURSOR - - def OnSizingEndDragLeft(self, pt, x, y, keys = 0, attachment = 0): - dc = wx.ClientDC(self.GetCanvas()) - self.GetCanvas().PrepareDC(dc) - - self.SetDisableLabel(False) - - if pt._type == CONTROL_POINT_LINE: - x, y = self._canvas.Snap(x, y) - - rpt = wx.RealPoint(x, y) - - # Move the control point back to where it was; - # MoveControlPoint will move it to the new position - # if it decides it wants. We only moved the position - # during user feedback so we could redraw the line - # as it changed shape. - pt._xpos = pt._originalPos[0] - pt._ypos = pt._originalPos[1] - pt._point[0] = pt._originalPos[0] - pt._point[1] = pt._originalPos[1] - - self.OnMoveMiddleControlPoint(dc, pt, rpt) - - if pt._type == CONTROL_POINT_ENDPOINT_FROM: - if pt._oldCursor: - self._canvas.SetCursor(pt._oldCursor) - - if self.GetFrom(): - self.GetFrom().MoveLineToNewAttachment(dc, self, x, y) - - if pt._type == CONTROL_POINT_ENDPOINT_TO: - if pt._oldCursor: - self._canvas.SetCursor(pt._oldCursor) - - if self.GetTo(): - self.GetTo().MoveLineToNewAttachment(dc, self, x, y) - - # This is called only when a non-end control point is moved - def OnMoveMiddleControlPoint(self, dc, lpt, pt): - lpt._xpos = pt[0] - lpt._ypos = pt[1] - - lpt._point[0] = pt[0] - lpt._point[1] = pt[1] - - self.GetEventHandler().OnMoveLink(dc) - - return True - - def AddArrow(self, type, end = ARROW_POSITION_END, size = 10.0, xOffset = 0.0, name = "", mf = None, arrowId = -1): - """Add an arrow (or annotation) to the line. - - type may currently be one of: - - ARROW_HOLLOW_CIRCLE - Hollow circle. - ARROW_FILLED_CIRCLE - Filled circle. - ARROW_ARROW - Conventional arrowhead. - ARROW_SINGLE_OBLIQUE - Single oblique stroke. - ARROW_DOUBLE_OBLIQUE - Double oblique stroke. - ARROW_DOUBLE_METAFILE - Custom arrowhead. - - end may currently be one of: - - ARROW_POSITION_END - Arrow appears at the end. - ARROW_POSITION_START - Arrow appears at the start. - - arrowSize specifies the length of the arrow. - - xOffset specifies the offset from the end of the line. - - name specifies a name for the arrow. - - mf can be a wxPseduoMetaFile, perhaps loaded from a simple Windows - metafile. - - arrowId is the id for the arrow. - """ - arrow = ArrowHead(type, end, size, xOffset, name, mf, arrowId) - self._arcArrows.append(arrow) - return arrow - - # Add arrowhead at a particular position in the arrowhead list - def AddArrowOrdered(self, arrow, referenceList, end): - """Add an arrowhead in the position indicated by the reference list - of arrowheads, which contains all legal arrowheads for this line, in - the correct order. E.g. - - Reference list: a b c d e - Current line list: a d - - Add c, then line list is: a c d. - - If no legal arrowhead position, return FALSE. Assume reference list - is for one end only, since it potentially defines the ordering for - any one of the 3 positions. So we don't check the reference list for - arrowhead position. - """ - if not referenceList: - return False - - targetName = arrow.GetName() - - # First check whether we need to insert in front of list, - # because this arrowhead is the first in the reference - # list and should therefore be first in the current list. - refArrow = referenceList[0] - if refArrow.GetName() == targetName: - self._arcArrows.insert(0, arrow) - return True - - i1 = i2 = 0 - while i1 < len(referenceList) and i2 < len(self._arcArrows): - refArrow = referenceList[i1] - currArrow = self._arcArrows[i2] - - # Matching: advance current arrow pointer - if currArrow.GetArrowEnd() == end and currArrow.GetName() == refArrow.GetName(): - i2 += 1 - - # Check if we're at the correct position in the - # reference list - if targetName == refArrow.GetName(): - if i2 < len(self._arcArrows): - self._arcArrows.insert(i2, arrow) - else: - self._arcArrows.append(arrow) - return True - i1 += 1 - - self._arcArrows.append(arrow) - return True - - def ClearArrowsAtPosition(self, end): - """Delete the arrows at the specified position, or at any position - if position is -1. - """ - if end == -1: - self._arcArrows = [] - return - - for arrow in self._arcArrows: - if arrow.GetArrowEnd() == end: - self._arcArrows.remove(arrow) - - def ClearArrow(self, name): - """Delete the arrow with the given name.""" - for arrow in self._arcArrows: - if arrow.GetName() == name: - self._arcArrows.remove(arrow) - return True - return False - - def FindArrowHead(self, position, name): - """Find arrowhead by position and name. - - if position is -1, matches any position. - """ - for arrow in self._arcArrows: - if (position == -1 or position == arrow.GetArrowEnd()) and arrow.GetName() == name: - return arrow - - return None - - def FindArrowHeadId(self, arrowId): - """Find arrowhead by id.""" - for arrow in self._arcArrows: - if arrowId == arrow.GetId(): - return arrow - - return None - - def DeleteArrowHead(self, position, name): - """Delete arrowhead by position and name. - - if position is -1, matches any position. - """ - for arrow in self._arcArrows: - if (position == -1 or position == arrow.GetArrowEnd()) and arrow.GetName() == name: - self._arcArrows.remove(arrow) - return True - return False - - def DeleteArrowHeadId(self, id): - """Delete arrowhead by id.""" - for arrow in self._arcArrows: - if arrowId == arrow.GetId(): - self._arcArrows.remove(arrow) - return True - return False - - # Calculate the minimum width a line - # occupies, for the purposes of drawing lines in tools. - def FindMinimumWidth(self): - """Find the horizontal width for drawing a line with arrows in - minimum space. Assume arrows at end only. - """ - minWidth = 0.0 - for arrowHead in self._arcArrows: - minWidth += arrowHead.GetSize() - if arrowHead != self._arcArrows[-1]: - minWidth += arrowHead + GetSpacing - - # We have ABSOLUTE minimum now. So - # scale it to give it reasonable aesthetics - # when drawing with line. - if minWidth > 0: - minWidth = minWidth * 1.4 - else: - minWidth = 20.0 - - self.SetEnds(0.0, 0.0, minWidth, 0.0) - self.Initialise() - - return minWidth - - def FindLinePosition(self, x, y): - """Find which position we're talking about at this x, y. - - Returns ARROW_POSITION_START, ARROW_POSITION_MIDDLE, ARROW_POSITION_END. - """ - startX, startY, endX, endY = self.GetEnds() - - # Find distances from centre, start and end. The smallest wins - centreDistance = math.sqrt((x - self._xpos) * (x - self._xpos) + (y - self._ypos) * (y - self._ypos)) - startDistance = math.sqrt((x - startX) * (x - startX) + (y - startY) * (y - startY)) - endDistance = math.sqrt((x - endX) * (x - endX) + (y - endY) * (y - endY)) - - if centreDistance < startDistance and centreDistance < endDistance: - return ARROW_POSITION_MIDDLE - elif startDistance < endDistance: - return ARROW_POSITION_START - else: - return ARROW_POSITION_END - - def SetAlignmentOrientation(self, isEnd, isHoriz): - if isEnd: - if isHoriz and self._alignmentEnd & LINE_ALIGNMENT_HORIZ != LINE_ALIGNMENT_HORIZ: - self._alignmentEnd != LINE_ALIGNMENT_HORIZ - elif not isHoriz and self._alignmentEnd & LINE_ALIGNMENT_HORIZ == LINE_ALIGNMENT_HORIZ: - self._alignmentEnd -= LINE_ALIGNMENT_HORIZ - else: - if isHoriz and self._alignmentStart & LINE_ALIGNMENT_HORIZ != LINE_ALIGNMENT_HORIZ: - self._alignmentStart != LINE_ALIGNMENT_HORIZ - elif not isHoriz and self._alignmentStart & LINE_ALIGNMENT_HORIZ == LINE_ALIGNMENT_HORIZ: - self._alignmentStart -= LINE_ALIGNMENT_HORIZ - - def SetAlignmentType(self, isEnd, alignType): - if isEnd: - if alignType == LINE_ALIGNMENT_TO_NEXT_HANDLE: - if self._alignmentEnd & LINE_ALIGNMENT_TO_NEXT_HANDLE != LINE_ALIGNMENT_TO_NEXT_HANDLE: - self._alignmentEnd |= LINE_ALIGNMENT_TO_NEXT_HANDLE - elif self._alignmentEnd & LINE_ALIGNMENT_TO_NEXT_HANDLE == LINE_ALIGNMENT_TO_NEXT_HANDLE: - self._alignmentEnd -= LINE_ALIGNMENT_TO_NEXT_HANDLE - else: - if alignType == LINE_ALIGNMENT_TO_NEXT_HANDLE: - if self._alignmentStart & LINE_ALIGNMENT_TO_NEXT_HANDLE != LINE_ALIGNMENT_TO_NEXT_HANDLE: - self._alignmentStart |= LINE_ALIGNMENT_TO_NEXT_HANDLE - elif self._alignmentStart & LINE_ALIGNMENT_TO_NEXT_HANDLE == LINE_ALIGNMENT_TO_NEXT_HANDLE: - self._alignmentStart -= LINE_ALIGNMENT_TO_NEXT_HANDLE - - def GetAlignmentOrientation(self, isEnd): - if isEnd: - return self._alignmentEnd & LINE_ALIGNMENT_HORIZ == LINE_ALIGNMENT_HORIZ - else: - return self._alignmentStart & LINE_ALIGNMENT_HORIZ == LINE_ALIGNMENT_HORIZ - - def GetAlignmentType(self, isEnd): - if isEnd: - return self._alignmentEnd & LINE_ALIGNMENT_TO_NEXT_HANDLE - else: - return self._alignmentStart & LINE_ALIGNMENT_TO_NEXT_HANDLE - - def GetNextControlPoint(self, shape): - """Find the next control point in the line after the start / end point, - depending on whether the shape is at the start or end. - """ - n = len(self._lineControlPoints) - if self._to == shape: - # Must be END of line, so we want (n - 1)th control point. - # But indexing ends at n-1, so subtract 2. - nn = n - 2 - else: - nn = 1 - if nn < len(self._lineControlPoints): - return self._lineControlPoints[nn] - return None - - def OnCreateLabelShape(self, parent, region, w, h): - return LabelShape(parent, region, w, h) - - - def OnLabelMovePre(self, dc, labelShape, x, y, old_x, old_y, display): - labelShape._shapeRegion.SetSize(labelShape.GetWidth(), labelShape.GetHeight()) - - # Find position in line's region list - i = self._regions.index(labelShape._shapeRegion) - - xx, yy = self.GetLabelPosition(i) - # Set the region's offset, relative to the default position for - # each region. - labelShape._shapeRegion.SetPosition(x - xx, y - yy) - labelShape.SetX(x) - labelShape.SetY(y) - - # Need to reformat to fit region - if labelShape._shapeRegion.GetText(): - s = labelShape._shapeRegion.GetText() - labelShape.FormatText(dc, s, i) - self.DrawRegion(dc, labelShape._shapeRegion, xx, yy) - return True -