pseudodc.cpp
Go to the documentation of this file.
00001 
00002 // Name:        common/pseudodc.cpp
00003 // Purpose:     Implementation of the wxPseudoDC Class
00004 // Author:      Paul Lanier
00005 // Modified by:
00006 // Created:     05/25/06
00007 // RCS-ID:      $Id: pseudodc.cpp,v 1.3 2006/10/21 01:22:11 RD Exp $
00008 // Copyright:   (c) wxWidgets team
00009 // Licence:     wxWindows licence
00011 
00012 // For compilers that support precompilation, includes "wx.h".
00013 //include "wx/wxprec.h"
00014 
00015 #undef DEBUG
00016 #include <Python.h>
00017 #include "wx/wxPython/wxPython.h"
00018 #include "wx/wxPython/pseudodc.h"
00019 
00020 // wxList based class definitions
00021 #include <wx/listimpl.cpp>
00022 WX_DEFINE_LIST(pdcOpList);
00023 WX_DEFINE_LIST(pdcObjectList);
00024 
00025 //----------------------------------------------------------------------------
00026 // Helper functions used for drawing greyed out versions of objects
00027 //----------------------------------------------------------------------------
00028 wxColour &MakeColourGrey(const wxColour &c)
00029 {
00030     static wxColour rval;
00031     rval.Set(byte((230-c.Red())*0.7+c.Red()),
00032              byte((230-c.Green())*0.7+c.Green()),
00033              byte((230-c.Blue())*0.7+c.Blue()));
00034     return rval;
00035 }
00036 wxBrush &GetGreyBrush(wxBrush &brush)
00037 {
00038         static wxBrush b;
00039         wxColour c;
00040         b = brush;
00041         c = MakeColourGrey(brush.GetColour());
00042         b.SetColour(c);
00043         return b;
00044 }
00045 
00046 wxPen &GetGreyPen(wxPen &pen)
00047 {
00048         static wxPen p;
00049         wxColour c;
00050         p = pen;
00051         c = MakeColourGrey(pen.GetColour());
00052         p.SetColour(c);
00053         return p;
00054 }
00055 
00056 void GreyOutImage(wxImage &img)
00057 {
00058     unsigned char *data = img.GetData();
00059     unsigned char r,g,b;
00060     unsigned char mr,mg,mb;
00061     int i, tst;
00062     int len = img.GetHeight()*img.GetWidth()*3;
00063     if (img.HasMask())
00064     {
00065         mr = img.GetMaskRed();
00066         mg = img.GetMaskGreen();
00067         mb = img.GetMaskBlue();
00068     }
00069     tst=0;
00070     for (i=0;i<len;i+=3)
00071     {
00072         r=data[i]; g=data[i+1]; b=data[i+2];
00073         if (!img.HasMask() || 
00074             r!=mr || g!=mg || b!=mb)
00075         {
00076             if (!tst)
00077             {
00078                 tst=1;
00079             }
00080             r = (unsigned char)((230.0-r)*0.7+r);
00081             g = (unsigned char)((230.0-g)*0.7+g);
00082             b = (unsigned char)((230.0-b)*0.7+b);
00083             data[i]=r; data[i+1]=g; data[i+2]=b;
00084         }
00085     }
00086 }
00087 
00088 wxIcon &GetGreyIcon(wxIcon &icon)
00089 {
00090     wxBitmap bmp;
00091     bmp.CopyFromIcon(icon);
00092     wxImage img = bmp.ConvertToImage();
00093     GreyOutImage(img);
00094     wxBitmap bmp2(img,32);
00095     static wxIcon rval;
00096     rval.CopyFromBitmap(bmp2);
00097     return rval;
00098 }
00099 
00100 wxBitmap &GetGreyBitmap(wxBitmap &bmp)
00101 {
00102     wxImage img = bmp.ConvertToImage();
00103     GreyOutImage(img);
00104     static wxBitmap rval(img,32);
00105     return rval;
00106 }
00107 
00108 // ============================================================================
00109 // various pdcOp class implementation methods
00110 // ============================================================================
00111 
00112 // ----------------------------------------------------------------------------
00113 // pdcDrawPolyPolygonOp constructor
00114 // ----------------------------------------------------------------------------
00115 pdcDrawPolyPolygonOp::pdcDrawPolyPolygonOp(int n, int count[], wxPoint points[],
00116                  wxCoord xoffset, wxCoord yoffset, int fillStyle) 
00117 {
00118     m_n=n; m_xoffset=xoffset; m_yoffset=yoffset; m_fillStyle=fillStyle;
00119     int total_n=0;
00120     if (n)
00121     {
00122         m_count = new int[n];
00123         for(int i=0; i<n; i++) 
00124         {
00125             total_n+=count[i];
00126             m_count[i]=count[i];
00127         }
00128         if (total_n)
00129         {
00130             m_points = new wxPoint[total_n];
00131             for(int j=0; j<total_n; j++)
00132                 m_points[j] = points[j];
00133         }
00134         else m_points=NULL;
00135     }
00136     else
00137     {
00138         m_points=NULL;
00139         m_count=NULL;
00140     }
00141     m_totaln = total_n;
00142 }
00143 
00144 // ----------------------------------------------------------------------------
00145 // pdcDrawPolyPolygonOp destructor
00146 // ----------------------------------------------------------------------------
00147 pdcDrawPolyPolygonOp::~pdcDrawPolyPolygonOp()
00148 {
00149     if (m_points) delete m_points;
00150     if (m_count) delete m_count;
00151     m_points=NULL;
00152     m_count=NULL;
00153 }
00154         
00155 // ----------------------------------------------------------------------------
00156 // pdcDrawLinesOp constructor
00157 // ----------------------------------------------------------------------------
00158 pdcDrawLinesOp::pdcDrawLinesOp(int n, wxPoint points[],
00159              wxCoord xoffset, wxCoord yoffset)
00160 {
00161     m_n=n; m_xoffset=xoffset; m_yoffset=yoffset;
00162     if (n)
00163     {
00164         m_points = new wxPoint[n];
00165         for (int i=0; i<n; i++)
00166             m_points[i] = points[i];
00167     }
00168     else m_points=NULL;
00169 }
00170 
00171 // ----------------------------------------------------------------------------
00172 // pdcDrawLinesOp destructor
00173 // ----------------------------------------------------------------------------
00174 pdcDrawLinesOp::~pdcDrawLinesOp()
00175 {
00176     if (m_points) delete m_points;
00177     m_points=NULL;
00178 }
00179         
00180 // ----------------------------------------------------------------------------
00181 // pdcDrawPolygonOp constructor
00182 // ----------------------------------------------------------------------------
00183 pdcDrawPolygonOp::pdcDrawPolygonOp(int n, wxPoint points[],
00184              wxCoord xoffset, wxCoord yoffset, int fillStyle)
00185 {
00186     m_n=n; m_xoffset=xoffset; m_yoffset=yoffset; m_fillStyle=fillStyle;
00187     if (n)
00188     {
00189         m_points = new wxPoint[n];
00190         for (int i=0; i<n; i++)
00191             m_points[i] = points[i];
00192     }
00193     else m_points=NULL;
00194 }
00195 
00196 // ----------------------------------------------------------------------------
00197 // pdcDrawPolygonOp destructor
00198 // ----------------------------------------------------------------------------
00199 pdcDrawPolygonOp::~pdcDrawPolygonOp()
00200 {
00201     if (m_points) delete m_points;
00202     m_points=NULL;
00203 }
00204 
00205 #if wxUSE_SPLINES
00206 // ----------------------------------------------------------------------------
00207 // pdcDrawSplineOp constructor
00208 // ----------------------------------------------------------------------------
00209 pdcDrawSplineOp::pdcDrawSplineOp(int n, wxPoint points[])
00210 {
00211     m_n=n;
00212     if (n)
00213     {
00214         m_points = new wxPoint[n];
00215         for(int i=0; i<n; i++)
00216             m_points[i] = points[i];
00217     }
00218     else m_points=NULL;
00219 }
00220 
00221 // ----------------------------------------------------------------------------
00222 // pdcDrawSplineOp destructor
00223 // ----------------------------------------------------------------------------
00224 pdcDrawSplineOp::~pdcDrawSplineOp()
00225 {
00226     if (m_points) delete m_points;
00227     m_points=NULL;
00228 }
00229 #endif // wxUSE_SPLINES
00230 
00231 // ============================================================================
00232 // pdcObject implementation
00233 // ============================================================================
00234 // ----------------------------------------------------------------------------
00235 // DrawToDC - play back the op list to the DC 
00236 // ----------------------------------------------------------------------------
00237 void pdcObject::DrawToDC(wxDC *dc)
00238 {
00239     pdcOpList::Node *node = m_oplist.GetFirst(); 
00240     while(node)
00241     {
00242         node->GetData()->DrawToDC(dc, m_greyedout);
00243         node = node->GetNext();
00244     }
00245 }
00246 
00247 // ----------------------------------------------------------------------------
00248 // Translate - translate all the operations by some dx,dy
00249 // ----------------------------------------------------------------------------
00250 void pdcObject::Translate(wxCoord dx, wxCoord dy)
00251 {
00252     pdcOpList::Node *node = m_oplist.GetFirst(); 
00253     while(node)
00254     {
00255         node->GetData()->Translate(dx,dy);
00256         node = node->GetNext();
00257     }
00258         if (m_bounded) 
00259         {
00260                 m_bounds.x += dx;
00261                 m_bounds.y += dy;
00262         }
00263 }
00264 
00265 // ----------------------------------------------------------------------------
00266 // SetGreyedOut - set the greyout member and cache grey versions of everything
00267 // if greyout is true
00268 // ----------------------------------------------------------------------------
00269 void pdcObject::SetGreyedOut(bool greyout) 
00270 {
00271         m_greyedout=greyout;
00272         if (greyout)
00273         {
00274                 pdcOpList::Node *node = m_oplist.GetFirst(); 
00275         pdcOp *obj;
00276                 while(node)
00277                 {
00278 
00279                         obj = node->GetData();
00280             obj->CacheGrey();
00281                         node = node->GetNext();
00282                 }
00283         }
00284 }
00285 
00286 // ============================================================================
00287 // wxPseudoDC implementation
00288 // ============================================================================
00289 
00290 // ----------------------------------------------------------------------------
00291 // Destructor
00292 // ----------------------------------------------------------------------------
00293 wxPseudoDC::~wxPseudoDC()
00294 {
00295     // delete all the nodes in the list
00296         RemoveAll();
00297         
00298 }
00299 
00300 // ----------------------------------------------------------------------------
00301 // ClearAll - remove all nodes from list
00302 // ----------------------------------------------------------------------------
00303 void wxPseudoDC::RemoveAll(void)
00304 {
00305     m_objectlist.Clear();
00306     m_currId = -1;
00307         m_lastObjNode = NULL;
00308 }
00309 
00310 // ----------------------------------------------------------------------------
00311 // GetLen - return the number of operations in the current op list
00312 // ----------------------------------------------------------------------------
00313 int wxPseudoDC::GetLen(void)
00314 {
00315     pdcObjectList::Node *pt = m_objectlist.GetFirst();
00316     int len=0;
00317     while (pt) 
00318     {
00319         len += pt->GetData()->GetLen();
00320         pt = pt->GetNext();
00321     }
00322     return len;
00323 }
00324 
00325 // ----------------------------------------------------------------------------
00326 // FindObjNode - find and return an object node by id.  If node doesn't exist
00327 //               and create is true then create one and return it.  Otherwise
00328 //               return NULL.
00329 // ----------------------------------------------------------------------------
00330 pdcObjectList::Node *wxPseudoDC::FindObjNode(int id, bool create)
00331 {
00332     // see if last operation was for same id
00333     if (m_lastObjNode && m_lastObjNode->GetData()->GetId() == id)
00334         return m_lastObjNode;
00335     // if not then search for it
00336     pdcObjectList::Node *pt = m_objectlist.GetFirst();
00337     while (pt) 
00338     {
00339         if (pt->GetData()->GetId() == id)
00340                 {
00341         
00342             // cache this node for future operations
00343             m_lastObjNode = pt;
00344             return pt;
00345         }
00346         pt = pt->GetNext();
00347     }
00348     // if create then create and return a new node
00349     if (create) 
00350     {
00351         // cache this node for future operations
00352         m_lastObjNode = m_objectlist.Append(new pdcObject(id));
00353         return m_lastObjNode;
00354     }
00355     // otherwise just return NULL
00356     return NULL;
00357 }
00358 
00359 // ----------------------------------------------------------------------------
00360 // AddToList - Add a node to the list at the end (preserve draw order)
00361 // ----------------------------------------------------------------------------
00362 void wxPseudoDC::AddToList(pdcOp *newOp)
00363 {
00364     pdcObjectList::Node *pt = FindObjNode(m_currId, true);
00365     pt->GetData()->AddOp(newOp);
00366 }
00367 
00368 // ----------------------------------------------------------------------------
00369 // ClearID - remove all the operations associated with a single ID
00370 // ----------------------------------------------------------------------------
00371 void wxPseudoDC::ClearId(int id)
00372 {
00373     pdcObjectList::Node *pt = FindObjNode(id);
00374     if (pt) pt->GetData()->Clear();
00375 }
00376 
00377 // ----------------------------------------------------------------------------
00378 // RemoveID - Remove the object node (and all operations) associated with an id
00379 // ----------------------------------------------------------------------------
00380 void wxPseudoDC::RemoveId(int id)
00381 {
00382     pdcObjectList::Node *pt = FindObjNode(id);
00383     if (pt) 
00384     {
00385         if (m_lastObjNode == pt)
00386             m_lastObjNode = NULL;
00387         m_objectlist.DeleteNode(pt);
00388     }
00389 }
00390 
00391 // ----------------------------------------------------------------------------
00392 // SetIdBounds - Set the bounding rect for a given id
00393 // ----------------------------------------------------------------------------
00394 void wxPseudoDC::SetIdBounds(int id, wxRect& rect)
00395 {
00396     pdcObjectList::Node *pt = FindObjNode(id, true);
00397     pt->GetData()->SetBounds(rect);
00398 }
00399 
00400 // ----------------------------------------------------------------------------
00401 // GetIdBounds - Get the bounding rect for a given id
00402 // ----------------------------------------------------------------------------
00403 void wxPseudoDC::GetIdBounds(int id, wxRect& rect)
00404 {
00405     pdcObjectList::Node *pt = FindObjNode(id);
00406         if (pt && pt->GetData()->IsBounded())
00407                 rect = pt->GetData()->GetBounds();
00408         else
00409                 rect.x = rect.y = rect.width = rect.height = 0;
00410 }
00411 
00412 // ----------------------------------------------------------------------------
00413 // TranslateId - Translate all the operations of a single id
00414 // ----------------------------------------------------------------------------
00415 void wxPseudoDC::TranslateId(int id, wxCoord dx, wxCoord dy)
00416 {
00417     pdcObjectList::Node *pt = FindObjNode(id);
00418     if (pt) pt->GetData()->Translate(dx,dy);
00419 }
00420 
00421 // ----------------------------------------------------------------------------
00422 // DrawIdToDC - Draw a specific id to the dc passed in
00423 // ----------------------------------------------------------------------------
00424 void wxPseudoDC::DrawIdToDC(int id, wxDC *dc)
00425 {
00426     pdcObjectList::Node *pt = FindObjNode(id);
00427     if (pt) pt->GetData()->DrawToDC(dc);
00428 }
00429 
00430 // ----------------------------------------------------------------------------
00431 // SetIdGreyedOut - Set the greyedout member of id
00432 // ----------------------------------------------------------------------------
00433 void wxPseudoDC::SetIdGreyedOut(int id, bool greyout)
00434 {
00435     pdcObjectList::Node *pt = FindObjNode(id);
00436     if (pt) pt->GetData()->SetGreyedOut(greyout);
00437 }
00438 
00439 // ----------------------------------------------------------------------------
00440 // GetIdGreyedOut - Get the greyedout member of id
00441 // ----------------------------------------------------------------------------
00442 bool wxPseudoDC::GetIdGreyedOut(int id)
00443 {
00444     pdcObjectList::Node *pt = FindObjNode(id);
00445     if (pt) return pt->GetData()->GetGreyedOut();
00446         else return false;
00447 }
00448 
00449 // ----------------------------------------------------------------------------
00450 // FindObjectsByBBox - Return a list of all the ids whose bounding boxes
00451 //                     contain (x,y)
00452 // ----------------------------------------------------------------------------
00453 PyObject *wxPseudoDC::FindObjectsByBBox(wxCoord x, wxCoord y)
00454 {
00455     //wxPyBlock_t blocked = wxPyBeginBlockThreads();
00456     pdcObjectList::Node *pt = m_objectlist.GetFirst();
00457     pdcObject *obj;
00458     PyObject* pyList = NULL;
00459     pyList = PyList_New(0);
00460     wxRect r;
00461     while (pt) 
00462     {
00463         obj = pt->GetData();
00464         r = obj->GetBounds();
00465         if (obj->IsBounded() && r.Contains(x,y))
00466         {
00467             PyObject* pyObj = PyInt_FromLong((long)obj->GetId());
00468             PyList_Insert(pyList, 0, pyObj);
00469             Py_DECREF(pyObj);
00470         }
00471         pt = pt->GetNext();
00472     }
00473     //wxPyEndBlockThreads(blocked);
00474     return pyList;
00475 }
00476 
00477 // ----------------------------------------------------------------------------
00478 // FindObjects - Return a list of all the ids that draw to (x,y)
00479 // ----------------------------------------------------------------------------
00480 PyObject *wxPseudoDC::FindObjects(wxCoord x, wxCoord y, 
00481                                   wxCoord radius, const wxColor& bg)
00482 {
00483     //wxPyBlock_t blocked = wxPyBeginBlockThreads();
00484     pdcObjectList::Node *pt = m_objectlist.GetFirst();
00485     pdcObject *obj;
00486     PyObject* pyList = NULL;
00487     pyList = PyList_New(0);
00488     wxBrush bgbrush(bg);
00489     wxPen bgpen(bg);
00490     // special case radius = 0
00491     if (radius == 0)
00492     {
00493         wxBitmap bmp(4,4,24);
00494         wxMemoryDC memdc;
00495         wxColor pix;
00496         wxRect viewrect(x-2,y-2,4,4);
00497         // setup the memdc for rendering
00498         memdc.SelectObject(bmp);
00499         memdc.SetBackground(bgbrush);
00500         memdc.Clear();
00501         memdc.SetDeviceOrigin(2-x,2-y);
00502         while (pt) 
00503         {
00504             obj = pt->GetData();
00505             if (obj->IsBounded() && obj->GetBounds().Contains(x,y))
00506             {
00507                 // start clean
00508                 memdc.SetBrush(bgbrush);
00509                 memdc.SetPen(bgpen);
00510                 memdc.DrawRectangle(viewrect);
00511                 // draw the object
00512                 obj->DrawToDC(&memdc);
00513                 memdc.GetPixel(x,y,&pix);
00514                 // clear and update rgn2
00515                 if (pix != bg)
00516                 {
00517                     PyObject* pyObj = PyInt_FromLong((long)obj->GetId());
00518                     PyList_Insert(pyList, 0, pyObj);
00519                     Py_DECREF(pyObj);
00520                 }
00521             }
00522             pt = pt->GetNext();
00523         }
00524         memdc.SelectObject(wxNullBitmap);
00525     }
00526     else
00527     {
00528         wxRect viewrect(x-radius,y-radius,2*radius,2*radius);
00529         wxBitmap maskbmp(2*radius,2*radius,24);
00530         wxMemoryDC maskdc;
00531         // create bitmap with circle for masking
00532         maskdc.SelectObject(maskbmp);
00533         maskdc.SetBackground(*wxBLACK_BRUSH);
00534         maskdc.Clear();
00535         maskdc.SetBrush(*wxWHITE_BRUSH);
00536         maskdc.SetPen(*wxWHITE_PEN);
00537         maskdc.DrawCircle(radius,radius,radius);
00538         // now setup a memdc for rendering our object
00539         wxBitmap bmp(2*radius,2*radius,24);
00540         wxMemoryDC memdc;
00541         memdc.SelectObject(bmp);
00542         // set the origin so (x,y) is in the bmp center
00543         memdc.SetDeviceOrigin(radius-x,radius-y);
00544         // a region will be used to see if the result is empty
00545         wxRegion rgn2;
00546         while (pt) 
00547         {
00548             obj = pt->GetData();
00549             if (obj->IsBounded() && viewrect.Intersects(obj->GetBounds()))
00550             {
00551                 // start clean
00552                 //memdc.Clear();
00553                 memdc.SetBrush(bgbrush);
00554                 memdc.SetPen(bgpen);
00555                 memdc.DrawRectangle(viewrect);
00556                 // draw the object
00557                 obj->DrawToDC(&memdc);
00558                 // remove background color
00559                 memdc.SetLogicalFunction(wxXOR);
00560                 memdc.SetBrush(bgbrush);
00561                 memdc.SetPen(bgpen);
00562                 memdc.DrawRectangle(viewrect);
00563                 memdc.SetLogicalFunction(wxCOPY);
00564 #ifdef __WXMAC__
00565                 // wxAND is not supported on wxMac, but it doesn't seem to
00566                 // hurt anything to use wxCOPY instead...
00567                 memdc.Blit(x-radius,y-radius,2*radius,2*radius,&maskdc,0,0,wxCOPY);
00568 #else
00569                 // AND with circle bitmap
00570                 memdc.Blit(x-radius,y-radius,2*radius,2*radius,&maskdc,0,0,wxAND);
00571 #endif
00572                 // clear and update rgn2
00573                 memdc.SelectObject(wxNullBitmap);
00574                 rgn2.Clear();
00575                 rgn2.Union(bmp, *wxBLACK);
00576                 //rgn2.Intersect(rgn);
00577                 memdc.SelectObject(bmp);
00578                 if (!rgn2.IsEmpty())
00579                 {
00580                     PyObject* pyObj = PyInt_FromLong((long)obj->GetId());
00581                     PyList_Insert(pyList, 0, pyObj);
00582                     Py_DECREF(pyObj);
00583                 }
00584             }
00585             pt = pt->GetNext();
00586         }
00587         maskdc.SelectObject(wxNullBitmap);
00588         memdc.SelectObject(wxNullBitmap);
00589     }
00590     //wxPyEndBlockThreads(blocked);
00591     return pyList;
00592 }
00593 
00594 // ----------------------------------------------------------------------------
00595 // DrawToDCClipped - play back the op list to the DC but clip any objects
00596 //                   known to be not in rect.  This is a coarse level of 
00597 //                   clipping to speed things up when lots of objects are off 
00598 //                   screen and doesn't affect the dc level clipping
00599 // ----------------------------------------------------------------------------
00600 void wxPseudoDC::DrawToDCClipped(wxDC *dc, const wxRect& rect)
00601 {
00602     pdcObjectList::Node *pt = m_objectlist.GetFirst();
00603     pdcObject *obj;
00604     while (pt) 
00605     {
00606         obj = pt->GetData();
00607         if (!obj->IsBounded() || rect.Intersects(obj->GetBounds()))
00608             obj->DrawToDC(dc);
00609         pt = pt->GetNext();
00610     }
00611 }
00612 void wxPseudoDC::DrawToDCClippedRgn(wxDC *dc, const wxRegion& region)
00613 {
00614     pdcObjectList::Node *pt = m_objectlist.GetFirst();
00615     pdcObject *obj;
00616     while (pt) 
00617     {
00618         obj = pt->GetData();
00619         if (!obj->IsBounded() || 
00620                     (region.Contains(obj->GetBounds()) != wxOutRegion))
00621             obj->DrawToDC(dc);
00622         pt = pt->GetNext();
00623     }
00624 }
00625 
00626 // ----------------------------------------------------------------------------
00627 // DrawToDC - play back the op list to the DC 
00628 // ----------------------------------------------------------------------------
00629 void wxPseudoDC::DrawToDC(wxDC *dc)
00630 {
00631     pdcObjectList::Node *pt = m_objectlist.GetFirst();
00632     while (pt) 
00633     {
00634         pt->GetData()->DrawToDC(dc);
00635         pt = pt->GetNext();
00636     }
00637 }
00638         


wxpython_swig_interface
Author(s):
autogenerated on Mon Oct 6 2014 07:25:55