Flicker war won.
[wxWidgets.git] / src / gtk / region.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: region.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 #ifdef __GNUG__
12 #pragma implementation "region.h"
13 #endif
14
15 #include "wx/region.h"
16
17 //-----------------------------------------------------------------------------
18 // wxRegion
19 //-----------------------------------------------------------------------------
20
21 class wxRegionRefData: public wxObjectRefData
22 {
23 public:
24
25 wxRegionRefData(void);
26 ~wxRegionRefData(void);
27
28 public:
29
30 GdkRegion *m_region;
31 wxList m_rects;
32 };
33
34 wxRegionRefData::wxRegionRefData(void)
35 {
36 m_region = (GdkRegion *) NULL;
37 }
38
39 wxRegionRefData::~wxRegionRefData(void)
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( long x, long y, long w, long 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 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) );
70 }
71
72 wxRegion::wxRegion( const wxPoint& topLeft, const wxPoint& bottomRight )
73 {
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) );
84 }
85
86 wxRegion::wxRegion( const wxRect& rect )
87 {
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 );
97
98 wxNode *node = M_REGIONDATA->m_rects.First();
99 while (node)
100 {
101 wxRect *r = (wxRect*)node->Data();
102 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
103 node = node->Next();
104 }
105 }
106
107 wxRegion::wxRegion(void)
108 {
109 m_refData = new wxRegionRefData();
110 M_REGIONDATA->m_region = gdk_region_new();
111 }
112
113 wxRegion::~wxRegion(void)
114 {
115 }
116
117 bool wxRegion::operator == ( const wxRegion& region )
118 {
119 return m_refData == region.m_refData;
120 }
121
122 bool wxRegion::operator != ( const wxRegion& region )
123 {
124 return m_refData != region.m_refData;
125 }
126
127 void wxRegion::Clear(void)
128 {
129 UnRef();
130 m_refData = new wxRegionRefData();
131 M_REGIONDATA->m_region = gdk_region_new();
132 }
133
134 bool wxRegion::Union( long x, long y, long width, long height )
135 {
136 GdkRectangle rect;
137 rect.x = x;
138 rect.y = y;
139 rect.width = width;
140 rect.height = height;
141 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
142 gdk_region_destroy( M_REGIONDATA->m_region );
143 M_REGIONDATA->m_region = reg;
144 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,width,height) );
145 return TRUE;
146 }
147
148 bool wxRegion::Union( const wxRect& rect )
149 {
150 GdkRectangle g_rect;
151 g_rect.x = rect.x;
152 g_rect.y = rect.y;
153 g_rect.width = rect.width;
154 g_rect.height = rect.height;
155 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &g_rect );
156 gdk_region_destroy( M_REGIONDATA->m_region );
157 M_REGIONDATA->m_region = reg;
158 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(rect.x,rect.y,rect.width,rect.height) );
159 return TRUE;
160 }
161
162 bool wxRegion::Union( const wxRegion& region )
163 {
164 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
165 gdk_region_destroy( M_REGIONDATA->m_region );
166 M_REGIONDATA->m_region = reg;
167
168 wxNode *node = region.GetRectList()->First();
169 while (node)
170 {
171 wxRect *r = (wxRect*)node->Data();
172 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
173 node = node->Next();
174 }
175
176 return TRUE;
177 }
178
179 bool wxRegion::Intersect( long x, long y, long width, long height )
180 {
181 wxRegion reg( x, y, width, height );
182 Intersect( reg );
183 return TRUE;
184 }
185
186 bool wxRegion::Intersect( const wxRect& rect )
187 {
188 wxRegion reg( rect );
189 Intersect( reg );
190 return TRUE;
191 }
192
193 bool wxRegion::Intersect( const wxRegion& region )
194 {
195 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
196 gdk_region_destroy( M_REGIONDATA->m_region );
197 M_REGIONDATA->m_region = reg;
198 return TRUE;
199 }
200
201 bool wxRegion::Subtract( long x, long y, long width, long height )
202 {
203 wxRegion reg( x, y, width, height );
204 Subtract( reg );
205 return TRUE;
206 }
207
208 bool wxRegion::Subtract( const wxRect& rect )
209 {
210 wxRegion reg( rect );
211 Subtract( reg );
212 return TRUE;
213 }
214
215 bool wxRegion::Subtract( const wxRegion& region )
216 {
217 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
218 gdk_region_destroy( M_REGIONDATA->m_region );
219 M_REGIONDATA->m_region = reg;
220 return TRUE;
221 }
222
223 bool wxRegion::Xor( long x, long y, long width, long height )
224 {
225 wxRegion reg( x, y, width, height );
226 Xor( reg );
227 return TRUE;
228 }
229
230 bool wxRegion::Xor( const wxRect& rect )
231 {
232 wxRegion reg( rect );
233 Xor( reg );
234 return TRUE;
235 }
236
237 bool wxRegion::Xor( const wxRegion& region )
238 {
239 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
240 gdk_region_destroy( M_REGIONDATA->m_region );
241 M_REGIONDATA->m_region = reg;
242
243 wxNode *node = region.GetRectList()->First();
244 while (node)
245 {
246 wxRect *r = (wxRect*)node->Data();
247 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
248 node = node->Next();
249 }
250
251 return TRUE;
252 }
253
254 void wxRegion::GetBox( long& x, long& y, long&w, long &h ) const
255 {
256 x = 0;
257 y = 0;
258 w = -1;
259 h = -1;
260 wxNode *node = GetRectList()->First();
261 while (node)
262 {
263 wxRect *r = (wxRect*)node->Data();
264 if (node == GetRectList()->First())
265 {
266 x = r->x;
267 y = r->y;
268 w = r->width;
269 h = r->height;
270 }
271 else
272 {
273 if (r->x < x)
274 {
275 x = r->x;
276 w += x - r->x;
277 }
278 if (r->y < y)
279 {
280 y = r->y;
281 h += y - r->y;
282 }
283 if (r->width+r->x > x+w)
284 {
285 w = r->x + r->width - x;
286 }
287 if (r->height+r->y > y+h)
288 {
289 h = r->y + r->height - y;
290 }
291 }
292 node = node->Next();
293 }
294 }
295
296 wxRect wxRegion::GetBox(void) const
297 {
298 long x = 0;
299 long y = 0;
300 long w = -1;
301 long h = -1;
302 GetBox( x, y, w, h );
303 return wxRect( x, y, w, h );
304 }
305
306 bool wxRegion::Empty(void) const
307 {
308 return gdk_region_empty( M_REGIONDATA->m_region );
309 }
310
311 wxRegionContain wxRegion::Contains( long x, long y ) const
312 {
313 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
314 return wxInRegion;
315 else
316 return wxOutRegion;
317 }
318
319 wxRegionContain wxRegion::Contains( long x, long y, long w, long h ) const
320 {
321 GdkRectangle rect;
322 rect.x = x;
323 rect.y = y;
324 rect.width = w;
325 rect.height = h;
326 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
327 switch (res)
328 {
329 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
330 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
331 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
332 }
333 return wxOutRegion;
334 }
335
336 wxRegionContain wxRegion::Contains(const wxPoint& pt) const
337 {
338 return Contains( pt.x, pt.y );
339 }
340
341 wxRegionContain wxRegion::Contains(const wxRect& rect) const
342 {
343 return Contains( rect.x, rect.y, rect.width, rect.height );
344 }
345
346 GdkRegion *wxRegion::GetRegion(void) const
347 {
348 return M_REGIONDATA->m_region;
349 }
350
351 wxList *wxRegion::GetRectList() const
352 {
353 return &(M_REGIONDATA->m_rects);
354 }
355
356 //-----------------------------------------------------------------------------
357 // wxRegion
358 //-----------------------------------------------------------------------------
359
360 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
361
362 wxRegionIterator::wxRegionIterator(void)
363 {
364 m_current = 0;
365 }
366
367 wxRegionIterator::wxRegionIterator( const wxRegion& region )
368 {
369 m_region = region;
370 m_current = 0;
371 }
372
373 void wxRegionIterator::Reset( const wxRegion& region )
374 {
375 m_region = region;
376 m_current = 0;
377 }
378
379 wxRegionIterator::operator bool (void) const
380 {
381 return m_current < m_region.GetRectList()->Number();
382 }
383
384 bool wxRegionIterator::HaveRects(void) const
385 {
386 return m_current < m_region.GetRectList()->Number();
387 }
388
389 void wxRegionIterator::operator ++ (void)
390 {
391 if (m_current < m_region.GetRectList()->Number()) ++m_current;
392 }
393
394 void wxRegionIterator::operator ++ (int)
395 {
396 if (m_current < m_region.GetRectList()->Number()) ++m_current;
397 }
398
399 long wxRegionIterator::GetX(void) const
400 {
401 wxNode *node = m_region.GetRectList()->Nth( m_current );
402 if (!node) return 0;
403 wxRect *r = (wxRect*)node->Data();
404 return r->x;
405 }
406
407 long wxRegionIterator::GetY(void) const
408 {
409 wxNode *node = m_region.GetRectList()->Nth( m_current );
410 if (!node) return 0;
411 wxRect *r = (wxRect*)node->Data();
412 return r->y;
413 }
414
415 long wxRegionIterator::GetW(void) const
416 {
417 wxNode *node = m_region.GetRectList()->Nth( m_current );
418 if (!node) return 0;
419 wxRect *r = (wxRect*)node->Data();
420 return r->width;
421 }
422
423 long wxRegionIterator::GetH(void) const
424 {
425 wxNode *node = m_region.GetRectList()->Nth( m_current );
426 if (!node) return 0;
427 wxRect *r = (wxRect*)node->Data();
428 return r->height;
429 }
430
431