]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/src/pseudodc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/pseudodc.cpp
3 // Purpose: Implementation of the wxPseudoDC Class
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 //include "wx/wxprec.h"
17 #include "wx/wxPython/wxPython.h"
18 #include "wx/wxPython/pseudodc.h"
20 // wxList based class definitions
21 #include <wx/listimpl.cpp>
22 WX_DEFINE_LIST(pdcOpList
);
23 WX_DEFINE_LIST(pdcObjectList
);
25 //----------------------------------------------------------------------------
26 // Helper functions used for drawing greyed out versions of objects
27 //----------------------------------------------------------------------------
28 wxColour
&MakeColourGrey(const wxColour
&c
)
31 rval
.Set(byte((230-c
.Red())*0.7+c
.Red()),
32 byte((230-c
.Green())*0.7+c
.Green()),
33 byte((230-c
.Blue())*0.7+c
.Blue()));
36 wxBrush
&GetGreyBrush(wxBrush
&brush
)
41 c
= MakeColourGrey(brush
.GetColour());
46 wxPen
&GetGreyPen(wxPen
&pen
)
51 c
= MakeColourGrey(pen
.GetColour());
56 void GreyOutImage(wxImage
&img
)
58 unsigned char *data
= img
.GetData();
60 unsigned char mr
,mg
,mb
;
62 int len
= img
.GetHeight()*img
.GetWidth()*3;
65 mr
= img
.GetMaskRed();
66 mg
= img
.GetMaskGreen();
67 mb
= img
.GetMaskBlue();
72 r
=data
[i
]; g
=data
[i
+1]; b
=data
[i
+2];
74 r
!=mr
|| g
!=mg
|| b
!=mb
)
80 r
= (unsigned char)((230.0-r
)*0.7+r
);
81 g
= (unsigned char)((230.0-g
)*0.7+g
);
82 b
= (unsigned char)((230.0-b
)*0.7+b
);
83 data
[i
]=r
; data
[i
+1]=g
; data
[i
+2]=b
;
88 wxIcon
&GetGreyIcon(wxIcon
&icon
)
91 bmp
.CopyFromIcon(icon
);
92 wxImage img
= bmp
.ConvertToImage();
94 wxBitmap
bmp2(img
,32);
96 rval
.CopyFromBitmap(bmp2
);
100 wxBitmap
&GetGreyBitmap(wxBitmap
&bmp
)
102 wxImage img
= bmp
.ConvertToImage();
104 static wxBitmap
rval(img
,32);
108 // ============================================================================
109 // various pdcOp class implementation methods
110 // ============================================================================
112 // ----------------------------------------------------------------------------
113 // pdcDrawPolyPolygonOp constructor
114 // ----------------------------------------------------------------------------
115 pdcDrawPolyPolygonOp::pdcDrawPolyPolygonOp(int n
, int count
[], wxPoint points
[],
116 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
118 m_n
=n
; m_xoffset
=xoffset
; m_yoffset
=yoffset
; m_fillStyle
=fillStyle
;
122 m_count
= new int[n
];
123 for(int i
=0; i
<n
; i
++)
130 m_points
= new wxPoint
[total_n
];
131 for(int j
=0; j
<total_n
; j
++)
132 m_points
[j
] = points
[j
];
144 // ----------------------------------------------------------------------------
145 // pdcDrawPolyPolygonOp destructor
146 // ----------------------------------------------------------------------------
147 pdcDrawPolyPolygonOp::~pdcDrawPolyPolygonOp()
149 if (m_points
) delete m_points
;
150 if (m_count
) delete m_count
;
155 // ----------------------------------------------------------------------------
156 // pdcDrawLinesOp constructor
157 // ----------------------------------------------------------------------------
158 pdcDrawLinesOp::pdcDrawLinesOp(int n
, wxPoint points
[],
159 wxCoord xoffset
, wxCoord yoffset
)
161 m_n
=n
; m_xoffset
=xoffset
; m_yoffset
=yoffset
;
164 m_points
= new wxPoint
[n
];
165 for (int i
=0; i
<n
; i
++)
166 m_points
[i
] = points
[i
];
171 // ----------------------------------------------------------------------------
172 // pdcDrawLinesOp destructor
173 // ----------------------------------------------------------------------------
174 pdcDrawLinesOp::~pdcDrawLinesOp()
176 if (m_points
) delete m_points
;
180 // ----------------------------------------------------------------------------
181 // pdcDrawPolygonOp constructor
182 // ----------------------------------------------------------------------------
183 pdcDrawPolygonOp::pdcDrawPolygonOp(int n
, wxPoint points
[],
184 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
186 m_n
=n
; m_xoffset
=xoffset
; m_yoffset
=yoffset
; m_fillStyle
=fillStyle
;
189 m_points
= new wxPoint
[n
];
190 for (int i
=0; i
<n
; i
++)
191 m_points
[i
] = points
[i
];
196 // ----------------------------------------------------------------------------
197 // pdcDrawPolygonOp destructor
198 // ----------------------------------------------------------------------------
199 pdcDrawPolygonOp::~pdcDrawPolygonOp()
201 if (m_points
) delete m_points
;
206 // ----------------------------------------------------------------------------
207 // pdcDrawSplineOp constructor
208 // ----------------------------------------------------------------------------
209 pdcDrawSplineOp::pdcDrawSplineOp(int n
, wxPoint points
[])
214 m_points
= new wxPoint
[n
];
215 for(int i
=0; i
<n
; i
++)
216 m_points
[i
] = points
[i
];
221 // ----------------------------------------------------------------------------
222 // pdcDrawSplineOp destructor
223 // ----------------------------------------------------------------------------
224 pdcDrawSplineOp::~pdcDrawSplineOp()
226 if (m_points
) delete m_points
;
229 #endif // wxUSE_SPLINES
231 // ============================================================================
232 // pdcObject implementation
233 // ============================================================================
234 // ----------------------------------------------------------------------------
235 // DrawToDC - play back the op list to the DC
236 // ----------------------------------------------------------------------------
237 void pdcObject::DrawToDC(wxDC
*dc
)
239 pdcOpList::Node
*node
= m_oplist
.GetFirst();
242 node
->GetData()->DrawToDC(dc
, m_greyedout
);
243 node
= node
->GetNext();
247 // ----------------------------------------------------------------------------
248 // Translate - translate all the operations by some dx,dy
249 // ----------------------------------------------------------------------------
250 void pdcObject::Translate(wxCoord dx
, wxCoord dy
)
252 pdcOpList::Node
*node
= m_oplist
.GetFirst();
255 node
->GetData()->Translate(dx
,dy
);
256 node
= node
->GetNext();
265 // ----------------------------------------------------------------------------
266 // SetGreyedOut - set the greyout member and cache grey versions of everything
267 // if greyout is true
268 // ----------------------------------------------------------------------------
269 void pdcObject::SetGreyedOut(bool greyout
)
274 pdcOpList::Node
*node
= m_oplist
.GetFirst();
279 obj
= node
->GetData();
281 node
= node
->GetNext();
286 // ============================================================================
287 // wxPseudoDC implementation
288 // ============================================================================
290 // ----------------------------------------------------------------------------
292 // ----------------------------------------------------------------------------
293 wxPseudoDC::~wxPseudoDC()
295 // delete all the nodes in the list
300 // ----------------------------------------------------------------------------
301 // ClearAll - remove all nodes from list
302 // ----------------------------------------------------------------------------
303 void wxPseudoDC::RemoveAll(void)
305 m_objectlist
.Clear();
307 m_lastObjNode
= NULL
;
310 // ----------------------------------------------------------------------------
311 // GetLen - return the number of operations in the current op list
312 // ----------------------------------------------------------------------------
313 int wxPseudoDC::GetLen(void)
315 pdcObjectList::Node
*pt
= m_objectlist
.GetFirst();
319 len
+= pt
->GetData()->GetLen();
325 // ----------------------------------------------------------------------------
326 // FindObjNode - find and return an object node by id. If node doesn't exist
327 // and create is true then create one and return it. Otherwise
329 // ----------------------------------------------------------------------------
330 pdcObjectList::Node
*wxPseudoDC::FindObjNode(int id
, bool create
)
332 // see if last operation was for same id
333 if (m_lastObjNode
&& m_lastObjNode
->GetData()->GetId() == id
)
334 return m_lastObjNode
;
335 // if not then search for it
336 pdcObjectList::Node
*pt
= m_objectlist
.GetFirst();
339 if (pt
->GetData()->GetId() == id
)
342 // cache this node for future operations
348 // if create then create and return a new node
351 // cache this node for future operations
352 m_lastObjNode
= m_objectlist
.Append(new pdcObject(id
));
353 return m_lastObjNode
;
355 // otherwise just return NULL
359 // ----------------------------------------------------------------------------
360 // AddToList - Add a node to the list at the end (preserve draw order)
361 // ----------------------------------------------------------------------------
362 void wxPseudoDC::AddToList(pdcOp
*newOp
)
364 pdcObjectList::Node
*pt
= FindObjNode(m_currId
, true);
365 pt
->GetData()->AddOp(newOp
);
368 // ----------------------------------------------------------------------------
369 // ClearID - remove all the operations associated with a single ID
370 // ----------------------------------------------------------------------------
371 void wxPseudoDC::ClearId(int id
)
373 pdcObjectList::Node
*pt
= FindObjNode(id
);
374 if (pt
) pt
->GetData()->Clear();
377 // ----------------------------------------------------------------------------
378 // RemoveID - Remove the object node (and all operations) associated with an id
379 // ----------------------------------------------------------------------------
380 void wxPseudoDC::RemoveId(int id
)
382 pdcObjectList::Node
*pt
= FindObjNode(id
);
385 if (m_lastObjNode
== pt
)
386 m_lastObjNode
= NULL
;
387 m_objectlist
.DeleteNode(pt
);
391 // ----------------------------------------------------------------------------
392 // SetIdBounds - Set the bounding rect for a given id
393 // ----------------------------------------------------------------------------
394 void wxPseudoDC::SetIdBounds(int id
, wxRect
& rect
)
396 pdcObjectList::Node
*pt
= FindObjNode(id
, true);
397 pt
->GetData()->SetBounds(rect
);
400 // ----------------------------------------------------------------------------
401 // GetIdBounds - Get the bounding rect for a given id
402 // ----------------------------------------------------------------------------
403 void wxPseudoDC::GetIdBounds(int id
, wxRect
& rect
)
405 pdcObjectList::Node
*pt
= FindObjNode(id
);
406 if (pt
&& pt
->GetData()->IsBounded())
407 rect
= pt
->GetData()->GetBounds();
409 rect
.x
= rect
.y
= rect
.width
= rect
.height
= 0;
412 // ----------------------------------------------------------------------------
413 // TranslateId - Translate all the operations of a single id
414 // ----------------------------------------------------------------------------
415 void wxPseudoDC::TranslateId(int id
, wxCoord dx
, wxCoord dy
)
417 pdcObjectList::Node
*pt
= FindObjNode(id
);
418 if (pt
) pt
->GetData()->Translate(dx
,dy
);
421 // ----------------------------------------------------------------------------
422 // DrawIdToDC - Draw a specific id to the dc passed in
423 // ----------------------------------------------------------------------------
424 void wxPseudoDC::DrawIdToDC(int id
, wxDC
*dc
)
426 pdcObjectList::Node
*pt
= FindObjNode(id
);
427 if (pt
) pt
->GetData()->DrawToDC(dc
);
430 // ----------------------------------------------------------------------------
431 // SetIdGreyedOut - Set the greyedout member of id
432 // ----------------------------------------------------------------------------
433 void wxPseudoDC::SetIdGreyedOut(int id
, bool greyout
)
435 pdcObjectList::Node
*pt
= FindObjNode(id
);
436 if (pt
) pt
->GetData()->SetGreyedOut(greyout
);
439 // ----------------------------------------------------------------------------
440 // GetIdGreyedOut - Get the greyedout member of id
441 // ----------------------------------------------------------------------------
442 bool wxPseudoDC::GetIdGreyedOut(int id
)
444 pdcObjectList::Node
*pt
= FindObjNode(id
);
445 if (pt
) return pt
->GetData()->GetGreyedOut();
449 // ----------------------------------------------------------------------------
450 // FindObjectsByBBox - Return a list of all the ids whose bounding boxes
452 // ----------------------------------------------------------------------------
453 PyObject
*wxPseudoDC::FindObjectsByBBox(wxCoord x
, wxCoord y
)
455 //wxPyBlock_t blocked = wxPyBeginBlockThreads();
456 pdcObjectList::Node
*pt
= m_objectlist
.GetFirst();
458 PyObject
* pyList
= NULL
;
459 pyList
= PyList_New(0);
464 r
= obj
->GetBounds();
465 if (obj
->IsBounded() && r
.Contains(x
,y
))
467 PyObject
* pyObj
= PyInt_FromLong((long)obj
->GetId());
468 PyList_Insert(pyList
, 0, pyObj
);
473 //wxPyEndBlockThreads(blocked);
477 // ----------------------------------------------------------------------------
478 // FindObjects - Return a list of all the ids that draw to (x,y)
479 // ----------------------------------------------------------------------------
480 PyObject
*wxPseudoDC::FindObjects(wxCoord x
, wxCoord y
,
481 wxCoord radius
, const wxColor
& bg
)
483 //wxPyBlock_t blocked = wxPyBeginBlockThreads();
484 pdcObjectList::Node
*pt
= m_objectlist
.GetFirst();
486 PyObject
* pyList
= NULL
;
487 pyList
= PyList_New(0);
490 // special case radius = 0
493 wxBitmap
bmp(4,4,24);
496 wxRect
viewrect(x
-2,y
-2,4,4);
497 // setup the memdc for rendering
498 memdc
.SelectObject(bmp
);
499 memdc
.SetBackground(bgbrush
);
501 memdc
.SetDeviceOrigin(2-x
,2-y
);
505 if (obj
->IsBounded() && obj
->GetBounds().Contains(x
,y
))
508 memdc
.SetBrush(bgbrush
);
510 memdc
.DrawRectangle(viewrect
);
512 obj
->DrawToDC(&memdc
);
513 memdc
.GetPixel(x
,y
,&pix
);
514 // clear and update rgn2
517 PyObject
* pyObj
= PyInt_FromLong((long)obj
->GetId());
518 PyList_Insert(pyList
, 0, pyObj
);
524 memdc
.SelectObject(wxNullBitmap
);
528 wxRect
viewrect(x
-radius
,y
-radius
,2*radius
,2*radius
);
529 wxBitmap
maskbmp(2*radius
,2*radius
,24);
531 // create bitmap with circle for masking
532 maskdc
.SelectObject(maskbmp
);
533 maskdc
.SetBackground(*wxBLACK_BRUSH
);
535 maskdc
.SetBrush(*wxWHITE_BRUSH
);
536 maskdc
.SetPen(*wxWHITE_PEN
);
537 maskdc
.DrawCircle(radius
,radius
,radius
);
538 // now setup a memdc for rendering our object
539 wxBitmap
bmp(2*radius
,2*radius
,24);
541 memdc
.SelectObject(bmp
);
542 // set the origin so (x,y) is in the bmp center
543 memdc
.SetDeviceOrigin(radius
-x
,radius
-y
);
544 // a region will be used to see if the result is empty
549 if (obj
->IsBounded() && viewrect
.Intersects(obj
->GetBounds()))
553 memdc
.SetBrush(bgbrush
);
555 memdc
.DrawRectangle(viewrect
);
557 obj
->DrawToDC(&memdc
);
558 // remove background color
559 memdc
.SetLogicalFunction(wxXOR
);
560 memdc
.SetBrush(bgbrush
);
562 memdc
.DrawRectangle(viewrect
);
563 memdc
.SetLogicalFunction(wxCOPY
);
565 // wxAND is not supported on wxMac, but it doesn't seem to
566 // hurt anything to use wxCOPY instead...
567 memdc
.Blit(x
-radius
,y
-radius
,2*radius
,2*radius
,&maskdc
,0,0,wxCOPY
);
569 // AND with circle bitmap
570 memdc
.Blit(x
-radius
,y
-radius
,2*radius
,2*radius
,&maskdc
,0,0,wxAND
);
572 // clear and update rgn2
573 memdc
.SelectObject(wxNullBitmap
);
575 rgn2
.Union(bmp
, *wxBLACK
);
576 //rgn2.Intersect(rgn);
577 memdc
.SelectObject(bmp
);
580 PyObject
* pyObj
= PyInt_FromLong((long)obj
->GetId());
581 PyList_Insert(pyList
, 0, pyObj
);
587 maskdc
.SelectObject(wxNullBitmap
);
588 memdc
.SelectObject(wxNullBitmap
);
590 //wxPyEndBlockThreads(blocked);
594 // ----------------------------------------------------------------------------
595 // DrawToDCClipped - play back the op list to the DC but clip any objects
596 // known to be not in rect. This is a coarse level of
597 // clipping to speed things up when lots of objects are off
598 // screen and doesn't affect the dc level clipping
599 // ----------------------------------------------------------------------------
600 void wxPseudoDC::DrawToDCClipped(wxDC
*dc
, const wxRect
& rect
)
602 pdcObjectList::Node
*pt
= m_objectlist
.GetFirst();
607 if (!obj
->IsBounded() || rect
.Intersects(obj
->GetBounds()))
612 void wxPseudoDC::DrawToDCClippedRgn(wxDC
*dc
, const wxRegion
& region
)
614 pdcObjectList::Node
*pt
= m_objectlist
.GetFirst();
619 if (!obj
->IsBounded() ||
620 (region
.Contains(obj
->GetBounds()) != wxOutRegion
))
626 // ----------------------------------------------------------------------------
627 // DrawToDC - play back the op list to the DC
628 // ----------------------------------------------------------------------------
629 void wxPseudoDC::DrawToDC(wxDC
*dc
)
631 pdcObjectList::Node
*pt
= m_objectlist
.GetFirst();
634 pt
->GetData()->DrawToDC(dc
);