gtk+ 1.3.1's region transformation code no longer returns a new region,
[wxWidgets.git] / src / gtk1 / region.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/region.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "region.h"
12 #endif
13
14 #include "wx/region.h"
15
16 #include <gdk/gdk.h>
17 #include <gtk/gtk.h>
18
19
20 //-----------------------------------------------------------------------------
21 // wxRegion
22 //-----------------------------------------------------------------------------
23
24 class wxRegionRefData: public wxObjectRefData
25 {
26 public:
27 wxRegionRefData();
28 ~wxRegionRefData();
29
30 GdkRegion *m_region;
31 wxList m_rects;
32 };
33
34 wxRegionRefData::wxRegionRefData()
35 {
36 m_region = (GdkRegion *) NULL;
37 }
38
39 wxRegionRefData::~wxRegionRefData()
40 {
41 if (m_region) gdk_region_destroy( m_region );
42
43 wxNode *node = m_rects.First();
44 while (node)
45 {
46 wxRect *r = (wxRect*)node->Data();
47 delete r;
48 node = node->Next();
49 }
50 }
51
52 //-----------------------------------------------------------------------------
53
54 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
55
56 IMPLEMENT_DYNAMIC_CLASS(wxRegion,wxGDIObject);
57
58 wxRegion::wxRegion( wxCoord x, wxCoord y, wxCoord w, wxCoord h )
59 {
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 #ifdef __WXGTK20__
68 gdk_region_union_with_rect( reg, &rect );
69 M_REGIONDATA->m_region = reg;
70 #else
71 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
72 gdk_region_destroy( reg );
73 #endif
74 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,w,h) );
75 }
76
77 wxRegion::wxRegion( const wxPoint& topLeft, const wxPoint& bottomRight )
78 {
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;
86 #ifdef __WXGTK20__
87 gdk_region_union_with_rect( reg, &rect );
88 M_REGIONDATA->m_region = reg;
89 #else
90 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
91 gdk_region_destroy( reg );
92 #endif
93 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(topLeft,bottomRight) );
94 }
95
96 wxRegion::wxRegion( const wxRect& rect )
97 {
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;
105 #ifdef __WXGTK20__
106 gdk_region_union_with_rect( reg, &g_rect );
107 M_REGIONDATA->m_region = reg;
108 #else
109 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &g_rect );
110 gdk_region_destroy( reg );
111 #endif
112 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(rect.x,rect.y,rect.width,rect.height) );
113 }
114
115 wxRegion::wxRegion()
116 {
117 }
118
119 wxRegion::~wxRegion()
120 {
121 }
122
123 bool wxRegion::operator == ( const wxRegion& region )
124 {
125 return m_refData == region.m_refData;
126 }
127
128 bool wxRegion::operator != ( const wxRegion& region )
129 {
130 return m_refData != region.m_refData;
131 }
132
133 void wxRegion::Clear()
134 {
135 UnRef();
136 }
137
138 bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
139 {
140 GdkRectangle rect;
141 rect.x = x;
142 rect.y = y;
143 rect.width = width;
144 rect.height = height;
145 if (!m_refData)
146 {
147 m_refData = new wxRegionRefData();
148 GdkRegion *reg = gdk_region_new();
149 #ifdef __WXGTK20__
150 gdk_region_union_with_rect( reg, &rect );
151 M_REGIONDATA->m_region = reg;
152 #else
153 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
154 gdk_region_destroy( reg );
155 #endif
156 }
157 else
158 {
159 #ifdef __WXGTK20__
160 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
161 #else
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;
165 #endif
166 }
167
168 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,width,height) );
169
170 return TRUE;
171 }
172
173 bool wxRegion::Union( const wxRect& rect )
174 {
175 return Union( rect.x, rect.y, rect.width, rect.height );
176 }
177
178 bool wxRegion::Union( const wxRegion& region )
179 {
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
189 #ifdef __WXGTK20__
190 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
191 #else
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;
195 #endif
196
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 }
204
205 return TRUE;
206 }
207
208 bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
209 {
210 if (!m_refData)
211 {
212 m_refData = new wxRegionRefData();
213 M_REGIONDATA->m_region = gdk_region_new();
214 }
215
216 wxRegion reg( x, y, width, height );
217 Intersect( reg );
218 return TRUE;
219 }
220
221 bool wxRegion::Intersect( const wxRect& rect )
222 {
223 if (!m_refData)
224 {
225 m_refData = new wxRegionRefData();
226 M_REGIONDATA->m_region = gdk_region_new();
227 }
228
229 wxRegion reg( rect );
230 Intersect( reg );
231 return TRUE;
232 }
233
234 bool wxRegion::Intersect( const wxRegion& region )
235 {
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
246 #ifdef __WXGTK20__
247 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
248 #else
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;
252 #endif
253 return TRUE;
254 }
255
256 bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
257 {
258 if (!m_refData)
259 {
260 m_refData = new wxRegionRefData();
261 M_REGIONDATA->m_region = gdk_region_new();
262 }
263
264 wxRegion reg( x, y, width, height );
265 Subtract( reg );
266 return TRUE;
267 }
268
269 bool wxRegion::Subtract( const wxRect& rect )
270 {
271 if (!m_refData)
272 {
273 m_refData = new wxRegionRefData();
274 M_REGIONDATA->m_region = gdk_region_new();
275 }
276
277 wxRegion reg( rect );
278 Subtract( reg );
279 return TRUE;
280 }
281
282 bool wxRegion::Subtract( const wxRegion& region )
283 {
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
293 #ifdef __WXGTK20__
294 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
295 #else
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;
299 #endif
300 return TRUE;
301 }
302
303 bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
304 {
305 if (!m_refData)
306 {
307 m_refData = new wxRegionRefData();
308 M_REGIONDATA->m_region = gdk_region_new();
309 }
310
311 wxRegion reg( x, y, width, height );
312 Xor( reg );
313 return TRUE;
314 }
315
316 bool wxRegion::Xor( const wxRect& rect )
317 {
318 if (!m_refData)
319 {
320 m_refData = new wxRegionRefData();
321 M_REGIONDATA->m_region = gdk_region_new();
322 }
323
324 wxRegion reg( rect );
325 Xor( reg );
326 return TRUE;
327 }
328
329 bool wxRegion::Xor( const wxRegion& region )
330 {
331 if (region.IsNull())
332 return FALSE;
333
334 if (!m_refData)
335 {
336 m_refData = new wxRegionRefData();
337 M_REGIONDATA->m_region = gdk_region_new();
338 }
339
340 #ifdef __WXGTK20__
341 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
342 #else
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;
346 #endif
347
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 }
355
356 return TRUE;
357 }
358
359 void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
360 {
361 x = 0;
362 y = 0;
363 w = -1;
364 h = -1;
365 if (!m_refData)
366 return;
367
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;
374 }
375
376 wxRect wxRegion::GetBox() const
377 {
378 wxCoord x = 0;
379 wxCoord y = 0;
380 wxCoord w = -1;
381 wxCoord h = -1;
382 GetBox( x, y, w, h );
383 return wxRect( x, y, w, h );
384 }
385
386 bool wxRegion::Empty() const
387 {
388 if (!m_refData)
389 return TRUE;
390
391 return gdk_region_empty( M_REGIONDATA->m_region );
392 }
393
394 wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
395 {
396 if (!m_refData)
397 return wxOutRegion;
398
399 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
400 return wxInRegion;
401 else
402 return wxOutRegion;
403 }
404
405 wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
406 {
407 if (!m_refData)
408 return wxOutRegion;
409
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;
423 }
424
425 wxRegionContain wxRegion::Contains(const wxPoint& pt) const
426 {
427 return Contains( pt.x, pt.y );
428 }
429
430 wxRegionContain wxRegion::Contains(const wxRect& rect) const
431 {
432 return Contains( rect.x, rect.y, rect.width, rect.height );
433 }
434
435 GdkRegion *wxRegion::GetRegion() const
436 {
437 if (!m_refData)
438 return (GdkRegion*) NULL;
439
440 return M_REGIONDATA->m_region;
441 }
442
443 wxList *wxRegion::GetRectList() const
444 {
445 if (!m_refData)
446 return (wxList*) NULL;
447
448 return &(M_REGIONDATA->m_rects);
449 }
450
451 //-----------------------------------------------------------------------------
452 // wxRegion
453 //-----------------------------------------------------------------------------
454
455 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
456
457 wxRegionIterator::wxRegionIterator()
458 {
459 Reset();
460 }
461
462 wxRegionIterator::wxRegionIterator( const wxRegion& region )
463 {
464 Reset(region);
465 }
466
467 void wxRegionIterator::Reset( const wxRegion& region )
468 {
469 m_region = region;
470 Reset();
471 }
472
473 wxRegionIterator::operator bool () const
474 {
475 return m_current < (size_t)m_region.GetRectList()->Number();
476 }
477
478 bool wxRegionIterator::HaveRects() const
479 {
480 return m_current < (size_t)m_region.GetRectList()->Number();
481 }
482
483 void wxRegionIterator::operator ++ ()
484 {
485 if (m_current < (size_t)m_region.GetRectList()->Number()) ++m_current;
486 }
487
488 void wxRegionIterator::operator ++ (int)
489 {
490 if (m_current < (size_t)m_region.GetRectList()->Number()) ++m_current;
491 }
492
493 wxCoord wxRegionIterator::GetX() const
494 {
495 wxNode *node = m_region.GetRectList()->Nth( m_current );
496 if (!node) return 0;
497 wxRect *r = (wxRect*)node->Data();
498 return r->x;
499 }
500
501 wxCoord wxRegionIterator::GetY() const
502 {
503 wxNode *node = m_region.GetRectList()->Nth( m_current );
504 if (!node) return 0;
505 wxRect *r = (wxRect*)node->Data();
506 return r->y;
507 }
508
509 wxCoord wxRegionIterator::GetW() const
510 {
511 wxNode *node = m_region.GetRectList()->Nth( m_current );
512 if (!node) return 0;
513 wxRect *r = (wxRect*)node->Data();
514 return r->width;
515 }
516
517 wxCoord wxRegionIterator::GetH() const
518 {
519 wxNode *node = m_region.GetRectList()->Nth( m_current );
520 if (!node) return 0;
521 wxRect *r = (wxRect*)node->Data();
522 return r->height;
523 }
524
525