]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/region.cpp
fixed (rare but fatal) bug in wxWindowDisabler
[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;
67 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
68 gdk_region_destroy( reg );
69 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,w,h) );
ff7b1510 70}
c801d85f
KB
71
72wxRegion::wxRegion( const wxPoint& topLeft, const wxPoint& bottomRight )
73{
bbe0af5b
RR
74 m_refData = new wxRegionRefData();
75 GdkRegion *reg = gdk_region_new();
76 GdkRectangle rect;
77 rect.x = topLeft.x;
78 rect.y = topLeft.y;
79 rect.width = bottomRight.x - rect.x;
80 rect.height = bottomRight.y - rect.y;
81 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
82 gdk_region_destroy( reg );
83 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(topLeft,bottomRight) );
ff7b1510 84}
c801d85f
KB
85
86wxRegion::wxRegion( const wxRect& rect )
87{
bbe0af5b
RR
88 m_refData = new wxRegionRefData();
89 GdkRegion *reg = gdk_region_new();
90 GdkRectangle g_rect;
91 g_rect.x = rect.x;
92 g_rect.y = rect.y;
93 g_rect.width = rect.width;
94 g_rect.height = rect.height;
95 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &g_rect );
96 gdk_region_destroy( reg );
e1208c31 97 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(rect.x,rect.y,rect.width,rect.height) );
ff7b1510 98}
c801d85f 99
bf57d1ad 100wxRegion::wxRegion()
c801d85f 101{
ff7b1510 102}
c801d85f 103
bf57d1ad 104wxRegion::~wxRegion()
c801d85f 105{
ff7b1510 106}
c801d85f 107
76ed8f8d
RR
108bool wxRegion::operator == ( const wxRegion& region )
109{
5fc7ede9 110 return m_refData == region.m_refData;
76ed8f8d
RR
111}
112
113bool wxRegion::operator != ( const wxRegion& region )
114{
5fc7ede9 115 return m_refData != region.m_refData;
76ed8f8d
RR
116}
117
bf57d1ad 118void wxRegion::Clear()
c801d85f 119{
bbe0af5b 120 UnRef();
ff7b1510 121}
c801d85f 122
5fc7ede9 123bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 124{
bbe0af5b
RR
125 GdkRectangle rect;
126 rect.x = x;
127 rect.y = y;
128 rect.width = width;
129 rect.height = height;
e1208c31
RR
130 if (!m_refData)
131 {
132 m_refData = new wxRegionRefData();
133 GdkRegion *reg = gdk_region_new();
134 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
135 gdk_region_destroy( reg );
136 }
137 else
138 {
139 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
140 gdk_region_destroy( M_REGIONDATA->m_region );
141 M_REGIONDATA->m_region = reg;
142 }
143
bbe0af5b 144 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,width,height) );
e1208c31 145
bbe0af5b 146 return TRUE;
ff7b1510 147}
c801d85f
KB
148
149bool wxRegion::Union( const wxRect& rect )
150{
e1208c31 151 return Union( rect.x, rect.y, rect.width, rect.height );
ff7b1510 152}
c801d85f
KB
153
154bool wxRegion::Union( const wxRegion& region )
155{
e1208c31
RR
156 if (region.IsNull())
157 return FALSE;
158
159 if (!m_refData)
160 {
161 m_refData = new wxRegionRefData();
162 M_REGIONDATA->m_region = gdk_region_new();
163 }
164
bbe0af5b
RR
165 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
166 gdk_region_destroy( M_REGIONDATA->m_region );
167 M_REGIONDATA->m_region = reg;
5fc7ede9 168
bbe0af5b
RR
169 wxNode *node = region.GetRectList()->First();
170 while (node)
171 {
172 wxRect *r = (wxRect*)node->Data();
173 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
174 node = node->Next();
175 }
5fc7ede9 176
bbe0af5b 177 return TRUE;
ff7b1510 178}
c801d85f 179
5fc7ede9 180bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 181{
e1208c31
RR
182 if (!m_refData)
183 {
184 m_refData = new wxRegionRefData();
185 M_REGIONDATA->m_region = gdk_region_new();
186 }
187
bbe0af5b
RR
188 wxRegion reg( x, y, width, height );
189 Intersect( reg );
190 return TRUE;
ff7b1510 191}
c801d85f
KB
192
193bool wxRegion::Intersect( const wxRect& rect )
194{
e1208c31
RR
195 if (!m_refData)
196 {
197 m_refData = new wxRegionRefData();
198 M_REGIONDATA->m_region = gdk_region_new();
199 }
200
bbe0af5b
RR
201 wxRegion reg( rect );
202 Intersect( reg );
203 return TRUE;
ff7b1510 204}
c801d85f
KB
205
206bool wxRegion::Intersect( const wxRegion& region )
207{
e1208c31
RR
208 if (region.IsNull())
209 return FALSE;
210
211 if (!m_refData)
212 {
213 m_refData = new wxRegionRefData();
214 M_REGIONDATA->m_region = gdk_region_new();
215 return TRUE;
216 }
217
bbe0af5b
RR
218 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
219 gdk_region_destroy( M_REGIONDATA->m_region );
220 M_REGIONDATA->m_region = reg;
221 return TRUE;
ff7b1510 222}
c801d85f 223
5fc7ede9 224bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 225{
e1208c31
RR
226 if (!m_refData)
227 {
228 m_refData = new wxRegionRefData();
229 M_REGIONDATA->m_region = gdk_region_new();
230 }
231
bbe0af5b
RR
232 wxRegion reg( x, y, width, height );
233 Subtract( reg );
234 return TRUE;
ff7b1510 235}
c801d85f
KB
236
237bool wxRegion::Subtract( const wxRect& rect )
238{
e1208c31
RR
239 if (!m_refData)
240 {
241 m_refData = new wxRegionRefData();
242 M_REGIONDATA->m_region = gdk_region_new();
243 }
244
bbe0af5b
RR
245 wxRegion reg( rect );
246 Subtract( reg );
247 return TRUE;
ff7b1510 248}
c801d85f
KB
249
250bool wxRegion::Subtract( const wxRegion& region )
251{
e1208c31
RR
252 if (region.IsNull())
253 return FALSE;
254
255 if (!m_refData)
256 {
257 m_refData = new wxRegionRefData();
258 M_REGIONDATA->m_region = gdk_region_new();
259 }
260
bbe0af5b
RR
261 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
262 gdk_region_destroy( M_REGIONDATA->m_region );
263 M_REGIONDATA->m_region = reg;
264 return TRUE;
ff7b1510 265}
c801d85f 266
5fc7ede9 267bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 268{
e1208c31
RR
269 if (!m_refData)
270 {
271 m_refData = new wxRegionRefData();
272 M_REGIONDATA->m_region = gdk_region_new();
273 }
274
bbe0af5b
RR
275 wxRegion reg( x, y, width, height );
276 Xor( reg );
277 return TRUE;
ff7b1510 278}
c801d85f
KB
279
280bool wxRegion::Xor( const wxRect& rect )
281{
e1208c31
RR
282 if (!m_refData)
283 {
284 m_refData = new wxRegionRefData();
285 M_REGIONDATA->m_region = gdk_region_new();
286 }
287
bbe0af5b
RR
288 wxRegion reg( rect );
289 Xor( reg );
290 return TRUE;
ff7b1510 291}
c801d85f
KB
292
293bool wxRegion::Xor( const wxRegion& region )
294{
e1208c31 295 if (region.IsNull())
05a11043 296 return FALSE;
e1208c31
RR
297
298 if (!m_refData)
299 {
300 m_refData = new wxRegionRefData();
301 M_REGIONDATA->m_region = gdk_region_new();
302 }
303
bbe0af5b
RR
304 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
305 gdk_region_destroy( M_REGIONDATA->m_region );
306 M_REGIONDATA->m_region = reg;
5fc7ede9 307
bbe0af5b
RR
308 wxNode *node = region.GetRectList()->First();
309 while (node)
310 {
311 wxRect *r = (wxRect*)node->Data();
312 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
313 node = node->Next();
314 }
5fc7ede9 315
bbe0af5b 316 return TRUE;
ff7b1510 317}
c801d85f 318
e1208c31 319void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
c801d85f 320{
bbe0af5b
RR
321 x = 0;
322 y = 0;
323 w = -1;
324 h = -1;
05a11043 325 if (!m_refData)
e1208c31
RR
326 return;
327
864e8bd0
RR
328 GdkRectangle rect;
329 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
330 x = rect.x;
331 y = rect.y;
332 w = rect.width;
333 h = rect.height;
ff7b1510 334}
c801d85f 335
bf57d1ad 336wxRect wxRegion::GetBox() const
c801d85f 337{
5fc7ede9
VZ
338 wxCoord x = 0;
339 wxCoord y = 0;
340 wxCoord w = -1;
341 wxCoord h = -1;
bbe0af5b
RR
342 GetBox( x, y, w, h );
343 return wxRect( x, y, w, h );
ff7b1510 344}
c801d85f 345
bf57d1ad 346bool wxRegion::Empty() const
c801d85f 347{
e1208c31
RR
348 if (!m_refData)
349 return TRUE;
350
bbe0af5b 351 return gdk_region_empty( M_REGIONDATA->m_region );
ff7b1510 352}
c801d85f 353
5fc7ede9 354wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
c801d85f 355{
e1208c31
RR
356 if (!m_refData)
357 return wxOutRegion;
358
bbe0af5b
RR
359 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
360 return wxInRegion;
361 else
362 return wxOutRegion;
ff7b1510 363}
c801d85f 364
5fc7ede9 365wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
c801d85f 366{
e1208c31
RR
367 if (!m_refData)
368 return wxOutRegion;
369
bbe0af5b
RR
370 GdkRectangle rect;
371 rect.x = x;
372 rect.y = y;
373 rect.width = w;
374 rect.height = h;
375 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
376 switch (res)
377 {
378 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
379 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
380 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
381 }
382 return wxOutRegion;
ff7b1510 383}
c801d85f 384
8429bec1
RR
385wxRegionContain wxRegion::Contains(const wxPoint& pt) const
386{
bbe0af5b 387 return Contains( pt.x, pt.y );
8429bec1
RR
388}
389
390wxRegionContain wxRegion::Contains(const wxRect& rect) const
391{
bbe0af5b 392 return Contains( rect.x, rect.y, rect.width, rect.height );
8429bec1
RR
393}
394
bf57d1ad 395GdkRegion *wxRegion::GetRegion() const
c801d85f 396{
e1208c31
RR
397 if (!m_refData)
398 return (GdkRegion*) NULL;
399
bbe0af5b 400 return M_REGIONDATA->m_region;
ff7b1510 401}
c801d85f 402
8429bec1
RR
403wxList *wxRegion::GetRectList() const
404{
e1208c31
RR
405 if (!m_refData)
406 return (wxList*) NULL;
407
bbe0af5b 408 return &(M_REGIONDATA->m_rects);
8429bec1
RR
409}
410
411//-----------------------------------------------------------------------------
412// wxRegion
413//-----------------------------------------------------------------------------
414
415IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
5fc7ede9 416
bf57d1ad 417wxRegionIterator::wxRegionIterator()
8429bec1 418{
6f2a55e3 419 Reset();
8429bec1
RR
420}
421
422wxRegionIterator::wxRegionIterator( const wxRegion& region )
423{
6f2a55e3 424 Reset(region);
8429bec1
RR
425}
426
427void wxRegionIterator::Reset( const wxRegion& region )
428{
bbe0af5b 429 m_region = region;
6f2a55e3 430 Reset();
8429bec1
RR
431}
432
5fc7ede9
VZ
433wxRegionIterator::operator bool () const
434{
674ac8b9 435 return m_current < (size_t)m_region.GetRectList()->Number();
8429bec1
RR
436}
437
5fc7ede9
VZ
438bool wxRegionIterator::HaveRects() const
439{
674ac8b9 440 return m_current < (size_t)m_region.GetRectList()->Number();
8429bec1
RR
441}
442
bf57d1ad 443void wxRegionIterator::operator ++ ()
8429bec1 444{
674ac8b9 445 if (m_current < (size_t)m_region.GetRectList()->Number()) ++m_current;
8429bec1
RR
446}
447
448void wxRegionIterator::operator ++ (int)
449{
674ac8b9 450 if (m_current < (size_t)m_region.GetRectList()->Number()) ++m_current;
8429bec1
RR
451}
452
bf57d1ad 453wxCoord wxRegionIterator::GetX() const
8429bec1 454{
bbe0af5b
RR
455 wxNode *node = m_region.GetRectList()->Nth( m_current );
456 if (!node) return 0;
457 wxRect *r = (wxRect*)node->Data();
458 return r->x;
8429bec1
RR
459}
460
bf57d1ad 461wxCoord wxRegionIterator::GetY() const
8429bec1 462{
bbe0af5b
RR
463 wxNode *node = m_region.GetRectList()->Nth( m_current );
464 if (!node) return 0;
465 wxRect *r = (wxRect*)node->Data();
466 return r->y;
8429bec1
RR
467}
468
bf57d1ad 469wxCoord wxRegionIterator::GetW() const
8429bec1 470{
bbe0af5b
RR
471 wxNode *node = m_region.GetRectList()->Nth( m_current );
472 if (!node) return 0;
473 wxRect *r = (wxRect*)node->Data();
474 return r->width;
8429bec1
RR
475}
476
bf57d1ad 477wxCoord wxRegionIterator::GetH() const
8429bec1 478{
bbe0af5b
RR
479 wxNode *node = m_region.GetRectList()->Nth( m_current );
480 if (!node) return 0;
481 wxRect *r = (wxRect*)node->Data();
482 return r->height;
8429bec1
RR
483}
484
485