]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/wx/lib/ogl/_lines.py
always use wxPyPanel
[wxWidgets.git] / wxPython / wx / lib / ogl / _lines.py
index 32ebb9c6c8186d4ce8011b38ceb8332c62a36b4f..fdee0ed6b5f400eb6b83058272cdea0d02a95a9a 100644 (file)
 # 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]<last_point[0]:
+            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]:
+                    if first_point[1] < last_point[1]:
                         y1 = first_point[1]
                         y2 = last_point[1]
                     else:
                         y2 = first_point[1]
                         y1 = last_point[1]
-                    point[0] = (x2-x1) / 2 + x1
-                    point[1] = (y2-y1) / 2 + y1
+                    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
@@ -368,7 +371,7 @@ class LineShape(Shape):
             w, h = 100, 50
             region.SetSize(w, h)
 
-        string_list = FormatText(dc, s, w-5, h-5, region.GetFormatMode())
+        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)
@@ -380,14 +383,14 @@ class LineShape(Shape):
             if actualW != w or actualH != h:
                 xx, yy = self.GetLabelPosition(i)
                 self.EraseRegion(dc, region, xx, yy)
-                if len(self._labelObjects)<i:
+                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:
+                if len(self._labelObjects) < i:
                     self._labelObjects[i].Select(True, dc)
                     self._labelObjects[i].Draw(dc)
 
@@ -415,7 +418,7 @@ class LineShape(Shape):
             # Now draw the text
             if region.GetFont():
                 dc.SetFont(region.GetFont())
-                dc.DrawRectangle(xp-w / 2, yp-h / 2, w, h)
+                dc.DrawRectangle(xp - w / 2.0, yp - h / 2.0, w, h)
 
                 if self._pen:
                     dc.SetPen(self._pen)
@@ -440,7 +443,7 @@ class LineShape(Shape):
             dc.SetPen(self.GetBackgroundPen())
             dc.SetBrush(self.GetBackgroundBrush())
 
-            dc.DrawRectangle(xp-w / 2, yp-h / 2, w, h)
+            dc.DrawRectangle(xp - w / 2.0, yp - h / 2.0, w, h)
 
     def GetLabelPosition(self, position):
         """Get the reference point for a label.
@@ -450,16 +453,16 @@ class LineShape(Shape):
         """
         if position == 0:
             # Want to take the middle section for the label
-            half_way = int(len(self._lineControlPoints) / 2)
+            half_way = int(len(self._lineControlPoints) / 2.0)
 
             # Find middle of this line
-            point = self._lineControlPoints[half_way-1]
+            point = self._lineControlPoints[half_way - 1]
             next_point = self._lineControlPoints[half_way]
 
-            dx = next_point[0]-point[0]
-            dy = next_point[1]-point[1]
+            dx = next_point[0] - point[0]
+            dy = next_point[1] - point[1]
 
-            return point[0] + dx / 2, point[1] + dy / 2
+            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:
@@ -467,7 +470,7 @@ class LineShape(Shape):
 
     def Straighten(self, dc = None):
         """Straighten verticals and horizontals."""
-        if len(self._lineControlPoints)<3:
+        if len(self._lineControlPoints) < 3:
             return
 
         if dc:
@@ -475,7 +478,7 @@ class LineShape(Shape):
 
         GraphicsStraightenLine(self._lineControlPoints[-1], self._lineControlPoints[-2])
 
-        for i in range(len(self._lineControlPoints)-2):
+        for i in range(len(self._lineControlPoints) - 2):
             GraphicsStraightenLine(self._lineControlPoints[i], self._lineControlPoints[i + 1])
                 
         if dc:
@@ -492,17 +495,12 @@ class LineShape(Shape):
 
     def SetEnds(self, x1, y1, x2, y2):
         """Set the end positions of the line."""
-        # Find centre point
-        first_point = self._lineControlPoints[0]
-        last_point = self._lineControlPoints[-1]
-
-        first_point[0] = x1
-        first_point[1] = y1
-        last_point[0] = x2
-        last_point[1] = y2
+        self._lineControlPoints[0] = wx.RealPoint(x1, y1)
+        self._lineControlPoints[-1] = wx.RealPoint(x2, y2)
 
-        self._xpos = (x1 + x2) / 2
-        self._ypos = (y1 + y2) / 2
+        # Find centre point
+        self._xpos = (x1 + x2) / 2.0
+        self._ypos = (y1 + y2) / 2.0
 
     # Get absolute positions of ends
     def GetEnds(self):
@@ -510,7 +508,7 @@ class LineShape(Shape):
         first_point = self._lineControlPoints[0]
         last_point = self._lineControlPoints[-1]
 
-        return (first_point[0], first_point[1]), (last_point[0], last_point[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
@@ -532,35 +530,35 @@ class LineShape(Shape):
                     xp, yp = self.GetLabelPosition(i)
                     # Offset region from default label position
                     cx, cy = region.GetPosition()
-                    cw, ch = region.GetSize()
+                    cw, ch = region.GetSize() 
                     cx += xp
                     cy += yp
                     
-                    rLeft = cx-cw / 2
-                    rTop = cy-ch / 2
-                    rRight = cx + cw / 2
-                    rBottom = cy + ch / 2
-                    if x>rLeft and x<rRight and y>rTop and y<rBottom:
+                    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):
+        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)<extra and distance_from_prev >= 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 = 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 * pi / 2
-                elif x1 == x2 and y2>y1:
-                    theta = pi / 2
-                elif x2>x1 and y2 >= y1:
-                    theta = math.atan((y2-y1) / (x2-x1))
-                elif x2<x1:
-                    theta = pi + math.atan((y2-y1) / (x2-x1))
-                elif x2>x1 and y2<y1:
-                    theta = 2 * pi + math.atan((y2-y1) / (x2-x1))
+                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"
 
@@ -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]<x1:
+            if point[0] < x1:
                 x1 = point[0]
-            if point[1]<y1:
+            if point[1] < y1:
                 y1 = point[1]
-            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 i<len(self._regions):
+                if i < len(self._regions):
                     xr, yr = self._regions[i].GetPosition()
                 else:
                     xr, yr = 0, 0
@@ -911,34 +909,39 @@ class LineShape(Shape):
         if not self._from or not self._to:
             return
 
-        if len(self._lineControlPoints)>2:
-            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 i1<len(referenceList) and i2<len(self._arcArrows):
+        while i1 < len(referenceList) and i2 < len(self._arcArrows):
             refArrow = referenceList[i1]
             currArrow = self._arcArrows[i2]
 
@@ -1337,7 +1341,7 @@ class LineShape(Shape):
             # Check if we're at the correct position in the
             # reference list
             if targetName == refArrow.GetName():
-                if i2<len(self._arcArrows):
+                if i2 < len(self._arcArrows):
                     self._arcArrows.insert(i2, arrow)
                 else:
                     self._arcArrows.append(arrow)
@@ -1351,7 +1355,7 @@ class LineShape(Shape):
         """Delete the arrows at the specified position, or at any position
         if position is -1.
         """
-        if end==-1:
+        if end == -1:
             self._arcArrows = []
             return
 
@@ -1373,8 +1377,8 @@ class LineShape(Shape):
         if position is -1, matches any position.
         """
         for arrow in self._arcArrows:
-            if (position==-1 or position == arrow.GetArrowEnd()) and arrow.GetName() == name:
-                return arow
+            if (position == -1 or position == arrow.GetArrowEnd()) and arrow.GetName() == name:
+                return arrow
 
         return None
 
@@ -1392,7 +1396,7 @@ class LineShape(Shape):
         if position is -1, matches any position.
         """
         for arrow in self._arcArrows:
-            if (position==-1 or position == arrow.GetArrowEnd()) and arrow.GetName() == name:
+            if (position == -1 or position == arrow.GetArrowEnd()) and arrow.GetName() == name:
                 self._arcArrows.remove(arrow)
                 return True
         return False
@@ -1420,7 +1424,7 @@ class LineShape(Shape):
         # We have ABSOLUTE minimum now. So
         # scale it to give it reasonable aesthetics
         # when drawing with line.
-        if minWidth>0:
+        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<startDistance and centreDistance<endDistance:
+        if centreDistance < startDistance and centreDistance < endDistance:
             return ARROW_POSITION_MIDDLE
-        elif startDistance<endDistance:
+        elif startDistance < endDistance:
             return ARROW_POSITION_START
         else:
             return ARROW_POSITION_END
@@ -1495,10 +1499,10 @@ class LineShape(Shape):
         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
+            nn = n - 2
         else:
             nn = 1
-        if nn<len(self._lineControlPoints):
+        if nn < len(self._lineControlPoints):
             return self._lineControlPoints[nn]
         return None
 
@@ -1510,17 +1514,12 @@ class LineShape(Shape):
         labelShape._shapeRegion.SetSize(labelShape.GetWidth(), labelShape.GetHeight())
 
         # Find position in line's region list
-        i = 0
-        for region in self.GetRegions():
-            if labelShape._shapeRegion == region:
-                self.GetRegions().remove(region)
-            else:
-                i += 1
+        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._shapeRegion.SetPosition(x - xx, y - yy)
         labelShape.SetX(x)
         labelShape.SetY(y)