📄 _composit.py
字号:
changed = False
for constrainedObject in self._constrainedObjects:
y3 = y + minHeight / 2.0
if not self.Equals(y3, constrainedObject.GetY()):
changed = True
constrainedObject.Move(dc, constrainedObject.GetX(), y3, False)
return changed
return False
OGLConstraint = wx._core._deprecated(Constraint,
"The OGLConstraint name is deprecated, use `ogl.Constraint` instead.")
class CompositeShape(RectangleShape):
"""This is an object with a list of child objects, and a list of size
and positioning constraints between the children.
Derived from:
wxRectangleShape
"""
def __init__(self):
RectangleShape.__init__(self, 100.0, 100.0)
self._oldX = self._xpos
self._oldY = self._ypos
self._constraints = []
self._divisions = [] # In case it's a container
def OnDraw(self, dc):
x1 = self._xpos - self._width / 2.0
y1 = self._ypos - self._height / 2.0
if self._shadowMode != SHADOW_NONE:
if self._shadowBrush:
dc.SetBrush(self._shadowBrush)
dc.SetPen(wx.Pen(wx.WHITE, 1, wx.TRANSPARENT))
if self._cornerRadius:
dc.DrawRoundedRectangle(x1 + self._shadowOffsetX, y1 + self._shadowOffsetY, self._width, self._height, self._cornerRadius)
else:
dc.DrawRectangle(x1 + self._shadowOffsetX, y1 + self._shadowOffsetY, self._width, self._height)
# For debug purposes /pi
#dc.DrawRectangle(x1, y1, self._width, self._height)
def OnDrawContents(self, dc):
for object in self._children:
object.Draw(dc)
object.DrawLinks(dc)
Shape.OnDrawContents(self, dc)
def OnMovePre(self, dc, x, y, old_x, old_y, display = True):
diffX = x - old_x
diffY = y - old_y
for object in self._children:
object.Erase(dc)
object.Move(dc, object.GetX() + diffX, object.GetY() + diffY, display)
return True
def OnErase(self, dc):
RectangleShape.OnErase(self, dc)
for object in self._children:
object.Erase(dc)
def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
xx, yy = self._canvas.Snap(x, y)
offsetX = xx - _objectStartX
offsetY = yy - _objectStartY
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)
self.GetEventHandler().OnDrawOutline(dc, self.GetX() + offsetX, self.GetY() + offsetY, self.GetWidth(), self.GetHeight())
def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
global _objectStartX, _objectStartY
_objectStartX = x
_objectStartY = y
dc = wx.ClientDC(self.GetCanvas())
self.GetCanvas().PrepareDC(dc)
#self.Erase(dc)
dc.SetLogicalFunction(OGLRBLF)
dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
dc.SetPen(dottedPen)
dc.SetBrush(wx.TRANSPARENT_BRUSH)
self._canvas.CaptureMouse()
xx, yy = self._canvas.Snap(x, y)
offsetX = xx - _objectStartX
offsetY = yy - _objectStartY
self.GetEventHandler().OnDrawOutline(dc, self.GetX() + offsetX, self.GetY() + offsetY, self.GetWidth(), self.GetHeight())
def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
dc = wx.ClientDC(self.GetCanvas())
self.GetCanvas().PrepareDC(dc)
if self._canvas.HasCapture():
self._canvas.ReleaseMouse()
if not self._draggable:
if self._parent:
self._parent.GetEventHandler().OnEndDragLeft(x, y, keys, 0)
return
self.Erase(dc)
dc.SetLogicalFunction(wx.COPY)
xx, yy = self._canvas.Snap(x, y)
offsetX = xx - _objectStartX
offsetY = yy - _objectStartY
self.Move(dc, self.GetX() + offsetX, self.GetY() + offsetY)
if self._canvas and not self._canvas.GetQuickEditMode():
self._canvas.Redraw(dc)
def OnRightClick(self, x, y, keys = 0, attachment = 0):
# If we get a ctrl-right click, this means send the message to
# the division, so we can invoke a user interface for dealing
# with regions.
if keys & KEY_CTRL:
for division in self._divisions:
hit = division.HitTest(x, y)
if hit:
division.GetEventHandler().OnRightClick(x, y, keys, hit[0])
break
def SetSize(self, w, h, recursive = True):
self.SetAttachmentSize(w, h)
xScale = float(w) / max(1, self.GetWidth())
yScale = float(h) / max(1, self.GetHeight())
self._width = w
self._height = h
if not recursive:
return
dc = wx.ClientDC(self.GetCanvas())
self.GetCanvas().PrepareDC(dc)
for object in self._children:
# Scale the position first
newX = (object.GetX() - self.GetX()) * xScale + self.GetX()
newY = (object.GetY() - self.GetY()) * yScale + self.GetY()
object.Show(False)
object.Move(dc, newX, newY)
object.Show(True)
# Now set the scaled size
xbound, ybound = object.GetBoundingBoxMax()
if not object.GetFixedWidth():
xbound *= xScale
if not object.GetFixedHeight():
ybound *= yScale
object.SetSize(xbound, ybound)
self.SetDefaultRegionSize()
def AddChild(self, child, addAfter = None):
"""Adds a child shape to the composite.
If addAfter is not None, the shape will be added after this shape.
"""
self._children.append(child)
child.SetParent(self)
if self._canvas:
# Ensure we add at the right position
if addAfter:
child.RemoveFromCanvas(self._canvas)
child.AddToCanvas(self._canvas, addAfter)
def RemoveChild(self, child):
"""Removes the child from the composite and any constraint
relationships, but does not delete the child.
"""
if child in self._children:
self._children.remove(child)
if child in self._divisions:
self._divisions.remove(child)
self.RemoveChildFromConstraints(child)
child.SetParent(None)
def Delete(self):
"""
Fully disconnect this shape from parents, children, the
canvas, etc.
"""
for child in self.GetChildren():
self.RemoveChild(child)
child.Delete()
RectangleShape.Delete(self)
self._constraints = []
self._divisions = []
def DeleteConstraintsInvolvingChild(self, child):
"""This function deletes constraints which mention the given child.
Used when deleting a child from the composite.
"""
for constraint in self._constraints:
if constraint._constrainingObject == child or child in constraint._constrainedObjects:
self._constraints.remove(constraint)
def RemoveChildFromConstraints(self, child):
for constraint in self._constraints:
if child in constraint._constrainedObjects:
constraint._constrainedObjects.remove(child)
if constraint._constrainingObject == child:
constraint._constrainingObject = None
# Delete the constraint if no participants left
if not constraint._constrainingObject:
self._constraints.remove(constraint)
def AddConstraint(self, constraint):
"""Adds a constraint to the composite."""
self._constraints.append(constraint)
if constraint._constraintId == 0:
constraint._constraintId = wx.NewId()
return constraint
def AddSimpleConstraint(self, type, constraining, constrained):
"""Add a constraint of the given type to the composite.
constraining is the shape doing the constraining
constrained is a list of shapes being constrained
"""
constraint = Constraint(type, constraining, constrained)
if constraint._constraintId == 0:
constraint._constraintId = wx.NewId()
self._constraints.append(constraint)
return constraint
def FindConstraint(self, cId):
"""Finds the constraint with the given id.
Returns a tuple of the constraint and the actual composite the
constraint was in, in case that composite was a descendant of
this composit.
Returns None if not found.
"""
for constraint in self._constraints:
if constraint._constraintId == cId:
return constraint, self
# If not found, try children
for child in self._children:
if isinstance(child, CompositeShape):
constraint = child.FindConstraint(cId)
if constraint:
return constraint[0], child
return None
def DeleteConstraint(self, constraint):
"""Deletes constraint from composite."""
self._constraints.remove(constraint)
def CalculateSize(self):
"""Calculates the size and position of the composite based on
child sizes and positions.
"""
maxX = -999999.9
maxY = -999999.9
minX = 999999.9
minY = 999999.9
for child in self._children:
# Recalculate size of composite objects because may not conform
# to size it was set to - depends on the children.
if isinstance(child, CompositeShape):
child.CalculateSize()
w, h = child.GetBoundingBoxMax()
if child.GetX() + w / 2.0 > maxX:
maxX = child.GetX() + w / 2.0
if child.GetX() - w / 2.0 < minX:
minX = child.GetX() - w / 2.0
if child.GetY() + h / 2.0 > maxY:
maxY = child.GetY() + h / 2.0
if child.GetY() - h / 2.0 < minY:
minY = child.GetY() - h / 2.0
self._width = maxX - minX
self._height = maxY - minY
self._xpos = self._width / 2.0 + minX
self._ypos = self._height / 2.0 + minY
def Recompute(self):
"""Recomputes any constraints associated with the object. If FALSE is
returned, the constraints could not be satisfied (there was an
inconsistency).
"""
noIterations = 0
changed = True
while changed and noIterations < 500:
changed = self.Constrain()
noIterations += 1
return not changed
def Constrain(self):
self.CalculateSize()
changed = False
for child in self._children:
if isinstance(child, CompositeShape) and child.Constrain():
changed = True
for constraint in self._constraints:
if constraint.Evaluate():
changed = True
return changed
def MakeContainer(self):
"""Makes this composite into a container by creating one child
DivisionShape.
"""
division = self.OnCreateDivision()
self._divisions.append(division)
self.AddChild(division)
division.SetSize(self._width, self._height)
dc = wx.ClientDC(self.GetCanvas())
self.GetCanvas().PrepareDC(dc)
division.Move(dc, self.GetX(), self.GetY())
self.Recompute()
division.Show(True)
def OnCreateDivision(self):
return DivisionShape()
def FindContainerImage(self):
"""Finds the image used to visualize a container. This is any child of
the composite that is not in the divisions list.
"""
for child in self._children:
if child in self._divisions:
return child
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -