📄 _lines.py
字号:
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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -