X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/31f8e937b872b889f41e363dd2cf07d3ffe32f1d..9d45af36fe32c2aba06e9692f7a133884ce75f53:/wxPython/wx/lib/ogl/_lines.py diff --git a/wxPython/wx/lib/ogl/_lines.py b/wxPython/wx/lib/ogl/_lines.py index 65978c484f..fdee0ed6b5 100644 --- a/wxPython/wx/lib/ogl/_lines.py +++ b/wxPython/wx/lib/ogl/_lines.py @@ -11,20 +11,18 @@ # Licence: wxWindows license #---------------------------------------------------------------------------- -from __future__ import division - import sys import math -from _basic import Shape, ShapeRegion, ControlPoint, RectangleShape +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 +LINE_ALIGNMENT_HORIZ = 1 +LINE_ALIGNMENT_VERT = 0 +LINE_ALIGNMENT_TO_NEXT_HANDLE = 2 +LINE_ALIGNMENT_NONE = 0 @@ -53,7 +51,7 @@ class LineControlPoint(ControlPoint): class ArrowHead(object): - def __init__(self, type = 0, end = 0, size = 0.0, dist = 0.0, name="",mf = None, arrowId=-1): + def __init__(self, type = 0, end = 0, size = 0.0, dist = 0.0, name = "", mf = None, arrowId = -1): if isinstance(type, ArrowHead): pass else: @@ -67,7 +65,7 @@ class ArrowHead(object): self._arrowName = name self._metaFile = mf self._id = arrowId - if self._id==-1: + if self._id == -1: self._id = wx.NewId() def _GetType(self): @@ -98,7 +96,7 @@ class ArrowHead(object): if oldWidth == 0: return - scale = size / oldWidth + scale = float(size) / oldWidth if scale != 1: self._metaFile.Scale(scale, scale) @@ -133,14 +131,14 @@ class LabelShape(RectangleShape): RectangleShape.__init__(self, w, h) self._lineShape = parent self._shapeRegion = region - self.SetPen(wx.ThePenList.FindOrCreatePen(wx.Colour(0, 0, 0), 1, wx.DOT)) + 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 - y1 = self._ypos-self._height / 2 + x1 = self._xpos - self._width / 2.0 + y1 = self._ypos - self._height / 2.0 if self._pen: if self._pen.GetWidth() == 0: @@ -149,7 +147,7 @@ class LabelShape(RectangleShape): dc.SetPen(self._pen) dc.SetBrush(wx.TRANSPARENT_BRUSH) - if self._cornerRadius>0: + if self._cornerRadius > 0: dc.DrawRoundedRectangle(x1, y1, self._width, self._height, self._cornerRadius) else: dc.DrawRectangle(x1, y1, self._width, self._height) @@ -222,7 +220,6 @@ class LineShape(Shape): def __del__(self): if self._lineControlPoints: - self.ClearPointList(self._lineControlPoints) self._lineControlPoints = [] for i in range(3): if self._labelObjects[i]: @@ -291,31 +288,36 @@ class LineShape(Shape): def MakeLineControlPoints(self, n): """Make a given number of control points (minimum of two).""" - if self._lineControlPoints: - self.ClearPointList(self._lineControlPoints) self._lineControlPoints = [] for _ in range(n): - point = wx.RealPoint(-999,-999) + point = wx.RealPoint(-999, -999) self._lineControlPoints.append(point) - def InsertLineControlPoint(self, dc = None): - """Insert a control point at an arbitrary position.""" + # 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) - last_point = self._lineControlPoints[-1] - second_last_point = self._lineControlPoints[-2] + 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 - line_y = (last_point[1] + second_last_point[1]) / 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), point) + self._lineControlPoints.insert(len(self._lineControlPoints)-1, point) def DeleteLineControlPoint(self): """Delete an arbitary point on the line.""" - if len(self._lineControlPoints)<3: + if len(self._lineControlPoints) < 3: return False del self._lineControlPoints[-2] @@ -332,22 +334,23 @@ class LineShape(Shape): # initialize them by placing them half way between the first # and the last. - for point in self._lineControlPoints[1:]: - if point[0]==-999: - if first_point[0]rLeft and xrTop and y rLeft and x < rRight and y > rTop and y < rBottom: inLabelRegion = True break - for i in range(len(self._lineControlPoints)-1): + 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] + dx = point2[0] - point1[0] + dy = point2[1] - point1[1] seg_len = math.sqrt(dx * dx + dy * dy) - if dy == 0 or dx == 0: - return False - distance_from_seg = seg_len * ((x-point1[0]) * dy-(y-point1[1]) * dx) / (dy * dy + dx * dx) - distance_from_prev = seg_len * ((y-point1[1]) * dy + (x-point1[0]) * dx) / (dy * dy + dx * dx) + 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)= 0 and distance_from_prev <= seg_len or inLabelRegion: + 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 @@ -612,7 +610,7 @@ class LineShape(Shape): # 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])) + 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) @@ -624,7 +622,7 @@ class LineShape(Shape): # 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])); + 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) @@ -633,14 +631,14 @@ class LineShape(Shape): 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 - y = (last_line_point[1] + second_last_line_point[1]) / 2 + 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)); + 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) @@ -663,25 +661,25 @@ class LineShape(Shape): # Where theta = math.tan(-1) of (y3-y1) / (x3-x1) x1 = startPositionX y1 = startPositionY - x3 = positionOnLineX - y3 = positionOnLineY - d=-arrow.GetYOffset() # Negate so +offset is above line + x3 = float(positionOnLineX) + y3 = float(positionOnLineY) + d = -arrow.GetYOffset() # Negate so +offset is above line if x3 == x1: - theta = math.pi / 2 + theta = math.pi / 2.0 else: - theta = math.atan((y3-y1) / (x3-x1)) + theta = math.atan((y3 - y1) / (x3 - x1)) - x4 = x3-d * math.sin(theta) + x4 = x3 - d * math.sin(theta) y4 = y3 + d * math.cos(theta) - deltaX = x4-positionOnLineX - deltaY = y4-positionOnLineY + deltaX = x4 - positionOnLineX + deltaY = y4 - positionOnLineY at = arrow._GetType() if at == ARROW_ARROW: arrowLength = arrow.GetSize() - arrowWidth = arrowLength / 3 + 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) @@ -699,9 +697,9 @@ class LineShape(Shape): diameter = arrow.GetSize() x, y = GetPointOnLine(startPositionX + deltaX, startPositionY + deltaY, positionOnLineX + deltaX, positionOnLineY + deltaY, - diameter / 2) - x1 = x-diameter / 2 - y1 = y-diameter / 2 + 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()) @@ -724,7 +722,7 @@ class LineShape(Shape): # x, y = GetPointOnLine(startPositionX, startPositionY, positionOnLineX, positionOnLineY, - arrow.GetMetaFile()._width / 2) + arrow.GetMetaFile()._width / 2.0) # Calculate theta for rotating the metafile. # # | @@ -738,21 +736,21 @@ class LineShape(Shape): theta = 0.0 x1 = startPositionX y1 = startPositionY - x2 = positionOnLineX - y2 = positionOnLineY + 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 - elif x1 == x2 and y2>y1: - theta = math.pi / 2 - elif x2>x1 and y2 >= y1: - theta = math.atan((y2-y1) / (x2-x1)) - elif x2x1 and y2 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" @@ -766,7 +764,7 @@ class LineShape(Shape): 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, deltaY + y + minY-extraPixels / 2, maxX-minX + extraPixels, maxY-minY + extraPixels) + 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) @@ -795,8 +793,8 @@ class LineShape(Shape): # 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-2, self._ypos-bound_y / 2-2, + 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 @@ -811,19 +809,19 @@ class LineShape(Shape): def GetBoundingBoxMin(self): x1, y1 = 10000, 10000 - x2, y2=-10000,-10000 + x2, y2 = -10000, -10000 for point in self._lineControlPoints: - if point[0]x2: + if point[0] > x2: x2 = point[0] - if point[1]>y2: + if point[1] > y2: y2 = point[1] - return x2-x1, y2-y1 + 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, @@ -834,7 +832,7 @@ class LineShape(Shape): Specify whether incoming or outgoing lines are being considered with incoming. """ - n=-1 + n = -1 num = 0 if image == self._to: @@ -884,8 +882,8 @@ class LineShape(Shape): 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 + 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: @@ -897,7 +895,7 @@ class LineShape(Shape): if self._labelObjects[i]: self._labelObjects[i].Erase(dc) xp, yp = self.GetLabelPosition(i) - if i2: - self.Initialise() - # 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() - first = self._lineControlPoints[0] - last = self._lineControlPoints[-1] - 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 + 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.x += x_offset - point.y += y_offset + point[0] += x_offset + point[1] += y_offset self.Move(dc, self._xpos, self._ypos) @@ -956,8 +959,10 @@ class LineShape(Shape): # manually if necessary. second_point = self._lineControlPoints[1] second_last_point = self._lineControlPoints[-2] - - if len(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) @@ -993,8 +998,8 @@ class LineShape(Shape): if self._to.GetAttachmentMode() == ATTACHMENT_MODE_NONE: other_end_x, other_end_y = self._to.GetPerimeterPoint(self._to.GetX(), self._to.GetY(), fromX, fromY) - #print type(self._from), type(self._to), end_x, end_y, other_end_x, other_end_y - return end_x, end_y, other_end_x, other_end_y + return end_x, end_y, other_end_x, other_end_y + def OnDraw(self, dc): if not self._lineControlPoints: @@ -1007,23 +1012,22 @@ class LineShape(Shape): points = [] for point in self._lineControlPoints: - points.append(wx.Point(point.x, point.y)) + points.append(wx.Point(point[0], point[1])) - #print points if self._isSpline: dc.DrawSpline(points) else: dc.DrawLines(points) - if sys.platform[:3]=="win": + if sys.platform[:3] == "win": # For some reason, last point isn't drawn under Windows pt = points[-1] - dc.DrawPoint(pt.x, pt.y) + 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.ThePenList().FindOrCreatePen(self._pen.GetColour(), 1, wx.SOLID) + solid_pen = wx.Pen(self._pen.GetColour(), 1, wx.SOLID) if solid_pen: dc.SetPen(solid_pen) @@ -1084,21 +1088,21 @@ class LineShape(Shape): 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) + 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) + 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) + self._controlPoints.append(control) def ResetControlPoints(self): - if self._canvas and self._lineControlPoints: + 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] @@ -1148,13 +1152,13 @@ class LineShape(Shape): dc.SetBrush(wx.TRANSPARENT_BRUSH) if pt._type == CONTROL_POINT_LINE: - x, y = self._canvas.Snap() + 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() @@ -1172,7 +1176,7 @@ class LineShape(Shape): if pt._type == CONTROL_POINT_LINE: pt._originalPos = pt._point - x, y = self._canvas.Snap() + x, y = self._canvas.Snap(x, y) self.Erase(dc) @@ -1204,7 +1208,7 @@ class LineShape(Shape): self.SetBrush(old_brush) if pt._type == CONTROL_POINT_ENDPOINT_FROM or pt._type == CONTROL_POINT_ENDPOINT_TO: - self._canvas.SetCursor(wx.Cursor(wx.CURSOR_BULLSEYE)) + self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_BULLSEYE)) pt._oldCursor = wx.STANDARD_CURSOR def OnSizingEndDragLeft(self, pt, x, y, keys = 0, attachment = 0): @@ -1214,7 +1218,7 @@ class LineShape(Shape): self.SetDisableLabel(False) if pt._type == CONTROL_POINT_LINE: - x, y = self._canvas.Snap() + x, y = self._canvas.Snap(x, y) rpt = wx.RealPoint(x, y) @@ -1234,15 +1238,15 @@ class LineShape(Shape): if pt._oldCursor: self._canvas.SetCursor(pt._oldCursor) - if self.GetFrom(): - self.GetFrom().MoveLineToNewAttachment(dc, self, x, y) + 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) + 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): @@ -1256,7 +1260,7 @@ class LineShape(Shape): return True - def AddArrow(self, type, end = ARROW_POSITION_END, size = 10.0, xOffset = 0.0, name="",mf = None, arrowId=-1): + 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: @@ -1326,7 +1330,7 @@ class LineShape(Shape): return True i1 = i2 = 0 - while i10: + if minWidth > 0: minWidth = minWidth * 1.4 else: minWidth = 20.0 @@ -1438,13 +1442,13 @@ class LineShape(Shape): 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)) + 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