📄 _drawn.py
字号:
# -*- coding: iso-8859-1 -*-
#----------------------------------------------------------------------------
# Name: drawn.py
# Purpose: DrawnShape class
#
# Author: Pierre Hj鋖m (from C++ original by Julian Smart)
#
# Created: 2004-08-25
# RCS-ID: $Id: _drawn.py,v 1.3 2006/02/03 06:51:34 RD Exp $
# Copyright: (c) 2004 Pierre Hj鋖m - 1998 Julian Smart
# License: wxWindows license
#----------------------------------------------------------------------------
import os.path
from _basic import RectangleShape
from _oglmisc import *
METAFLAGS_OUTLINE = 1
METAFLAGS_ATTACHMENTS = 2
DRAWN_ANGLE_0 = 0
DRAWN_ANGLE_90 = 1
DRAWN_ANGLE_180 = 2
DRAWN_ANGLE_270 = 3
# Drawing operations
DRAWOP_SET_PEN = 1
DRAWOP_SET_BRUSH = 2
DRAWOP_SET_FONT = 3
DRAWOP_SET_TEXT_COLOUR = 4
DRAWOP_SET_BK_COLOUR = 5
DRAWOP_SET_BK_MODE = 6
DRAWOP_SET_CLIPPING_RECT = 7
DRAWOP_DESTROY_CLIPPING_RECT = 8
DRAWOP_DRAW_LINE = 20
DRAWOP_DRAW_POLYLINE = 21
DRAWOP_DRAW_POLYGON = 22
DRAWOP_DRAW_RECT = 23
DRAWOP_DRAW_ROUNDED_RECT = 24
DRAWOP_DRAW_ELLIPSE = 25
DRAWOP_DRAW_POINT = 26
DRAWOP_DRAW_ARC = 27
DRAWOP_DRAW_TEXT = 28
DRAWOP_DRAW_SPLINE = 29
DRAWOP_DRAW_ELLIPTIC_ARC = 30
class DrawOp(object):
def __init__(self, theOp):
self._op = theOp
def GetOp(self):
return self._op
def GetPerimeterPoint(self, x1, y1, x2, y2, xOffset, yOffset, attachmentMode):
return False
def Scale(self,scaleX, scaleY):
pass
def Translate(self, x, y):
pass
def Rotate(self, x, y, theta, sinTheta, cosTheta):
pass
class OpSetGDI(DrawOp):
"""Set font, brush, text colour."""
def __init__(self, theOp, theImage, theGdiIndex, theMode = 0):
DrawOp.__init__(self, theOp)
self._gdiIndex = theGdiIndex
self._image = theImage
self._mode = theMode
def Do(self, dc, xoffset = 0, yoffset = 0):
if self._op == DRAWOP_SET_PEN:
# Check for overriding this operation for outline colour
if self._gdiIndex in self._image._outlineColours:
if self._image._outlinePen:
dc.SetPen(self._image._outlinePen)
else:
try:
dc.SetPen(self._image._gdiObjects[self._gdiIndex])
except IndexError:
pass
elif self._op == DRAWOP_SET_BRUSH:
# Check for overriding this operation for outline or fill colour
if self._gdiIndex in self._image._outlineColours:
# Need to construct a brush to match the outline pen's colour
if self._image._outlinePen:
br = wx.Brush(self._image._outlinePen, wx.SOLID)
if br:
dc.SetBrush(br)
elif self._gdiIndex in self._image._fillColours:
if self._image._fillBrush:
dc.SetBrush(self._image._fillBrush)
else:
brush = self._image._gdiObjects[self._gdiIndex]
if brush:
dc.SetBrush(brush)
elif self._op == DRAWOP_SET_FONT:
try:
dc.SetFont(self._image._gdiObjects[self._gdiIndex])
except IndexError:
pass
elif self._op == DRAWOP_SET_TEXT_COLOUR:
dc.SetTextForeground(wx.Colour(self._r, self._g, self._b))
elif self._op == DRAWOP_SET_BK_COLOUR:
dc.SetTextBackground(wx.Colour(self._r, self._g, self._b))
elif self._op == DRAWOP_SET_BK_MODE:
dc.SetBackgroundMode(self._mode)
class OpSetClipping(DrawOp):
"""Set/destroy clipping."""
def __init__(self, theOp, theX1, theY1, theX2, theY2):
DrawOp.__init__(self, theOp)
self._x1 = theX1
self._y1 = theY1
self._x2 = theX2
self._y2 = theY2
def Do(self, dc, xoffset, yoffset):
if self._op == DRAWOP_SET_CLIPPING_RECT:
dc.SetClippingRegion(self._x1 + xoffset, self._y1 + yoffset, self._x2 + xoffset, self._y2 + yoffset)
elif self._op == DRAWOP_DESTROY_CLIPPING_RECT:
dc.DestroyClippingRegion()
def Scale(self, scaleX, scaleY):
self._x1 *= scaleX
self._y1 *= scaleY
self._x2 *= scaleX
self._y2 *= scaleY
def Translate(self, x, y):
self._x1 += x
self._y1 += y
class OpDraw(DrawOp):
"""Draw line, rectangle, rounded rectangle, ellipse, point, arc, text."""
def __init__(self, theOp, theX1, theY1, theX2, theY2, theRadius = 0.0, s = ""):
DrawOp.__init__(self, theOp)
self._x1 = theX1
self._y1 = theY1
self._x2 = theX2
self._y2 = theY2
self._x3 = 0.0
self._y3 = 0.0
self._radius = theRadius
self._textString = s
def Do(self, dc, xoffset, yoffset):
if self._op == DRAWOP_DRAW_LINE:
dc.DrawLine(self._x1 + xoffset, self._y1 + yoffset, self._x2 + xoffset, self._y2 + yoffset)
elif self._op == DRAWOP_DRAW_RECT:
dc.DrawRectangle(self._x1 + xoffset, self._y1 + yoffset, self._x2, self._y2)
elif self._op == DRAWOP_DRAW_ROUNDED_RECT:
dc.DrawRoundedRectangle(self._x1 + xoffset, self._y1 + yoffset, self._x2, self._y2, self._radius)
elif self._op == DRAWOP_DRAW_ELLIPSE:
dc.DrawEllipse(self._x1 + xoffset, self._y1 + yoffset, self._x2, self._y2)
elif self._op == DRAWOP_DRAW_ARC:
dc.DrawArc(self._x2 + xoffset, self._y2 + yoffset, self._x3 + xoffset, self._y3 + yoffset, self._x1 + xoffset, self._y1 + yoffset)
elif self._op == DRAWOP_DRAW_ELLIPTIC_ARC:
dc.DrawEllipticArc(self._x1 + xoffset, self._y1 + yoffset, self._x2, self._y2, self._x3 * 360 / (2 * math.pi), self._y3 * 360 / (2 * math.pi))
elif self._op == DRAWOP_DRAW_POINT:
dc.DrawPoint(self._x1 + xoffset, self._y1 + yoffset)
elif self._op == DRAWOP_DRAW_TEXT:
dc.DrawText(self._textString, self._x1 + xoffset, self._y1 + yoffset)
def Scale(self, scaleX, scaleY):
self._x1 *= scaleX
self._y1 *= scaleY
self._x2 *= scaleX
self._y2 *= scaleY
if self._op != DRAWOP_DRAW_ELLIPTIC_ARC:
self._x3 *= scaleX
self._y3 *= scaleY
self._radius *= scaleX
def Translate(self, x, y):
self._x1 += x
self._y1 += y
if self._op == DRAWOP_DRAW_LINE:
self._x2 += x
self._y2 += y
elif self._op == DRAWOP_DRAW_ARC:
self._x2 += x
self._y2 += y
self._x3 += x
self._y3 += y
def Rotate(self, x, y, theta, sinTheta, cosTheta):
newX1 = self._x1 * cosTheta + self._y1 * sinTheta + x * (1 - cosTheta) + y * sinTheta
newY1 = self._x1 * sinTheta + self._y1 * cosTheta + y * (1 - cosTheta) + x * sinTheta
if self._op == DRAWOP_DRAW_LINE:
newX2 = self._x2 * cosTheta - self._y2 * sinTheta + x * (1 - cosTheta) + y * sinTheta
newY2 = self._x2 * sinTheta + self._y2 * cosTheta + y * (1 - cosTheta) + x * sinTheta;
self._x1 = newX1
self._y1 = newY1
self._x2 = newX2
self._y2 = newY2
elif self._op in [DRAWOP_DRAW_RECT, DRAWOP_DRAW_ROUNDED_RECT, DRAWOP_DRAW_ELLIPTIC_ARC]:
# Assume only 0, 90, 180, 270 degree rotations.
# oldX1, oldY1 represents the top left corner. Find the
# bottom right, and rotate that. Then the width/height is
# the difference between x/y values.
oldBottomRightX = self._x1 + self._x2
oldBottomRightY = self._y1 + self._y2
newBottomRightX = oldBottomRightX * cosTheta - oldBottomRightY * sinTheta + x * (1 - cosTheta) + y * sinTheta
newBottomRightY = oldBottomRightX * sinTheta + oldBottomRightY * cosTheta + y * (1 - cosTheta) + x * sinTheta
# Now find the new top-left, bottom-right coordinates.
minX = min(newX1, newBottomRightX)
minY = min(newY1, newBottomRightY)
maxX = max(newX1, newBottomRightX)
maxY = max(newY1, newBottomRightY)
self._x1 = minX
self._y1 = minY
self._x2 = maxX - minX # width
self._y2 = maxY - minY # height
if self._op == DRAWOP_DRAW_ELLIPTIC_ARC:
# Add rotation to angles
self._x3 += theta
self._y3 += theta
elif self._op == DRAWOP_DRAW_ARC:
newX2 = self._x2 * cosTheta - self._y2 * sinTheta + x * (1 - cosTheta) + y * sinTheta
newY2 = self._x2 * sinTheta + self._y2 * cosTheta + y * (1 - cosTheta) + x * sinTheta
newX3 = self._x3 * cosTheta - self._y3 * sinTheta + x * (1 - cosTheta) + y * sinTheta
newY3 = self._x3 * sinTheta + self._y3 * cosTheta + y * (1 - cosTheta) + x * sinTheta
self._x1 = newX1
self._y1 = newY1
self._x2 = newX2
self._y2 = newY2
self._x3 = newX3
self._y3 = newY3
class OpPolyDraw(DrawOp):
"""Draw polygon, polyline, spline."""
def __init__(self, theOp, thePoints):
DrawOp.__init__(self, theOp)
self._noPoints = len(thePoints)
self._points = thePoints
def Do(self, dc, xoffset, yoffset):
if self._op == DRAWOP_DRAW_POLYLINE:
dc.DrawLines(self._points, xoffset, yoffset)
elif self._op == DRAWOP_DRAW_POLYGON:
dc.DrawPolygon(self._points, xoffset, yoffset)
elif self._op == DRAWOP_DRAW_SPLINE:
dc.DrawSpline(self._points) # no offsets in DrawSpline
def Scale(self, scaleX, scaleY):
for i in range(self._noPoints):
self._points[i] = wx.Point(self._points[i][0] * scaleX, self._points[i][1] * scaleY)
def Translate(self, x, y):
for i in range(self._noPoints):
self._points[i][0] += x
self._points[i][1] += y
def Rotate(self, x, y, theta, sinTheta, cosTheta):
for i in range(self._noPoints):
x1 = self._points[i][0]
y1 = self._points[i][1]
self._points[i] = x1 * cosTheta - y1 * sinTheta + x * (1 - cosTheta) + y * sinTheta, x1 * sinTheta + y1 * cosTheta + y * (1 - cosTheta) + x * sinTheta
def OnDrawOutline(self, dc, x, y, w, h, oldW, oldH):
dc.SetBrush(wx.TRANSPARENT_BRUSH)
# Multiply all points by proportion of new size to old size
x_proportion = abs(w / oldW)
y_proportion = abs(h / oldH)
dc.DrawPolygon([(x_proportion * x, y_proportion * y) for x, y in self._points], x, y)
def GetPerimeterPoint(self, x1, y1, x2, y2, xOffset, yOffset, attachmentMode):
# First check for situation where the line is vertical,
# and we would want to connect to a point on that vertical --
# oglFindEndForPolyline can't cope with this (the arrow
# gets drawn to the wrong place).
if attachmentMode == ATTACHMENT_MODE_NONE and x1 == x2:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -