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