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