]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/region.cpp
Virtualized coordinate system for wxCanvas.
[wxWidgets.git] / src / gtk1 / region.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
5fc7ede9 2// Name: gtk/region.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
f96aa4d9
RR
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
5fc7ede9 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
c801d85f
KB
10#ifdef __GNUG__
11#pragma implementation "region.h"
12#endif
13
14#include "wx/region.h"
15
aed8ac3f
RR
16#include <gdk/gdk.h>
17#include <gtk/gtk.h>
bbe0af5b 18
864e8bd0 19
c801d85f
KB
20//-----------------------------------------------------------------------------
21// wxRegion
22//-----------------------------------------------------------------------------
23
24class wxRegionRefData: public wxObjectRefData
25{
864e8bd0 26public:
bf57d1ad
VZ
27 wxRegionRefData();
28 ~wxRegionRefData();
5fc7ede9 29
c801d85f 30 GdkRegion *m_region;
8429bec1 31 wxList m_rects;
c801d85f
KB
32};
33
bf57d1ad 34wxRegionRefData::wxRegionRefData()
c801d85f 35{
bbe0af5b 36 m_region = (GdkRegion *) NULL;
ff7b1510 37}
c801d85f 38
bf57d1ad 39wxRegionRefData::~wxRegionRefData()
c801d85f 40{
bbe0af5b 41 if (m_region) gdk_region_destroy( m_region );
5fc7ede9 42
bbe0af5b
RR
43 wxNode *node = m_rects.First();
44 while (node)
45 {
46 wxRect *r = (wxRect*)node->Data();
47 delete r;
48 node = node->Next();
49 }
ff7b1510 50}
c801d85f
KB
51
52//-----------------------------------------------------------------------------
53
54#define M_REGIONDATA ((wxRegionRefData *)m_refData)
55
56IMPLEMENT_DYNAMIC_CLASS(wxRegion,wxGDIObject);
5fc7ede9
VZ
57
58wxRegion::wxRegion( wxCoord x, wxCoord y, wxCoord w, wxCoord h )
c801d85f 59{
bbe0af5b
RR
60 m_refData = new wxRegionRefData();
61 GdkRegion *reg = gdk_region_new();
62 GdkRectangle rect;
63 rect.x = x;
64 rect.y = y;
65 rect.width = w;
66 rect.height = h;
b7c2d6ff
OK
67#ifdef __WXGTK20__
68 gdk_region_union_with_rect( reg, &rect );
69 M_REGIONDATA->m_region = reg;
70#else
bbe0af5b
RR
71 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
72 gdk_region_destroy( reg );
b7c2d6ff 73#endif
bbe0af5b 74 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,w,h) );
ff7b1510 75}
c801d85f
KB
76
77wxRegion::wxRegion( const wxPoint& topLeft, const wxPoint& bottomRight )
78{
bbe0af5b
RR
79 m_refData = new wxRegionRefData();
80 GdkRegion *reg = gdk_region_new();
81 GdkRectangle rect;
82 rect.x = topLeft.x;
83 rect.y = topLeft.y;
84 rect.width = bottomRight.x - rect.x;
85 rect.height = bottomRight.y - rect.y;
b7c2d6ff
OK
86#ifdef __WXGTK20__
87 gdk_region_union_with_rect( reg, &rect );
88 M_REGIONDATA->m_region = reg;
89#else
bbe0af5b
RR
90 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
91 gdk_region_destroy( reg );
b7c2d6ff 92#endif
bbe0af5b 93 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(topLeft,bottomRight) );
ff7b1510 94}
c801d85f
KB
95
96wxRegion::wxRegion( const wxRect& rect )
97{
bbe0af5b
RR
98 m_refData = new wxRegionRefData();
99 GdkRegion *reg = gdk_region_new();
100 GdkRectangle g_rect;
101 g_rect.x = rect.x;
102 g_rect.y = rect.y;
103 g_rect.width = rect.width;
104 g_rect.height = rect.height;
b7c2d6ff
OK
105#ifdef __WXGTK20__
106 gdk_region_union_with_rect( reg, &g_rect );
107 M_REGIONDATA->m_region = reg;
108#else
bbe0af5b
RR
109 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &g_rect );
110 gdk_region_destroy( reg );
b7c2d6ff 111#endif
e1208c31 112 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(rect.x,rect.y,rect.width,rect.height) );
ff7b1510 113}
c801d85f 114
bf57d1ad 115wxRegion::wxRegion()
c801d85f 116{
ff7b1510 117}
c801d85f 118
bf57d1ad 119wxRegion::~wxRegion()
c801d85f 120{
ff7b1510 121}
c801d85f 122
76ed8f8d
RR
123bool wxRegion::operator == ( const wxRegion& region )
124{
5fc7ede9 125 return m_refData == region.m_refData;
76ed8f8d
RR
126}
127
128bool wxRegion::operator != ( const wxRegion& region )
129{
5fc7ede9 130 return m_refData != region.m_refData;
76ed8f8d
RR
131}
132
bf57d1ad 133void wxRegion::Clear()
c801d85f 134{
bbe0af5b 135 UnRef();
ff7b1510 136}
c801d85f 137
5fc7ede9 138bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 139{
bbe0af5b
RR
140 GdkRectangle rect;
141 rect.x = x;
142 rect.y = y;
143 rect.width = width;
144 rect.height = height;
e1208c31
RR
145 if (!m_refData)
146 {
147 m_refData = new wxRegionRefData();
148 GdkRegion *reg = gdk_region_new();
b7c2d6ff
OK
149#ifdef __WXGTK20__
150 gdk_region_union_with_rect( reg, &rect );
151 M_REGIONDATA->m_region = reg;
152#else
e1208c31
RR
153 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
154 gdk_region_destroy( reg );
b7c2d6ff 155#endif
e1208c31
RR
156 }
157 else
158 {
b7c2d6ff
OK
159#ifdef __WXGTK20__
160 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
161#else
e1208c31
RR
162 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
163 gdk_region_destroy( M_REGIONDATA->m_region );
164 M_REGIONDATA->m_region = reg;
b7c2d6ff 165#endif
e1208c31
RR
166 }
167
bbe0af5b 168 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,width,height) );
e1208c31 169
bbe0af5b 170 return TRUE;
ff7b1510 171}
c801d85f
KB
172
173bool wxRegion::Union( const wxRect& rect )
174{
e1208c31 175 return Union( rect.x, rect.y, rect.width, rect.height );
ff7b1510 176}
c801d85f
KB
177
178bool wxRegion::Union( const wxRegion& region )
179{
e1208c31
RR
180 if (region.IsNull())
181 return FALSE;
182
183 if (!m_refData)
184 {
185 m_refData = new wxRegionRefData();
186 M_REGIONDATA->m_region = gdk_region_new();
187 }
188
b7c2d6ff
OK
189#ifdef __WXGTK20__
190 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
191#else
bbe0af5b
RR
192 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
193 gdk_region_destroy( M_REGIONDATA->m_region );
194 M_REGIONDATA->m_region = reg;
b7c2d6ff 195#endif
5fc7ede9 196
bbe0af5b
RR
197 wxNode *node = region.GetRectList()->First();
198 while (node)
199 {
200 wxRect *r = (wxRect*)node->Data();
201 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
202 node = node->Next();
203 }
5fc7ede9 204
bbe0af5b 205 return TRUE;
ff7b1510 206}
c801d85f 207
5fc7ede9 208bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 209{
e1208c31
RR
210 if (!m_refData)
211 {
212 m_refData = new wxRegionRefData();
213 M_REGIONDATA->m_region = gdk_region_new();
214 }
215
bbe0af5b
RR
216 wxRegion reg( x, y, width, height );
217 Intersect( reg );
218 return TRUE;
ff7b1510 219}
c801d85f
KB
220
221bool wxRegion::Intersect( const wxRect& rect )
222{
e1208c31
RR
223 if (!m_refData)
224 {
225 m_refData = new wxRegionRefData();
226 M_REGIONDATA->m_region = gdk_region_new();
227 }
228
bbe0af5b
RR
229 wxRegion reg( rect );
230 Intersect( reg );
231 return TRUE;
ff7b1510 232}
c801d85f
KB
233
234bool wxRegion::Intersect( const wxRegion& region )
235{
e1208c31
RR
236 if (region.IsNull())
237 return FALSE;
238
239 if (!m_refData)
240 {
241 m_refData = new wxRegionRefData();
242 M_REGIONDATA->m_region = gdk_region_new();
243 return TRUE;
244 }
245
b7c2d6ff
OK
246#ifdef __WXGTK20__
247 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
248#else
bbe0af5b
RR
249 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
250 gdk_region_destroy( M_REGIONDATA->m_region );
251 M_REGIONDATA->m_region = reg;
b7c2d6ff 252#endif
bbe0af5b 253 return TRUE;
ff7b1510 254}
c801d85f 255
5fc7ede9 256bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 257{
e1208c31
RR
258 if (!m_refData)
259 {
260 m_refData = new wxRegionRefData();
261 M_REGIONDATA->m_region = gdk_region_new();
262 }
263
bbe0af5b
RR
264 wxRegion reg( x, y, width, height );
265 Subtract( reg );
266 return TRUE;
ff7b1510 267}
c801d85f
KB
268
269bool wxRegion::Subtract( const wxRect& rect )
270{
e1208c31
RR
271 if (!m_refData)
272 {
273 m_refData = new wxRegionRefData();
274 M_REGIONDATA->m_region = gdk_region_new();
275 }
276
bbe0af5b
RR
277 wxRegion reg( rect );
278 Subtract( reg );
279 return TRUE;
ff7b1510 280}
c801d85f
KB
281
282bool wxRegion::Subtract( const wxRegion& region )
283{
e1208c31
RR
284 if (region.IsNull())
285 return FALSE;
286
287 if (!m_refData)
288 {
289 m_refData = new wxRegionRefData();
290 M_REGIONDATA->m_region = gdk_region_new();
291 }
292
b7c2d6ff
OK
293#ifdef __WXGTK20__
294 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
295#else
bbe0af5b
RR
296 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
297 gdk_region_destroy( M_REGIONDATA->m_region );
298 M_REGIONDATA->m_region = reg;
b7c2d6ff 299#endif
bbe0af5b 300 return TRUE;
ff7b1510 301}
c801d85f 302
5fc7ede9 303bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 304{
e1208c31
RR
305 if (!m_refData)
306 {
307 m_refData = new wxRegionRefData();
308 M_REGIONDATA->m_region = gdk_region_new();
309 }
310
bbe0af5b
RR
311 wxRegion reg( x, y, width, height );
312 Xor( reg );
313 return TRUE;
ff7b1510 314}
c801d85f
KB
315
316bool wxRegion::Xor( const wxRect& rect )
317{
e1208c31
RR
318 if (!m_refData)
319 {
320 m_refData = new wxRegionRefData();
321 M_REGIONDATA->m_region = gdk_region_new();
322 }
323
bbe0af5b
RR
324 wxRegion reg( rect );
325 Xor( reg );
326 return TRUE;
ff7b1510 327}
c801d85f
KB
328
329bool wxRegion::Xor( const wxRegion& region )
330{
e1208c31 331 if (region.IsNull())
05a11043 332 return FALSE;
e1208c31
RR
333
334 if (!m_refData)
335 {
336 m_refData = new wxRegionRefData();
337 M_REGIONDATA->m_region = gdk_region_new();
338 }
339
b7c2d6ff
OK
340#ifdef __WXGTK20__
341 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
342#else
bbe0af5b
RR
343 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
344 gdk_region_destroy( M_REGIONDATA->m_region );
345 M_REGIONDATA->m_region = reg;
b7c2d6ff 346#endif
5fc7ede9 347
bbe0af5b
RR
348 wxNode *node = region.GetRectList()->First();
349 while (node)
350 {
351 wxRect *r = (wxRect*)node->Data();
352 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
353 node = node->Next();
354 }
5fc7ede9 355
bbe0af5b 356 return TRUE;
ff7b1510 357}
c801d85f 358
e1208c31 359void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
c801d85f 360{
bbe0af5b
RR
361 x = 0;
362 y = 0;
363 w = -1;
364 h = -1;
05a11043 365 if (!m_refData)
e1208c31
RR
366 return;
367
864e8bd0
RR
368 GdkRectangle rect;
369 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
370 x = rect.x;
371 y = rect.y;
372 w = rect.width;
373 h = rect.height;
ff7b1510 374}
c801d85f 375
bf57d1ad 376wxRect wxRegion::GetBox() const
c801d85f 377{
5fc7ede9
VZ
378 wxCoord x = 0;
379 wxCoord y = 0;
380 wxCoord w = -1;
381 wxCoord h = -1;
bbe0af5b
RR
382 GetBox( x, y, w, h );
383 return wxRect( x, y, w, h );
ff7b1510 384}
c801d85f 385
bf57d1ad 386bool wxRegion::Empty() const
c801d85f 387{
e1208c31
RR
388 if (!m_refData)
389 return TRUE;
390
bbe0af5b 391 return gdk_region_empty( M_REGIONDATA->m_region );
ff7b1510 392}
c801d85f 393
5fc7ede9 394wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
c801d85f 395{
e1208c31
RR
396 if (!m_refData)
397 return wxOutRegion;
398
bbe0af5b
RR
399 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
400 return wxInRegion;
401 else
402 return wxOutRegion;
ff7b1510 403}
c801d85f 404
5fc7ede9 405wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
c801d85f 406{
e1208c31
RR
407 if (!m_refData)
408 return wxOutRegion;
409
bbe0af5b
RR
410 GdkRectangle rect;
411 rect.x = x;
412 rect.y = y;
413 rect.width = w;
414 rect.height = h;
415 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
416 switch (res)
417 {
418 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
419 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
420 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
421 }
422 return wxOutRegion;
ff7b1510 423}
c801d85f 424
8429bec1
RR
425wxRegionContain wxRegion::Contains(const wxPoint& pt) const
426{
bbe0af5b 427 return Contains( pt.x, pt.y );
8429bec1
RR
428}
429
430wxRegionContain wxRegion::Contains(const wxRect& rect) const
431{
bbe0af5b 432 return Contains( rect.x, rect.y, rect.width, rect.height );
8429bec1
RR
433}
434
bf57d1ad 435GdkRegion *wxRegion::GetRegion() const
c801d85f 436{
e1208c31
RR
437 if (!m_refData)
438 return (GdkRegion*) NULL;
439
bbe0af5b 440 return M_REGIONDATA->m_region;
ff7b1510 441}
c801d85f 442
8429bec1
RR
443wxList *wxRegion::GetRectList() const
444{
e1208c31
RR
445 if (!m_refData)
446 return (wxList*) NULL;
447
bbe0af5b 448 return &(M_REGIONDATA->m_rects);
8429bec1
RR
449}
450
451//-----------------------------------------------------------------------------
452// wxRegion
453//-----------------------------------------------------------------------------
454
455IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
5fc7ede9 456
bf57d1ad 457wxRegionIterator::wxRegionIterator()
8429bec1 458{
6f2a55e3 459 Reset();
8429bec1
RR
460}
461
462wxRegionIterator::wxRegionIterator( const wxRegion& region )
463{
6f2a55e3 464 Reset(region);
8429bec1
RR
465}
466
467void wxRegionIterator::Reset( const wxRegion& region )
468{
bbe0af5b 469 m_region = region;
6f2a55e3 470 Reset();
8429bec1
RR
471}
472
5fc7ede9
VZ
473wxRegionIterator::operator bool () const
474{
674ac8b9 475 return m_current < (size_t)m_region.GetRectList()->Number();
8429bec1
RR
476}
477
5fc7ede9
VZ
478bool wxRegionIterator::HaveRects() const
479{
674ac8b9 480 return m_current < (size_t)m_region.GetRectList()->Number();
8429bec1
RR
481}
482
bf57d1ad 483void wxRegionIterator::operator ++ ()
8429bec1 484{
674ac8b9 485 if (m_current < (size_t)m_region.GetRectList()->Number()) ++m_current;
8429bec1
RR
486}
487
488void wxRegionIterator::operator ++ (int)
489{
674ac8b9 490 if (m_current < (size_t)m_region.GetRectList()->Number()) ++m_current;
8429bec1
RR
491}
492
bf57d1ad 493wxCoord wxRegionIterator::GetX() const
8429bec1 494{
bbe0af5b
RR
495 wxNode *node = m_region.GetRectList()->Nth( m_current );
496 if (!node) return 0;
497 wxRect *r = (wxRect*)node->Data();
498 return r->x;
8429bec1
RR
499}
500
bf57d1ad 501wxCoord wxRegionIterator::GetY() const
8429bec1 502{
bbe0af5b
RR
503 wxNode *node = m_region.GetRectList()->Nth( m_current );
504 if (!node) return 0;
505 wxRect *r = (wxRect*)node->Data();
506 return r->y;
8429bec1
RR
507}
508
bf57d1ad 509wxCoord wxRegionIterator::GetW() const
8429bec1 510{
bbe0af5b
RR
511 wxNode *node = m_region.GetRectList()->Nth( m_current );
512 if (!node) return 0;
513 wxRect *r = (wxRect*)node->Data();
514 return r->width;
8429bec1
RR
515}
516
bf57d1ad 517wxCoord wxRegionIterator::GetH() const
8429bec1 518{
bbe0af5b
RR
519 wxNode *node = m_region.GetRectList()->Nth( m_current );
520 if (!node) return 0;
521 wxRect *r = (wxRect*)node->Data();
522 return r->height;
8429bec1
RR
523}
524
525