]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/region.cpp
Up-ported code to make tree item visible when programmatically
[wxWidgets.git] / src / gtk1 / region.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
5fc7ede9 2// Name: gtk/region.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
1e6feb95 5// Modified: VZ at 05.10.00: use Unshare(), comparison fixed
f96aa4d9
RR
6// Id: $Id$
7// Copyright: (c) 1998 Robert Roebling
5fc7ede9 8// Licence: wxWindows licence
c801d85f
KB
9/////////////////////////////////////////////////////////////////////////////
10
1e6feb95
VZ
11// ============================================================================
12// declarations
13// ============================================================================
14
c801d85f 15#ifdef __GNUG__
1e6feb95 16 #pragma implementation "region.h"
c801d85f
KB
17#endif
18
1e6feb95
VZ
19// ----------------------------------------------------------------------------
20// headers
21// ----------------------------------------------------------------------------
22
c801d85f
KB
23#include "wx/region.h"
24
aed8ac3f
RR
25#include <gdk/gdk.h>
26#include <gtk/gtk.h>
bbe0af5b 27
d52e91c9
JS
28// Unfortunately the new way of implementing the region iterator
29// doesn't work with GTK+ 2.0 or above (can't access a Region in
30// GdkPrivateRegion)
31#ifdef __WXGTK20__
32#define OLDCODE 1
33#else
3d0c4d2e 34#define OLDCODE 0
d52e91c9 35#endif
864e8bd0 36
1e6feb95
VZ
37#include "wx/log.h"
38
39// ----------------------------------------------------------------------------
40// wxRegionRefData: private class containing the information about the region
41// ----------------------------------------------------------------------------
c801d85f 42
1e6feb95 43class wxRegionRefData : public wxObjectRefData
c801d85f 44{
864e8bd0 45public:
bf57d1ad 46 wxRegionRefData();
1e6feb95
VZ
47 wxRegionRefData(const wxRegionRefData& refData);
48 virtual ~wxRegionRefData();
5fc7ede9 49
c801d85f 50 GdkRegion *m_region;
3d0c4d2e 51#if OLDCODE
8429bec1 52 wxList m_rects;
3d0c4d2e 53#endif
c801d85f
KB
54};
55
1e6feb95
VZ
56// ----------------------------------------------------------------------------
57// macros
58// ----------------------------------------------------------------------------
59
60#define M_REGIONDATA ((wxRegionRefData *)m_refData)
61#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
62
63IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject);
64IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
65
66// ============================================================================
67// implementation
68// ============================================================================
69
70// ----------------------------------------------------------------------------
71// wxRegionRefData
72// ----------------------------------------------------------------------------
73
bf57d1ad 74wxRegionRefData::wxRegionRefData()
c801d85f 75{
bbe0af5b 76 m_region = (GdkRegion *) NULL;
ff7b1510 77}
c801d85f 78
1e6feb95
VZ
79wxRegionRefData::wxRegionRefData(const wxRegionRefData& refData)
80{
81#ifdef __WXGTK20__
82 m_region = gdk_region_copy(refData.m_region);
83#else
84 m_region = gdk_region_new();
85 GdkRegion *regCopy = gdk_regions_union(m_region, refData.m_region);
86 gdk_region_destroy(m_region);
87 m_region = regCopy;
88#endif
89
29149a64 90#if OLDCODE
1e6feb95
VZ
91 wxNode *node = refData.m_rects.First();
92 while (node)
93 {
94 wxRect *r = (wxRect*)node->Data();
95 m_rects.Append( (wxObject*) new wxRect(*r) );
96 node = node->Next();
97 }
29149a64 98#endif
1e6feb95
VZ
99}
100
bf57d1ad 101wxRegionRefData::~wxRegionRefData()
c801d85f 102{
bbe0af5b 103 if (m_region) gdk_region_destroy( m_region );
5fc7ede9 104
3d0c4d2e 105#if OLDCODE
bbe0af5b
RR
106 wxNode *node = m_rects.First();
107 while (node)
108 {
109 wxRect *r = (wxRect*)node->Data();
110 delete r;
111 node = node->Next();
112 }
3d0c4d2e 113#endif
ff7b1510 114}
c801d85f 115
1e6feb95
VZ
116// ----------------------------------------------------------------------------
117// wxRegion construction
118// ----------------------------------------------------------------------------
c801d85f
KB
119
120#define M_REGIONDATA ((wxRegionRefData *)m_refData)
121
1e6feb95
VZ
122wxRegion::wxRegion()
123{
124}
125
5fc7ede9 126wxRegion::wxRegion( wxCoord x, wxCoord y, wxCoord w, wxCoord h )
c801d85f 127{
bbe0af5b
RR
128 m_refData = new wxRegionRefData();
129 GdkRegion *reg = gdk_region_new();
130 GdkRectangle rect;
131 rect.x = x;
132 rect.y = y;
133 rect.width = w;
134 rect.height = h;
b7c2d6ff
OK
135#ifdef __WXGTK20__
136 gdk_region_union_with_rect( reg, &rect );
137 M_REGIONDATA->m_region = reg;
138#else
bbe0af5b
RR
139 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
140 gdk_region_destroy( reg );
b7c2d6ff 141#endif
3d0c4d2e 142#if OLDCODE
bbe0af5b 143 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,w,h) );
3d0c4d2e 144#endif
ff7b1510 145}
c801d85f
KB
146
147wxRegion::wxRegion( const wxPoint& topLeft, const wxPoint& bottomRight )
148{
bbe0af5b
RR
149 m_refData = new wxRegionRefData();
150 GdkRegion *reg = gdk_region_new();
151 GdkRectangle rect;
152 rect.x = topLeft.x;
153 rect.y = topLeft.y;
154 rect.width = bottomRight.x - rect.x;
155 rect.height = bottomRight.y - rect.y;
b7c2d6ff
OK
156#ifdef __WXGTK20__
157 gdk_region_union_with_rect( reg, &rect );
158 M_REGIONDATA->m_region = reg;
159#else
bbe0af5b
RR
160 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
161 gdk_region_destroy( reg );
b7c2d6ff 162#endif
3d0c4d2e 163#if OLDCODE
bbe0af5b 164 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(topLeft,bottomRight) );
3d0c4d2e 165#endif
ff7b1510 166}
c801d85f
KB
167
168wxRegion::wxRegion( const wxRect& rect )
169{
bbe0af5b
RR
170 m_refData = new wxRegionRefData();
171 GdkRegion *reg = gdk_region_new();
172 GdkRectangle g_rect;
173 g_rect.x = rect.x;
174 g_rect.y = rect.y;
175 g_rect.width = rect.width;
176 g_rect.height = rect.height;
b7c2d6ff
OK
177#ifdef __WXGTK20__
178 gdk_region_union_with_rect( reg, &g_rect );
179 M_REGIONDATA->m_region = reg;
180#else
bbe0af5b
RR
181 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &g_rect );
182 gdk_region_destroy( reg );
b7c2d6ff 183#endif
3d0c4d2e 184#if OLDCODE
e1208c31 185 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(rect.x,rect.y,rect.width,rect.height) );
3d0c4d2e 186#endif
ff7b1510 187}
c801d85f 188
1e6feb95 189wxRegion::~wxRegion()
c801d85f 190{
ff7b1510 191}
c801d85f 192
1e6feb95 193bool wxRegion::operator==( const wxRegion& region )
c801d85f 194{
1e6feb95
VZ
195 // VZ: compare the regions themselves, not the pointers to ref data!
196 return gdk_region_equal(M_REGIONDATA->m_region,
197 M_REGIONDATA_OF(region)->m_region);
ff7b1510 198}
c801d85f 199
1e6feb95 200bool wxRegion::operator != ( const wxRegion& region )
76ed8f8d 201{
1e6feb95 202 return !(*this == region);
76ed8f8d
RR
203}
204
1e6feb95 205void wxRegion::Unshare()
76ed8f8d 206{
1e6feb95
VZ
207 if ( !m_refData )
208 {
209 m_refData = new wxRegionRefData;
210 M_REGIONDATA->m_region = gdk_region_new();
211 }
212 else if ( m_refData->GetRefCount() > 1 )
213 {
214 wxRegionRefData *refData = new wxRegionRefData(*M_REGIONDATA);
215 UnRef();
216 m_refData = refData;
217 }
218 //else: we're not shared
76ed8f8d
RR
219}
220
1e6feb95
VZ
221// ----------------------------------------------------------------------------
222// wxRegion operations
223// ----------------------------------------------------------------------------
224
bf57d1ad 225void wxRegion::Clear()
c801d85f 226{
bbe0af5b 227 UnRef();
ff7b1510 228}
c801d85f 229
5fc7ede9 230bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 231{
bbe0af5b
RR
232 GdkRectangle rect;
233 rect.x = x;
234 rect.y = y;
235 rect.width = width;
236 rect.height = height;
e1208c31
RR
237 if (!m_refData)
238 {
239 m_refData = new wxRegionRefData();
240 GdkRegion *reg = gdk_region_new();
b7c2d6ff
OK
241#ifdef __WXGTK20__
242 gdk_region_union_with_rect( reg, &rect );
243 M_REGIONDATA->m_region = reg;
244#else
e1208c31
RR
245 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
246 gdk_region_destroy( reg );
b7c2d6ff 247#endif
e1208c31
RR
248 }
249 else
250 {
1e6feb95
VZ
251 Unshare();
252
b7c2d6ff
OK
253#ifdef __WXGTK20__
254 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
255#else
e1208c31
RR
256 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
257 gdk_region_destroy( M_REGIONDATA->m_region );
258 M_REGIONDATA->m_region = reg;
b7c2d6ff 259#endif
e1208c31 260 }
1e6feb95 261
3d0c4d2e 262#if OLDCODE
bbe0af5b 263 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,width,height) );
3d0c4d2e 264#endif
e1208c31 265
bbe0af5b 266 return TRUE;
ff7b1510 267}
c801d85f
KB
268
269bool wxRegion::Union( const wxRect& rect )
270{
e1208c31 271 return Union( rect.x, rect.y, rect.width, rect.height );
ff7b1510 272}
c801d85f
KB
273
274bool wxRegion::Union( const wxRegion& region )
275{
e1208c31
RR
276 if (region.IsNull())
277 return FALSE;
278
1e6feb95 279 Unshare();
e1208c31 280
b7c2d6ff
OK
281#ifdef __WXGTK20__
282 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
283#else
bbe0af5b
RR
284 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
285 gdk_region_destroy( M_REGIONDATA->m_region );
286 M_REGIONDATA->m_region = reg;
b7c2d6ff 287#endif
5fc7ede9 288
3d0c4d2e 289#if OLDCODE
bbe0af5b
RR
290 wxNode *node = region.GetRectList()->First();
291 while (node)
292 {
293 wxRect *r = (wxRect*)node->Data();
294 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
295 node = node->Next();
296 }
3d0c4d2e 297#endif
5fc7ede9 298
bbe0af5b 299 return TRUE;
ff7b1510 300}
c801d85f 301
5fc7ede9 302bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 303{
bbe0af5b 304 wxRegion reg( x, y, width, height );
1e6feb95
VZ
305
306 return Intersect( reg );
ff7b1510 307}
c801d85f
KB
308
309bool wxRegion::Intersect( const wxRect& rect )
310{
bbe0af5b 311 wxRegion reg( rect );
1e6feb95 312 return Intersect( reg );
ff7b1510 313}
c801d85f 314
1e6feb95
VZ
315// this helper function just computes the region intersection without updating
316// the list of rectangles each region maintaints: this allows us to call it
317// from Intersect() itself without going into infinite recursion as we would
318// if we called Intersect() itself recursively
319bool wxRegion::IntersectRegionOnly(const wxRegion& region)
c801d85f 320{
1e6feb95 321 Unshare();
e1208c31 322
b7c2d6ff
OK
323#ifdef __WXGTK20__
324 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
325#else
bbe0af5b
RR
326 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
327 gdk_region_destroy( M_REGIONDATA->m_region );
328 M_REGIONDATA->m_region = reg;
b7c2d6ff 329#endif
1e6feb95 330
bbe0af5b 331 return TRUE;
ff7b1510 332}
c801d85f 333
1e6feb95 334bool wxRegion::Intersect( const wxRegion& region )
c801d85f 335{
1e6feb95
VZ
336 if (region.IsNull())
337 return FALSE;
338
e1208c31
RR
339 if (!m_refData)
340 {
341 m_refData = new wxRegionRefData();
342 M_REGIONDATA->m_region = gdk_region_new();
1e6feb95
VZ
343 return TRUE;
344 }
345
346 if ( !IntersectRegionOnly(region) )
347 {
348 GetRectList()->Clear();
349
350 return FALSE;
351 }
352
353 // we need to update the rect list as well
2a365b7d 354#if OLDCODE
1e6feb95
VZ
355 wxList& list = *GetRectList();
356 wxNode *node = list.First();
357 while (node)
358 {
359 wxRect *r = (wxRect*)node->Data();
360
361 wxRegion regCopy = region;
362 if ( regCopy.IntersectRegionOnly(*r) )
363 {
364 // replace the node with the intersection
365 *r = regCopy.GetBox();
366 }
367 else
368 {
369 // TODO remove the rect from the list
370 r->width = 0;
371 r->height = 0;
372 }
373
374 node = node->Next();
e1208c31 375 }
2a365b7d 376#endif
bbe0af5b 377 return TRUE;
ff7b1510 378}
c801d85f 379
1e6feb95 380bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 381{
1e6feb95
VZ
382 wxRegion reg( x, y, width, height );
383 return Subtract( reg );
384}
e1208c31 385
1e6feb95
VZ
386bool wxRegion::Subtract( const wxRect& rect )
387{
bbe0af5b 388 wxRegion reg( rect );
1e6feb95 389 return Subtract( reg );
ff7b1510 390}
c801d85f
KB
391
392bool wxRegion::Subtract( const wxRegion& region )
393{
e1208c31
RR
394 if (region.IsNull())
395 return FALSE;
396
397 if (!m_refData)
398 {
399 m_refData = new wxRegionRefData();
400 M_REGIONDATA->m_region = gdk_region_new();
401 }
402
1e6feb95
VZ
403 Unshare();
404
b7c2d6ff
OK
405#ifdef __WXGTK20__
406 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
407#else
bbe0af5b
RR
408 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
409 gdk_region_destroy( M_REGIONDATA->m_region );
410 M_REGIONDATA->m_region = reg;
b7c2d6ff 411#endif
1e6feb95 412
bbe0af5b 413 return TRUE;
ff7b1510 414}
c801d85f 415
5fc7ede9 416bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 417{
bbe0af5b 418 wxRegion reg( x, y, width, height );
1e6feb95 419 return Xor( reg );
ff7b1510 420}
c801d85f
KB
421
422bool wxRegion::Xor( const wxRect& rect )
423{
bbe0af5b 424 wxRegion reg( rect );
1e6feb95 425 return Xor( reg );
ff7b1510 426}
c801d85f
KB
427
428bool wxRegion::Xor( const wxRegion& region )
429{
e1208c31 430 if (region.IsNull())
05a11043 431 return FALSE;
e1208c31
RR
432
433 if (!m_refData)
434 {
435 m_refData = new wxRegionRefData();
436 M_REGIONDATA->m_region = gdk_region_new();
437 }
1e6feb95
VZ
438 else
439 {
440 Unshare();
441 }
e1208c31 442
b7c2d6ff
OK
443#ifdef __WXGTK20__
444 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
445#else
bbe0af5b
RR
446 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
447 gdk_region_destroy( M_REGIONDATA->m_region );
448 M_REGIONDATA->m_region = reg;
b7c2d6ff 449#endif
5fc7ede9 450
3d0c4d2e 451#if OLDCODE
bbe0af5b
RR
452 wxNode *node = region.GetRectList()->First();
453 while (node)
454 {
455 wxRect *r = (wxRect*)node->Data();
456 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
457 node = node->Next();
458 }
3d0c4d2e 459#endif
5fc7ede9 460
bbe0af5b 461 return TRUE;
ff7b1510 462}
c801d85f 463
1e6feb95
VZ
464// ----------------------------------------------------------------------------
465// wxRegion tests
466// ----------------------------------------------------------------------------
467
e1208c31 468void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
c801d85f 469{
1e6feb95
VZ
470 if ( m_refData )
471 {
472 GdkRectangle rect;
473 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
474 x = rect.x;
475 y = rect.y;
476 w = rect.width;
477 h = rect.height;
478 }
479 else
480 {
481 x = 0;
482 y = 0;
483 w = -1;
484 h = -1;
485 }
ff7b1510 486}
c801d85f 487
bf57d1ad 488wxRect wxRegion::GetBox() const
c801d85f 489{
1e6feb95 490 wxCoord x, y, w, h;
bbe0af5b
RR
491 GetBox( x, y, w, h );
492 return wxRect( x, y, w, h );
ff7b1510 493}
c801d85f 494
bf57d1ad 495bool wxRegion::Empty() const
c801d85f 496{
e1208c31
RR
497 if (!m_refData)
498 return TRUE;
499
bbe0af5b 500 return gdk_region_empty( M_REGIONDATA->m_region );
ff7b1510 501}
c801d85f 502
5fc7ede9 503wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
c801d85f 504{
e1208c31
RR
505 if (!m_refData)
506 return wxOutRegion;
507
bbe0af5b
RR
508 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
509 return wxInRegion;
510 else
511 return wxOutRegion;
ff7b1510 512}
c801d85f 513
5fc7ede9 514wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
c801d85f 515{
e1208c31
RR
516 if (!m_refData)
517 return wxOutRegion;
518
bbe0af5b
RR
519 GdkRectangle rect;
520 rect.x = x;
521 rect.y = y;
522 rect.width = w;
523 rect.height = h;
524 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
525 switch (res)
526 {
527 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
528 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
529 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
530 }
531 return wxOutRegion;
ff7b1510 532}
c801d85f 533
8429bec1
RR
534wxRegionContain wxRegion::Contains(const wxPoint& pt) const
535{
bbe0af5b 536 return Contains( pt.x, pt.y );
8429bec1
RR
537}
538
539wxRegionContain wxRegion::Contains(const wxRect& rect) const
540{
bbe0af5b 541 return Contains( rect.x, rect.y, rect.width, rect.height );
8429bec1
RR
542}
543
bf57d1ad 544GdkRegion *wxRegion::GetRegion() const
c801d85f 545{
e1208c31
RR
546 if (!m_refData)
547 return (GdkRegion*) NULL;
548
bbe0af5b 549 return M_REGIONDATA->m_region;
ff7b1510 550}
c801d85f 551
8429bec1
RR
552wxList *wxRegion::GetRectList() const
553{
3d0c4d2e 554#if OLDCODE
e1208c31
RR
555 if (!m_refData)
556 return (wxList*) NULL;
557
bbe0af5b 558 return &(M_REGIONDATA->m_rects);
3d0c4d2e
RR
559#else
560 return (wxList*) NULL;
561#endif
8429bec1
RR
562}
563
1e6feb95 564// ----------------------------------------------------------------------------
3d0c4d2e 565// wxRegionIterator
1e6feb95 566// ----------------------------------------------------------------------------
8429bec1 567
3d0c4d2e
RR
568#if OLDCODE
569
bf57d1ad 570wxRegionIterator::wxRegionIterator()
8429bec1 571{
6f2a55e3 572 Reset();
8429bec1
RR
573}
574
575wxRegionIterator::wxRegionIterator( const wxRegion& region )
576{
6f2a55e3 577 Reset(region);
8429bec1
RR
578}
579
580void wxRegionIterator::Reset( const wxRegion& region )
581{
bbe0af5b 582 m_region = region;
6f2a55e3 583 Reset();
8429bec1
RR
584}
585
5fc7ede9
VZ
586wxRegionIterator::operator bool () const
587{
3d0c4d2e 588 return m_region.GetRectList() && m_current < (size_t)m_region.GetRectList()->Number();
8429bec1
RR
589}
590
5fc7ede9
VZ
591bool wxRegionIterator::HaveRects() const
592{
3d0c4d2e 593 return m_region.GetRectList() && m_current < (size_t)m_region.GetRectList()->Number();
8429bec1
RR
594}
595
bf57d1ad 596void wxRegionIterator::operator ++ ()
8429bec1 597{
3d0c4d2e 598 if (HaveRects()) ++m_current;
8429bec1
RR
599}
600
601void wxRegionIterator::operator ++ (int)
602{
3d0c4d2e 603 if (HaveRects()) ++m_current;
8429bec1
RR
604}
605
bf57d1ad 606wxCoord wxRegionIterator::GetX() const
8429bec1 607{
bbe0af5b
RR
608 wxNode *node = m_region.GetRectList()->Nth( m_current );
609 if (!node) return 0;
610 wxRect *r = (wxRect*)node->Data();
611 return r->x;
8429bec1
RR
612}
613
bf57d1ad 614wxCoord wxRegionIterator::GetY() const
8429bec1 615{
bbe0af5b
RR
616 wxNode *node = m_region.GetRectList()->Nth( m_current );
617 if (!node) return 0;
618 wxRect *r = (wxRect*)node->Data();
619 return r->y;
8429bec1
RR
620}
621
bf57d1ad 622wxCoord wxRegionIterator::GetW() const
8429bec1 623{
bbe0af5b
RR
624 wxNode *node = m_region.GetRectList()->Nth( m_current );
625 if (!node) return 0;
626 wxRect *r = (wxRect*)node->Data();
627 return r->width;
8429bec1
RR
628}
629
bf57d1ad 630wxCoord wxRegionIterator::GetH() const
8429bec1 631{
bbe0af5b
RR
632 wxNode *node = m_region.GetRectList()->Nth( m_current );
633 if (!node) return 0;
634 wxRect *r = (wxRect*)node->Data();
635 return r->height;
8429bec1
RR
636}
637
3d0c4d2e
RR
638#else
639
640// the following structures must match the private structures
641// in X11 region code ( xc/lib/X11/region.h )
642
643// this makes the Region type transparent
644// and we have access to the region rectangles
645
646struct _XBox {
647 short x1, x2, y1, y2;
648};
1e6feb95 649
3d0c4d2e
RR
650struct _XRegion {
651 long size , numRects;
652 _XBox *rects, extents;
653};
654
655class wxRIRefData: public wxObjectRefData
656{
657public:
658
659 wxRIRefData() : m_rects(0), m_numRects(0){}
660 ~wxRIRefData();
661
662 wxRect *m_rects;
663 size_t m_numRects;
664
665 void CreateRects( const wxRegion& r );
666};
667
668wxRIRefData::~wxRIRefData()
669{
670 delete m_rects;
671}
672
673#include <gdk/gdkprivate.h>
674
675void wxRIRefData::CreateRects( const wxRegion& region )
676{
677 if( m_rects )
678 delete m_rects;
679 m_rects = 0;
680 m_numRects= 0;
681 GdkRegion *gdkregion= region.GetRegion();
682 if( gdkregion ){
683 Region r= ((GdkRegionPrivate *)gdkregion)->xregion;
684 if( r ){
685 m_numRects= r->numRects;
686 if( m_numRects )
687 {
688 m_rects= new wxRect[m_numRects];
689 for( size_t i=0; i<m_numRects; ++i )
690 {
691 _XBox &xr= r->rects[i];
692 wxRect&wr= m_rects[i];
693 wr.x = xr.x1;
694 wr.y = xr.y1;
695 wr.width = xr.x2-xr.x1;
696 wr.height= xr.y2-xr.y1;
697 }
698 }
699 }
700 }
701}
702
3d0c4d2e
RR
703wxRegionIterator::wxRegionIterator()
704{
705 m_refData = new wxRIRefData();
706 Reset();
707}
708
709wxRegionIterator::wxRegionIterator( const wxRegion& region )
710{
711 m_refData = new wxRIRefData();
712 Reset(region);
713}
714
715void wxRegionIterator::Reset( const wxRegion& region )
716{
717 m_region = region;
718 ((wxRIRefData*)m_refData)->CreateRects(region);
719 Reset();
720}
721
722bool wxRegionIterator::HaveRects() const
723{
724 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
725}
726
727wxRegionIterator::operator bool () const
728{
729 return HaveRects();
730}
731
732void wxRegionIterator::operator ++ ()
733{
734 if (HaveRects()) ++m_current;
735}
736
737void wxRegionIterator::operator ++ (int)
738{
739 if (HaveRects()) ++m_current;
740}
741
742wxCoord wxRegionIterator::GetX() const
743{
744 if( !HaveRects() ) return 0;
745 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
746}
747
748wxCoord wxRegionIterator::GetY() const
749{
750 if( !HaveRects() ) return 0;
751 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
752}
753
754wxCoord wxRegionIterator::GetW() const
755{
756 if( !HaveRects() ) return -1;
757 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
758}
759
760wxCoord wxRegionIterator::GetH() const
761{
762 if( !HaveRects() ) return -1;
763 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
764}
765
1e6feb95
VZ
766wxRect wxRegionIterator::GetRect() const
767{
768 wxRect r;
3379ed37
VZ
769 if( HaveRects() )
770 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
1e6feb95
VZ
771
772 return r;
773}
774
3d0c4d2e 775#endif
8429bec1 776