]> git.saurik.com Git - wxWidgets.git/commitdiff
Added the PseudoDC class from Paul Lanier. It provides a way to
authorRobin Dunn <robin@alldunn.com>
Mon, 10 Jul 2006 15:06:31 +0000 (15:06 +0000)
committerRobin Dunn <robin@alldunn.com>
Mon, 10 Jul 2006 15:06:31 +0000 (15:06 +0000)
record operations on a DC and then play them back later.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@40054 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

wxPython/demo/Main.py
wxPython/demo/PseudoDC.py [new file with mode: 0644]
wxPython/docs/CHANGES.txt
wxPython/include/wx/wxPython/pseudodc.h [new file with mode: 0644]
wxPython/setup.py
wxPython/src/_pseudodc.i [new file with mode: 0644]
wxPython/src/pseudodc.cpp [new file with mode: 0644]

index 33d9b9ecdf742564d583ce6cc1216f16f664ff57..c89232c97951dac3f882585c93c421ae5dc83d08 100644 (file)
@@ -51,6 +51,7 @@ _treeList = [
         'AUI',
         'CheckListCtrlMixin',
         'Pickers',
+        'PseudoDC',
         'RichTextCtrl',
         'Treebook',
         'Toolbook',
@@ -248,6 +249,7 @@ _treeList = [
         'MouseGestures',
         'OGL',
         'PrintFramework',
+        'PseudoDC',
         'ShapedWindow',
         'Sound',
         'StandardPaths',
diff --git a/wxPython/demo/PseudoDC.py b/wxPython/demo/PseudoDC.py
new file mode 100644 (file)
index 0000000..379ac42
--- /dev/null
@@ -0,0 +1,306 @@
+
+import wx
+import images
+import random
+
+#---------------------------------------------------------------------------
+
+W = 1000
+H = 1000
+SW = 150
+SH = 150
+SHAPE_COUNT = 100
+MOVING_COUNT = 10
+
+#---------------------------------------------------------------------------
+
+colours = [
+    "BLACK",
+    "BLUE",
+    "BLUE VIOLET",
+    "BROWN",
+    "CYAN",
+    "DARK GREY",
+    "DARK GREEN",
+    "GOLD",
+    "GREY",
+    "GREEN",
+    "MAGENTA",
+    "NAVY",
+    "PINK",
+    "RED",
+    "SKY BLUE",
+    "VIOLET",
+    "YELLOW",
+    ]
+
+
+
+class MyCanvas(wx.ScrolledWindow):
+    def __init__(self, parent, id, log, size = wx.DefaultSize):
+        wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, style=wx.SUNKEN_BORDER)
+
+        self.lines = []
+        self.maxWidth  = W
+        self.maxHeight = H
+        self.x = self.y = 0
+        self.curLine = []
+        self.drawing = False
+
+        self.SetBackgroundColour("WHITE")
+        bmp = images.getTest2Bitmap()
+        mask = wx.Mask(bmp, wx.BLUE)
+        bmp.SetMask(mask)
+        self.bmp = bmp
+
+        self.SetVirtualSize((self.maxWidth, self.maxHeight))
+        self.SetScrollRate(20,20)
+        
+        # create a PseudoDC to record our drawing
+        self.pdc = wx.PseudoDC()
+        self.pen_cache = {}
+        self.brush_cache = {}
+        self.DoDrawing(self.pdc)
+        log.write('Created PseudoDC draw list with %d operations!'%self.pdc.GetLen())
+
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x:None)
+        
+        # use timer to move one of the objects around
+        self.timer = wx.Timer()
+        self.timer.SetOwner(self)
+        self.Bind(wx.EVT_TIMER, self.OnTimer)
+        self.timer.Start(50)
+        self.movingids = random.sample(self.objids, MOVING_COUNT)
+        self.velocitydict = {}
+        for id in self.movingids:
+            vx = random.randint(1,5) * random.choice([-1,1])
+            vy = random.randint(1,5) * random.choice([-1,1])
+            self.velocitydict[id] = (vx,vy)
+
+    def OnTimer(self, event):
+        # get the current position
+        xv, yv = self.GetViewStart()
+        dx, dy = self.GetScrollPixelsPerUnit()
+        x, y   = (xv * dx, yv * dy)
+        w, h   = self.GetClientSizeTuple()
+        clip = wx.Rect(x,y,w,h)
+        refreshed = False
+        for id in self.movingids:
+            r = self.pdc.GetIdBounds(id)
+            # get new object position
+            (vx,vy) = self.velocitydict[id]
+            x = r.x + vx
+            y = r.y + vy
+            # check for bounce
+            if x < 0: 
+                x = -x
+                vx = -vx
+            if x >= W: 
+                x = W - (x - W)
+                vx = -vx
+            if y < 0: 
+                y = -y
+                vy = -vy
+            if y >= H:
+                y = H - (y - H)
+                vy = -vy
+            self.velocitydict[id] = (vx,vy)
+            # get change
+            dx = x - r.x
+            dy = y - r.y
+            # translate the object
+            self.pdc.TranslateId(id, dx, dy)
+            # redraw
+            r.x -= 20
+            if dx < 0:
+                r.x = x
+            r.y -= 20
+            if dy < 0:
+                r.y = y
+            r.width += abs(dx) + 40
+            r.height += abs(dy) + 40
+            if r.Intersects(clip):
+                r.x -= clip.x
+                r.y -= clip.y
+                refreshed = True
+                self.RefreshRect(r, False)
+
+    def RandomPen(self):
+        c = random.choice(colours)
+        t = random.randint(1, 4)
+        if not self.pen_cache.has_key( (c, t) ):
+            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):
+            self.brush_cache[c] = wx.Brush(c)
+
+        return self.brush_cache[c]
+
+    def RandomColor(self):
+        return random.choice(colours)
+
+
+    def OnPaint(self, event):
+        # Create a buffered paint DC.  It will create the real
+        # wx.PaintDC and then blit the bitmap to it when dc is
+        # deleted.  
+        dc = wx.BufferedPaintDC(self)
+        # we need to clear the dc BEFORE calling PrepareDC
+        bg = wx.Brush(self.GetBackgroundColour())
+        dc.SetBackground(bg)
+        dc.Clear()
+        # use PrepateDC to set position correctly
+        self.PrepareDC(dc)
+        # create a clipping rect from our position and size
+        # and the Update Region
+        xv, yv = self.GetViewStart()
+        dx, dy = self.GetScrollPixelsPerUnit()
+        x, y   = (xv * dx, yv * dy)
+        rgn = self.GetUpdateRegion()
+        rgn.Offset(x,y)
+        r = rgn.GetBox()
+        # draw to the dc using the calculated clipping rect
+        self.pdc.DrawToDCClipped(dc,r)
+
+    def DoDrawing(self, dc):
+        random.seed()
+        self.objids = []
+        self.boundsdict = {}
+        dc.BeginDrawing()
+        for i in range(SHAPE_COUNT):
+            id = wx.NewId()
+            dc.SetId(id)
+            choice = random.randint(0,8)
+            if choice in (0,1):
+                x = random.randint(0, W)
+                y = random.randint(0, H)
+                dc.SetPen(self.RandomPen())
+                dc.DrawPoint(x,y)
+                dc.SetIdBounds(id,wx.Rect(x,y,1,1))
+            elif choice in (2,3):
+                x1 = random.randint(0, W-SW)
+                y1 = random.randint(0, H-SH)
+                x2 = random.randint(x1, x1+SW)
+                y2 = random.randint(y1, y1+SH)
+                dc.SetPen(self.RandomPen())
+                dc.DrawLine(x1,y1,x2,y2)
+                dc.SetIdBounds(id,wx.Rect(x1,y1,x2-x1,y2-y1))
+            elif choice in (4,5):
+                w = random.randint(10, SW)
+                h = random.randint(10, SH)
+                x = random.randint(0, W - w)
+                y = random.randint(0, H - h)
+                dc.SetPen(self.RandomPen())
+                dc.SetBrush(self.RandomBrush())
+                dc.DrawRectangle(x,y,w,h)
+                dc.SetIdBounds(id,wx.Rect(x,y,w,h))
+                self.objids.append(id)
+            elif choice == 6:
+                Np = 8 # number of characters in text
+                word = []
+                for i in range(Np):
+                    c = chr( random.randint(48, 122) )
+                    word.append( c )
+                word = "".join(word)
+                w,h = self.GetFullTextExtent(word)[0:2]
+                x = random.randint(0, W-w)
+                y = random.randint(0, H-h)
+                dc.SetTextForeground(self.RandomColor())
+                dc.SetTextBackground(self.RandomColor())
+                dc.DrawText(word, x, y)
+                dc.SetIdBounds(id,wx.Rect(x,y,w,h))
+                self.objids.append(id)
+            elif choice == 7:
+                Np = 8 # number of points per polygon
+                poly = []
+                minx = SW
+                miny = SH
+                maxx = 0
+                maxy = 0
+                for i in range(Np):
+                    x = random.randint(0, SW)
+                    y = random.randint(0, SH)
+                    if x < minx: minx = x
+                    if x > maxx: maxx = x
+                    if y < miny: miny = y
+                    if y > maxy: maxy = y
+                    poly.append(wx.Point(x,y))
+                x = random.randint(0, W-SW)
+                y = random.randint(0, H-SH)
+                dc.SetPen(self.RandomPen())
+                dc.SetBrush(self.RandomBrush())
+                dc.DrawPolygon(poly, x,y)
+                dc.SetIdBounds(id,wx.Rect(minx+x,miny+y,maxx-minx+x,maxy-miny+y))
+                self.objids.append(id)
+            elif choice == 8:
+                w,h = self.bmp.GetSize()
+                x = random.randint(0, W-w)
+                y = random.randint(0, H-h)
+                dc.DrawBitmap(self.bmp,x,y,True)
+                dc.SetIdBounds(id,wx.Rect(x,y,w,h))
+                self.objids.append(id)
+        dc.EndDrawing()
+
+    def ShutdownDemo(self):
+        self.timer.Stop()
+        del self.timer
+
+#---------------------------------------------------------------------------
+
+def runTest(frame, nb, log):
+    win = MyCanvas(nb, wx.ID_ANY, log)
+    return win
+
+#---------------------------------------------------------------------------
+
+
+
+overview = """
+<html>
+<body>
+The wx.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
+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
+specific object.  To do this use:<pre>
+SetId(id)
+</pre>
+Every operation after this will be associated with id until SetId is called
+again.  The PseudoDC also supports object level clipping.  To enable this use:<pre>
+SetIdBounds(id,rect)
+</pre>
+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.
+
+Objects can be moved around without re-drawing using:<pre>
+TranslateId(id, dx, dy)
+</pre>
+
+To re-draw an object use:<pre>
+ClearId(id)
+SetId(id)
+</pre>
+and then re-draw the object.
+</body>
+</html>
+"""
+
+
+if __name__ == '__main__':
+    import sys,os
+    import run
+    run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
+
index 6538e02483b93d2823dc8725c11f372baabd9900..d056255450ff13e292d0cb22fd49cd7f5bf519a6 100644 (file)
@@ -172,6 +172,10 @@ channel.
 
 Added wrappers for the wxAUI classes, in the wx.aui module.
 
+Added the PseudoDC class from Paul Lanier.  It provides a way to
+record operations on a DC and then play them back later.
+
+
 
 
 
diff --git a/wxPython/include/wx/wxPython/pseudodc.h b/wxPython/include/wx/wxPython/pseudodc.h
new file mode 100644 (file)
index 0000000..622e999
--- /dev/null
@@ -0,0 +1,736 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        pseudodc.h
+// Purpose:     wxPseudoDC class
+// Author:      Paul Lanier
+// Modified by:
+// Created:     05/25/06
+// RCS-ID:      $Id$
+// Copyright:   (c) wxWidgets team
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+#ifndef _WX_PSUEDO_DC_H_BASE_
+#define _WX_PSUEDO_DC_H_BASE_
+
+#include "wx/wx.h"
+#include "wx/dc.h"
+
+//----------------------------------------------------------------------------
+// Base class for all pdcOp classes
+//----------------------------------------------------------------------------
+class pdcOp
+{
+    public:
+        // Constructor and Destructor
+        pdcOp() {}
+        virtual ~pdcOp() {}
+
+        // Virtual Drawing Methods
+        virtual void DrawToDC(wxDC *dc)=0;
+        virtual void Translate(wxCoord WXUNUSED(dx), wxCoord WXUNUSED(dy)) {}
+};
+
+//----------------------------------------------------------------------------
+// declare a list class for list of pdcOps
+//----------------------------------------------------------------------------
+WX_DECLARE_LIST(pdcOp, pdcOpList);
+
+//----------------------------------------------------------------------------
+// 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) {dc->SetFont(m_font);}
+    protected:
+        wxFont m_font;
+};
+
+class pdcSetBrushOp : public pdcOp
+{
+    public:
+        pdcSetBrushOp(const wxBrush& brush) 
+            {m_brush=brush;}
+        virtual void DrawToDC(wxDC *dc) {dc->SetBrush(m_brush);}
+    protected:
+        wxBrush m_brush;
+};
+
+class pdcSetBackgroundOp : public pdcOp
+{
+    public:
+        pdcSetBackgroundOp(const wxBrush& brush) 
+            {m_brush=brush;}
+        virtual void DrawToDC(wxDC *dc) {dc->SetBackground(m_brush);}
+    protected:
+        wxBrush m_brush;
+};
+
+class pdcSetPenOp : public pdcOp
+{
+    public:
+        pdcSetPenOp(const wxPen& pen) 
+            {m_pen=pen;}
+        virtual void DrawToDC(wxDC *dc) {dc->SetPen(m_pen);}
+    protected:
+        wxPen m_pen;
+};
+
+class pdcSetTextBackgroundOp : public pdcOp
+{
+    public:
+        pdcSetTextBackgroundOp(const wxColour& colour) 
+            {m_colour=colour;}
+        virtual void DrawToDC(wxDC *dc) {dc->SetTextBackground(m_colour);}
+    protected:
+        wxColour m_colour;
+};
+
+class pdcSetTextForegroundOp : public pdcOp
+{
+    public:
+        pdcSetTextForegroundOp(const wxColour& colour) 
+            {m_colour=colour;}
+        virtual void DrawToDC(wxDC *dc) {dc->SetTextForeground(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) {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) {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) {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) {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) {dc->Clear();}
+};
+
+class pdcBeginDrawingOp : public pdcOp
+{
+    public:
+        pdcBeginDrawingOp() {}
+        virtual void DrawToDC(wxDC *dc) {dc->BeginDrawing();}
+};
+
+class pdcEndDrawingOp : public pdcOp
+{
+    public:
+        pdcEndDrawingOp() {}
+        virtual void DrawToDC(wxDC *dc) {dc->EndDrawing();}
+};
+
+class pdcFloodFillOp : public pdcOp
+{
+    public:
+        pdcFloodFillOp(wxCoord x, wxCoord y, const wxColour& col,
+                   int style) {m_x=x; m_y=y; m_col=col; m_style=style;}
+        virtual void DrawToDC(wxDC *dc) {dc->FloodFill(m_x,m_y,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;
+        int m_style;
+};
+
+class pdcCrossHairOp : public pdcOp
+{
+    public:
+        pdcCrossHairOp(wxCoord x, wxCoord y) {m_x=x; m_y=y;}
+        virtual void DrawToDC(wxDC *dc) {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) 
+            {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) 
+            {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) 
+            {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) {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) 
+            {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) {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) {dc->DrawIcon(m_icon,m_x,m_y);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxIcon m_icon;
+        wxCoord m_x,m_y;
+};
+
+class pdcDrawLinesOp : public pdcOp
+{
+    public:
+        pdcDrawLinesOp(int n, wxPoint points[],
+               wxCoord xoffset = 0, wxCoord yoffset = 0);
+        virtual ~pdcDrawLinesOp();
+        virtual void DrawToDC(wxDC *dc) 
+            {dc->DrawLines(m_n,m_points,m_xoffset,m_yoffset);}
+        virtual void Translate(wxCoord dx, wxCoord dy)
+        { 
+            for(int i=0; i<m_n; i++)
+            {
+                m_points[i].x+=dx; 
+                m_points[i].y+=dy;
+            }
+        }
+    protected:
+        int m_n;
+        wxPoint *m_points;
+        wxCoord m_xoffset,m_yoffset;
+};
+
+class pdcDrawPolygonOp : public pdcOp
+{
+    public:
+        pdcDrawPolygonOp(int n, wxPoint points[],
+                     wxCoord xoffset = 0, wxCoord yoffset = 0,
+                     int fillStyle = wxODDEVEN_RULE);
+        virtual ~pdcDrawPolygonOp();
+        virtual void DrawToDC(wxDC *dc) 
+            { dc->DrawPolygon(m_n,m_points,m_xoffset,m_yoffset,m_fillStyle); }
+                
+        virtual void Translate(wxCoord dx, wxCoord dy)
+        { 
+            for(int i=0; i<m_n; i++)
+            {
+                m_points[i].x+=dx; 
+                m_points[i].y+=dy;
+            }
+        }
+    protected:
+        int m_n;
+        wxPoint *m_points;
+        wxCoord m_xoffset,m_yoffset;
+        int m_fillStyle;
+};
+
+class pdcDrawPolyPolygonOp : public pdcOp
+{
+    public:
+        pdcDrawPolyPolygonOp(int n, int count[], wxPoint points[],
+                         wxCoord xoffset = 0, wxCoord yoffset = 0,
+                         int fillStyle = wxODDEVEN_RULE);
+        virtual ~pdcDrawPolyPolygonOp();
+        virtual void DrawToDC(wxDC *dc) 
+            {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;
+        int 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) 
+            {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) {dc->DrawBitmap(m_bmp,m_x,m_y,m_useMask);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxBitmap m_bmp;
+        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) 
+            {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(int n, wxPoint points[]);
+        virtual ~pdcDrawSplineOp();
+        virtual void DrawToDC(wxDC *dc) {dc->DrawSpline(m_n,m_points);}
+        virtual void Translate(wxCoord dx, wxCoord dy)
+        {
+            int i;
+            for(i=0; i<m_n; i++)
+                m_points[i].x+=dx; m_points[i].y+=dy;
+        }
+    protected:
+        wxPoint *m_points;
+        int m_n;
+};
+#endif // wxUSE_SPLINES
+
+#if wxUSE_PALETTE
+class pdcSetPaletteOp : public pdcOp
+{
+    public:
+        pdcSetPaletteOp(const wxPalette& palette) {m_palette=palette;}
+        virtual void DrawToDC(wxDC *dc) {dc->SetPalette(m_palette);}
+    protected:
+        wxPalette m_palette;
+};
+#endif // wxUSE_PALETTE
+
+class pdcSetLogicalFunctionOp : public pdcOp
+{
+    public:
+        pdcSetLogicalFunctionOp(int function) {m_function=function;}
+        virtual void DrawToDC(wxDC *dc) {dc->SetLogicalFunction(m_function);}
+    protected:
+        int 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);}
+
+        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;}
+    
+        // Op List Management Methods
+        void Clear() {m_oplist.Clear();}
+        void AddOp(pdcOp *op) {m_oplist.Append(op);}
+        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
+};
+
+
+//----------------------------------------------------------------------------
+// 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 WXDLLEXPORT pdcObjectList;
+WX_DECLARE_LIST(pdcObject, pdcObjectList);
+
+
+// ----------------------------------------------------------------------------
+// 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 WXDLLEXPORT wxPseudoDC : public wxObject
+{
+public:
+    wxPseudoDC() 
+        {m_currId=-1; m_lastObjNode=NULL; m_objectlist.DeleteContents(true);}
+    ~wxPseudoDC();
+    // ------------------------------------------------------------------------
+    // List managment 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);
+    void GetIdBounds(int id, wxRect& rect);
+    // Translate all the operations for this id
+    void TranslateId(int id, wxCoord dx, wxCoord dy);
+
+    // ------------------------------------------------------------------------
+    // 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);
+        
+    // ------------------------------------------------------------------------
+    // Methods mirrored from wxDC
+    //
+    void FloodFill(wxCoord x, wxCoord y, const wxColour& col,
+                   int style = wxFLOOD_SURFACE)
+        {AddToList(new pdcFloodFillOp(x,y,col,style));}
+    void FloodFill(const wxPoint& pt, const wxColour& col,
+                   int 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(int n, wxPoint points[],
+                     wxCoord xoffset = 0, wxCoord yoffset = 0,
+                     int fillStyle = wxODDEVEN_RULE)
+        {AddToList(new pdcDrawPolygonOp(n,points,xoffset,yoffset,fillStyle));}
+
+    void DrawPolyPolygon(int n, int count[], wxPoint points[],
+                         wxCoord xoffset = 0, wxCoord yoffset = 0,
+                         int 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(int n, wxPoint points[],
+               wxCoord xoffset = 0, wxCoord yoffset = 0)
+        {AddToList(new pdcDrawLinesOp(n,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(int n, wxPoint points[])
+        {AddToList(new pdcDrawSplineOp(n,points));}
+#endif // wxUSE_SPLINES
+
+#if wxUSE_PALETTE
+    void SetPalette(const wxPalette& palette)
+        {AddToList(new pdcSetPaletteOp(palette));}
+#endif // wxUSE_PALETTE
+
+    void SetLogicalFunction(int 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);
+    pdcObjectList::Node *FindObjNode(int id, bool create=false);
+    
+    // ------------------------------------------------------------------------
+    // Data members
+    // 
+    int m_currId; // id to use for operations done on the PseudoDC
+    pdcObjectList::Node *m_lastObjNode; // used to find last used object quickly
+    pdcObjectList m_objectlist; // list of objects
+};
+
+#endif
+
index 51eef48d553b29ea2b94b010ef0cc85ded26f73f..26a60965568728dec509bb95e17628b2652527c5 100755 (executable)
@@ -207,11 +207,11 @@ swig_sources = run_swig(['gdi.i'], 'src', GENDIR, PKGDIR,
                          'src/_pen.i',
                          'src/_palette.i',
                          'src/_renderer.i',
-##                         'src/_pseudodc.i',
+                         'src/_pseudodc.i',
                          ],
                         True)
 ext = Extension('_gdi_', ['src/drawlist.cpp',
-##                          'src/pseudodc.cpp'
+                          'src/pseudodc.cpp'
                           ] + swig_sources,
                 include_dirs =  includes,
                 define_macros = defines,
diff --git a/wxPython/src/_pseudodc.i b/wxPython/src/_pseudodc.i
new file mode 100644 (file)
index 0000000..e2f6710
--- /dev/null
@@ -0,0 +1,580 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        
+// Purpose:     Wraper definitions for the wxPseudoDC Class
+// Author:      Paul Lanier 
+// Modified by:
+// Created:     05/25/06
+// RCS-ID:      $Id$
+// Copyright:   (c) wxWidgets team
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+
+%{
+#include "wx/wxPython/pseudodc.h"
+%}
+
+%newgroup;
+
+DocStr(wxPseudoDC,
+"A PseudoDC is an object that can be used as if it were a `wx.DC`.  All
+commands issued to the PseudoDC are stored in a list.  You can then
+play these commands back to a real DC object using the DrawToDC
+method.  Commands in the command list are indexed by ID.  You can use
+this to clear the operations associated with a single ID and then
+re-draw the object associated with that ID.", "");
+
+class wxPseudoDC : public wxObject
+{
+public:
+    DocCtorStr(
+        wxPseudoDC(),
+        "Constructs a new Pseudo device context for recording dc operations","");
+    DocDeclStr(
+        void , BeginDrawing(),
+        "Allows for optimization of drawing code on platforms that need it.  On
+other platforms this is just an empty function and is harmless.  To
+take advantage of this postential optimization simply enclose each
+group of calls to the drawing primitives within calls to
+`BeginDrawing` and `EndDrawing`.", "");
+    
+    DocDeclStr(
+        void , EndDrawing(),
+        "Ends the group of drawing primitives started with `BeginDrawing`, and
+invokes whatever optimization is available for this DC type on the
+current platform.", "");
+    DocCtorStr(
+        ~wxPseudoDC(),
+        "Frees memory used by the operation list of the pseudo dc","");
+    DocDeclStr(
+        void, RemoveAll(),
+        "Removes all objects and operations from the recorded list.", "");
+    DocDeclStr(
+        int, GetLen(),
+        "Returns the number of operations in the recorded list.", "");
+    DocDeclStr(
+        void, SetId(int id),
+        "Sets the id to be associated with subsequent operations.", "");
+    DocDeclStr(
+        void, ClearId(int id),
+        "Removes all operations associated with id so the object can be redrawn.", "");
+    DocDeclStr(
+        void, RemoveId(int id),
+        "Remove the object node (and all operations) associated with an id.", "");
+    DocDeclStr(
+        void, TranslateId(int id, wxCoord dx, wxCoord dy),
+        "Translate the operations of id by dx,dy.", "");
+    DocDeclStr(
+        void, DrawIdToDC(int id, wxDC *dc),
+        "Draw recorded operations of id to dc.", "");
+    DocDeclStr(
+        void, SetIdBounds(int id, wxRect& rect),
+        "Set the bounding rect of a given object.  This will create 
+an object node if one doesn't exist.", "");
+    %extend {
+        DocStr(
+            GetIdBounds,
+            "Returns the bounding rectangle previouly set with SetIdBounds.  If
+no bounds have been set, it returns wx.Rect(0,0,0,0).", "");
+        wxRect GetIdBounds(int id) {
+            wxRect rect;
+            self->GetIdBounds(id, rect);
+            return rect;
+        }
+    }
+    DocDeclStr(
+        void, DrawToDCClipped(wxDC *dc, const wxRect& rect),
+        "Draws the recorded operations to dc unless the operation is known to
+be outside rect.", "");
+    DocDeclStr(
+        void, DrawToDCClippedRgn(wxDC *dc, const wxRegion& region),
+        "Draws the recorded operations to dc unless the operation is known to
+be outside rect.", "");
+    DocDeclStr(
+        void, DrawToDC(wxDC *dc),
+        "Draws the recorded operations to dc.", "");
+    
+    //-------------------------------------------------------------------------
+    // Methods Mirrored from wxDC
+    //-------------------------------------------------------------------------
+//
+//    DocDeclStr(
+//        void , SetFont(const wxFont& font),
+//        "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`");
+//    
+//    DocDeclStr(
+//        void , SetPen(const wxPen& pen),
+//        "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`");
+//    
+//    DocDeclStr(
+//        void , SetBrush(const wxBrush& brush),
+//        "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`");
+//    
+//    DocDeclStr(
+//        void , SetBackground(const wxBrush& brush),
+//        "Sets the current background brush for the DC.", "");
+//    
+//    DocDeclStr(
+//        void , SetBackgroundMode(int mode),
+//        "*mode* may be one of ``wx.SOLID`` and ``wx.TRANSPARENT``. This setting
+//determines whether text will be drawn with a background colour or
+//not.", "");
+//    
+//    DocDeclStr(
+//        void , SetTextForeground(const wxColour& colour),
+//        "Sets the current text foreground colour for the DC.", "");
+//    
+//    DocDeclStr(
+//        void , SetTextBackground(const wxColour& colour),
+//        "Sets the current text background colour for the DC.", "");
+//    DocDeclStr(
+//        void , DrawLabel(const wxString& text, const wxRect& rect,
+//                         int alignment = wxALIGN_LEFT | wxALIGN_TOP,
+//                         int indexAccel = -1),
+//        "Draw *text* within the specified rectangle, abiding by the alignment
+//flags.  Will additionally emphasize the character at *indexAccel* if
+//it is not -1.", "
+//
+//:see: `DrawImageLabel`");
+//    DocStr(
+//        DrawText,
+//        "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 `GetTextExtent` for how to get the dimensions of a
+//text string, which can be used to position the text more precisely.
+//
+//**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`");
+//    void DrawText(const wxString& text, wxCoord x, wxCoord y);
+//    DocStr(
+//        DrawLine,
+//        "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).", "");
+//    void DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2);
+//    DocDeclStr(
+//        void, DrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height),
+//        "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.", "");
+//    DocDeclStr(
+//        void , Clear(),
+//        "Clears the device context using the current background brush.", "");
+
+    DocStr(
+        FloodFill,
+        "Flood fills the device context starting from the given point, using
+the current brush colour, and using a style:
+
+    - **wxFLOOD_SURFACE**: the flooding occurs until a colour other than
+      the given colour is encountered.
+
+    - **wxFLOOD_BORDER**: the area to be flooded is bounded by the given
+      colour.
+
+Returns False if the operation failed.
+
+Note: The present implementation for non-Windows platforms may fail to
+find colour borders if the pixels do not match the colour
+exactly. However the function will still return true.", "");
+    void FloodFill(wxCoord x, wxCoord y, const wxColour& col, int style = wxFLOOD_SURFACE);
+    %Rename(FloodFillPoint, void, FloodFill(const wxPoint& pt, const wxColour& col, int style = wxFLOOD_SURFACE));
+
+    
+    DocStr(
+        DrawLine,
+        "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).", "");
+    void DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2);
+    %Rename(DrawLinePoint, void, DrawLine(const wxPoint& pt1, const wxPoint& pt2));
+
+
+    DocStr(
+        CrossHair,
+        "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.", "");
+    void CrossHair(wxCoord x, wxCoord y);
+    %Rename(CrossHairPoint, void, CrossHair(const wxPoint& pt));
+
+
+    DocStr(
+        DrawArc,
+        "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.", "");
+    void DrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc);
+    %Rename(DrawArcPoint, void, DrawArc(const wxPoint& pt1, const wxPoint& pt2, const wxPoint& center));
+
+
+    DocStr(
+        DrawCheckMark,
+        "Draws a check mark inside the given rectangle.", "");
+    void DrawCheckMark(wxCoord x, wxCoord y, wxCoord width, wxCoord height);
+    %Rename(DrawCheckMarkRect, void, DrawCheckMark(const wxRect& rect));
+
+    DocStr(
+        DrawEllipticArc,
+        "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.", "");
+    void DrawEllipticArc(wxCoord x, wxCoord y, wxCoord w, wxCoord h, double start, double end);
+    %Rename(DrawEllipticArcPointSize, void, DrawEllipticArc(const wxPoint& pt, const wxSize& sz, double start, double end));
+
+
+    DocStr(
+        DrawPoint,
+        "Draws a point using the current pen.", "");
+    void DrawPoint(wxCoord x, wxCoord y);
+    %Rename(DrawPointPoint, void, DrawPoint(const wxPoint& pt));
+
+
+    DocStr(
+        DrawRectangle,
+        "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.", "");
+    void DrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height);
+    %Rename(DrawRectangleRect,void, DrawRectangle(const wxRect& rect));
+    %Rename(DrawRectanglePointSize, void, DrawRectangle(const wxPoint& pt, const wxSize& sz));
+
+
+    DocStr(
+        DrawRoundedRectangle,
+        "Draws a rectangle with the given top left corner, and with the given
+size. The corners are quarter-circles using the given radius. The
+current pen is used for the outline and the current brush for filling
+the shape.
+
+If radius is positive, the value is assumed to be the radius of the
+rounded corner. If radius is negative, the absolute value is assumed
+to be the proportion of the smallest dimension of the rectangle. This
+means that the corner can be a sensible size relative to the size of
+the rectangle, and also avoids the strange effects X produces when the
+corners are too big for the rectangle.", "");
+    void DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius);
+    %Rename(DrawRoundedRectangleRect, void, DrawRoundedRectangle(const wxRect& r, double radius));
+    %Rename(DrawRoundedRectanglePointSize, void, DrawRoundedRectangle(const wxPoint& pt, const wxSize& sz, double radius));
+
+
+    DocStr(
+        DrawCircle,
+        "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`");
+    void DrawCircle(wxCoord x, wxCoord y, wxCoord radius);
+    %Rename(DrawCirclePoint, void, DrawCircle(const wxPoint& pt, wxCoord radius));
+
+
+    DocStr(
+        DrawEllipse,
+        "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`");
+    void DrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height);
+    %Rename(DrawEllipseRect, void, DrawEllipse(const wxRect& rect));
+    %Rename(DrawEllipsePointSize, void, DrawEllipse(const wxPoint& pt, const wxSize& sz));
+
+
+    DocStr(
+        DrawIcon,
+        "Draw an icon on the display (does nothing if the device context is
+PostScript). This can be the simplest way of drawing bitmaps on a
+window.", "");
+    void DrawIcon(const wxIcon& icon, wxCoord x, wxCoord y);
+    %Rename(DrawIconPoint, void, DrawIcon(const wxIcon& icon, const wxPoint& pt));
+
+
+    DocStr(
+        DrawBitmap,
+        "Draw a bitmap on the device context at the specified point. If
+*transparent* 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`");
+    void DrawBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask = false);
+    %Rename(DrawBitmapPoint, void, DrawBitmap(const wxBitmap &bmp, const wxPoint& pt, bool useMask = false));
+
+
+    DocStr(
+        DrawText,
+        "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 `GetTextExtent` for how to get the dimensions of a
+text string, which can be used to position the text more precisely.
+
+**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`");
+    void DrawText(const wxString& text, wxCoord x, wxCoord y);
+    %Rename(DrawTextPoint, void, DrawText(const wxString& text, const wxPoint& pt));
+
+
+    DocStr(
+        DrawRotatedText,
+        "Draws the text rotated by *angle* degrees, if supported by the platform.
+
+**NOTE**: Under Win9x only TrueType fonts can be drawn by this
+function. In particular, a font different from ``wx.NORMAL_FONT``
+should be used as the it is not normally a TrueType
+font. ``wx.SWISS_FONT`` is an example of a font which is.","
+
+:see: `DrawText`");
+    void DrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle);
+    %Rename(DrawRotatedTextPoint, void, DrawRotatedText(const wxString& text, const wxPoint& pt, double angle));
+
+
+//    DocDeclStr(
+//        bool , Blit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
+//                    wxDC *source, wxCoord xsrc, wxCoord ysrc,
+//                    int rop = wxCOPY, bool useMask = false,
+//                    wxCoord xsrcMask = -1, wxCoord ysrcMask = -1),
+//        "Copy from a source DC to this DC.  Parameters specify the destination
+//coordinates, size of area to copy, source DC, source coordinates,
+//logical function, whether to use a bitmap mask, and mask source
+//position.", "
+//
+//    :param xdest:       Destination device context x position.
+//    :param ydest:       Destination device context y position.
+//    :param width:       Width of source area to be copied.
+//    :param height:      Height of source area to be copied.
+//    :param source:      Source device context.
+//    :param xsrc:        Source device context x position.
+//    :param ysrc:        Source device context y position.
+//    :param rop:         Logical function to use: see `SetLogicalFunction`.
+//    :param useMask:     If true, Blit does a transparent blit using the mask
+//                        that is associated with the bitmap selected into the
+//                        source device context.
+//    :param xsrcMask:    Source x position on the mask. If both xsrcMask and
+//                        ysrcMask are -1, xsrc and ysrc will be assumed for
+//                        the mask source position.
+//    :param ysrcMask:    Source y position on the mask. 
+//");
+    
+//    DocDeclStrName(
+//        bool , Blit(const wxPoint& destPt, const wxSize& sz,
+//                    wxDC *source, const wxPoint& srcPt,
+//                    int rop = wxCOPY, bool useMask = false,
+//                    const wxPoint& srcPtMask = wxDefaultPosition),
+//        "Copy from a source DC to this DC.  Parameters specify the destination
+//coordinates, size of area to copy, source DC, source coordinates,
+//logical function, whether to use a bitmap mask, and mask source
+//position.", "
+//
+//    :param destPt:      Destination device context position.
+//    :param sz:          Size of source area to be copied.
+//    :param source:      Source device context.
+//    :param srcPt:       Source device context position.
+//    :param rop:         Logical function to use: see `SetLogicalFunction`.
+//    :param useMask:     If true, Blit does a transparent blit using the mask
+//                        that is associated with the bitmap selected into the
+//                        source device context.
+//    :param srcPtMask:   Source position on the mask. 
+//",
+//        BlitPointSize);
+    
+
+    DocDeclAStr(
+        void , DrawLines(int points, wxPoint* points_array,
+                         wxCoord xoffset = 0, wxCoord yoffset = 0),
+        "DrawLines(self, List points, int xoffset=0, int yoffset=0)",
+        "Draws lines using a sequence of `wx.Point` objects, adding the
+optional offset coordinate. The current pen is used for drawing the
+lines.", "");
+    
+
+    DocDeclAStr(
+        void , DrawPolygon(int points, wxPoint* points_array,
+                     wxCoord xoffset = 0, wxCoord yoffset = 0,
+                           int fillStyle = wxODDEVEN_RULE),
+        "DrawPolygon(self, List points, int xoffset=0, int yoffset=0,
+    int fillStyle=ODDEVEN_RULE)",
+        "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.", "");
+    
+
+    // TODO:  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(
+        void , DrawLabel(const wxString& text, const wxRect& rect,
+                         int alignment = wxALIGN_LEFT | wxALIGN_TOP,
+                         int indexAccel = -1),
+        "Draw *text* within the specified rectangle, abiding by the alignment
+flags.  Will additionally emphasize the character at *indexAccel* if
+it is not -1.", "
+
+:see: `DrawImageLabel`");
+
+    DocDeclStrName(
+        void, DrawLabel(const wxString& text,
+                              const wxBitmap& image,
+                              const wxRect& rect,
+                              int alignment = wxALIGN_LEFT | wxALIGN_TOP,
+                              int indexAccel = -1),
+       "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.", "", DrawImageLabel);
+
+    
+    DocDeclAStr(
+        void , DrawSpline(int points, wxPoint* points_array),
+        "DrawSpline(self, List points)",
+        "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'.", "");
+
+
+    DocDeclStr(
+        virtual void , Clear(),
+        "Clears the device context using the current background brush.", "");
+    
+
+    // set objects to use for drawing
+    // ------------------------------
+
+    DocDeclStr(
+        virtual void , SetFont(const wxFont& font),
+        "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`");
+    
+    DocDeclStr(
+        virtual void , SetPen(const wxPen& pen),
+        "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`");
+    
+    DocDeclStr(
+        virtual void , SetBrush(const wxBrush& brush),
+        "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`");
+    
+    DocDeclStr(
+        virtual void , SetBackground(const wxBrush& brush),
+        "Sets the current background brush for the DC.", "");
+    
+    DocDeclStr(
+        virtual void , SetBackgroundMode(int mode),
+        "*mode* may be one of ``wx.SOLID`` and ``wx.TRANSPARENT``. This setting
+determines whether text will be drawn with a background colour or
+not.", "");
+    
+    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`");
+    
+
+    DocDeclStr(
+        virtual void , SetTextForeground(const wxColour& colour),
+        "Sets the current text foreground colour for the DC.", "");
+    
+    DocDeclStr(
+        virtual void , SetTextBackground(const wxColour& colour),
+        "Sets the current text background colour for the DC.", "");
+    
+    DocDeclStr(
+        virtual void , SetLogicalFunction(int function),
+        "Sets the current logical function for the device context. This
+determines how a source pixel (from a pen or brush colour, or source
+device context if using `Blit`) 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 as follows:
+
+    ================       ==========================
+    wx.AND                 src AND dst
+    wx.AND_INVERT          (NOT src) AND dst
+    wx.AND_REVERSE         src AND (NOT dst)
+    wx.CLEAR               0
+    wx.COPY                src
+    wx.EQUIV               (NOT src) XOR dst
+    wx.INVERT              NOT dst
+    wx.NAND                (NOT src) OR (NOT dst)
+    wx.NOR                 (NOT src) AND (NOT dst)
+    wx.NO_OP               dst
+    wx.OR                  src OR dst
+    wx.OR_INVERT           (NOT src) OR dst
+    wx.OR_REVERSE          src OR (NOT dst)
+    wx.SET                 1
+    wx.SRC_INVERT          NOT src
+    wx.XOR                 src XOR dst
+    ================       ==========================
+
+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.
+", "");
+};
diff --git a/wxPython/src/pseudodc.cpp b/wxPython/src/pseudodc.cpp
new file mode 100644 (file)
index 0000000..dc2d2eb
--- /dev/null
@@ -0,0 +1,368 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        common/pseudodc.cpp
+// Purpose:     Implementation of the wxPseudoDC Class
+// Author:      Paul Lanier
+// Modified by:
+// Created:     05/25/06
+// RCS-ID:      $Id$
+// Copyright:   (c) wxWidgets team
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#include "wx/wxPython/pseudodc.h"
+#include <stdio.h>
+
+// wxList based class definitions
+#include <wx/listimpl.cpp>
+WX_DEFINE_LIST(pdcOpList);
+WX_DEFINE_LIST(pdcObjectList);
+
+// ============================================================================
+// various pdcOp class implementation methods
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// pdcDrawPolyPolygonOp constructor
+// ----------------------------------------------------------------------------
+pdcDrawPolyPolygonOp::pdcDrawPolyPolygonOp(int n, int count[], wxPoint points[],
+                 wxCoord xoffset, wxCoord yoffset, int 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 destructor
+// ----------------------------------------------------------------------------
+pdcDrawPolyPolygonOp::~pdcDrawPolyPolygonOp()
+{
+    if (m_points) delete m_points;
+    if (m_count) delete m_count;
+    m_points=NULL;
+    m_count=NULL;
+}
+        
+// ----------------------------------------------------------------------------
+// pdcDrawLinesOp constructor
+// ----------------------------------------------------------------------------
+pdcDrawLinesOp::pdcDrawLinesOp(int n, wxPoint points[],
+             wxCoord xoffset, wxCoord yoffset)
+{
+    m_n=n; m_xoffset=xoffset; m_yoffset=yoffset;
+    if (n)
+    {
+        m_points = new wxPoint[n];
+        for (int i=0; i<n; i++)
+            m_points[i] = points[i];
+    }
+    else m_points=NULL;
+}
+
+// ----------------------------------------------------------------------------
+// pdcDrawLinesOp destructor
+// ----------------------------------------------------------------------------
+pdcDrawLinesOp::~pdcDrawLinesOp()
+{
+    if (m_points) delete m_points;
+    m_points=NULL;
+}
+        
+// ----------------------------------------------------------------------------
+// pdcDrawPolygonOp constructor
+// ----------------------------------------------------------------------------
+pdcDrawPolygonOp::pdcDrawPolygonOp(int n, wxPoint points[],
+             wxCoord xoffset, wxCoord yoffset, int fillStyle)
+{
+    m_n=n; m_xoffset=xoffset; m_yoffset=yoffset; m_fillStyle=fillStyle;
+    if (n)
+    {
+        m_points = new wxPoint[n];
+        for (int i=0; i<n; i++)
+            m_points[i] = points[i];
+    }
+    else m_points=NULL;
+}
+
+// ----------------------------------------------------------------------------
+// pdcDrawPolygonOp destructor
+// ----------------------------------------------------------------------------
+pdcDrawPolygonOp::~pdcDrawPolygonOp()
+{
+    if (m_points) delete m_points;
+    m_points=NULL;
+}
+
+#if wxUSE_SPLINES
+// ----------------------------------------------------------------------------
+// pdcDrawSplineOp constructor
+// ----------------------------------------------------------------------------
+pdcDrawSplineOp::pdcDrawSplineOp(int n, wxPoint points[])
+{
+    m_n=n;
+    if (n)
+    {
+        m_points = new wxPoint[n];
+        for(int i=0; i<n; i++)
+            m_points[i] = points[i];
+    }
+    else m_points=NULL;
+}
+
+// ----------------------------------------------------------------------------
+// pdcDrawSplineOp destructor
+// ----------------------------------------------------------------------------
+pdcDrawSplineOp::~pdcDrawSplineOp()
+{
+    if (m_points) delete m_points;
+    m_points=NULL;
+}
+#endif // wxUSE_SPLINES
+
+// ============================================================================
+// pdcObject implementation
+// ============================================================================
+// ----------------------------------------------------------------------------
+// DrawToDC - play back the op list to the DC 
+// ----------------------------------------------------------------------------
+void pdcObject::DrawToDC(wxDC *dc)
+{
+    pdcOpList::Node *node = m_oplist.GetFirst(); 
+    while(node)
+    {
+        node->GetData()->DrawToDC(dc);
+        node = node->GetNext();
+    }
+}
+
+// ----------------------------------------------------------------------------
+// Translate - translate all the operations by some dx,dy
+// ----------------------------------------------------------------------------
+void pdcObject::Translate(wxCoord dx, wxCoord dy)
+{
+    pdcOpList::Node *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;
+       }
+}
+
+// ============================================================================
+// 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_currId = -1;
+       m_lastObjNode = NULL;
+}
+
+// ----------------------------------------------------------------------------
+// GetLen - return the number of operations in the current op list
+// ----------------------------------------------------------------------------
+int wxPseudoDC::GetLen(void)
+{
+    pdcObjectList::Node *pt = m_objectlist.GetFirst();
+    int len=0;
+    while (pt) 
+    {
+        len += pt->GetData()->GetLen();
+        pt = pt->GetNext();
+    }
+    return len;
+}
+
+// ----------------------------------------------------------------------------
+// FindObjNode - 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.
+// ----------------------------------------------------------------------------
+pdcObjectList::Node *wxPseudoDC::FindObjNode(int id, bool create)
+{
+    // see if last operation was for same id
+    if (m_lastObjNode && m_lastObjNode->GetData()->GetId() == id)
+        return m_lastObjNode;
+    // if not then search for it
+    pdcObjectList::Node *pt = m_objectlist.GetFirst();
+    while (pt) 
+    {
+        if (pt->GetData()->GetId() == id)
+               {
+        
+            // cache this node for future operations
+            m_lastObjNode = pt;
+            return pt;
+        }
+        pt = pt->GetNext();
+    }
+    // if create then create and return a new node
+    if (create) 
+    {
+        // cache this node for future operations
+        m_lastObjNode = m_objectlist.Append(new pdcObject(id));
+        return m_lastObjNode;
+    }
+    // otherwise just return NULL
+    return NULL;
+}
+
+// ----------------------------------------------------------------------------
+// AddToList - Add a node to the list at the end (preserve draw order)
+// ----------------------------------------------------------------------------
+void wxPseudoDC::AddToList(pdcOp *newOp)
+{
+    pdcObjectList::Node *pt = FindObjNode(m_currId, true);
+    pt->GetData()->AddOp(newOp);
+}
+
+// ----------------------------------------------------------------------------
+// ClearID - remove all the operations associated with a single ID
+// ----------------------------------------------------------------------------
+void wxPseudoDC::ClearId(int id)
+{
+    pdcObjectList::Node *pt = FindObjNode(id);
+    if (pt) pt->GetData()->Clear();
+}
+
+// ----------------------------------------------------------------------------
+// RemoveID - Remove the object node (and all operations) associated with an id
+// ----------------------------------------------------------------------------
+void wxPseudoDC::RemoveId(int id)
+{
+    pdcObjectList::Node *pt = FindObjNode(id);
+    if (pt) 
+    {
+        if (m_lastObjNode == pt)
+            m_lastObjNode = NULL;
+        m_objectlist.DeleteNode(pt);
+    }
+}
+
+// ----------------------------------------------------------------------------
+// SetIdBounds - Set the bounding rect for a given id
+// ----------------------------------------------------------------------------
+void wxPseudoDC::SetIdBounds(int id, wxRect& rect)
+{
+    pdcObjectList::Node *pt = FindObjNode(id, true);
+    pt->GetData()->SetBounds(rect);
+}
+
+// ----------------------------------------------------------------------------
+// GetIdBounds - Get the bounding rect for a given id
+// ----------------------------------------------------------------------------
+void wxPseudoDC::GetIdBounds(int id, wxRect& rect)
+{
+    pdcObjectList::Node *pt = FindObjNode(id);
+       if (pt && pt->GetData()->IsBounded())
+               rect = pt->GetData()->GetBounds();
+       else
+               rect.x = rect.y = rect.width = rect.height = 0;
+}
+
+// ----------------------------------------------------------------------------
+// TranslateId - Translate all the operations of a single id
+// ----------------------------------------------------------------------------
+void wxPseudoDC::TranslateId(int id, wxCoord dx, wxCoord dy)
+{
+    pdcObjectList::Node *pt = FindObjNode(id);
+    if (pt) pt->GetData()->Translate(dx,dy);
+}
+
+// ----------------------------------------------------------------------------
+// DrawIdToDC - Draw a specific id to the dc passed in
+// ----------------------------------------------------------------------------
+void wxPseudoDC::DrawIdToDC(int id, wxDC *dc)
+{
+    pdcObjectList::Node *pt = FindObjNode(id);
+    if (pt) pt->GetData()->DrawToDC(dc);
+}
+
+// ----------------------------------------------------------------------------
+// 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::Node *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::Node *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::Node *pt = m_objectlist.GetFirst();
+    while (pt) 
+    {
+        pt->GetData()->DrawToDC(dc);
+        pt = pt->GetNext();
+    }
+}
+