From 7e664d85e6512d807ce2eb186ed9e0bbd60d6e8b Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Mon, 10 Jul 2006 15:06:31 +0000 Subject: [PATCH] Added the PseudoDC class from Paul Lanier. It provides a way to 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 | 2 + wxPython/demo/PseudoDC.py | 306 ++++++++++ wxPython/docs/CHANGES.txt | 4 + wxPython/include/wx/wxPython/pseudodc.h | 736 ++++++++++++++++++++++++ wxPython/setup.py | 4 +- wxPython/src/_pseudodc.i | 580 +++++++++++++++++++ wxPython/src/pseudodc.cpp | 368 ++++++++++++ 7 files changed, 1998 insertions(+), 2 deletions(-) create mode 100644 wxPython/demo/PseudoDC.py create mode 100644 wxPython/include/wx/wxPython/pseudodc.h create mode 100644 wxPython/src/_pseudodc.i create mode 100644 wxPython/src/pseudodc.cpp diff --git a/wxPython/demo/Main.py b/wxPython/demo/Main.py index 33d9b9ecdf..c89232c979 100644 --- a/wxPython/demo/Main.py +++ b/wxPython/demo/Main.py @@ -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 index 0000000000..379ac42329 --- /dev/null +++ b/wxPython/demo/PseudoDC.py @@ -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 = """ + + +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:
+DrawToDC(dc)
+
+The operations can be tagged with an id in order to associated them with a +specific object. To do this use:
+SetId(id)
+
+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:
+SetIdBounds(id,rect)
+
+for each object that should be clipped. Then use:
+DrawToDCClipped(dc, clippingRect)
+
+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:
+TranslateId(id, dx, dy)
+
+ +To re-draw an object use:
+ClearId(id)
+SetId(id)
+
+and then re-draw the object. + + +""" + + +if __name__ == '__main__': + import sys,os + import run + run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]) + diff --git a/wxPython/docs/CHANGES.txt b/wxPython/docs/CHANGES.txt index 6538e02483..d056255450 100644 --- a/wxPython/docs/CHANGES.txt +++ b/wxPython/docs/CHANGES.txt @@ -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 index 0000000000..622e99977e --- /dev/null +++ b/wxPython/include/wx/wxPython/pseudodc.h @@ -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; iDrawPolygon(m_n,m_points,m_xoffset,m_yoffset,m_fillStyle); } + + virtual void Translate(wxCoord dx, wxCoord dy) + { + for(int i=0; iDrawPolyPolygon(m_n,m_count,m_points, + m_xoffset,m_yoffset,m_fillStyle);} + virtual void Translate(wxCoord dx, wxCoord dy) + { + for(int i=0; iDrawRotatedText(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; iSetPalette(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 + diff --git a/wxPython/setup.py b/wxPython/setup.py index 51eef48d55..26a6096556 100755 --- a/wxPython/setup.py +++ b/wxPython/setup.py @@ -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 index 0000000000..e2f6710c53 --- /dev/null +++ b/wxPython/src/_pseudodc.i @@ -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 index 0000000000..dc2d2eb1af --- /dev/null +++ b/wxPython/src/pseudodc.cpp @@ -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 + +// wxList based class definitions +#include +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; iGetData()->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(); + } +} + -- 2.45.2