📄 _basic.py
字号:
def GetNumberOfAttachments(self):
"""Get the number of attachment points for this shape."""
# Should return the MAXIMUM attachment point id here,
# so higher-level functions can iterate through all attachments,
# even if they're not contiguous.
if len(self._attachmentPoints) == 0:
return 4
else:
maxN = 3
for point in self._attachmentPoints:
if point._id > maxN:
maxN = point._id
return maxN + 1
def AttachmentIsValid(self, attachment):
"""TRUE if attachment is a valid attachment point."""
if len(self._attachmentPoints) == 0:
return attachment in range(4)
for point in self._attachmentPoints:
if point._id == attachment:
return True
return False
def GetAttachmentPosition(self, attachment, nth = 0, no_arcs = 1, line = None):
"""Get the position at which the given attachment point should be drawn.
If attachment isn't found among the attachment points of the shape,
returns None.
"""
if self._attachmentMode == ATTACHMENT_MODE_NONE:
return self._xpos, self._ypos
elif self._attachmentMode == ATTACHMENT_MODE_BRANCHING:
pt, stemPt = self.GetBranchingAttachmentPoint(attachment, nth)
return pt[0], pt[1]
elif self._attachmentMode == ATTACHMENT_MODE_EDGE:
if len(self._attachmentPoints):
for point in self._attachmentPoints:
if point._id == attachment:
return self._xpos + point._x, self._ypos + point._y
return None
else:
# Assume is rectangular
w, h = self.GetBoundingBoxMax()
top = self._ypos + h / 2.0
bottom = self._ypos - h / 2.0
left = self._xpos - w / 2.0
right = self._xpos + w / 2.0
# wtf?
line and line.IsEnd(self)
physicalAttachment = self.LogicalToPhysicalAttachment(attachment)
# Simplified code
if physicalAttachment == 0:
pt = self.CalcSimpleAttachment((left, bottom), (right, bottom), nth, no_arcs, line)
elif physicalAttachment == 1:
pt = self.CalcSimpleAttachment((right, bottom), (right, top), nth, no_arcs, line)
elif physicalAttachment == 2:
pt = self.CalcSimpleAttachment((left, top), (right, top), nth, no_arcs, line)
elif physicalAttachment == 3:
pt = self.CalcSimpleAttachment((left, bottom), (left, top), nth, no_arcs, line)
else:
return None
return pt[0], pt[1]
return None
def GetBoundingBoxMax(self):
"""Get the maximum bounding box for the shape, taking into account
external features such as shadows.
"""
ww, hh = self.GetBoundingBoxMin()
if self._shadowMode != SHADOW_NONE:
ww += self._shadowOffsetX
hh += self._shadowOffsetY
return ww, hh
def GetBoundingBoxMin(self):
"""Get the minimum bounding box for the shape, that defines the area
available for drawing the contents (such as text).
Must be overridden.
"""
return 0, 0
def HasDescendant(self, image):
"""TRUE if image is a descendant of this composite."""
if image == self:
return True
for child in self._children:
if child.HasDescendant(image):
return True
return False
# Assuming the attachment lies along a vertical or horizontal line,
# calculate the position on that point.
def CalcSimpleAttachment(self, pt1, pt2, nth, noArcs, line):
"""Assuming the attachment lies along a vertical or horizontal line,
calculate the position on that point.
Parameters:
pt1
The first point of the line repesenting the edge of the shape.
pt2
The second point of the line representing the edge of the shape.
nth
The position on the edge (for example there may be 6 lines at
this attachment point, and this may be the 2nd line.
noArcs
The number of lines at this edge.
line
The line shape.
Remarks
This function expects the line to be either vertical or horizontal,
and determines which.
"""
isEnd = line and line.IsEnd(self)
# Are we horizontal or vertical?
isHorizontal = RoughlyEqual(pt1[1], pt2[1])
if isHorizontal:
if pt1[0] > pt2[0]:
firstPoint = pt2
secondPoint = pt1
else:
firstPoint = pt1
secondPoint = pt2
if self._spaceAttachments:
if line and line.GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE:
# Align line according to the next handle along
point = line.GetNextControlPoint(self)
if point[0] < firstPoint[0]:
x = firstPoint[0]
elif point[0] > secondPoint[0]:
x = secondPoint[0]
else:
x = point[0]
else:
x = firstPoint[0] + (nth + 1) * (secondPoint[0] - firstPoint[0]) / (noArcs + 1.0)
else:
x = (secondPoint[0] - firstPoint[0]) / 2.0 # Midpoint
y = pt1[1]
else:
assert RoughlyEqual(pt1[0], pt2[0])
if pt1[1] > pt2[1]:
firstPoint = pt2
secondPoint = pt1
else:
firstPoint = pt1
secondPoint = pt2
if self._spaceAttachments:
if line and line.GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE:
# Align line according to the next handle along
point = line.GetNextControlPoint(self)
if point[1] < firstPoint[1]:
y = firstPoint[1]
elif point[1] > secondPoint[1]:
y = secondPoint[1]
else:
y = point[1]
else:
y = firstPoint[1] + (nth + 1) * (secondPoint[1] - firstPoint[1]) / (noArcs + 1.0)
else:
y = (secondPoint[1] - firstPoint[1]) / 2.0 # Midpoint
x = pt1[0]
return x, y
# Return the zero-based position in m_lines of line
def GetLinePosition(self, line):
"""Get the zero-based position of line in the list of lines
for this shape.
"""
try:
return self._lines.index(line)
except:
return 0
# |________|
# | <- root
# | <- neck
# shoulder1 ->---------<- shoulder2
# | | | | |
# <- branching attachment point N-1
def GetBranchingAttachmentInfo(self, attachment):
"""Get information about where branching connections go.
Returns FALSE if there are no lines at this attachment.
"""
physicalAttachment = self.LogicalToPhysicalAttachment(attachment)
# Number of lines at this attachment
lineCount = self.GetAttachmentLineCount(attachment)
if not lineCount:
return False
totalBranchLength = self._branchSpacing * (lineCount - 1)
root = self.GetBranchingAttachmentRoot(attachment)
neck = wx.RealPoint()
shoulder1 = wx.RealPoint()
shoulder2 = wx.RealPoint()
# Assume that we have attachment points 0 to 3: top, right, bottom, left
if physicalAttachment == 0:
neck[0] = self.GetX()
neck[1] = root[1] - self._branchNeckLength
shoulder1[0] = root[0] - totalBranchLength / 2.0
shoulder2[0] = root[0] + totalBranchLength / 2.0
shoulder1[1] = neck[1]
shoulder2[1] = neck[1]
elif physicalAttachment == 1:
neck[0] = root[0] + self._branchNeckLength
neck[1] = root[1]
shoulder1[0] = neck[0]
shoulder2[0] = neck[0]
shoulder1[1] = neck[1] - totalBranchLength / 2.0
shoulder1[1] = neck[1] + totalBranchLength / 2.0
elif physicalAttachment == 2:
neck[0] = self.GetX()
neck[1] = root[1] + self._branchNeckLength
shoulder1[0] = root[0] - totalBranchLength / 2.0
shoulder2[0] = root[0] + totalBranchLength / 2.0
shoulder1[1] = neck[1]
shoulder2[1] = neck[1]
elif physicalAttachment == 3:
neck[0] = root[0] - self._branchNeckLength
neck[1] = root[1]
shoulder1[0] = neck[0]
shoulder2[0] = neck[0]
shoulder1[1] = neck[1] - totalBranchLength / 2.0
shoulder2[1] = neck[1] + totalBranchLength / 2.0
else:
raise "Unrecognised attachment point in GetBranchingAttachmentInfo"
return root, neck, shoulder1, shoulder2
def GetBranchingAttachmentPoint(self, attachment, n):
physicalAttachment = self.LogicalToPhysicalAttachment(attachment)
root, neck, shoulder1, shoulder2 = self.GetBranchingAttachmentInfo(attachment)
pt = wx.RealPoint()
stemPt = wx.RealPoint()
if physicalAttachment == 0:
pt[1] = neck[1] - self._branchStemLength
pt[0] = shoulder1[0] + n * self._branchSpacing
stemPt[0] = pt[0]
stemPt[1] = neck[1]
elif physicalAttachment == 2:
pt[1] = neck[1] + self._branchStemLength
pt[0] = shoulder1[0] + n * self._branchStemLength
stemPt[0] = pt[0]
stemPt[1] = neck[1]
elif physicalAttachment == 1:
pt[0] = neck[0] + self._branchStemLength
pt[1] = shoulder1[1] + n * self._branchSpacing
stemPt[0] = neck[0]
stemPt[1] = pt[1]
elif physicalAttachment == 3:
pt[0] = neck[0] - self._branchStemLength
pt[1] = shoulder1[1] + n * self._branchSpacing
stemPt[0] = neck[0]
stemPt[1] = pt[1]
else:
raise "Unrecognised attachment point in GetBranchingAttachmentPoint"
return pt, stemPt
def GetAttachmentLineCount(self, attachment):
"""Get the number of lines at this attachment position."""
count = 0
for lineShape in self._lines:
if lineShape.GetFrom() == self and lineShape.GetAttachmentFrom() == attachment:
count += 1
elif lineShape.GetTo() == self and lineShape.GetAttachmentTo() == attachment:
count += 1
return count
def GetBranchingAttachmentRoot(self, attachment):
"""Get the root point at the given attachment."""
physicalAttachment = self.LogicalToPhysicalAttachment(attachment)
root = wx.RealPoint()
width, height = self.GetBoundingBoxMax()
# Assume that we have attachment points 0 to 3: top, right, bottom, left
if physicalAttachment == 0:
root[0] = self.GetX()
root[1] = self.GetY() - height / 2.0
elif physicalAttachment == 1:
root[0] = self.GetX() + width / 2.0
root[1] = self.GetY()
elif physicalAttachment == 2:
root[0] = self.GetX()
root[1] = self.GetY() + height / 2.0
elif physicalAttachment == 3:
root[0] = self.GetX() - width / 2.0
root[1] = self.GetY()
else:
raise "Unrecognised attachment point in GetBranchingAttachmentRoot"
return root
# Draw or erase the branches (not the actual arcs though)
def OnDrawBranchesAttachment(self, dc, attachment, erase = False):
count = self.GetAttachmentLineCount(attachment)
if count == 0:
return
root, neck, shoulder1, shoulder2 = self.GetBranchingAttachmentInfo(attachment)
if erase:
dc.SetPen(wx.WHITE_PEN)
dc.SetBrush(wx.WHITE_BRUSH)
else:
dc.SetPen(wx.BLACK_PEN)
dc.SetBrush(wx.BLACK_BRUSH)
# Draw neck
dc.DrawLine(root[0], root[1], neck[0], neck[1])
if count > 1:
# Draw shoulder-to-shoulder line
dc.DrawLine(shoulder1[0], shoulder1[1], shoulder2[0], shoulder2[1])
# Draw all the little branches
for i in range(count):
pt, stemPt = self.GetBranchingAttachmentPoint(attachment, i)
dc.DrawLine(stemPt[0], stemPt[1], pt[0], pt[1])
if self.GetBranchStyle() & BRANCHING_ATTACHMENT_BLOB and count > 1:
blobSize = 6.0
dc.DrawEllipse(stemPt[0] - blobSize / 2.0, stemPt[1] - blobSize / 2.0, blobSize, blobSize)
def OnDrawBranches(self, dc, erase = False):
if self._attachmentMode != ATTACHMENT_MODE_BRANCHING:
return
for i in range(self.GetNumbe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -