📄 _lines.py
字号:
# -*- coding: iso-8859-1 -*-
#----------------------------------------------------------------------------
# Name: lines.py
# Purpose: LineShape class
#
# Author: Pierre Hj鋖m (from C++ original by Julian Smart)
#
# Created: 2004-05-08
# RCS-ID: $Id: _lines.py,v 1.17 2006/02/03 06:51:34 RD Exp $
# Copyright: (c) 2004 Pierre Hj鋖m - 1998 Julian Smart
# Licence: wxWindows license
#----------------------------------------------------------------------------
import sys
import math
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
class LineControlPoint(ControlPoint):
def __init__(self, theCanvas = None, object = None, size = 0.0, x = 0.0, y = 0.0, the_type = 0):
ControlPoint.__init__(self, theCanvas, object, size, x, y, the_type)
self._xpos = x
self._ypos = y
self._type = the_type
self._point = None
self._originalPos = None
def OnDraw(self, dc):
RectangleShape.OnDraw(self, dc)
# Implement movement of Line point
def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
self._shape.GetEventHandler().OnSizingDragLeft(self, draw, x, y, keys, attachment)
def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
self._shape.GetEventHandler().OnSizingBeginDragLeft(self, x, y, keys, attachment)
def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
self._shape.GetEventHandler().OnSizingEndDragLeft(self, x, y, keys, attachment)
class ArrowHead(object):
def __init__(self, type = 0, end = 0, size = 0.0, dist = 0.0, name = "", mf = None, arrowId = -1):
if isinstance(type, ArrowHead):
pass
else:
self._arrowType = type
self._arrowEnd = end
self._arrowSize = size
self._xOffset = dist
self._yOffset = 0.0
self._spacing = 5.0
self._arrowName = name
self._metaFile = mf
self._id = arrowId
if self._id == -1:
self._id = wx.NewId()
def _GetType(self):
return self._arrowType
def GetPosition(self):
return self._arrowEnd
def SetPosition(self, pos):
self._arrowEnd = pos
def GetXOffset(self):
return self._xOffset
def GetYOffset(self):
return self._yOffset
def GetSpacing(self):
return self._spacing
def GetSize(self):
return self._arrowSize
def SetSize(self, size):
self._arrowSize = size
if self._arrowType == ARROW_METAFILE and self._metaFile:
oldWidth = self._metaFile._width
if oldWidth == 0:
return
scale = float(size) / oldWidth
if scale != 1:
self._metaFile.Scale(scale, scale)
def GetName(self):
return self._arrowName
def SetXOffset(self, x):
self._xOffset = x
def SetYOffset(self, y):
self._yOffset = y
def GetMetaFile(self):
return self._metaFile
def GetId(self):
return self._id
def GetArrowEnd(self):
return self._arrowEnd
def GetArrowSize(self):
return self._arrowSize
def SetSpacing(self, sp):
self._spacing = sp
class LabelShape(RectangleShape):
def __init__(self, parent, region, w, h):
RectangleShape.__init__(self, w, h)
self._lineShape = parent
self._shapeRegion = region
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.0
y1 = self._ypos - self._height / 2.0
if self._pen:
if self._pen.GetWidth() == 0:
dc.SetPen(wx.Pen(wx.WHITE, 1, wx.TRANSPARENT))
else:
dc.SetPen(self._pen)
dc.SetBrush(wx.TRANSPARENT_BRUSH)
if self._cornerRadius > 0:
dc.DrawRoundedRectangle(x1, y1, self._width, self._height, self._cornerRadius)
else:
dc.DrawRectangle(x1, y1, self._width, self._height)
def OnDrawContents(self, dc):
pass
def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
RectangleShape.OnDragLeft(self, draw, x, y, keys, attachment)
def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
RectangleShape.OnBeginDragLeft(self, x, y, keys, attachment)
def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
RectangleShape.OnEndDragLeft(self, x, y, keys, attachment)
def OnMovePre(self, dc, x, y, old_x, old_y, display):
return self._lineShape.OnLabelMovePre(dc, self, x, y, old_x, old_y, display)
# Divert left and right clicks to line object
def OnLeftClick(self, x, y, keys = 0, attachment = 0):
self._lineShape.GetEventHandler().OnLeftClick(x, y, keys, attachment)
def OnRightClick(self, x, y, keys = 0, attachment = 0):
self._lineShape.GetEventHandler().OnRightClick(x, y, keys, attachment)
class LineShape(Shape):
"""LineShape may be attached to two nodes;
it may be segmented, in which case a control point is drawn for each joint.
A wxLineShape may have arrows at the beginning, end and centre.
Derived from:
Shape
"""
def __init__(self):
Shape.__init__(self)
self._sensitivity = OP_CLICK_LEFT | OP_CLICK_RIGHT
self._draggable = False
self._attachmentTo = 0
self._attachmentFrom = 0
self._from = None
self._to = None
self._erasing = False
self._arrowSpacing = 5.0
self._ignoreArrowOffsets = False
self._isSpline = False
self._maintainStraightLines = False
self._alignmentStart = 0
self._alignmentEnd = 0
self._lineControlPoints = None
# Clear any existing regions (created in an earlier constructor)
# and make the three line regions.
self.ClearRegions()
for name in ["Middle","Start","End"]:
newRegion = ShapeRegion()
newRegion.SetName(name)
newRegion.SetSize(150, 50)
self._regions.append(newRegion)
self._labelObjects = [None, None, None]
self._lineOrientations = []
self._lineControlPoints = []
self._arcArrows = []
def __del__(self):
if self._lineControlPoints:
self._lineControlPoints = []
for i in range(3):
if self._labelObjects[i]:
self._labelObjects[i].Select(False)
self._labelObjects[i].RemoveFromCanvas(self._canvas)
self._labelObjects = []
self.ClearArrowsAtPosition(-1)
def GetFrom(self):
"""Return the 'from' object."""
return self._from
def GetTo(self):
"""Return the 'to' object."""
return self._to
def GetAttachmentFrom(self):
"""Return the attachment point on the 'from' node."""
return self._attachmentFrom
def GetAttachmentTo(self):
"""Return the attachment point on the 'to' node."""
return self._attachmentTo
def GetLineControlPoints(self):
return self._lineControlPoints
def SetSpline(self, spline):
"""Specifies whether a spline is to be drawn through the control points."""
self._isSpline = spline
def IsSpline(self):
"""TRUE if a spline is drawn through the control points."""
return self._isSpline
def SetAttachmentFrom(self, attach):
"""Set the 'from' shape attachment."""
self._attachmentFrom = attach
def SetAttachmentTo(self, attach):
"""Set the 'to' shape attachment."""
self._attachmentTo = attach
# This is really to distinguish between lines and other images.
# For lines, want to pass drag to canvas, since lines tend to prevent
# dragging on a canvas (they get in the way.)
def Draggable(self):
return False
def SetIgnoreOffsets(self, ignore):
"""Set whether to ignore offsets from the end of the line when drawing."""
self._ignoreArrowOffsets = ignore
def GetArrows(self):
return self._arcArrows
def GetAlignmentStart(self):
return self._alignmentStart
def GetAlignmentEnd(self):
return self._alignmentEnd
def IsEnd(self, nodeObject):
"""TRUE if shape is at the end of the line."""
return self._to == nodeObject
def MakeLineControlPoints(self, n):
"""Make a given number of control points (minimum of two)."""
self._lineControlPoints = []
for _ in range(n):
point = wx.RealPoint(-999, -999)
self._lineControlPoints.append(point)
# 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)
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.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)-1, point)
def DeleteLineControlPoint(self):
"""Delete an arbitary point on the line."""
if len(self._lineControlPoints) < 3:
return False
del self._lineControlPoints[-2]
return True
def Initialise(self):
"""Initialise the line object."""
if self._lineControlPoints:
# Just move the first and last control points
first_point = self._lineControlPoints[0]
last_point = self._lineControlPoints[-1]
# If any of the line points are at -999, we must
# initialize them by placing them half way between the first
# and the last.
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]:
y1 = first_point[1]
y2 = last_point[1]
else:
y2 = first_point[1]
y1 = last_point[1]
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
strings with positions to region text list.
"""
self.ClearText(i)
if len(self._regions) == 0 or i >= len(self._regions):
return
region = self._regions[i]
region.SetText(s)
dc.SetFont(region.GetFont())
w, h = region.GetSize()
# Initialize the size if zero
if (w == 0 or h == 0) and s:
w, h = 100, 50
region.SetSize(w, h)
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)
actualW = w
actualH = h
if region.GetFormatMode() & FORMAT_SIZE_TO_CONTENTS:
actualW, actualH = GetCentredTextExtent(dc, region.GetFormattedText(), self._xpos, self._ypos, w, h)
if actualW != w or actualH != h:
xx, yy = self.GetLabelPosition(i)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -