]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/region.cpp
Add "checked" property for toolbar tool elements in XRC.
[wxWidgets.git] / src / gtk / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk/region.cpp
3// Purpose:
4// Author: Robert Roebling
5// Modified: VZ at 05.10.00: use AllocExclusive(), comparison fixed
6// Id: $Id$
7// Copyright: (c) 1998 Robert Roebling
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#include "wx/region.h"
23
24#ifndef WX_PRECOMP
25 #include "wx/log.h"
26#endif
27
28#include "wx/gtk/private.h"
29
30
31// ----------------------------------------------------------------------------
32// wxRegionRefData: private class containing the information about the region
33// ----------------------------------------------------------------------------
34
35class wxRegionRefData : public wxGDIRefData
36{
37public:
38 wxRegionRefData()
39 {
40 m_region = NULL;
41 }
42
43 wxRegionRefData(const wxRegionRefData& refData)
44 : wxGDIRefData()
45 {
46 m_region = gdk_region_copy(refData.m_region);
47 }
48
49 virtual ~wxRegionRefData()
50 {
51 if (m_region)
52 gdk_region_destroy( m_region );
53 }
54
55 GdkRegion *m_region;
56};
57
58// ----------------------------------------------------------------------------
59// macros
60// ----------------------------------------------------------------------------
61
62#define M_REGIONDATA ((wxRegionRefData *)m_refData)
63#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
64
65IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
66IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
67
68// ----------------------------------------------------------------------------
69// wxRegion construction
70// ----------------------------------------------------------------------------
71
72#define M_REGIONDATA ((wxRegionRefData *)m_refData)
73
74void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
75{
76 GdkRectangle rect;
77 rect.x = x;
78 rect.y = y;
79 rect.width = w;
80 rect.height = h;
81
82 m_refData = new wxRegionRefData();
83
84 M_REGIONDATA->m_region = gdk_region_rectangle( &rect );
85}
86
87wxRegion::wxRegion( GdkRegion *region )
88{
89 m_refData = new wxRegionRefData();
90 M_REGIONDATA->m_region = gdk_region_copy( region );
91}
92
93wxRegion::wxRegion( size_t n, const wxPoint *points,
94 wxPolygonFillMode fillStyle )
95{
96 GdkPoint *gdkpoints = new GdkPoint[n];
97 for ( size_t i = 0 ; i < n ; i++ )
98 {
99 gdkpoints[i].x = points[i].x;
100 gdkpoints[i].y = points[i].y;
101 }
102
103 m_refData = new wxRegionRefData();
104
105 GdkRegion* reg = gdk_region_polygon
106 (
107 gdkpoints,
108 n,
109 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
110 : GDK_EVEN_ODD_RULE
111 );
112
113 M_REGIONDATA->m_region = reg;
114
115 delete [] gdkpoints;
116}
117
118wxRegion::~wxRegion()
119{
120 // m_refData unrefed in ~wxObject
121}
122
123wxGDIRefData *wxRegion::CreateGDIRefData() const
124{
125 return new wxRegionRefData;
126}
127
128wxGDIRefData *wxRegion::CloneGDIRefData(const wxGDIRefData *data) const
129{
130 return new wxRegionRefData(*(wxRegionRefData *)data);
131}
132
133// ----------------------------------------------------------------------------
134// wxRegion comparison
135// ----------------------------------------------------------------------------
136
137bool wxRegion::DoIsEqual(const wxRegion& region) const
138{
139 return gdk_region_equal(M_REGIONDATA->m_region,
140 M_REGIONDATA_OF(region)->m_region);
141}
142
143// ----------------------------------------------------------------------------
144// wxRegion operations
145// ----------------------------------------------------------------------------
146
147void wxRegion::Clear()
148{
149 UnRef();
150}
151
152bool wxRegion::DoUnionWithRect(const wxRect& r)
153{
154 // workaround for a strange GTK/X11 bug: taking union with an empty
155 // rectangle results in an empty region which is definitely not what we
156 // want
157 if ( r.IsEmpty() )
158 return true;
159
160 if ( !m_refData )
161 {
162 InitRect(r.x, r.y, r.width, r.height);
163 }
164 else
165 {
166 AllocExclusive();
167
168 GdkRectangle rect;
169 rect.x = r.x;
170 rect.y = r.y;
171 rect.width = r.width;
172 rect.height = r.height;
173
174 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
175 }
176
177 return true;
178}
179
180bool wxRegion::DoUnionWithRegion( const wxRegion& region )
181{
182 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
183
184 if (!m_refData)
185 {
186 m_refData = new wxRegionRefData(*M_REGIONDATA_OF(region));
187 }
188 else
189 {
190 AllocExclusive();
191 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
192 }
193
194 return true;
195}
196
197bool wxRegion::DoIntersect( const wxRegion& region )
198{
199 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
200
201 if (!m_refData)
202 {
203 // intersecting with invalid region doesn't make sense
204 return false;
205 }
206
207 AllocExclusive();
208
209 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
210
211 return true;
212}
213
214bool wxRegion::DoSubtract( const wxRegion& region )
215{
216 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
217
218 if (!m_refData)
219 {
220 // subtracting from an invalid region doesn't make sense
221 return false;
222 }
223
224 AllocExclusive();
225
226 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
227
228 return true;
229}
230
231bool wxRegion::DoXor( const wxRegion& region )
232{
233 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
234
235 if (!m_refData)
236 {
237 // XOR-ing with an invalid region is the same as XOR-ing with an empty
238 // one, i.e. it is simply a copy.
239 m_refData = new wxRegionRefData(*M_REGIONDATA_OF(region));
240 }
241 else
242 {
243 AllocExclusive();
244
245 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
246 }
247
248 return true;
249}
250
251bool wxRegion::DoOffset( wxCoord x, wxCoord y )
252{
253 wxCHECK_MSG( m_refData, false, wxS("invalid region") );
254
255 AllocExclusive();
256
257 gdk_region_offset( M_REGIONDATA->m_region, x, y );
258
259 return true;
260}
261
262// ----------------------------------------------------------------------------
263// wxRegion tests
264// ----------------------------------------------------------------------------
265
266bool wxRegion::DoGetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
267{
268 if ( m_refData )
269 {
270 GdkRectangle rect;
271 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
272 x = rect.x;
273 y = rect.y;
274 w = rect.width;
275 h = rect.height;
276
277 return true;
278 }
279 else
280 {
281 x = 0;
282 y = 0;
283 w = -1;
284 h = -1;
285
286 return false;
287 }
288}
289
290bool wxRegion::IsEmpty() const
291{
292 if (!m_refData)
293 return true;
294
295 return gdk_region_empty( M_REGIONDATA->m_region );
296}
297
298wxRegionContain wxRegion::DoContainsPoint( wxCoord x, wxCoord y ) const
299{
300 if (!m_refData)
301 return wxOutRegion;
302
303 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
304 return wxInRegion;
305 else
306 return wxOutRegion;
307}
308
309wxRegionContain wxRegion::DoContainsRect(const wxRect& r) const
310{
311 if (!m_refData)
312 return wxOutRegion;
313
314 GdkRectangle rect;
315 rect.x = r.x;
316 rect.y = r.y;
317 rect.width = r.width;
318 rect.height = r.height;
319 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
320 switch (res)
321 {
322 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
323 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
324 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
325 }
326 return wxOutRegion;
327}
328
329GdkRegion *wxRegion::GetRegion() const
330{
331 if (!m_refData)
332 return NULL;
333
334 return M_REGIONDATA->m_region;
335}
336
337// ----------------------------------------------------------------------------
338// wxRegionIterator
339// ----------------------------------------------------------------------------
340
341wxRegionIterator::wxRegionIterator()
342{
343 Init();
344 Reset();
345}
346
347wxRegionIterator::wxRegionIterator( const wxRegion& region )
348{
349 Init();
350 Reset(region);
351}
352
353void wxRegionIterator::Init()
354{
355 m_rects = NULL;
356 m_numRects = 0;
357}
358
359wxRegionIterator::~wxRegionIterator()
360{
361 wxDELETEA(m_rects);
362}
363
364void wxRegionIterator::CreateRects( const wxRegion& region )
365{
366 wxDELETEA(m_rects);
367 m_numRects = 0;
368
369 GdkRegion *gdkregion = region.GetRegion();
370 if (!gdkregion)
371 return;
372
373 GdkRectangle *gdkrects = NULL;
374 gint numRects = 0;
375 gdk_region_get_rectangles( gdkregion, &gdkrects, &numRects );
376
377 m_numRects = numRects;
378 if (numRects)
379 {
380 m_rects = new wxRect[m_numRects];
381 for (size_t i=0; i < m_numRects; ++i)
382 {
383 GdkRectangle &gr = gdkrects[i];
384 wxRect &wr = m_rects[i];
385 wr.x = gr.x;
386 wr.y = gr.y;
387 wr.width = gr.width;
388 wr.height = gr.height;
389 }
390 }
391 g_free( gdkrects );
392}
393
394void wxRegionIterator::Reset( const wxRegion& region )
395{
396 m_region = region;
397 CreateRects(region);
398 Reset();
399}
400
401bool wxRegionIterator::HaveRects() const
402{
403 return m_current < m_numRects;
404}
405
406wxRegionIterator& wxRegionIterator::operator ++ ()
407{
408 if (HaveRects())
409 ++m_current;
410
411 return *this;
412}
413
414wxRegionIterator wxRegionIterator::operator ++ (int)
415{
416 wxRegionIterator tmp = *this;
417
418 if (HaveRects())
419 ++m_current;
420
421 return tmp;
422}
423
424wxCoord wxRegionIterator::GetX() const
425{
426 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
427
428 return m_rects[m_current].x;
429}
430
431wxCoord wxRegionIterator::GetY() const
432{
433 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
434
435 return m_rects[m_current].y;
436}
437
438wxCoord wxRegionIterator::GetW() const
439{
440 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
441
442 return m_rects[m_current].width;
443}
444
445wxCoord wxRegionIterator::GetH() const
446{
447 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
448
449 return m_rects[m_current].height;
450}
451
452wxRect wxRegionIterator::GetRect() const
453{
454 wxRect r;
455 if( HaveRects() )
456 r = m_rects[m_current];
457
458 return r;
459}
460
461wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& ri)
462{
463 wxDELETEA(m_rects);
464
465 m_current = ri.m_current;
466 m_numRects = ri.m_numRects;
467 if ( m_numRects )
468 {
469 m_rects = new wxRect[m_numRects];
470 for ( unsigned int n = 0; n < m_numRects; n++ )
471 m_rects[n] = ri.m_rects[n];
472 }
473 else
474 {
475 m_rects = NULL;
476 }
477
478 return *this;
479}