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