[GRASS-SVN] r35446 - grass/trunk/gui/wxpython/vdigit

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Jan 16 16:56:14 EST 2009


Author: martinl
Date: 2009-01-16 16:56:13 -0500 (Fri, 16 Jan 2009)
New Revision: 35446

Added:
   grass/trunk/gui/wxpython/vdigit/pseudodc.cpp
   grass/trunk/gui/wxpython/vdigit/pseudodc.h
Modified:
   grass/trunk/gui/wxpython/vdigit/Makefile
   grass/trunk/gui/wxpython/vdigit/driver.cpp
   grass/trunk/gui/wxpython/vdigit/driver.h
   grass/trunk/gui/wxpython/vdigit/driver_draw.cpp
Log:
wxvdigit: local copies of pseudodc.cpp|h added


Modified: grass/trunk/gui/wxpython/vdigit/Makefile
===================================================================
--- grass/trunk/gui/wxpython/vdigit/Makefile	2009-01-16 21:40:59 UTC (rev 35445)
+++ grass/trunk/gui/wxpython/vdigit/Makefile	2009-01-16 21:56:13 UTC (rev 35446)
@@ -13,10 +13,10 @@
 ifeq ($(findstring darwin,$(ARCH)),darwin)
 EXTRA_LIBS := -bundle -undefined dynamic_lookup $(EXTRA_LIBS)
 else
-EXTRA_LIBS := $(PYTHONLDFLAGS) $(EXTRA_LIBS) -lgdi
+EXTRA_LIBS := $(PYTHONLDFLAGS) $(EXTRA_LIBS)
 endif
 
-LOCAL_HEADERS = digit.h driver.h
+LOCAL_HEADERS = digit.h driver.h pseudodc.h
 
 ETCDIR = $(ETC)/wxpython
 

Modified: grass/trunk/gui/wxpython/vdigit/driver.cpp
===================================================================
--- grass/trunk/gui/wxpython/vdigit/driver.cpp	2009-01-16 21:40:59 UTC (rev 35445)
+++ grass/trunk/gui/wxpython/vdigit/driver.cpp	2009-01-16 21:56:13 UTC (rev 35446)
@@ -36,8 +36,8 @@
 
     mapInfo = NULL;
 
-    dc = (wxPseudoDC *) device;
-    dcTmp = (wxPseudoDC *) deviceTmp;
+    dc = (wxvdigit::wxPseudoDC *) device;
+    dcTmp = (wxvdigit::wxPseudoDC *) deviceTmp;
 
     points = Vect_new_line_struct();
     pointsScreen = new wxList();
@@ -88,7 +88,7 @@
 */
 void DisplayDriver::SetDevice(void *device)
 {
-    dc = (wxPseudoDC *) device;
+    dc = (wxvdigit::wxPseudoDC *) device;
 
     return;
 }

Modified: grass/trunk/gui/wxpython/vdigit/driver.h
===================================================================
--- grass/trunk/gui/wxpython/vdigit/driver.h	2009-01-16 21:40:59 UTC (rev 35445)
+++ grass/trunk/gui/wxpython/vdigit/driver.h	2009-01-16 21:56:13 UTC (rev 35446)
@@ -23,7 +23,7 @@
 #include <wx/string.h>
 
 #include <Python.h>
-#include <wx/wxPython/pseudodc.h>
+#include "pseudodc.h"
 
 extern "C" {
 #include <grass/gis.h>
@@ -34,7 +34,7 @@
 {
 private:
     friend class Digit;
-    wxPseudoDC *dc, *dcTmp;  // device content
+    wxvdigit::wxPseudoDC *dc, *dcTmp;  // device content
     wxWindow *parentWin;
     
     /* disabled due to expensive calling dc->SetId()
@@ -135,7 +135,7 @@
 		     double *, double *, double *);
     double DistanceInPixels(double);
 
-    int DrawCross(wxPseudoDC *, int, const wxPoint *, int size=5);
+    int DrawCross(wxvdigit::wxPseudoDC *, int, const wxPoint *, int size=5);
     int DrawArrow(double, double, double, double, double,
 		   int);
 

Modified: grass/trunk/gui/wxpython/vdigit/driver_draw.cpp
===================================================================
--- grass/trunk/gui/wxpython/vdigit/driver_draw.cpp	2009-01-16 21:40:59 UTC (rev 35445)
+++ grass/trunk/gui/wxpython/vdigit/driver_draw.cpp	2009-01-16 21:56:13 UTC (rev 35446)
@@ -223,7 +223,7 @@
     double x, y, z; // screen coordinates
     bool draw;      // draw object ?
     wxPen *pen;
-    wxPseudoDC *pdc;
+    wxvdigit::wxPseudoDC *pdc;
 
     pen = NULL;
     draw = false;
@@ -395,7 +395,7 @@
     int dcId;
     wxPoint *point;
     wxPen *pen;
-    wxPseudoDC *pdc;
+    wxvdigit::wxPseudoDC *pdc;
 
     if (!IsSelected(line) && !settings.vertex.enabled)
 	return -1;
@@ -471,7 +471,7 @@
     bool draw;
 
     wxPen *pen;
-    wxPseudoDC *pdc;
+    wxvdigit::wxPseudoDC *pdc;
 
     pdc = NULL;
 
@@ -563,7 +563,7 @@
    \return 1 on success
    \return -1 on failure
 */
-int DisplayDriver::DrawCross(wxPseudoDC *pdc, int line, const wxPoint* point, int size)
+int DisplayDriver::DrawCross(wxvdigit::wxPseudoDC *pdc, int line, const wxPoint* point, int size)
 {
     if (!pdc || !point)
 	return -1;

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

Added: grass/trunk/gui/wxpython/vdigit/pseudodc.h
===================================================================
--- grass/trunk/gui/wxpython/vdigit/pseudodc.h	                        (rev 0)
+++ grass/trunk/gui/wxpython/vdigit/pseudodc.h	2009-01-16 21:56:13 UTC (rev 35446)
@@ -0,0 +1,829 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        pseudodc.h
+// Purpose:     wxPseudoDC class
+// Author:      Paul Lanier
+// Modified by:
+// Created:     05/25/06
+// RCS-ID:      $Id: pseudodc.h 49047 2007-10-05 18:08:39Z RD $
+// Copyright:   (c) wxWidgets team
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+#ifndef WXVDIGIT_PSEUDODC_H
+#define WXVDIGIT_PSEUDODC_H
+
+namespace wxvdigit {
+
+//----------------------------------------------------------------------------
+// Base class for all pdcOp classes
+//----------------------------------------------------------------------------
+class pdcOp
+{
+    public:
+        // Constructor and Destructor
+        pdcOp() {}
+        virtual ~pdcOp() {}
+
+        // Virtual Drawing Methods
+        virtual void DrawToDC(wxDC *dc, bool grey=false)=0;
+        virtual void Translate(wxCoord WXUNUSED(dx), wxCoord WXUNUSED(dy)) {}
+        virtual void CacheGrey() {}
+};
+
+//----------------------------------------------------------------------------
+// declare a list class for list of pdcOps
+//----------------------------------------------------------------------------
+WX_DECLARE_LIST(pdcOp, pdcOpList);
+
+
+//----------------------------------------------------------------------------
+// Helper functions used for drawing greyed out versions of objects
+//----------------------------------------------------------------------------
+wxColour &MakeColourGrey(const wxColour &c);
+wxBrush &GetGreyBrush(wxBrush &brush);
+wxPen &GetGreyPen(wxPen &pen);
+wxIcon &GetGreyIcon(wxIcon &icon);
+wxBitmap &GetGreyBitmap(wxBitmap &bmp);
+
+//----------------------------------------------------------------------------
+// Classes derived from pdcOp
+// There is one class for each method mirrored from wxDC to wxPseudoDC
+//----------------------------------------------------------------------------
+class pdcSetFontOp : public pdcOp
+{
+    public:
+        pdcSetFontOp(const wxFont& font) 
+            {m_font=font;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->SetFont(m_font);}
+    protected:
+        wxFont m_font;
+};
+
+class pdcSetBrushOp : public pdcOp
+{
+    public:
+        pdcSetBrushOp(const wxBrush& brush) 
+            {m_greybrush=m_brush=brush;} 
+        virtual void DrawToDC(wxDC *dc, bool grey=false) 
+        {
+            if (!grey) dc->SetBrush(m_brush);
+            else dc->SetBrush(m_greybrush);
+        }
+        virtual void CacheGrey() {m_greybrush=GetGreyBrush(m_brush);}
+    protected:
+        wxBrush m_brush;
+        wxBrush m_greybrush;
+};
+
+class pdcSetBackgroundOp : public pdcOp
+{
+    public:
+        pdcSetBackgroundOp(const wxBrush& brush) 
+            {m_greybrush=m_brush=brush;} 
+        virtual void DrawToDC(wxDC *dc, bool grey=false)
+        {
+            if (!grey) dc->SetBackground(m_brush);
+            else dc->SetBackground(m_greybrush);
+        }
+        virtual void CacheGrey() {m_greybrush=GetGreyBrush(m_brush);}
+    protected:
+        wxBrush m_brush;
+        wxBrush m_greybrush;
+};
+
+class pdcSetPenOp : public pdcOp
+{
+    public:
+        pdcSetPenOp(const wxPen& pen) 
+            {m_greypen=m_pen=pen;}
+        virtual void DrawToDC(wxDC *dc, bool grey=false)
+        {
+            if (!grey) dc->SetPen(m_pen);
+            else dc->SetPen(m_greypen);
+        }
+        virtual void CacheGrey() {m_greypen=GetGreyPen(m_pen);}
+    protected:
+        wxPen m_pen;
+        wxPen m_greypen;
+};
+
+class pdcSetTextBackgroundOp : public pdcOp
+{
+    public:
+        pdcSetTextBackgroundOp(const wxColour& colour) 
+            {m_colour=colour;}
+        virtual void DrawToDC(wxDC *dc, bool grey=false) 
+        {
+            if (!grey) dc->SetTextBackground(m_colour);
+            else dc->SetTextBackground(MakeColourGrey(m_colour));
+        }
+    protected:
+        wxColour m_colour;
+};
+
+class pdcSetTextForegroundOp : public pdcOp
+{
+    public:
+        pdcSetTextForegroundOp(const wxColour& colour) 
+            {m_colour=colour;}
+        virtual void DrawToDC(wxDC *dc, bool grey=false)
+        {
+            if (!grey) dc->SetTextForeground(m_colour);
+            else dc->SetTextForeground(MakeColourGrey(m_colour));
+        }
+    protected:
+        wxColour m_colour;
+};
+
+class pdcDrawRectangleOp : public pdcOp
+{
+    public:
+        pdcDrawRectangleOp(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
+            {m_x=x; m_y=y; m_w=w; m_h=h;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawRectangle(m_x,m_y,m_w,m_h);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx;m_y+=dy;}
+    protected:
+        wxCoord m_x,m_y,m_w,m_h;
+};
+
+class pdcDrawLineOp : public pdcOp
+{
+    public:
+        pdcDrawLineOp(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
+            {m_x1=x1; m_y1=y1; m_x2=x2; m_y2=y2;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawLine(m_x1,m_y1,m_x2,m_y2);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x1+=dx; m_y1+=dy; m_x2+=dx; m_y2+=dy;}
+    protected:
+        wxCoord m_x1,m_y1,m_x2,m_y2;
+};
+
+class pdcSetBackgroundModeOp : public pdcOp
+{
+    public:
+        pdcSetBackgroundModeOp(int mode) {m_mode=mode;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->SetBackgroundMode(m_mode);}
+    protected:
+        int m_mode;
+};
+
+class pdcDrawTextOp : public pdcOp
+{
+    public:
+        pdcDrawTextOp(const wxString& text, wxCoord x, wxCoord y)
+            {m_text=text; m_x=x; m_y=y;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawText(m_text, m_x, m_y);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxString m_text;
+        wxCoord m_x, m_y;
+};
+
+class pdcClearOp : public pdcOp
+{
+    public:
+        pdcClearOp() {}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->Clear();}
+};
+
+class pdcBeginDrawingOp : public pdcOp
+{
+    public:
+        pdcBeginDrawingOp() {}
+        virtual void DrawToDC(wxDC *WXUNUSED(dc), bool WXUNUSED(grey)=false) {}
+};
+
+class pdcEndDrawingOp : public pdcOp
+{
+    public:
+        pdcEndDrawingOp() {}
+        virtual void DrawToDC(wxDC *WXUNUSED(dc), bool WXUNUSED(grey)=false) {}
+};
+
+class pdcFloodFillOp : public pdcOp
+{
+    public:
+        pdcFloodFillOp(wxCoord x, wxCoord y, const wxColour& col,
+                   int style) {m_x=x; m_y=y; m_col=col; m_style=style;}
+        virtual void DrawToDC(wxDC *dc, bool grey=false) 
+        {
+            if (!grey) dc->FloodFill(m_x,m_y,m_col,m_style);
+            else dc->FloodFill(m_x,m_y,MakeColourGrey(m_col),m_style);
+        }
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxCoord m_x,m_y;
+        wxColour m_col;
+        int m_style;
+};
+
+class pdcCrossHairOp : public pdcOp
+{
+    public:
+        pdcCrossHairOp(wxCoord x, wxCoord y) {m_x=x; m_y=y;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->CrossHair(m_x,m_y);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxCoord m_x,m_y;
+};
+
+class pdcDrawArcOp : public pdcOp
+{
+    public:
+        pdcDrawArcOp(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
+                         wxCoord xc, wxCoord yc) 
+            {m_x1=x1; m_y1=y1; m_x2=x2; m_y2=y2; m_xc=xc; m_yc=yc;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) 
+            {dc->DrawArc(m_x1,m_y1,m_x2,m_y2,m_xc,m_yc);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x1+=dx; m_x2+=dx; m_y1+=dy; m_y2+=dy;}
+    protected:
+        wxCoord m_x1,m_x2,m_xc;
+        wxCoord m_y1,m_y2,m_yc;
+};
+
+class pdcDrawCheckMarkOp : public pdcOp
+{
+    public:
+        pdcDrawCheckMarkOp(wxCoord x, wxCoord y,
+                       wxCoord width, wxCoord height) 
+            {m_x=x; m_y=y; m_w=width; m_h=height;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) 
+            {dc->DrawCheckMark(m_x,m_y,m_w,m_h);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxCoord m_x,m_y,m_w,m_h;
+};
+
+class pdcDrawEllipticArcOp : public pdcOp
+{
+    public:
+        pdcDrawEllipticArcOp(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
+                         double sa, double ea) 
+            {m_x=x; m_y=y; m_w=w; m_h=h; m_sa=sa; m_ea=ea;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) 
+            {dc->DrawEllipticArc(m_x,m_y,m_w,m_h,m_sa,m_ea);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxCoord m_x,m_y,m_w,m_h;
+        double m_sa,m_ea;
+};
+
+class pdcDrawPointOp : public pdcOp
+{
+    public:
+        pdcDrawPointOp(wxCoord x, wxCoord y) 
+            {m_x=x; m_y=y;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawPoint(m_x,m_y);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxCoord m_x,m_y;
+};
+
+class pdcDrawRoundedRectangleOp : public pdcOp
+{
+    public:
+        pdcDrawRoundedRectangleOp(wxCoord x, wxCoord y, wxCoord width, 
+                                  wxCoord height, double radius) 
+            {m_x=x; m_y=y; m_w=width; m_h=height; m_r=radius;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) 
+            {dc->DrawRoundedRectangle(m_x,m_y,m_w,m_h,m_r);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxCoord m_x,m_y,m_w,m_h;
+        double m_r;
+};
+
+class pdcDrawEllipseOp : public pdcOp
+{
+    public:
+        pdcDrawEllipseOp(wxCoord x, wxCoord y, wxCoord width, wxCoord height) 
+            {m_x=x; m_y=y; m_w=width; m_h=height;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawEllipse(m_x,m_y,m_w,m_h);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxCoord m_x,m_y,m_w,m_h;
+};
+
+class pdcDrawIconOp : public pdcOp
+{
+    public:
+        pdcDrawIconOp(const wxIcon& icon, wxCoord x, wxCoord y) 
+            {m_icon=icon; m_x=x; m_y=y;}
+        virtual void DrawToDC(wxDC *dc, bool grey=false) 
+        {
+            if (grey) dc->DrawIcon(m_greyicon,m_x,m_y);
+            else dc->DrawIcon(m_icon,m_x,m_y);
+        }
+        virtual void CacheGrey() {m_greyicon=GetGreyIcon(m_icon);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxIcon m_icon;
+        wxIcon m_greyicon;
+        wxCoord m_x,m_y;
+};
+
+class pdcDrawLinesOp : public pdcOp
+{
+    public:
+        pdcDrawLinesOp(int n, wxPoint points[],
+               wxCoord xoffset = 0, wxCoord yoffset = 0);
+        virtual ~pdcDrawLinesOp();
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) 
+            {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, bool WXUNUSED(grey)=false) 
+            {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, bool WXUNUSED(grey)=false) 
+            {dc->DrawPolyPolygon(m_n,m_count,m_points,
+                    m_xoffset,m_yoffset,m_fillStyle);}
+        virtual void Translate(wxCoord dx, wxCoord dy)
+        { 
+            for(int i=0; i<m_totaln; i++)
+            {
+                m_points[i].x += dx; 
+                m_points[i].y += dy;
+            }
+        }
+    protected:
+        int m_n;
+        int m_totaln;
+        int *m_count;
+        wxPoint *m_points;
+        wxCoord m_xoffset, m_yoffset;
+        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, bool WXUNUSED(grey)=false) 
+            {dc->DrawRotatedText(m_text,m_x,m_y,m_angle);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxString m_text;
+        wxCoord m_x,m_y;
+        double m_angle;
+};
+
+class pdcDrawBitmapOp : public pdcOp
+{
+    public:
+        pdcDrawBitmapOp(const wxBitmap &bmp, wxCoord x, wxCoord y,
+                        bool useMask = false) 
+            {m_bmp=bmp; m_x=x; m_y=y; m_useMask=useMask;}
+        virtual void DrawToDC(wxDC *dc, bool grey=false) 
+        {
+            if (grey) dc->DrawBitmap(m_greybmp,m_x,m_y,m_useMask);
+            else dc->DrawBitmap(m_bmp,m_x,m_y,m_useMask);
+        }
+        virtual void CacheGrey() {m_greybmp=GetGreyBitmap(m_bmp);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_x+=dx; m_y+=dy;}
+    protected:
+        wxBitmap m_bmp;
+        wxBitmap m_greybmp;
+        wxCoord m_x,m_y;
+        bool m_useMask;
+};
+
+class pdcDrawLabelOp : public pdcOp
+{
+    public:
+        pdcDrawLabelOp(const wxString& text,
+                           const wxBitmap& image,
+                           const wxRect& rect,
+                           int alignment = wxALIGN_LEFT | wxALIGN_TOP,
+                           int indexAccel = -1)
+            {m_text=text; m_image=image; m_rect=rect; 
+             m_align=alignment; m_iAccel=indexAccel;}
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) 
+            {dc->DrawLabel(m_text,m_image,m_rect,m_align,m_iAccel);}
+        virtual void Translate(wxCoord dx, wxCoord dy) 
+            {m_rect.x+=dx; m_rect.y+=dy;}
+    protected:
+        wxString m_text;
+        wxBitmap m_image;
+        wxRect m_rect;
+        int m_align;
+        int m_iAccel;
+};
+
+#if wxUSE_SPLINES
+class pdcDrawSplineOp : public pdcOp
+{
+    public:
+        pdcDrawSplineOp(int n, wxPoint points[]);
+        virtual ~pdcDrawSplineOp();
+        virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {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, bool WXUNUSED(grey)=false) {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, bool WXUNUSED(grey)=false) {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);
+             m_greyedout=false;}
+
+        virtual ~pdcObject() {m_oplist.Clear();}
+        
+        // Protected Member Access
+        void SetId(int id) {m_id=id;}
+        int  GetId() {return m_id;}
+        void   SetBounds(wxRect& rect) {m_bounds=rect; m_bounded=true;}
+        wxRect GetBounds() {return m_bounds;}
+        void SetBounded(bool bounded) {m_bounded=bounded;}
+        bool IsBounded() {return m_bounded;}
+        void SetGreyedOut(bool greyout=true);
+        bool GetGreyedOut() {return m_greyedout;}
+    
+        // Op List Management Methods
+        void Clear() {m_oplist.Clear();}
+        void AddOp(pdcOp *op) 
+        {
+            m_oplist.Append(op);
+            if (m_greyedout) op->CacheGrey();
+        }
+        int  GetLen() {return m_oplist.GetCount();}
+        virtual void Translate(wxCoord dx, wxCoord dy);
+        
+        // Drawing Method
+        virtual void DrawToDC(wxDC *dc);
+    protected:
+        int m_id; // id of object (associates this pdcObject
+                  //               with a Python object with same id)
+        wxRect m_bounds;  // bounding rect of this object
+        bool m_bounded;   // true if bounds is valid, false by default
+        pdcOpList m_oplist; // list of operations for this object
+        bool m_greyedout; // if true then draw this object in greys only
+};
+
+
+//----------------------------------------------------------------------------
+// Declare a wxList to hold all the objects.  List order reflects drawing
+// order (Z order) and is the same order as objects are added to the list
+//----------------------------------------------------------------------------
+class pdcObjectList;
+WX_DECLARE_LIST(pdcObject, pdcObjectList);
+
+//Declare a hashmap that maps from ids to nodes in the object list.
+WX_DECLARE_HASH_MAP(
+    int,
+    pdcObject *,
+    wxIntegerHash,
+    wxIntegerEqual,
+    pdcObjectHash
+);
+
+
+// ----------------------------------------------------------------------------
+// wxPseudoDC class
+// ----------------------------------------------------------------------------
+// This is the actual PseudoDC class
+// This class stores a list of recorded dc operations in m_list
+// and plays them back to a real dc using DrawToDC or DrawToDCClipped.
+// Drawing methods are mirrored from wxDC but add nodes to m_list 
+// instead of doing any real drawing.
+// ----------------------------------------------------------------------------
+class wxPseudoDC : public wxObject
+{
+public:
+    wxPseudoDC() 
+        {m_currId=-1; m_lastObject=NULL; m_objectlist.DeleteContents(true);m_objectIndex.clear();}
+    ~wxPseudoDC();
+    // ------------------------------------------------------------------------
+    // List 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);
+    // Grey-out an object
+    void SetIdGreyedOut(int id, bool greyout=true);
+    bool GetIdGreyedOut(int id);
+    // Find Objects at a point.  Returns Python list of id's
+    // sorted in reverse drawing order (result[0] is top object)
+    // This version looks at drawn pixels
+    PyObject *FindObjects(wxCoord x, wxCoord y, 
+                          wxCoord radius=1, const wxColor& bg=*wxWHITE);
+    // This version only looks at bounding boxes
+    PyObject *FindObjectsByBBox(wxCoord x, wxCoord y);
+
+    // ------------------------------------------------------------------------
+    // Playback Methods
+    //
+    // draw to dc but skip objects known to be outside of rect
+    // This is a coarse level of clipping to speed things up 
+    // when lots of objects are off screen and doesn't affect the dc level 
+    // clipping
+    void DrawToDCClipped(wxDC *dc, const wxRect& rect);
+        void DrawToDCClippedRgn(wxDC *dc, const wxRegion& region);
+    // draw to dc with no clipping (well the dc will still clip)
+    void DrawToDC(wxDC *dc);
+    // draw a single object to the dc
+    void DrawIdToDC(int id, wxDC *dc);
+
+    // ------------------------------------------------------------------------
+    // Hit Detection Methods
+    //
+    // returns list of object with a drawn pixel within radius pixels of (x,y)
+    // the list is in reverse draw order so last drawn is first in list
+    // PyObject *HitTest(wxCoord x, wxCoord y, double radius)
+    // returns list of objects whose bounding boxes include (x,y)
+    // PyObject *HitTestBB(wxCoord x, wxCoord y)
+    
+        
+    // ------------------------------------------------------------------------
+    // Methods mirrored from wxDC
+    //
+    void FloodFill(wxCoord x, wxCoord y, const wxColour& col,
+                   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);
+    pdcObject *FindObject(int id, bool create=false);
+    
+    // ------------------------------------------------------------------------
+    // Data members
+    // 
+    int m_currId; // id to use for operations done on the PseudoDC
+    pdcObject *m_lastObject; // used to find last used object quickly
+    pdcObjectList m_objectlist; // list of objects
+    pdcObjectHash m_objectIndex; //id->object lookup index
+    
+};
+
+}
+
+#endif
+



More information about the grass-commit mailing list