Merge branch 'master' into wip-demo

This commit is contained in:
Robin Dunn
2016-07-30 12:35:05 -07:00
12 changed files with 2861 additions and 565 deletions

View File

@@ -78,7 +78,7 @@ if __name__ == '__main__':
unitteststub = """\
import unittest
import wtc
from unittests import wtc
import wx
#---------------------------------------------------------------------------

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python
import wx
import wx.adv
import images
import random
@@ -10,7 +11,7 @@ W = 2000
H = 2000
SW = 150
SH = 150
SHAPE_COUNT = 2500
SHAPE_COUNT = 750
hitradius = 5
#---------------------------------------------------------------------------
@@ -58,7 +59,7 @@ class MyCanvas(wx.ScrolledWindow):
self.SetScrollRate(20,20)
# create a PseudoDC to record our drawing
self.pdc = wx.PseudoDC()
self.pdc = wx.adv.PseudoDC()
self.pen_cache = {}
self.brush_cache = {}
self.DoDrawing(self.pdc)
@@ -81,7 +82,7 @@ class MyCanvas(wx.ScrolledWindow):
def OffsetRect(self, r):
xView, yView = self.GetViewStart()
xDelta, yDelta = self.GetScrollPixelsPerUnit()
r.OffsetXY(-(xView*xDelta),-(yView*yDelta))
r.Offset(-(xView*xDelta),-(yView*yDelta))
def OnMouse(self, event):
global hitradius
@@ -123,14 +124,14 @@ class MyCanvas(wx.ScrolledWindow):
def RandomPen(self):
c = random.choice(colours)
t = random.randint(1, 4)
if not self.pen_cache.has_key( (c, t) ):
if (c, t) not in self.pen_cache:
self.pen_cache[(c, t)] = wx.Pen(c, t)
return self.pen_cache[(c, t)]
def RandomBrush(self):
c = random.choice(colours)
if not self.brush_cache.has_key(c):
if c not in self.brush_cache:
self.brush_cache[c] = wx.Brush(c)
return self.brush_cache[c]
@@ -144,12 +145,15 @@ class MyCanvas(wx.ScrolledWindow):
# wx.PaintDC and then blit the bitmap to it when dc is
# deleted.
dc = wx.BufferedPaintDC(self)
# use PrepateDC to set position correctly
self.PrepareDC(dc)
# we need to clear the dc BEFORE calling PrepareDC
bg = wx.Brush(self.GetBackgroundColour())
dc.SetBackground(bg)
dc.Clear()
# use PrepareDC to set position correctly
self.PrepareDC(dc)
# create a clipping rect from our position and size
# and the Update Region
xv, yv = self.GetViewStart()
@@ -158,9 +162,12 @@ class MyCanvas(wx.ScrolledWindow):
rgn = self.GetUpdateRegion()
rgn.Offset(x,y)
r = rgn.GetBox()
# draw to the dc using the calculated clipping rect
# Draw the saved drawing operations to the dc using the calculated
# clipping rect
self.pdc.DrawToDCClipped(dc,r)
def DoDrawing(self, dc):
random.seed()
self.objids = []
@@ -298,9 +305,9 @@ def runTest(frame, nb, log):
overview = """
<html>
<body>
<h2>wx.PseudoDC</h2>
<h2>wx.adv.PseudoDC</h2>
The wx.PseudoDC class provides a way to record operations on a DC and then
The wx.adv.PseudoDC class provides a way to record operations on a DC and then
play them back later. The PseudoDC can be passed to a drawing routine as
if it were a real DC. All Drawing methods are supported except Blit but
GetXXX methods are not supported and none of the drawing methods return
@@ -308,11 +315,11 @@ a value. The PseudoDC records the drawing to an operation
list. The operations can be played back to a real DC using:<pre>
DrawToDC(dc)
</pre>
The operations can be tagged with an id in order to associated them with a
The operations can be tagged with an id in order to associate them with a
specific object. To do this use:<pre>
SetId(id)
</pre>
Every operation after this will be associated with id until SetId is called
Every operation after this will be associated with that tag id until SetId is called
again. The PseudoDC also supports object level clipping. To enable this use:<pre>
SetIdBounds(id,rect)
</pre>
@@ -320,7 +327,7 @@ for each object that should be clipped. Then use:<pre>
DrawToDCClipped(dc, clippingRect)
</pre>
To draw the PseudoDC to a real dc. This is useful for large scrolled windows
where many objects are offscreen.
where many objects are off screen.
Objects can be moved around without re-drawing using:<pre>
TranslateId(id, dx, dy)

File diff suppressed because it is too large Load Diff

View File

@@ -2514,6 +2514,7 @@
"ProgressDialog":"wx.",
"PropagateOnce":"wx.",
"PropagationDisabler":"wx.",
"PseudoDC":"wx.adv.",
"PyApp":"wx.",
"PyAxBaseWindow":"wx.msw.",
"PyCommandEvent":"wx.",

View File

@@ -52,6 +52,7 @@ INCLUDES = [
'richtooltip',
'timectrl',
'wizard',
'pseudodc',
]

687
etg/pseudodc.py Normal file
View File

@@ -0,0 +1,687 @@
#---------------------------------------------------------------------------
# Name: etg/pseudodc.py
# Author: Robin Dunn
#
# Created: 26-Jul-2016
# Copyright: (c) 2016 by Total Control Software
# License: wxWindows License
#---------------------------------------------------------------------------
import etgtools
import etgtools.tweaker_tools as tools
from etgtools.extractors import ClassDef, MethodDef, ParamDef
PACKAGE = "wx"
MODULE = "_adv"
NAME = "pseudodc" # Base name of the file to generate to for this script
DOCSTRING = ""
# The classes and/or the basename of the Doxygen XML files to be processed by
# this script.
ITEMS = [ ]
OTHERDEPS = [ 'src/pseudodc.h',
'src/pseudodc.cpp',
]
#---------------------------------------------------------------------------
def run():
# Parse the XML file(s) building a collection of Extractor objects
module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING)
etgtools.parseDoxyXML(module, ITEMS)
#-----------------------------------------------------------------
# Tweak the parsed meta objects in the module object as needed for
# customizing the generated code and docstrings.
# The PseudoDC class is not in wxWidgets, so there is no Doxygen XML for
# them. That means we'll have to construct the extractor objects here,
# from scratch.
module.addHeaderCode('#include "pseudodc.h"')
module.includeCppCode('src/pseudodc.cpp')
cls = ClassDef(name='wxPseudoDC', bases=['wxObject'],
briefDoc="""\
A PseudoDC is an object that can be used much like real
:class:`wx.DC`, however it provides some additional features for
object recording and manipulation beyond what a ``wx.DC`` can
provide.
All commands issued to the ``PseudoDC`` are stored in a list. You
can then play these commands back to a real DC object as often as
needed, using the :meth:`DrawToDC` method or one of the similar
methods. Commands in the command list can be tagged by an ID. You
can use this ID to clear the operations associated with a single
ID, redraw the objects associated with that ID, grey them, adjust
their position, etc.
""",
items=[
# ----------------------------------------------
# Constructor and Destructor
MethodDef(name='wxPseudoDC', isCtor=True, items=[],
briefDoc="""\
Constructs a new Pseudo device context for recording and
replaying DC operations."""),
MethodDef(name='~wxPseudoDC', isDtor=True),
# ----------------------------------------------
# PseudoDC-specific functionality
MethodDef(type='void', name='RemoveAll', items=[],
briefDoc="Removes all objects and operations from the recorded list."),
MethodDef(type='int', name='GetLen', items=[],
briefDoc="Returns the number of operations in the recorded list."),
MethodDef(type='void', name='SetId',
items=[ParamDef(type='int', name='id')],
briefDoc="Sets the id to be associated with subsequent operations."),
MethodDef(type='void', name='ClearId',
items=[ParamDef(type='int', name='id')],
briefDoc="Removes all operations associated with id so the object can be redrawn."),
MethodDef(type='void', name='RemoveId',
items=[ParamDef(type='int', name='id')],
briefDoc="Remove the object node (and all operations) associated with an id."),
MethodDef(type='void', name='TranslateId',
items=[ParamDef(type='int', name='id'),
ParamDef(type='wxCoord', name='dx'),
ParamDef(type='wxCoord', name='dy'),
],
briefDoc="Translate the position of the operations of tag `id` by (`dx`, `dy`)."),
MethodDef(type='void', name='SetIdGreyedOut',
items=[ParamDef(type='int', name='id'),
ParamDef(type='bool', name='greyout'),
],
briefDoc="Set whether the set of objects with tag `id` are drawn greyed out or not."),
MethodDef(type='bool', name='GetIdGreyedOut',
items=[ParamDef(type='int', name='id')],
briefDoc="Get whether the set of objects with tag `id` are drawn greyed out or not."),
MethodDef(type='PyObject*', name='FindObjects',
items=[ ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y'),
ParamDef(type='wxCoord', name='radius', default='1'),
ParamDef(type='const wxColour &', name='bg', default='*wxWHITE'),
],
briefDoc="""\
Returns a list of all the id's that draw a pixel with
color not equal to bg within radius of (x,y). Returns an
empty list if nothing is found. The list is in reverse
drawing order so list[0] is the top id."""),
MethodDef(type='PyObject*', name='FindObjectsByBBox',
items=[ ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y')],
briefDoc="""\
Returns a list of all the id's whose bounding boxes include (x,y).
Returns an empty list if nothing is found. The list is in
reverse drawing order so list[0] is the top id."""),
MethodDef(type='void', name='DrawIdToDC',
items=[ ParamDef(type='int', name='id'),
ParamDef(type='wxDC *', name='dc')],
briefDoc="Draw recorded operations tagged with id to dc."),
MethodDef(type='void', name='SetIdBounds',
items=[ ParamDef(type='int', name='id'),
ParamDef(type='wxRect &', name='rect')],
briefDoc="""\
Set the bounding rect of a given object.
This will create an object node if one doesn't exist."""),
MethodDef(type='wxRect', name='GetIdBounds',
items=[ParamDef(type='int', name='id')],
briefDoc="""\
Returns the bounding rectangle previously set with `SetIdBounds`.
If no bounds have been set, it returns wx.Rect(0,0,0,0)."""),
MethodDef(type='void', name='DrawToDCClipped',
items=[ ParamDef(type='wxDC *', name='dc'),
ParamDef(type='const wxRect &', name='rect')],
briefDoc="""\
Draws the recorded operations to dc,
unless the operation is known to be outside of rect."""),
MethodDef(type='void', name='DrawToDCClippedRgn',
items=[ParamDef(type='wxDC *', name='dc'),
ParamDef(type='const wxRegion &', name='region')],
briefDoc="""\
Draws the recorded operations to dc,
unless the operation is known to be outside the given region."""),
MethodDef(type='void', name='DrawToDC',
items=[ParamDef(type='wxDC *', name='dc')],
briefDoc="Draws the recorded operations to dc."),
#----------------------------------------------
# Methods which mirror the wxDC API
MethodDef(type='void', name='FloodFill',
items=[ ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y'),
ParamDef(type='const wxColour &', name='col'),
ParamDef(type='wxFloodFillStyle', name='style', default='wxFLOOD_SURFACE')],
briefDoc="""\
Flood fills the device context starting from the given point,
using the current brush colour, and using a style:
- ``wx.FLOOD_SURFACE``: the flooding occurs until a colour other than the given colour is encountered.
- ``wx.FLOOD_BORDER``: the area to be flooded is bounded by the given colour.
""",
overloads=[
MethodDef(type='void', name='FloodFill',
items=[ ParamDef(type='const wxPoint &', name='pt'),
ParamDef(type='const wxColour &', name='col'),
ParamDef(type='wxFloodFillStyle', name='style', default='wxFLOOD_SURFACE')]),
]),
MethodDef(type='void', name='DrawLine',
items=[ ParamDef(type='wxCoord', name='x1'),
ParamDef(type='wxCoord', name='y1'),
ParamDef(type='wxCoord', name='x2'),
ParamDef(type='wxCoord', name='y2')],
briefDoc="""\
Draws a line from the first point to the second.
The current pen is used for drawing the line. Note that
the second point is *not* part of the line and is not
drawn by this function (this is consistent with the
behaviour of many other toolkits).
""",
overloads=[
MethodDef(type='void', name='DrawLine',
items=[ ParamDef(type='const wxPoint &', name='pt1'),
ParamDef(type='const wxPoint &', name='pt2')])
]),
MethodDef(type='void', name='CrossHair',
items=[ ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y')],
briefDoc="""\
Displays a cross hair using the current pen. This is a
vertical and horizontal line the height and width of the
window, centred on the given point.""",
overloads=[
MethodDef(type='void', name='CrossHair',
items=[ ParamDef(type='const wxPoint &', name='pt') ])
]),
MethodDef(type='void', name='DrawArc',
items=[ ParamDef(type='wxCoord', name='x1'),
ParamDef(type='wxCoord', name='y1'),
ParamDef(type='wxCoord', name='x2'),
ParamDef(type='wxCoord', name='y2'),
ParamDef(type='wxCoord', name='xc'),
ParamDef(type='wxCoord', name='yc'),],
briefDoc="""\
Draws an arc of a circle, centred on the *center* point
(xc, yc), from the first point to the second. The current
pen is used for the outline and the current brush for
filling the shape.
The arc is drawn in an anticlockwise direction from the
start point to the end point.
""",
overload=[
MethodDef(type='void', name='DrawArc',
items=[ParamDef(type='wxCoord', name='x1'),
ParamDef(type='wxCoord', name='xc'),
ParamDef(type='wxCoord', name='yc'), ]),
]),
MethodDef(type='void', name='DrawCheckMark',
items=[ ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y'),
ParamDef(type='wxCoord', name='width'),
ParamDef(type='wxCoord', name='height')],
briefDoc="Draws a check mark inside the given rectangle",
overloads=[
MethodDef(type='void', name='DrawCheckMark',
items=[ ParamDef(type='const wxRect &', name='rect') ])
]),
MethodDef(type='void', name='DrawEllipticArc',
items=[ ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y'),
ParamDef(type='wxCoord', name='w'),
ParamDef(type='wxCoord', name='h'),
ParamDef(type='double', name='start'),
ParamDef(type='double', name='end')],
briefDoc="""\
Draws an arc of an ellipse, with the given rectangle
defining the bounds of the ellipse. The current pen is
used for drawing the arc and the current brush is used for
drawing the pie.
The *start* and *end* parameters specify the start and end
of the arc relative to the three-o'clock position from the
center of the rectangle. Angles are specified in degrees
(360 is a complete circle). Positive values mean
counter-clockwise motion. If start is equal to end, a
complete ellipse will be drawn.""",
overloads=[
MethodDef(type='void', name='DrawEllipticArc',
items=[ ParamDef(type='const wxPoint &', name='pt'),
ParamDef(type='const wxSize &', name='sz'),
ParamDef(type='double', name='start'),
ParamDef(type='double', name='end')])
]),
MethodDef(type='void', name='DrawPoint',
items=[ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y')],
briefDoc="Draws a point using the current pen.",
overloads=[
MethodDef(type='void', name='DrawPoint',
items=[ParamDef(type='const wxPoint &', name='pt') ])
]),
MethodDef(type='void', name='DrawRectangle',
items=[ ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y'),
ParamDef(type='wxCoord', name='width'),
ParamDef(type='wxCoord', name='height') ],
briefDoc="""\
Draws a rectangle with the given top left corner, and with
the given size. The current pen is used for the outline
and the current brush for filling the shape.
""",
overloads=[
MethodDef(type='void', name='DrawRectangle',
items=[ ParamDef(type='const wxRect &', name='rect') ]),
MethodDef(type='void', name='DrawRectangle',
items=[ ParamDef(type='const wxPoint &', name='pt'),
ParamDef(type='const wxSize &', name='sz') ])
]),
MethodDef(type='void', name='DrawRoundedRectangle',
items=[ ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y'),
ParamDef(type='wxCoord', name='width'),
ParamDef(type='wxCoord', name='height'),
ParamDef(type='double', name='radius')],
briefDoc="""\
Draws a rectangle with the given top left corner, and with
the given size. The current pen is used for the outline
and the current brush for filling the shape.
""",
overloads=[
MethodDef(type='void', name='DrawRoundedRectangle',
items=[ ParamDef(type='const wxRect &', name='rect'),
ParamDef(type='double', name='radius') ]),
MethodDef(type='void', name='DrawRoundedRectangle',
items=[ ParamDef(type='const wxPoint &', name='pt'),
ParamDef(type='const wxSize &', name='sz'),
ParamDef(type='double', name='radius') ])
]),
MethodDef(type='void', name='DrawCircle',
items=[ ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y'),
ParamDef(type='wxCoord', name='radius'),],
briefDoc="""\
Draws a circle with the given center point and radius.
The current pen is used for the outline and the current
brush for filling the shape.
:see: `DrawEllipse`
""",
overloads=[
MethodDef(type='void', name='DrawCircle',
items=[ ParamDef(type='const wxPoint &', name='pt'),
ParamDef(type='wxCoord', name='radius') ]),
]),
MethodDef(type='void', name='DrawEllipse',
items=[ ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y'),
ParamDef(type='wxCoord', name='width'),
ParamDef(type='wxCoord', name='height')],
briefDoc="""\
Draws an ellipse contained in the specified rectangle. The current pen
is used for the outline and the current brush for filling the shape.", "
:see: `DrawCircle`
""",
overloads=[
MethodDef(type='void', name='DrawEllipse',
items=[ ParamDef(type='const wxRect &', name='rect') ]),
MethodDef(type='void', name='DrawEllipse',
items=[ ParamDef(type='const wxPoint &', name='pt'),
ParamDef(type='const wxSize &', name='sz') ])
]),
MethodDef(type='void', name='DrawIcon',
items=[ ParamDef(type='const wxIcon &', name='icon'),
ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y')
],
briefDoc="Draw an icon on the display at the given position.",
overloads=[
MethodDef(type='void', name='DrawIcon',
items=[ ParamDef(type='const wxIcon &', name='icon'),
ParamDef(type='const wxPoint &', name='pt') ])
]),
MethodDef(type='void', name='DrawBitmap',
items=[ ParamDef(type='const wxBitmap &', name='bmp'),
ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y'),
ParamDef(type='bool', name='useMask', default='false') ],
briefDoc="""\
Draw a bitmap on the device context at the specified
point. If *useMask* is true and the bitmap has a
transparency mask, (or alpha channel on the platforms that
support it) then the bitmap will be drawn transparently.
When drawing a mono-bitmap, the current text foreground
colour will be used to draw the foreground of the bitmap
(all bits set to 1), and the current text background
colour to draw the background (all bits set to 0).
:see: `SetTextForeground`, `SetTextBackground` and `wx.MemoryDC`
""",
overloads=[
MethodDef(type='void', name='DrawBitmap',
items=[ ParamDef(type='const wxBitmap &', name='bmp'),
ParamDef(type='const wxPoint &', name='pt'),
ParamDef(type='bool', name='useMask', default='false') ])
]),
MethodDef(type='void', name='DrawText',
items=[ ParamDef(type='const wxString &', name='text'),
ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y') ],
briefDoc="""\
Draws a text string at the specified point, using the
current text font, and the current text foreground and
background colours.
The coordinates refer to the top-left corner of the
rectangle bounding the string. See `wx.DC.GetTextExtent`
for how to get the dimensions of a text string, which can
be used to position the text more precisely, (you will
need to use a real DC with GetTextExtent as wx.PseudoDC
does not implement it.)
**NOTE**: under wxGTK the current logical function is used
*by this function but it is ignored by wxMSW. Thus, you
*should avoid using logical functions with this function
*in portable programs.", "
:see: `DrawRotatedText`
""",
overloads=[
MethodDef(type='void', name='DrawText',
items=[ ParamDef(type='const wxString &', name='text'),
ParamDef(type='const wxPoint &', name='pt') ])
]),
MethodDef(type='void', name='DrawRotatedText',
items=[ ParamDef(type='const wxString &', name='text'),
ParamDef(type='wxCoord', name='x'),
ParamDef(type='wxCoord', name='y'),
ParamDef(type='double', name='angle') ],
briefDoc="Draws the text rotated by *angle* degrees, if supported by the platform.",
overloads=[
MethodDef(type='void', name='DrawRotatedText',
items=[ ParamDef(type='const wxString &', name='text'),
ParamDef(type='const wxPoint &', name='pt'),
ParamDef(type='double', name='angle') ])
]),
MethodDef(type='void', name='DrawLabel',
items=[ ParamDef(type='const wxString &', name='text'),
ParamDef(type='const wxRect &', name='rect'),
ParamDef(type='int', name='alignment', default='wxALIGN_LEFT|wxALIGN_TOP'),
ParamDef(type='int', name='indexAccel', default='-1'),
],
briefDoc="""\
Draw *text* within the specified rectangle, abiding by the
alignment flags. Will additionally emphasize the
character at *indexAccel* if it is not -1.
""",
overloads=[
MethodDef(type='void', name='DrawLabel',
items=[ ParamDef(type='const wxString &', name='text'),
ParamDef(type='const wxBitmap &', name='image'),
ParamDef(type='const wxRect &', name='rect'),
ParamDef(type='int', name='alignment', default='wxALIGN_LEFT|wxALIGN_TOP'),
ParamDef(type='int', name='indexAccel', default='-1'),
],
briefDoc="""\
Draw *text* and an image (which may be ``wx.NullBitmap`` to skip
drawing it) within the specified rectangle, abiding by the alignment
flags. Will additionally emphasize the character at *indexAccel* if
it is not -1.
""")]
),
MethodDef(type='void', name='Clear',
items=[],
briefDoc="Clears the device context using the current background brush.",
overloads=[]),
MethodDef(type='void', name='SetFont',
items=[ ParamDef(type='const wxFont &', name='font') ],
briefDoc="""\
Sets the current font for the DC. It must be a valid font, in
particular you should not pass ``wx.NullFont`` to this method.
:see: `wx.Font`
""",
overloads=[]),
MethodDef(type='void', name='SetPen',
items=[ParamDef(type='const wxPen &', name='pen')],
briefDoc="""\
Sets the current pen for the DC.
If the argument is ``wx.NullPen``, the current pen is selected out of the
device context, and the original pen restored.
:see: `wx.Pen`
""",
overloads=[]),
MethodDef(type='void', name='SetBrush',
items=[ParamDef(type='const wxBrush &', name='brush')],
briefDoc="""\
Sets the current brush for the DC.
If the argument is ``wx.NullBrush``, the current brush is selected out
of the device context, and the original brush restored, allowing the
current brush to be destroyed safely.
:see: `wx.Brush`
""",
overloads=[]),
MethodDef(type='void', name='SetBackground',
items=[ ParamDef(type='const wxBrush &', name='brush') ],
briefDoc="Sets the current background brush for the DC.",
overloads=[]),
MethodDef(type='void', name='SetBackgroundMode',
items=[ ParamDef(type='int', name='mode') ],
briefDoc="""\
The *mode* parameter may be one of ``wx.SOLID`` and
``wx.TRANSPARENT``. This setting determines whether text
will be drawn with a background colour or not.
""",
overloads=[]),
MethodDef(type='void', name='SetTextForeground',
items=[ ParamDef(type='const wxColour &', name='colour') ],
briefDoc="Sets the current text foreground colour for the DC.",
overloads=[]),
MethodDef(type='void', name='SetTextBackground',
items=[ ParamDef(type='const wxColour&', name='colour') ],
briefDoc="Sets the current text background colour for the DC.",
overloads=[]),
MethodDef(type='void', name='SetLogicalFunction',
items=[ ParamDef(type='wxRasterOperationMode', name='function') ],
briefDoc="""\
Sets the current logical function for the device context. This
determines how a source pixel (from a pen or brush colour, combines
with a destination pixel in the current device context.
The possible values and their meaning in terms of source and
destination pixel values are defined in the :ref:`wx.RasterOperationMode`
enumeration.
The default is wx.COPY, which simply draws with the current
colour. The others combine the current colour and the background using
a logical operation. wx.INVERT is commonly used for drawing rubber
bands or moving outlines, since drawing twice reverts to the original
colour.
""",
overloads=[]),
MethodDef(type='void', name='DrawLines',
items=[ ParamDef(type='const wxPointList *', name='points'),
ParamDef(type='wxCoord', name='xoffset', default='0'),
ParamDef(type='wxCoord', name='yoffset', default='0')],
briefDoc="""\
Draws lines using a sequence of `wx.Point` objects, adding the
optional offset coordinate. The current pen is used for drawing the
lines.
""",
overloads=[]),
MethodDef(type='void', name='DrawPolygon',
items=[ ParamDef(type='const wxPointList *', name='points'),
ParamDef(type='wxCoord', name='xoffset', default='0'),
ParamDef(type='wxCoord', name='yoffset', default='0'),
ParamDef(type='wxPolygonFillMode', name='fillStyle', default='wxODDEVEN_RULE'),
],
briefDoc="""\
Draws a filled polygon using a sequence of `wx.Point` objects, adding
the optional offset coordinate. The last argument specifies the fill
rule: ``wx.ODDEVEN_RULE`` (the default) or ``wx.WINDING_RULE``.
The current pen is used for drawing the outline, and the current brush
for filling the shape. Using a transparent brush suppresses
filling. Note that wxWidgets automatically closes the first and last
points.
""",
overloads=[]),
MethodDef(type='void', name='DrawSpline',
items=[ ParamDef(type='const wxPointList *', name='points') ],
briefDoc="""\
Draws a spline between all given control points, (a list of `wx.Point`
objects) using the current pen. The spline is drawn using a series of
lines, using an algorithm taken from the X drawing program 'XFIG'.
""",
overloads=[]),
])
# add deprecation warnings for the old method names
cls.addPyCode("""\
PseudoDC.BeginDrawing = wx.deprecated(lambda *args: None, 'BeginDrawing has been removed.')
PseudoDC.EndDrawing = wx.deprecated(lambda *args: None, 'EndDrawing has been removed.')
PseudoDC.FloodFillPoint = wx.deprecated(PseudoDC.FloodFill, 'Use FloodFill instead.')
PseudoDC.DrawLinePoint = wx.deprecated(PseudoDC.DrawLine, 'Use DrawLine instead.')
PseudoDC.CrossHairPoint = wx.deprecated(PseudoDC.CrossHair, 'Use CrossHair instead.')
PseudoDC.DrawArcPoint = wx.deprecated(PseudoDC.DrawArc, 'Use DrawArc instead.')
PseudoDC.DrawCheckMarkRect = wx.deprecated(PseudoDC.DrawCheckMark, 'Use DrawArc instead.')
PseudoDC.DrawEllipticArcPointSize = wx.deprecated(PseudoDC.DrawEllipticArc, 'Use DrawEllipticArc instead.')
PseudoDC.DrawPointPoint = wx.deprecated(PseudoDC.DrawPoint, 'Use DrawPoint instead.')
PseudoDC.DrawRectangleRect = wx.deprecated(PseudoDC.DrawRectangle, 'Use DrawRectangle instead.')
PseudoDC.DrawRectanglePointSize = wx.deprecated(PseudoDC.DrawRectangle, 'Use DrawRectangle instead.')
PseudoDC.DrawRoundedRectangleRect = wx.deprecated(PseudoDC.DrawRoundedRectangle, 'Use DrawRectangle instead.')
PseudoDC.DrawRoundedRectanglePointSize = wx.deprecated(PseudoDC.DrawRoundedRectangle, 'Use DrawRectangle instead.')
PseudoDC.DrawCirclePoint = wx.deprecated(PseudoDC.DrawCircle, 'Use DrawCircle instead.')
PseudoDC.DrawEllipseRect = wx.deprecated(PseudoDC.DrawEllipse, 'Use DrawEllipse instead.')
PseudoDC.DrawEllipsePointSize = wx.deprecated(PseudoDC.DrawEllipse, 'Use DrawEllipse instead.')
PseudoDC.DrawIconPoint = wx.deprecated(PseudoDC.DrawIcon, 'Use DrawIcon instead.')
PseudoDC.DrawBitmapPoint = wx.deprecated(PseudoDC.DrawBitmap, 'Use DrawBitmap instead.')
PseudoDC.DrawTextPoint = wx.deprecated(PseudoDC.DrawText, 'Use DrawText instead.')
PseudoDC.DrawRotatedTextPoint = wx.deprecated(PseudoDC.DrawRotatedText, 'Use DrawRotatedText instead.')
PseudoDC.DrawImageLabel = wx.deprecated(PseudoDC.DrawLabel, 'Use DrawLabel instead.')
""")
# Other stuff not wrapped yet
# // Figure out a good typemap for this...
# // Convert the first 3 args from a sequence of sequences?
# // void DrawPolyPolygon(int n, int count[], wxPoint points[],
# // wxCoord xoffset = 0, wxCoord yoffset = 0,
# // int fillStyle = wxODDEVEN_RULE);
#
#
# DocDeclStr(
# virtual void , SetPalette(const wxPalette& palette),
# "If this is a window DC or memory DC, assigns the given palette to the
# window or bitmap associated with the DC. If the argument is
# ``wx.NullPalette``, the current palette is selected out of the device
# context, and the original palette restored.", "
#
# :see: `wx.Palette`");
module.addItem(cls)
#-----------------------------------------------------------------
tools.doCommonTweaks(module)
tools.runGenerators(module)
#---------------------------------------------------------------------------
if __name__ == '__main__':
run()

View File

@@ -180,6 +180,8 @@ def replaceCppItems(line):
if 'wxString' in item:
item = 'string'
elif 'wxCoord' == item:
item = 'int'
elif item == 'char':
item = 'int'
elif item == 'double':

View File

@@ -64,7 +64,7 @@ def deprecated(item, msg='', useName=False):
elif callable(item):
# wrap a new function around the callable
def deprecated_func(*args, **kw):
warnings.warn("Call to deprecated item %s. %s" % (name, msg),
warnings.warn("Call to deprecated item%s. %s" % (name, msg),
wxPyDeprecationWarning, stacklevel=2)
if not kw:
return item(*args)

661
src/pseudodc.cpp Normal file
View File

@@ -0,0 +1,661 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/pseudodc.cpp
// Purpose: Implementation of the wxPseudoDC classes
// Author: Paul Lanier
// Modified by: Robin Dunn
//
// Created: 05/25/06
// Copyright: (c) 2006-2016 Total Control Software
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
//include "wx/wxprec.h"
//#undef DEBUG
// wxList based class definitions
#include <wx/listimpl.cpp>
WX_DEFINE_LIST(pdcOpList);
WX_DEFINE_LIST(pdcObjectList);
//----------------------------------------------------------------------------
// Helper functions used for drawing greyed out versions of objects
//----------------------------------------------------------------------------
wxColour &MakeColourGrey(const wxColour &c)
{
static wxColour rval;
rval.Set(byte((230-c.Red())*0.7+c.Red()),
byte((230-c.Green())*0.7+c.Green()),
byte((230-c.Blue())*0.7+c.Blue()));
return rval;
}
wxBrush &GetGreyBrush(wxBrush &brush)
{
static wxBrush b;
wxColour c;
b = brush;
c = MakeColourGrey(brush.GetColour());
b.SetColour(c);
return b;
}
wxPen &GetGreyPen(wxPen &pen)
{
static wxPen p;
wxColour c;
p = pen;
c = MakeColourGrey(pen.GetColour());
p.SetColour(c);
return p;
}
void GreyOutImage(wxImage &img)
{
unsigned char *data = img.GetData();
unsigned char r,g,b;
unsigned char mr,mg,mb;
int i, tst;
int len = img.GetHeight()*img.GetWidth()*3;
if (img.HasMask())
{
mr = img.GetMaskRed();
mg = img.GetMaskGreen();
mb = img.GetMaskBlue();
}
tst=0;
for (i=0;i<len;i+=3)
{
r=data[i]; g=data[i+1]; b=data[i+2];
if (!img.HasMask() ||
r!=mr || g!=mg || b!=mb)
{
if (!tst)
{
tst=1;
}
r = (unsigned char)((230.0-r)*0.7+r);
g = (unsigned char)((230.0-g)*0.7+g);
b = (unsigned char)((230.0-b)*0.7+b);
data[i]=r; data[i+1]=g; data[i+2]=b;
}
}
}
wxIcon &GetGreyIcon(wxIcon &icon)
{
wxBitmap bmp;
bmp.CopyFromIcon(icon);
wxImage img = bmp.ConvertToImage();
GreyOutImage(img);
wxBitmap bmp2(img,32);
static wxIcon rval;
rval.CopyFromBitmap(bmp2);
return rval;
}
wxBitmap &GetGreyBitmap(wxBitmap &bmp)
{
wxImage img = bmp.ConvertToImage();
GreyOutImage(img);
static wxBitmap rval(img,32);
return rval;
}
// ============================================================================
// various pdcOp class implementation methods
// ============================================================================
// ----------------------------------------------------------------------------
// pdcDrawPolyPolygonOp
// ----------------------------------------------------------------------------
pdcDrawPolyPolygonOp::pdcDrawPolyPolygonOp(int n, int count[], wxPoint points[],
wxCoord xoffset, wxCoord yoffset, wxPolygonFillMode fillStyle)
{
m_n=n; m_xoffset=xoffset; m_yoffset=yoffset; m_fillStyle=fillStyle;
int total_n=0;
if (n)
{
m_count = new int[n];
for(int i=0; i<n; i++)
{
total_n+=count[i];
m_count[i]=count[i];
}
if (total_n)
{
m_points = new wxPoint[total_n];
for(int j=0; j<total_n; j++)
m_points[j] = points[j];
}
else m_points=NULL;
}
else
{
m_points=NULL;
m_count=NULL;
}
m_totaln = total_n;
}
pdcDrawPolyPolygonOp::~pdcDrawPolyPolygonOp()
{
if (m_points) delete m_points;
if (m_count) delete m_count;
m_points=NULL;
m_count=NULL;
}
// ----------------------------------------------------------------------------
// pdcDrawLinesOp
// ----------------------------------------------------------------------------
pdcDrawLinesOp::pdcDrawLinesOp(const wxPointList* points,
wxCoord xoffset,
wxCoord yoffset)
{
m_xoffset = xoffset;
m_yoffset = yoffset;
m_points = new wxPointList;
wxPointList::const_iterator iter;
for (iter = points->begin(); iter != points->end(); iter++)
{
// The first * gives us a wxPoint ptr, second * dereferences that ptr
m_points->push_back(new wxPoint(**iter));
}
}
pdcDrawLinesOp::~pdcDrawLinesOp()
{
m_points->clear();
delete m_points;
m_points = NULL;
}
void pdcDrawLinesOp::Translate(wxCoord dx, wxCoord dy)
{
wxPointList::const_iterator iter;
for (iter = m_points->begin(); iter != m_points->end(); iter++)
{
(*iter)->x += dx;
(*iter)->y += dy;
}
}
// ----------------------------------------------------------------------------
// pdcDrawPolygonOp
// ----------------------------------------------------------------------------
pdcDrawPolygonOp::pdcDrawPolygonOp(const wxPointList* points,
wxCoord xoffset,
wxCoord yoffset,
wxPolygonFillMode fillStyle)
{
m_xoffset = xoffset;
m_yoffset = yoffset;
m_fillStyle = fillStyle;
m_points = new wxPointList;
wxPointList::const_iterator iter;
for (iter = points->begin(); iter != points->end(); ++iter)
{
// The first * gives us a wxPoint ptr, second * dereferences that ptr
m_points->push_back(new wxPoint(**iter));
}
}
pdcDrawPolygonOp::~pdcDrawPolygonOp()
{
m_points->clear();
delete m_points;
}
void pdcDrawPolygonOp::Translate(wxCoord dx, wxCoord dy)
{
wxPointList::const_iterator iter;
for (iter = m_points->begin(); iter != m_points->end(); iter++)
{
(*iter)->x += dx;
(*iter)->y += dy;
}
}
#if wxUSE_SPLINES
// ----------------------------------------------------------------------------
// pdcDrawSplineOp
// ----------------------------------------------------------------------------
pdcDrawSplineOp::pdcDrawSplineOp(const wxPointList* points)
{
m_points = new wxPointList;
wxPointList::const_iterator iter;
for (iter = points->begin(); iter != points->end(); iter++)
{
// The first * gives us a wxPoint ptr, second * dereferences that ptr
m_points->push_back(new wxPoint(**iter));
}
}
pdcDrawSplineOp::~pdcDrawSplineOp()
{
m_points->clear();
delete m_points;
}
void pdcDrawSplineOp::Translate(wxCoord dx, wxCoord dy)
{
wxPointList::const_iterator iter;
for (iter = m_points->begin(); iter != m_points->end(); iter++)
{
(*iter)->x += dx;
(*iter)->y += dy;
}
}
#endif // wxUSE_SPLINES
// ============================================================================
// pdcObject implementation
// ============================================================================
// ----------------------------------------------------------------------------
// DrawToDC - play back the op list to the DC
// ----------------------------------------------------------------------------
void pdcObject::DrawToDC(wxDC *dc)
{
pdcOpList::compatibility_iterator node = m_oplist.GetFirst();
while(node)
{
node->GetData()->DrawToDC(dc, m_greyedout);
node = node->GetNext();
}
}
// ----------------------------------------------------------------------------
// Translate - translate all the operations by some dx,dy
// ----------------------------------------------------------------------------
void pdcObject::Translate(wxCoord dx, wxCoord dy)
{
pdcOpList::compatibility_iterator node = m_oplist.GetFirst();
while(node)
{
node->GetData()->Translate(dx,dy);
node = node->GetNext();
}
if (m_bounded)
{
m_bounds.x += dx;
m_bounds.y += dy;
}
}
// ----------------------------------------------------------------------------
// SetGreyedOut - set the greyout member and cache grey versions of everything
// if greyout is true
// ----------------------------------------------------------------------------
void pdcObject::SetGreyedOut(bool greyout)
{
m_greyedout=greyout;
if (greyout)
{
pdcOpList::compatibility_iterator node = m_oplist.GetFirst();
pdcOp *obj;
while(node)
{
obj = node->GetData();
obj->CacheGrey();
node = node->GetNext();
}
}
}
// ============================================================================
// wxPseudoDC implementation
// ============================================================================
// ----------------------------------------------------------------------------
// Destructor
// ----------------------------------------------------------------------------
wxPseudoDC::~wxPseudoDC()
{
// delete all the nodes in the list
RemoveAll();
}
// ----------------------------------------------------------------------------
// ClearAll - remove all nodes from list
// ----------------------------------------------------------------------------
void wxPseudoDC::RemoveAll(void)
{
m_objectlist.Clear();
m_objectIndex.clear();
m_currId = -1;
m_lastObject = NULL;
}
// ----------------------------------------------------------------------------
// GetLen - return the number of operations in the current op list
// ----------------------------------------------------------------------------
int wxPseudoDC::GetLen(void)
{
pdcObjectList::compatibility_iterator pt = m_objectlist.GetFirst();
int len=0;
while (pt)
{
len += pt->GetData()->GetLen();
pt = pt->GetNext();
}
return len;
}
// ----------------------------------------------------------------------------
// FindObject - find and return an object node by id. If node doesn't exist
// and create is true then create one and return it. Otherwise
// return NULL.
// ----------------------------------------------------------------------------
pdcObject *wxPseudoDC::FindObject(int id, bool create)
{
// see if last operation was for same id
//~ if (m_lastObject && m_lastObject->GetId() == id)
//~ return m_lastObject;
// if not then search for it
pdcObjectHash::iterator lookup = m_objectIndex.find(id);
if (lookup == m_objectIndex.end()) {//not found
if (create) {
m_lastObject = new pdcObject(id);
m_objectlist.Append(m_lastObject);
pdcObjectHash::value_type insert(id, m_lastObject);
m_objectIndex.insert(insert);
return m_lastObject;
} else {
return NULL;
}
} else { //found
return lookup->second;
}
}
// ----------------------------------------------------------------------------
// AddToList - Add a node to the list at the end (preserve draw order)
// ----------------------------------------------------------------------------
void wxPseudoDC::AddToList(pdcOp *newOp)
{
pdcObject *obj = FindObject(m_currId, true);
obj->AddOp(newOp);
}
// ----------------------------------------------------------------------------
// ClearID - remove all the operations associated with a single ID
// ----------------------------------------------------------------------------
void wxPseudoDC::ClearId(int id)
{
pdcObject *obj = FindObject(id);
if (obj) obj->Clear();
}
// ----------------------------------------------------------------------------
// RemoveID - Remove the object node (and all operations) associated with an id
// ----------------------------------------------------------------------------
void wxPseudoDC::RemoveId(int id)
{
pdcObject *obj = FindObject(id);
if (obj)
{
if (m_lastObject == obj)
m_lastObject = obj;
m_objectlist.DeleteObject(obj);
}
m_objectIndex.erase(id);
}
// ----------------------------------------------------------------------------
// SetIdBounds - Set the bounding rect for a given id
// ----------------------------------------------------------------------------
void wxPseudoDC::SetIdBounds(int id, wxRect& rect)
{
pdcObject *obj = FindObject(id, true);
obj->SetBounds(rect);
}
// ----------------------------------------------------------------------------
// GetIdBounds - Get the bounding rect for a given id
// ----------------------------------------------------------------------------
wxRect wxPseudoDC::GetIdBounds(int id)
{
wxRect rect;
pdcObject *obj = FindObject(id);
if (obj && obj->IsBounded())
rect = obj->GetBounds();
else
rect.x = rect.y = rect.width = rect.height = 0;
return rect;
}
// ----------------------------------------------------------------------------
// TranslateId - Translate all the operations of a single id
// ----------------------------------------------------------------------------
void wxPseudoDC::TranslateId(int id, wxCoord dx, wxCoord dy)
{
pdcObject *obj = FindObject(id);
if (obj) obj->Translate(dx,dy);
}
// ----------------------------------------------------------------------------
// DrawIdToDC - Draw a specific id to the dc passed in
// ----------------------------------------------------------------------------
void wxPseudoDC::DrawIdToDC(int id, wxDC *dc)
{
pdcObject *obj = FindObject(id);
if (obj) obj->DrawToDC(dc);
}
// ----------------------------------------------------------------------------
// SetIdGreyedOut - Set the greyedout member of id
// ----------------------------------------------------------------------------
void wxPseudoDC::SetIdGreyedOut(int id, bool greyout)
{
pdcObject *obj = FindObject(id);
if (obj) obj->SetGreyedOut(greyout);
}
// ----------------------------------------------------------------------------
// GetIdGreyedOut - Get the greyedout member of id
// ----------------------------------------------------------------------------
bool wxPseudoDC::GetIdGreyedOut(int id)
{
pdcObject *obj = FindObject(id);
if (obj) return obj->GetGreyedOut();
else return false;
}
// ----------------------------------------------------------------------------
// FindObjectsByBBox - Return a list of all the ids whose bounding boxes
// contain (x,y)
// ----------------------------------------------------------------------------
PyObject *wxPseudoDC::FindObjectsByBBox(wxCoord x, wxCoord y)
{
//wxPyBlock_t blocked = wxPyBeginBlockThreads();
pdcObjectList::compatibility_iterator pt = m_objectlist.GetFirst();
pdcObject *obj;
PyObject* pyList = NULL;
pyList = PyList_New(0);
wxRect r;
while (pt)
{
obj = pt->GetData();
r = obj->GetBounds();
if (obj->IsBounded() && r.Contains(x,y))
{
PyObject* pyObj = wxPyInt_FromLong((long)obj->GetId());
PyList_Insert(pyList, 0, pyObj);
Py_DECREF(pyObj);
}
pt = pt->GetNext();
}
//wxPyEndBlockThreads(blocked);
return pyList;
}
// ----------------------------------------------------------------------------
// FindObjects - Return a list of all the ids that draw to (x,y)
// ----------------------------------------------------------------------------
PyObject *wxPseudoDC::FindObjects(wxCoord x, wxCoord y,
wxCoord radius, const wxColor& bg)
{
//wxPyBlock_t blocked = wxPyBeginBlockThreads();
pdcObjectList::compatibility_iterator pt = m_objectlist.GetFirst();
pdcObject *obj;
PyObject* pyList = NULL;
pyList = PyList_New(0);
wxBrush bgbrush(bg);
wxPen bgpen(bg);
// special case radius = 0
if (radius == 0)
{
wxBitmap bmp(4,4,24);
wxMemoryDC memdc;
wxColor pix;
wxRect viewrect(x-2,y-2,4,4);
// setup the memdc for rendering
memdc.SelectObject(bmp);
memdc.SetBackground(bgbrush);
memdc.Clear();
memdc.SetDeviceOrigin(2-x,2-y);
while (pt)
{
obj = pt->GetData();
if (obj->IsBounded() && obj->GetBounds().Contains(x,y))
{
// start clean
memdc.SetBrush(bgbrush);
memdc.SetPen(bgpen);
memdc.DrawRectangle(viewrect);
// draw the object
obj->DrawToDC(&memdc);
memdc.GetPixel(x,y,&pix);
// clear and update rgn2
if (pix != bg)
{
PyObject* pyObj = wxPyInt_FromLong((long)obj->GetId());
PyList_Insert(pyList, 0, pyObj);
Py_DECREF(pyObj);
}
}
pt = pt->GetNext();
}
memdc.SelectObject(wxNullBitmap);
}
else
{
wxRect viewrect(x-radius,y-radius,2*radius,2*radius);
wxBitmap maskbmp(2*radius,2*radius,24);
wxMemoryDC maskdc;
// create bitmap with circle for masking
maskdc.SelectObject(maskbmp);
maskdc.SetBackground(*wxBLACK_BRUSH);
maskdc.Clear();
maskdc.SetBrush(*wxWHITE_BRUSH);
maskdc.SetPen(*wxWHITE_PEN);
maskdc.DrawCircle(radius,radius,radius);
// now setup a memdc for rendering our object
wxBitmap bmp(2*radius,2*radius,24);
wxMemoryDC memdc;
memdc.SelectObject(bmp);
// set the origin so (x,y) is in the bmp center
memdc.SetDeviceOrigin(radius-x,radius-y);
// a region will be used to see if the result is empty
wxRegion rgn2;
while (pt)
{
obj = pt->GetData();
if (obj->IsBounded() && viewrect.Intersects(obj->GetBounds()))
{
// start clean
//memdc.Clear();
memdc.SetBrush(bgbrush);
memdc.SetPen(bgpen);
memdc.DrawRectangle(viewrect);
// draw the object
obj->DrawToDC(&memdc);
// remove background color
memdc.SetLogicalFunction(wxXOR);
memdc.SetBrush(bgbrush);
memdc.SetPen(bgpen);
memdc.DrawRectangle(viewrect);
memdc.SetLogicalFunction(wxCOPY);
memdc.Blit(x-radius,y-radius,2*radius,2*radius,&maskdc,0,0,wxCOPY);
// clear and update rgn2
memdc.SelectObject(wxNullBitmap);
rgn2.Clear();
rgn2.Union(bmp, *wxBLACK);
//rgn2.Intersect(rgn);
memdc.SelectObject(bmp);
if (!rgn2.IsEmpty())
{
PyObject* pyObj = wxPyInt_FromLong((long)obj->GetId());
PyList_Insert(pyList, 0, pyObj);
Py_DECREF(pyObj);
}
}
pt = pt->GetNext();
}
maskdc.SelectObject(wxNullBitmap);
memdc.SelectObject(wxNullBitmap);
}
//wxPyEndBlockThreads(blocked);
return pyList;
}
// ----------------------------------------------------------------------------
// DrawToDCClipped - play back the op list to the DC but clip any objects
// known to be not in rect. This is a coarse level of
// clipping to speed things up when lots of objects are off
// screen and doesn't affect the dc level clipping
// ----------------------------------------------------------------------------
void wxPseudoDC::DrawToDCClipped(wxDC *dc, const wxRect& rect)
{
pdcObjectList::compatibility_iterator pt = m_objectlist.GetFirst();
pdcObject *obj;
while (pt)
{
obj = pt->GetData();
if (!obj->IsBounded() || rect.Intersects(obj->GetBounds()))
obj->DrawToDC(dc);
pt = pt->GetNext();
}
}
void wxPseudoDC::DrawToDCClippedRgn(wxDC *dc, const wxRegion& region)
{
pdcObjectList::compatibility_iterator pt = m_objectlist.GetFirst();
pdcObject *obj;
while (pt)
{
obj = pt->GetData();
if (!obj->IsBounded() ||
(region.Contains(obj->GetBounds()) != wxOutRegion))
obj->DrawToDC(dc);
pt = pt->GetNext();
}
}
// ----------------------------------------------------------------------------
// DrawToDC - play back the op list to the DC
// ----------------------------------------------------------------------------
void wxPseudoDC::DrawToDC(wxDC *dc)
{
pdcObjectList::compatibility_iterator pt = m_objectlist.GetFirst();
while (pt)
{
pt->GetData()->DrawToDC(dc);
pt = pt->GetNext();
}
}

817
src/pseudodc.h Normal file
View File

@@ -0,0 +1,817 @@
/////////////////////////////////////////////////////////////////////////////
// Name: pseudodc.h
// Purpose: wxPseudoDC classes
// Author: Paul Lanier
// Modified by: Robin Dunn
//
// Created: 05/25/06
// Copyright: (c) 2006-2016 Total Control Software
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _WX_PSUEDO_DC_H_BASE_
#define _WX_PSUEDO_DC_H_BASE_
//----------------------------------------------------------------------------
// Base class for all pdcOp classes
//----------------------------------------------------------------------------
class pdcOp
{
public:
// Constructor and Destructor
pdcOp() {}
virtual ~pdcOp() {}
// Virtual Drawing Methods
virtual void DrawToDC(wxDC *dc, bool grey=false)=0;
virtual void Translate(wxCoord WXUNUSED(dx), wxCoord WXUNUSED(dy)) {}
virtual void CacheGrey() {}
};
//----------------------------------------------------------------------------
// declare a list class for list of pdcOps
//----------------------------------------------------------------------------
WX_DECLARE_LIST(pdcOp, pdcOpList);
//----------------------------------------------------------------------------
// Helper functions used for drawing greyed out versions of objects
//----------------------------------------------------------------------------
wxColour &MakeColourGrey(const wxColour &c);
wxBrush &GetGreyBrush(wxBrush &brush);
wxPen &GetGreyPen(wxPen &pen);
wxIcon &GetGreyIcon(wxIcon &icon);
wxBitmap &GetGreyBitmap(wxBitmap &bmp);
//----------------------------------------------------------------------------
// Classes derived from pdcOp
// There is one class for each method mirrored from wxDC to wxPseudoDC
//----------------------------------------------------------------------------
class pdcSetFontOp : public pdcOp
{
public:
pdcSetFontOp(const wxFont& font)
{m_font=font;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->SetFont(m_font);}
protected:
wxFont m_font;
};
class pdcSetBrushOp : public pdcOp
{
public:
pdcSetBrushOp(const wxBrush& brush)
{m_greybrush=m_brush=brush;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->SetBrush(m_brush);
else dc->SetBrush(m_greybrush);
}
virtual void CacheGrey() {m_greybrush=GetGreyBrush(m_brush);}
protected:
wxBrush m_brush;
wxBrush m_greybrush;
};
class pdcSetBackgroundOp : public pdcOp
{
public:
pdcSetBackgroundOp(const wxBrush& brush)
{m_greybrush=m_brush=brush;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->SetBackground(m_brush);
else dc->SetBackground(m_greybrush);
}
virtual void CacheGrey() {m_greybrush=GetGreyBrush(m_brush);}
protected:
wxBrush m_brush;
wxBrush m_greybrush;
};
class pdcSetPenOp : public pdcOp
{
public:
pdcSetPenOp(const wxPen& pen)
{m_greypen=m_pen=pen;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->SetPen(m_pen);
else dc->SetPen(m_greypen);
}
virtual void CacheGrey() {m_greypen=GetGreyPen(m_pen);}
protected:
wxPen m_pen;
wxPen m_greypen;
};
class pdcSetTextBackgroundOp : public pdcOp
{
public:
pdcSetTextBackgroundOp(const wxColour& colour)
{m_colour=colour;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->SetTextBackground(m_colour);
else dc->SetTextBackground(MakeColourGrey(m_colour));
}
protected:
wxColour m_colour;
};
class pdcSetTextForegroundOp : public pdcOp
{
public:
pdcSetTextForegroundOp(const wxColour& colour)
{m_colour=colour;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->SetTextForeground(m_colour);
else dc->SetTextForeground(MakeColourGrey(m_colour));
}
protected:
wxColour m_colour;
};
class pdcDrawRectangleOp : public pdcOp
{
public:
pdcDrawRectangleOp(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
{m_x=x; m_y=y; m_w=w; m_h=h;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawRectangle(m_x,m_y,m_w,m_h);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx;m_y+=dy;}
protected:
wxCoord m_x,m_y,m_w,m_h;
};
class pdcDrawLineOp : public pdcOp
{
public:
pdcDrawLineOp(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
{m_x1=x1; m_y1=y1; m_x2=x2; m_y2=y2;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawLine(m_x1,m_y1,m_x2,m_y2);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x1+=dx; m_y1+=dy; m_x2+=dx; m_y2+=dy;}
protected:
wxCoord m_x1,m_y1,m_x2,m_y2;
};
class pdcSetBackgroundModeOp : public pdcOp
{
public:
pdcSetBackgroundModeOp(int mode) {m_mode=mode;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->SetBackgroundMode(m_mode);}
protected:
int m_mode;
};
class pdcDrawTextOp : public pdcOp
{
public:
pdcDrawTextOp(const wxString& text, wxCoord x, wxCoord y)
{m_text=text; m_x=x; m_y=y;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawText(m_text, m_x, m_y);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxString m_text;
wxCoord m_x, m_y;
};
class pdcClearOp : public pdcOp
{
public:
pdcClearOp() {}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->Clear();}
};
class pdcBeginDrawingOp : public pdcOp
{
public:
pdcBeginDrawingOp() {}
virtual void DrawToDC(wxDC *WXUNUSED(dc), bool WXUNUSED(grey)=false) {}
};
class pdcEndDrawingOp : public pdcOp
{
public:
pdcEndDrawingOp() {}
virtual void DrawToDC(wxDC *WXUNUSED(dc), bool WXUNUSED(grey)=false) {}
};
class pdcFloodFillOp : public pdcOp
{
public:
pdcFloodFillOp(wxCoord x, wxCoord y, const wxColour& col,
wxFloodFillStyle style) {m_x=x; m_y=y; m_col=col; m_style=style;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->FloodFill(m_x,m_y,m_col,m_style);
else dc->FloodFill(m_x,m_y,MakeColourGrey(m_col),m_style);
}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxCoord m_x,m_y;
wxColour m_col;
wxFloodFillStyle m_style;
};
class pdcCrossHairOp : public pdcOp
{
public:
pdcCrossHairOp(wxCoord x, wxCoord y) {m_x=x; m_y=y;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->CrossHair(m_x,m_y);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxCoord m_x,m_y;
};
class pdcDrawArcOp : public pdcOp
{
public:
pdcDrawArcOp(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
wxCoord xc, wxCoord yc)
{m_x1=x1; m_y1=y1; m_x2=x2; m_y2=y2; m_xc=xc; m_yc=yc;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawArc(m_x1,m_y1,m_x2,m_y2,m_xc,m_yc);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x1+=dx; m_x2+=dx; m_y1+=dy; m_y2+=dy;}
protected:
wxCoord m_x1,m_x2,m_xc;
wxCoord m_y1,m_y2,m_yc;
};
class pdcDrawCheckMarkOp : public pdcOp
{
public:
pdcDrawCheckMarkOp(wxCoord x, wxCoord y,
wxCoord width, wxCoord height)
{m_x=x; m_y=y; m_w=width; m_h=height;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawCheckMark(m_x,m_y,m_w,m_h);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxCoord m_x,m_y,m_w,m_h;
};
class pdcDrawEllipticArcOp : public pdcOp
{
public:
pdcDrawEllipticArcOp(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
double sa, double ea)
{m_x=x; m_y=y; m_w=w; m_h=h; m_sa=sa; m_ea=ea;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawEllipticArc(m_x,m_y,m_w,m_h,m_sa,m_ea);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxCoord m_x,m_y,m_w,m_h;
double m_sa,m_ea;
};
class pdcDrawPointOp : public pdcOp
{
public:
pdcDrawPointOp(wxCoord x, wxCoord y)
{m_x=x; m_y=y;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawPoint(m_x,m_y);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxCoord m_x,m_y;
};
class pdcDrawRoundedRectangleOp : public pdcOp
{
public:
pdcDrawRoundedRectangleOp(wxCoord x, wxCoord y, wxCoord width,
wxCoord height, double radius)
{m_x=x; m_y=y; m_w=width; m_h=height; m_r=radius;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawRoundedRectangle(m_x,m_y,m_w,m_h,m_r);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxCoord m_x,m_y,m_w,m_h;
double m_r;
};
class pdcDrawEllipseOp : public pdcOp
{
public:
pdcDrawEllipseOp(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
{m_x=x; m_y=y; m_w=width; m_h=height;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawEllipse(m_x,m_y,m_w,m_h);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxCoord m_x,m_y,m_w,m_h;
};
class pdcDrawIconOp : public pdcOp
{
public:
pdcDrawIconOp(const wxIcon& icon, wxCoord x, wxCoord y)
{m_icon=icon; m_x=x; m_y=y;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (grey) dc->DrawIcon(m_greyicon,m_x,m_y);
else dc->DrawIcon(m_icon,m_x,m_y);
}
virtual void CacheGrey() {m_greyicon=GetGreyIcon(m_icon);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxIcon m_icon;
wxIcon m_greyicon;
wxCoord m_x,m_y;
};
class pdcDrawLinesOp : public pdcOp
{
public:
pdcDrawLinesOp(const wxPointList* points,
wxCoord xoffset = 0,
wxCoord yoffset = 0);
virtual ~pdcDrawLinesOp();
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{ dc->DrawLines(m_points, m_xoffset, m_yoffset); }
virtual void Translate(wxCoord dx, wxCoord dy);
protected:
wxPointList* m_points;
wxCoord m_xoffset;
wxCoord m_yoffset;
};
class pdcDrawPolygonOp : public pdcOp
{
public:
pdcDrawPolygonOp(const wxPointList* points,
wxCoord xoffset = 0,
wxCoord yoffset = 0,
wxPolygonFillMode fillStyle = wxODDEVEN_RULE);
virtual ~pdcDrawPolygonOp();
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{ dc->DrawPolygon(m_points, m_xoffset, m_yoffset, m_fillStyle); }
virtual void Translate(wxCoord dx, wxCoord dy);
protected:
wxPointList* m_points;
wxCoord m_xoffset;
wxCoord m_yoffset;
wxPolygonFillMode m_fillStyle;
};
class pdcDrawPolyPolygonOp : public pdcOp
{
public:
pdcDrawPolyPolygonOp(int n, int count[], wxPoint points[],
wxCoord xoffset = 0, wxCoord yoffset = 0,
wxPolygonFillMode fillStyle = wxODDEVEN_RULE);
virtual ~pdcDrawPolyPolygonOp();
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawPolyPolygon(m_n,m_count,m_points,
m_xoffset,m_yoffset,m_fillStyle);}
virtual void Translate(wxCoord dx, wxCoord dy)
{
for(int i=0; i<m_totaln; i++)
{
m_points[i].x += dx;
m_points[i].y += dy;
}
}
protected:
int m_n;
int m_totaln;
int *m_count;
wxPoint *m_points;
wxCoord m_xoffset, m_yoffset;
wxPolygonFillMode m_fillStyle;
};
class pdcDrawRotatedTextOp : public pdcOp
{
public:
pdcDrawRotatedTextOp(const wxString& text, wxCoord x, wxCoord y, double angle)
{m_text=text; m_x=x; m_y=y; m_angle=angle;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawRotatedText(m_text,m_x,m_y,m_angle);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxString m_text;
wxCoord m_x,m_y;
double m_angle;
};
class pdcDrawBitmapOp : public pdcOp
{
public:
pdcDrawBitmapOp(const wxBitmap &bmp, wxCoord x, wxCoord y,
bool useMask = false)
{m_bmp=bmp; m_x=x; m_y=y; m_useMask=useMask;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (grey) dc->DrawBitmap(m_greybmp,m_x,m_y,m_useMask);
else dc->DrawBitmap(m_bmp,m_x,m_y,m_useMask);
}
virtual void CacheGrey() {m_greybmp=GetGreyBitmap(m_bmp);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxBitmap m_bmp;
wxBitmap m_greybmp;
wxCoord m_x,m_y;
bool m_useMask;
};
class pdcDrawLabelOp : public pdcOp
{
public:
pdcDrawLabelOp(const wxString& text,
const wxBitmap& image,
const wxRect& rect,
int alignment = wxALIGN_LEFT | wxALIGN_TOP,
int indexAccel = -1)
{m_text=text; m_image=image; m_rect=rect;
m_align=alignment; m_iAccel=indexAccel;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawLabel(m_text,m_image,m_rect,m_align,m_iAccel);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_rect.x+=dx; m_rect.y+=dy;}
protected:
wxString m_text;
wxBitmap m_image;
wxRect m_rect;
int m_align;
int m_iAccel;
};
#if wxUSE_SPLINES
class pdcDrawSplineOp : public pdcOp
{
public:
pdcDrawSplineOp(const wxPointList* points);
virtual ~pdcDrawSplineOp();
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{ dc->DrawSpline(m_points); }
virtual void Translate(wxCoord dx, wxCoord dy);
protected:
wxPointList* m_points;
};
#endif // wxUSE_SPLINES
#if wxUSE_PALETTE
class pdcSetPaletteOp : public pdcOp
{
public:
pdcSetPaletteOp(const wxPalette& palette) {m_palette=palette;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->SetPalette(m_palette);}
protected:
wxPalette m_palette;
};
#endif // wxUSE_PALETTE
class pdcSetLogicalFunctionOp : public pdcOp
{
public:
pdcSetLogicalFunctionOp(wxRasterOperationMode function) {m_function=function;}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->SetLogicalFunction(m_function);}
protected:
wxRasterOperationMode m_function;
};
//----------------------------------------------------------------------------
// pdcObject type to contain list of operations for each real (Python) object
//----------------------------------------------------------------------------
class pdcObject
{
public:
pdcObject(int id)
{m_id=id; m_bounded=false; m_oplist.DeleteContents(true);
m_greyedout=false;}
virtual ~pdcObject() {m_oplist.Clear();}
// Protected Member Access
void SetId(int id) {m_id=id;}
int GetId() {return m_id;}
void SetBounds(wxRect& rect) {m_bounds=rect; m_bounded=true;}
wxRect GetBounds() {return m_bounds;}
void SetBounded(bool bounded) {m_bounded=bounded;}
bool IsBounded() {return m_bounded;}
void SetGreyedOut(bool greyout=true);
bool GetGreyedOut() {return m_greyedout;}
// Op List Management Methods
void Clear() {m_oplist.Clear();}
void AddOp(pdcOp *op)
{
m_oplist.Append(op);
if (m_greyedout) op->CacheGrey();
}
int GetLen() {return m_oplist.GetCount();}
virtual void Translate(wxCoord dx, wxCoord dy);
// Drawing Method
virtual void DrawToDC(wxDC *dc);
protected:
int m_id; // id of object (associates this pdcObject
// with a Python object with same id)
wxRect m_bounds; // bounding rect of this object
bool m_bounded; // true if bounds is valid, false by default
pdcOpList m_oplist; // list of operations for this object
bool m_greyedout; // if true then draw this object in greys only
};
//----------------------------------------------------------------------------
// Declare a wxList to hold all the objects. List order reflects drawing
// order (Z order) and is the same order as objects are added to the list
//----------------------------------------------------------------------------
class pdcObjectList;
WX_DECLARE_LIST(pdcObject, pdcObjectList);
//Declare a hashmap that maps from ids to nodes in the object list.
WX_DECLARE_HASH_MAP(
int,
pdcObject *,
wxIntegerHash,
wxIntegerEqual,
pdcObjectHash
);
// ----------------------------------------------------------------------------
// wxPseudoDC class
// ----------------------------------------------------------------------------
// This is the actual PseudoDC class
// This class stores a list of recorded dc operations in m_list
// and plays them back to a real dc using DrawToDC or DrawToDCClipped.
// Drawing methods are mirrored from wxDC but add nodes to m_list
// instead of doing any real drawing.
// ----------------------------------------------------------------------------
class wxPseudoDC : public wxObject
{
public:
wxPseudoDC()
{m_currId=-1; m_lastObject=NULL; m_objectlist.DeleteContents(true);m_objectIndex.clear();}
~wxPseudoDC();
// ------------------------------------------------------------------------
// List management methods
//
void RemoveAll();
int GetLen();
// ------------------------------------------------------------------------
// methods for managing operations by ID
//
// Set the Id for all subsequent operations (until SetId is called again)
void SetId(int id) {m_currId = id;}
// Remove all the operations associated with an id so it can be redrawn
void ClearId(int id);
// Remove the object node (and all operations) associated with an id
void RemoveId(int id);
// Set the bounding rect of a given object
// This will create an object node if one doesn't exist
void SetIdBounds(int id, wxRect& rect);
wxRect GetIdBounds(int id);
// Translate all the operations for this id
void TranslateId(int id, wxCoord dx, wxCoord dy);
// Grey-out an object
void SetIdGreyedOut(int id, bool greyout=true);
bool GetIdGreyedOut(int id);
// Find Objects at a point. Returns Python list of id's
// sorted in reverse drawing order (result[0] is top object)
// This version looks at drawn pixels
PyObject *FindObjects(wxCoord x, wxCoord y,
wxCoord radius=1, const wxColor& bg=*wxWHITE);
// This version only looks at bounding boxes
PyObject *FindObjectsByBBox(wxCoord x, wxCoord y);
// ------------------------------------------------------------------------
// Playback Methods
//
// draw to dc but skip objects known to be outside of rect
// This is a coarse level of clipping to speed things up
// when lots of objects are off screen and doesn't affect the dc level
// clipping
void DrawToDCClipped(wxDC *dc, const wxRect& rect);
void DrawToDCClippedRgn(wxDC *dc, const wxRegion& region);
// draw to dc with no clipping (well the dc will still clip)
void DrawToDC(wxDC *dc);
// draw a single object to the dc
void DrawIdToDC(int id, wxDC *dc);
// ------------------------------------------------------------------------
// Hit Detection Methods
//
// returns list of object with a drawn pixel within radius pixels of (x,y)
// the list is in reverse draw order so last drawn is first in list
// PyObject *HitTest(wxCoord x, wxCoord y, double radius)
// returns list of objects whose bounding boxes include (x,y)
// PyObject *HitTestBB(wxCoord x, wxCoord y)
// ------------------------------------------------------------------------
// Methods mirrored from wxDC
//
void FloodFill(wxCoord x, wxCoord y, const wxColour& col,
wxFloodFillStyle style = wxFLOOD_SURFACE)
{AddToList(new pdcFloodFillOp(x,y,col,style));}
void FloodFill(const wxPoint& pt, const wxColour& col,
wxFloodFillStyle style = wxFLOOD_SURFACE)
{ FloodFill(pt.x, pt.y, col, style); }
void DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
{AddToList(new pdcDrawLineOp(x1, y1, x2, y2));}
void DrawLine(const wxPoint& pt1, const wxPoint& pt2)
{ DrawLine(pt1.x, pt1.y, pt2.x, pt2.y); }
void CrossHair(wxCoord x, wxCoord y)
{AddToList(new pdcCrossHairOp(x,y));}
void CrossHair(const wxPoint& pt)
{ CrossHair(pt.x, pt.y); }
void DrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
wxCoord xc, wxCoord yc)
{AddToList(new pdcDrawArcOp(x1,y1,x2,y2,xc,yc));}
void DrawArc(const wxPoint& pt1, const wxPoint& pt2, const wxPoint& centre)
{ DrawArc(pt1.x, pt1.y, pt2.x, pt2.y, centre.x, centre.y); }
void DrawCheckMark(wxCoord x, wxCoord y,
wxCoord width, wxCoord height)
{AddToList(new pdcDrawCheckMarkOp(x,y,width,height));}
void DrawCheckMark(const wxRect& rect)
{ DrawCheckMark(rect.x, rect.y, rect.width, rect.height); }
void DrawEllipticArc(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
double sa, double ea)
{AddToList(new pdcDrawEllipticArcOp(x,y,w,h,sa,ea));}
void DrawEllipticArc(const wxPoint& pt, const wxSize& sz,
double sa, double ea)
{ DrawEllipticArc(pt.x, pt.y, sz.x, sz.y, sa, ea); }
void DrawPoint(wxCoord x, wxCoord y)
{AddToList(new pdcDrawPointOp(x,y));}
void DrawPoint(const wxPoint& pt)
{ DrawPoint(pt.x, pt.y); }
void DrawPolygon(const wxPointList* points,
wxCoord xoffset = 0,
wxCoord yoffset = 0,
wxPolygonFillMode fillStyle = wxODDEVEN_RULE)
{AddToList(new pdcDrawPolygonOp(points, xoffset, yoffset, fillStyle));}
void DrawPolyPolygon(int n, int count[], wxPoint points[],
wxCoord xoffset = 0, wxCoord yoffset = 0,
wxPolygonFillMode fillStyle = wxODDEVEN_RULE)
{AddToList(new pdcDrawPolyPolygonOp(n,count,points,xoffset,yoffset,fillStyle));}
void DrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
{AddToList(new pdcDrawRectangleOp(x, y, width, height));}
void DrawRectangle(const wxPoint& pt, const wxSize& sz)
{ DrawRectangle(pt.x, pt.y, sz.x, sz.y); }
void DrawRectangle(const wxRect& rect)
{ DrawRectangle(rect.x, rect.y, rect.width, rect.height); }
void DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height,
double radius)
{AddToList(new pdcDrawRoundedRectangleOp(x,y,width,height,radius));}
void DrawRoundedRectangle(const wxPoint& pt, const wxSize& sz,
double radius)
{ DrawRoundedRectangle(pt.x, pt.y, sz.x, sz.y, radius); }
void DrawRoundedRectangle(const wxRect& r, double radius)
{ DrawRoundedRectangle(r.x, r.y, r.width, r.height, radius); }
void DrawCircle(wxCoord x, wxCoord y, wxCoord radius)
{ DrawEllipse(x - radius, y - radius, 2*radius, 2*radius); }
void DrawCircle(const wxPoint& pt, wxCoord radius)
{ DrawCircle(pt.x, pt.y, radius); }
void DrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
{AddToList(new pdcDrawEllipseOp(x,y,width,height));}
void DrawEllipse(const wxPoint& pt, const wxSize& sz)
{ DrawEllipse(pt.x, pt.y, sz.x, sz.y); }
void DrawEllipse(const wxRect& rect)
{ DrawEllipse(rect.x, rect.y, rect.width, rect.height); }
void DrawIcon(const wxIcon& icon, wxCoord x, wxCoord y)
{AddToList(new pdcDrawIconOp(icon,x,y));}
void DrawIcon(const wxIcon& icon, const wxPoint& pt)
{ DrawIcon(icon, pt.x, pt.y); }
void DrawLines(const wxPointList* points,
wxCoord xoffset = 0, wxCoord yoffset = 0)
{ AddToList(new pdcDrawLinesOp(points, xoffset, yoffset)); }
void DrawBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y,
bool useMask = false)
{AddToList(new pdcDrawBitmapOp(bmp,x,y,useMask));}
void DrawBitmap(const wxBitmap &bmp, const wxPoint& pt,
bool useMask = false)
{ DrawBitmap(bmp, pt.x, pt.y, useMask); }
void DrawText(const wxString& text, wxCoord x, wxCoord y)
{AddToList(new pdcDrawTextOp(text, x, y));}
void DrawText(const wxString& text, const wxPoint& pt)
{ DrawText(text, pt.x, pt.y); }
void DrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle)
{AddToList(new pdcDrawRotatedTextOp(text,x,y,angle));}
void DrawRotatedText(const wxString& text, const wxPoint& pt, double angle)
{ DrawRotatedText(text, pt.x, pt.y, angle); }
// this version puts both optional bitmap and the text into the given
// rectangle and aligns is as specified by alignment parameter; it also
// will emphasize the character with the given index if it is != -1
void DrawLabel(const wxString& text,
const wxBitmap& image,
const wxRect& rect,
int alignment = wxALIGN_LEFT | wxALIGN_TOP,
int indexAccel = -1)
{AddToList(new pdcDrawLabelOp(text,image,rect,alignment,indexAccel));}
void DrawLabel(const wxString& text, const wxRect& rect,
int alignment = wxALIGN_LEFT | wxALIGN_TOP,
int indexAccel = -1)
{ DrawLabel(text, wxNullBitmap, rect, alignment, indexAccel); }
/*?????? I don't think that the source dc would stick around
void Blit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
wxDC *source, wxCoord xsrc, wxCoord ysrc,
int rop = wxCOPY, bool useMask = false, wxCoord xsrcMask = wxDefaultCoord, wxCoord ysrcMask = wxDefaultCoord)
{AddToList(new pdcBlitOp(xdest,ydest,width,height,source,xsrc,
ysrc,rop,useMask,xsrcMask,ysrcMask));}
void Blit(const wxPoint& destPt, const wxSize& sz,
wxDC *source, const wxPoint& srcPt,
int rop = wxCOPY, bool useMask = false, const wxPoint& srcPtMask = wxDefaultPosition)
{
Blit(destPt.x, destPt.y, sz.x, sz.y, source, srcPt.x, srcPt.y,
rop, useMask, srcPtMask.x, srcPtMask.y);
}
??????*/
#if wxUSE_SPLINES
void DrawSpline(const wxPointList* points)
{ AddToList(new pdcDrawSplineOp(points)); }
#endif // wxUSE_SPLINES
#if wxUSE_PALETTE
void SetPalette(const wxPalette& palette)
{AddToList(new pdcSetPaletteOp(palette));}
#endif // wxUSE_PALETTE
void SetLogicalFunction(wxRasterOperationMode function)
{AddToList(new pdcSetLogicalFunctionOp(function));}
void SetFont(const wxFont& font)
{AddToList(new pdcSetFontOp(font));}
void SetPen(const wxPen& pen)
{AddToList(new pdcSetPenOp(pen));}
void SetBrush(const wxBrush& brush)
{AddToList(new pdcSetBrushOp(brush));}
void SetBackground(const wxBrush& brush)
{AddToList(new pdcSetBackgroundOp(brush));}
void SetBackgroundMode(int mode)
{AddToList(new pdcSetBackgroundModeOp(mode));}
void SetTextBackground(const wxColour& colour)
{AddToList(new pdcSetTextBackgroundOp(colour));}
void SetTextForeground(const wxColour& colour)
{AddToList(new pdcSetTextForegroundOp(colour));}
void Clear()
{AddToList(new pdcClearOp());}
void BeginDrawing()
{AddToList(new pdcBeginDrawingOp());}
void EndDrawing()
{AddToList(new pdcEndDrawingOp());}
protected:
// ------------------------------------------------------------------------
// protected helper methods
void AddToList(pdcOp *newOp);
pdcObject *FindObject(int id, bool create=false);
// ------------------------------------------------------------------------
// Data members
//
int m_currId; // id to use for operations done on the PseudoDC
pdcObject *m_lastObject; // used to find last used object quickly
pdcObjectList m_objectlist; // list of objects
pdcObjectHash m_objectIndex; //id->object lookup index
};
#endif

117
unittests/test_pseudodc.py Normal file
View File

@@ -0,0 +1,117 @@
import unittest
from unittests import wtc
import wx
import wx.adv
WAITFOR = 250
#---------------------------------------------------------------------------
class pseudodc_Tests(wtc.WidgetTestCase):
def setUp(self):
super(pseudodc_Tests, self).setUp()
self.pnl = wx.Panel(self.frame)
self.pnl.Bind(wx.EVT_PAINT, self._paintIt)
self.pdc = wx.adv.PseudoDC()
self.pdc.SetBackground(wx.Brush('pink'))
self.pdc.Clear()
self.pdc.SetPen(wx.Pen('navy', 2))
self.pdc.SetBrush(wx.Brush('white'))
def _paintIt(self, evt):
# Paint event handler for the panel
dc = wx.PaintDC(self.pnl)
if 'wxMac' not in wx.PlatformInfo:
dc = wx.GCDC(dc)
self.pdc.DrawToDC(dc)
def _showIt(self):
self.pnl.Refresh()
self.waitFor(WAITFOR)
def test_pseudodc01(self):
assert self.pdc.GetLen() == 4
assert self.pdc.Len == 4
def test_pseudodc02(self):
self.pdc.DrawRectangle(10, 10, 50, 25)
self.pdc.DrawRectangle(wx.Rect(10, 40, 50, 25))
self.pdc.DrawRectangle((10, 70), (50,25))
self._showIt()
def test_pseudodc03(self):
self.pdc.DrawRoundedRectangle(10, 10, 50, 25, 4.5)
self.pdc.DrawRoundedRectangle(wx.Rect(10, 40, 50, 25), 4.5)
self.pdc.DrawRoundedRectangle((10, 70), (50,25), 4.5)
self._showIt()
def test_pseudodc04(self):
points = [ (10, 10),
(50, 10),
(50, 50),
(10, 50),
(10, 90),
(50, 90),
]
self.pdc.DrawLines(points)
self._showIt()
def test_pseudodc05(self):
for offset in range(0, 300, 10):
self.pdc.DrawLine(0, offset, offset, 0)
self._showIt()
def test_pseudodc06(self):
for offset in range(0, 300, 10):
self.pdc.DrawLine((0, offset), (offset, 0))
self._showIt()
def test_pseudodc07(self):
points = [ (10, 10),
(25, 50),
(10, 75),
(75, 100)]
self.pdc.DrawSpline(points)
self._showIt()
def test_pseudodc08(self):
points = [ (10, 10),
(50, 10),
(50, 50),
(10, 50),
(10, 90),
(50, 90),
]
self.pdc.DrawPolygon(points)
self._showIt()
def test_pseudodc09(self):
self.pdc.DrawEllipse(10, 10, 50, 25)
self.pdc.DrawEllipse(wx.Rect(10, 40, 50, 25))
self.pdc.DrawEllipse((10, 70), (50,25))
self._showIt()
def test_pseudodc10(self):
self.pdc.SetId(123)
self.test_pseudodc02()
self.pdc.TranslateId(123, 25, 25)
self._showIt()
#---------------------------------------------------------------------------
if __name__ == '__main__':
unittest.main()

View File

@@ -192,9 +192,12 @@ class datetime_Tests(wtc.WidgetTestCase):
def test_datetimeParseRfc822Date(self):
d = wx.DateTime()
val = d.ParseRfc822Date('Wed, 25 Feb 2015 13:34:45 -0800')
rfc822str = 'Wed, 25 Feb 2015 13:34:45 -0800'
import email.utils as eu
st = time.localtime(eu.mktime_tz(eu.parsedate_tz(rfc822str)))
val = d.ParseRfc822Date(rfc822str)
self.assertEqual(val, 31)
self.assertEqual(d.hour, 13)
self.assertEqual(d.hour, st.tm_hour)
self.assertEqual(d.minute, 34)