]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/region.cpp
Use the iconIndex in the default case too.
[wxWidgets.git] / src / gtk1 / region.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
5fc7ede9 2// Name: gtk/region.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
9fe4c99c 5// Modified: VZ at 05.10.00: use AllocExclusive(), 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
9e691f46 23#include "wx/log.h"
c801d85f 24
9e691f46 25#include "wx/region.h"
bbe0af5b 26
9e691f46 27#include "wx/gtk/private.h"
1e6feb95 28
57f2b902
VZ
29#ifndef __WXGTK20__
30
31// ----------------------------------------------------------------------------
32// wxGdkRegion: creates a new region in ctor and destroys in dtor
33// ----------------------------------------------------------------------------
34
35class wxGdkRegion
36{
37public:
38 wxGdkRegion() { m_region = gdk_region_new(); }
39 ~wxGdkRegion() { gdk_region_destroy(m_region); }
40
41 operator GdkRegion *() const { return m_region; }
42
43private:
44 GdkRegion *m_region;
45};
46
47#endif // __WXGTK20__
48
1e6feb95
VZ
49// ----------------------------------------------------------------------------
50// wxRegionRefData: private class containing the information about the region
51// ----------------------------------------------------------------------------
c801d85f 52
1e6feb95 53class wxRegionRefData : public wxObjectRefData
c801d85f 54{
864e8bd0 55public:
48850fa7
RR
56 wxRegionRefData()
57 {
58 m_region = NULL;
59 }
57f2b902 60
48850fa7 61 wxRegionRefData(const wxRegionRefData& refData)
d84afea9 62 : wxObjectRefData()
48850fa7
RR
63 {
64#ifdef __WXGTK20__
65 m_region = gdk_region_copy(refData.m_region);
66#else
57f2b902 67 m_region = gdk_regions_union(wxGdkRegion(), refData.m_region);
48850fa7
RR
68#endif
69 }
57f2b902 70
48850fa7
RR
71 ~wxRegionRefData()
72 {
73 if (m_region)
74 gdk_region_destroy( m_region );
75 }
5fc7ede9 76
c801d85f
KB
77 GdkRegion *m_region;
78};
79
1e6feb95
VZ
80// ----------------------------------------------------------------------------
81// macros
82// ----------------------------------------------------------------------------
83
84#define M_REGIONDATA ((wxRegionRefData *)m_refData)
85#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
86
d84afea9
GD
87IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
88IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
1e6feb95 89
1e6feb95
VZ
90// ----------------------------------------------------------------------------
91// wxRegion construction
92// ----------------------------------------------------------------------------
c801d85f
KB
93
94#define M_REGIONDATA ((wxRegionRefData *)m_refData)
95
9fe4c99c 96void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
c801d85f 97{
bbe0af5b
RR
98 GdkRectangle rect;
99 rect.x = x;
100 rect.y = y;
101 rect.width = w;
102 rect.height = h;
57f2b902 103
48850fa7 104 m_refData = new wxRegionRefData();
57f2b902 105
b7c2d6ff 106#ifdef __WXGTK20__
9e691f46 107 M_REGIONDATA->m_region = gdk_region_rectangle( &rect );
b7c2d6ff 108#else
57f2b902 109 M_REGIONDATA->m_region = gdk_region_union_with_rect( wxGdkRegion(), &rect );
b7c2d6ff 110#endif
ff7b1510 111}
c801d85f 112
b15ed747
RR
113wxRegion::wxRegion( GdkRegion *region )
114{
115 m_refData = new wxRegionRefData();
57f2b902 116#ifdef __WXGTK20__
b15ed747 117 M_REGIONDATA->m_region = gdk_region_copy( region );
57f2b902
VZ
118#else
119 M_REGIONDATA->m_region = gdk_regions_union(wxGdkRegion(), region);
120#endif
b15ed747
RR
121}
122
5549e9f7
VZ
123wxRegion::wxRegion( size_t n, const wxPoint *points, int fillStyle )
124{
125 GdkPoint *gdkpoints = new GdkPoint[n];
126 for ( size_t i = 0 ; i < n ; i++ )
127 {
128 gdkpoints[i].x = points[i].x;
129 gdkpoints[i].y = points[i].y;
130 }
131
132 m_refData = new wxRegionRefData();
133
134 GdkRegion* reg = gdk_region_polygon
135 (
136 gdkpoints,
137 n,
138 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
139 : GDK_EVEN_ODD_RULE
140 );
141
142 M_REGIONDATA->m_region = reg;
143
144 delete [] gdkpoints;
145}
146
1e6feb95 147wxRegion::~wxRegion()
c801d85f 148{
e0f0b197 149 // m_refData unrefed in ~wxObject
ff7b1510 150}
c801d85f 151
e0f0b197
RR
152wxObjectRefData *wxRegion::CreateRefData() const
153{
154 return new wxRegionRefData;
155}
156
157wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
158{
159 return new wxRegionRefData(*(wxRegionRefData *)data);
160}
c89f5c02 161
9fe4c99c
VZ
162// ----------------------------------------------------------------------------
163// wxRegion comparison
164// ----------------------------------------------------------------------------
165
1e6feb95 166bool wxRegion::operator==( const wxRegion& region )
c801d85f 167{
c89f5c02
RR
168 if (m_refData == region.m_refData) return TRUE;
169
170 if (!m_refData || !region.m_refData) return FALSE;
57f2b902 171
9fe4c99c 172 // compare the regions themselves, not the pointers to ref data!
1e6feb95
VZ
173 return gdk_region_equal(M_REGIONDATA->m_region,
174 M_REGIONDATA_OF(region)->m_region);
ff7b1510 175}
c801d85f 176
1e6feb95
VZ
177// ----------------------------------------------------------------------------
178// wxRegion operations
179// ----------------------------------------------------------------------------
180
bf57d1ad 181void wxRegion::Clear()
c801d85f 182{
bbe0af5b 183 UnRef();
ff7b1510 184}
c801d85f 185
5fc7ede9 186bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 187{
57351df0
VZ
188 // workaround for a strange GTK/X11 bug: taking union with an empty
189 // rectangle results in an empty region which is definitely not what we
190 // want
191 if ( !width || !height )
192 return TRUE;
193
bbe0af5b
RR
194 GdkRectangle rect;
195 rect.x = x;
196 rect.y = y;
197 rect.width = width;
198 rect.height = height;
57f2b902 199
e1208c31
RR
200 if (!m_refData)
201 {
202 m_refData = new wxRegionRefData();
b7c2d6ff 203#ifdef __WXGTK20__
9e691f46 204 M_REGIONDATA->m_region = gdk_region_rectangle( &rect );
b7c2d6ff 205#else
57f2b902 206 M_REGIONDATA->m_region = gdk_region_union_with_rect(wxGdkRegion(), &rect);
b7c2d6ff 207#endif
e1208c31
RR
208 }
209 else
210 {
9fe4c99c 211 AllocExclusive();
1e6feb95 212
b7c2d6ff
OK
213#ifdef __WXGTK20__
214 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
215#else
e1208c31
RR
216 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
217 gdk_region_destroy( M_REGIONDATA->m_region );
218 M_REGIONDATA->m_region = reg;
b7c2d6ff 219#endif
e1208c31 220 }
1e6feb95 221
bbe0af5b 222 return TRUE;
ff7b1510 223}
c801d85f
KB
224
225bool wxRegion::Union( const wxRect& rect )
226{
e1208c31 227 return Union( rect.x, rect.y, rect.width, rect.height );
ff7b1510 228}
c801d85f
KB
229
230bool wxRegion::Union( const wxRegion& region )
231{
e1208c31
RR
232 if (region.IsNull())
233 return FALSE;
234
48850fa7
RR
235 if (!m_refData)
236 {
237 m_refData = new wxRegionRefData();
238 M_REGIONDATA->m_region = gdk_region_new();
239 }
240 else
241 {
242 AllocExclusive();
243 }
e1208c31 244
b7c2d6ff
OK
245#ifdef __WXGTK20__
246 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
247#else
bbe0af5b
RR
248 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
249 gdk_region_destroy( M_REGIONDATA->m_region );
250 M_REGIONDATA->m_region = reg;
b7c2d6ff 251#endif
5fc7ede9 252
bbe0af5b 253 return TRUE;
ff7b1510 254}
c801d85f 255
5fc7ede9 256bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 257{
bbe0af5b 258 wxRegion reg( x, y, width, height );
1e6feb95
VZ
259
260 return Intersect( reg );
ff7b1510 261}
c801d85f
KB
262
263bool wxRegion::Intersect( const wxRect& rect )
264{
bbe0af5b 265 wxRegion reg( rect );
57f2b902 266
1e6feb95 267 return Intersect( reg );
ff7b1510 268}
c801d85f 269
1e6feb95 270bool wxRegion::Intersect( const wxRegion& region )
c801d85f 271{
1e6feb95
VZ
272 if (region.IsNull())
273 return FALSE;
274
e1208c31
RR
275 if (!m_refData)
276 {
277 m_refData = new wxRegionRefData();
278 M_REGIONDATA->m_region = gdk_region_new();
57f2b902
VZ
279
280 // leave here
1e6feb95
VZ
281 return TRUE;
282 }
48850fa7 283 else
1e6feb95 284 {
48850fa7 285 AllocExclusive();
1e6feb95
VZ
286 }
287
48850fa7
RR
288#ifdef __WXGTK20__
289 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
290#else
291 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
292 gdk_region_destroy( M_REGIONDATA->m_region );
293 M_REGIONDATA->m_region = reg;
294#endif
9fe4c99c 295
bbe0af5b 296 return TRUE;
ff7b1510 297}
c801d85f 298
1e6feb95 299bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 300{
1e6feb95
VZ
301 wxRegion reg( x, y, width, height );
302 return Subtract( reg );
303}
e1208c31 304
1e6feb95
VZ
305bool wxRegion::Subtract( const wxRect& rect )
306{
bbe0af5b 307 wxRegion reg( rect );
1e6feb95 308 return Subtract( reg );
ff7b1510 309}
c801d85f
KB
310
311bool wxRegion::Subtract( const wxRegion& region )
312{
e1208c31
RR
313 if (region.IsNull())
314 return FALSE;
315
316 if (!m_refData)
317 {
318 m_refData = new wxRegionRefData();
319 M_REGIONDATA->m_region = gdk_region_new();
320 }
48850fa7
RR
321 else
322 {
323 AllocExclusive();
324 }
1e6feb95 325
b7c2d6ff
OK
326#ifdef __WXGTK20__
327 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
328#else
bbe0af5b
RR
329 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
330 gdk_region_destroy( M_REGIONDATA->m_region );
331 M_REGIONDATA->m_region = reg;
b7c2d6ff 332#endif
1e6feb95 333
bbe0af5b 334 return TRUE;
ff7b1510 335}
c801d85f 336
5fc7ede9 337bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 338{
bbe0af5b 339 wxRegion reg( x, y, width, height );
1e6feb95 340 return Xor( reg );
ff7b1510 341}
c801d85f
KB
342
343bool wxRegion::Xor( const wxRect& rect )
344{
bbe0af5b 345 wxRegion reg( rect );
1e6feb95 346 return Xor( reg );
ff7b1510 347}
c801d85f
KB
348
349bool wxRegion::Xor( const wxRegion& region )
350{
e1208c31 351 if (region.IsNull())
05a11043 352 return FALSE;
e1208c31
RR
353
354 if (!m_refData)
355 {
356 m_refData = new wxRegionRefData();
357 M_REGIONDATA->m_region = gdk_region_new();
358 }
1e6feb95
VZ
359 else
360 {
9fe4c99c 361 AllocExclusive();
1e6feb95 362 }
e1208c31 363
b7c2d6ff
OK
364#ifdef __WXGTK20__
365 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
366#else
bbe0af5b
RR
367 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
368 gdk_region_destroy( M_REGIONDATA->m_region );
369 M_REGIONDATA->m_region = reg;
b7c2d6ff 370#endif
5fc7ede9 371
bbe0af5b 372 return TRUE;
ff7b1510 373}
c801d85f 374
1e6feb95
VZ
375// ----------------------------------------------------------------------------
376// wxRegion tests
377// ----------------------------------------------------------------------------
378
e1208c31 379void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
c801d85f 380{
1e6feb95
VZ
381 if ( m_refData )
382 {
383 GdkRectangle rect;
384 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
385 x = rect.x;
386 y = rect.y;
387 w = rect.width;
388 h = rect.height;
389 }
390 else
391 {
392 x = 0;
393 y = 0;
394 w = -1;
395 h = -1;
396 }
ff7b1510 397}
c801d85f 398
bf57d1ad 399wxRect wxRegion::GetBox() const
c801d85f 400{
1e6feb95 401 wxCoord x, y, w, h;
bbe0af5b
RR
402 GetBox( x, y, w, h );
403 return wxRect( x, y, w, h );
ff7b1510 404}
c801d85f 405
35917d22
RR
406bool wxRegion::Offset( wxCoord x, wxCoord y )
407{
408 if (!m_refData)
409 return FALSE;
410
9fe4c99c
VZ
411 AllocExclusive();
412
35917d22 413 gdk_region_offset( M_REGIONDATA->m_region, x, y );
9fe4c99c 414
35917d22
RR
415 return TRUE;
416}
417
bf57d1ad 418bool wxRegion::Empty() const
c801d85f 419{
e1208c31
RR
420 if (!m_refData)
421 return TRUE;
422
bbe0af5b 423 return gdk_region_empty( M_REGIONDATA->m_region );
ff7b1510 424}
c801d85f 425
5fc7ede9 426wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
c801d85f 427{
e1208c31
RR
428 if (!m_refData)
429 return wxOutRegion;
430
bbe0af5b
RR
431 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
432 return wxInRegion;
433 else
434 return wxOutRegion;
ff7b1510 435}
c801d85f 436
5fc7ede9 437wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
c801d85f 438{
e1208c31
RR
439 if (!m_refData)
440 return wxOutRegion;
441
bbe0af5b
RR
442 GdkRectangle rect;
443 rect.x = x;
444 rect.y = y;
445 rect.width = w;
446 rect.height = h;
447 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
448 switch (res)
449 {
450 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
451 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
452 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
453 }
454 return wxOutRegion;
ff7b1510 455}
c801d85f 456
8429bec1
RR
457wxRegionContain wxRegion::Contains(const wxPoint& pt) const
458{
bbe0af5b 459 return Contains( pt.x, pt.y );
8429bec1
RR
460}
461
462wxRegionContain wxRegion::Contains(const wxRect& rect) const
463{
bbe0af5b 464 return Contains( rect.x, rect.y, rect.width, rect.height );
8429bec1
RR
465}
466
bf57d1ad 467GdkRegion *wxRegion::GetRegion() const
c801d85f 468{
e1208c31
RR
469 if (!m_refData)
470 return (GdkRegion*) NULL;
471
bbe0af5b 472 return M_REGIONDATA->m_region;
ff7b1510 473}
c801d85f 474
1e6feb95 475// ----------------------------------------------------------------------------
3d0c4d2e 476// wxRegionIterator
1e6feb95 477// ----------------------------------------------------------------------------
8429bec1 478
48850fa7 479#ifndef __WXGTK20__
3d0c4d2e
RR
480
481// the following structures must match the private structures
482// in X11 region code ( xc/lib/X11/region.h )
483
484// this makes the Region type transparent
485// and we have access to the region rectangles
486
48850fa7
RR
487#include <gdk/gdkprivate.h>
488
3d0c4d2e
RR
489struct _XBox {
490 short x1, x2, y1, y2;
491};
1e6feb95 492
3d0c4d2e
RR
493struct _XRegion {
494 long size , numRects;
495 _XBox *rects, extents;
496};
497
48850fa7
RR
498#endif
499
3d0c4d2e
RR
500class wxRIRefData: public wxObjectRefData
501{
502public:
3f0fb1d4
VZ
503 wxRIRefData() { Init(); }
504 virtual ~wxRIRefData();
3d0c4d2e 505
3f0fb1d4
VZ
506 void CreateRects( const wxRegion& r );
507
508 void Init() { m_rects = NULL; m_numRects = 0; }
3d0c4d2e
RR
509
510 wxRect *m_rects;
511 size_t m_numRects;
3d0c4d2e
RR
512};
513
514wxRIRefData::~wxRIRefData()
515{
64423153 516 delete [] m_rects;
3d0c4d2e
RR
517}
518
3d0c4d2e
RR
519void wxRIRefData::CreateRects( const wxRegion& region )
520{
64423153 521 delete [] m_rects;
48850fa7 522
3f0fb1d4 523 Init();
57f2b902 524
48850fa7 525 GdkRegion *gdkregion = region.GetRegion();
3f0fb1d4
VZ
526 if (!gdkregion)
527 return;
57f2b902 528
48850fa7 529#ifdef __WXGTK20__
9e691f46 530 GdkRectangle *gdkrects = NULL;
48850fa7 531 gint numRects = 0;
9e691f46 532 gdk_region_get_rectangles( gdkregion, &gdkrects, &numRects );
57f2b902 533
48850fa7
RR
534 m_numRects = numRects;
535 if (numRects)
536 {
537 m_rects = new wxRect[m_numRects];
538 for (size_t i=0; i < m_numRects; ++i)
3d0c4d2e 539 {
48850fa7
RR
540 GdkRectangle &gr = gdkrects[i];
541 wxRect &wr = m_rects[i];
542 wr.x = gr.x;
543 wr.y = gr.y;
544 wr.width = gr.width;
545 wr.height = gr.height;
3d0c4d2e 546 }
3d0c4d2e 547 }
9e691f46
VZ
548 g_free( gdkrects );
549#else // GTK+ 1.x
48850fa7
RR
550 Region r = ((GdkRegionPrivate *)gdkregion)->xregion;
551 if (r)
552 {
553 m_numRects = r->numRects;
554 if (m_numRects)
555 {
556 m_rects = new wxRect[m_numRects];
557 for (size_t i=0; i < m_numRects; ++i)
558 {
559 _XBox &xr = r->rects[i];
560 wxRect &wr = m_rects[i];
561 wr.x = xr.x1;
562 wr.y = xr.y1;
563 wr.width = xr.x2-xr.x1;
564 wr.height = xr.y2-xr.y1;
565 }
566 }
567 }
9e691f46 568#endif // GTK+ 2.0/1.x
3d0c4d2e
RR
569}
570
3d0c4d2e
RR
571wxRegionIterator::wxRegionIterator()
572{
573 m_refData = new wxRIRefData();
574 Reset();
575}
576
577wxRegionIterator::wxRegionIterator( const wxRegion& region )
578{
579 m_refData = new wxRIRefData();
580 Reset(region);
581}
582
583void wxRegionIterator::Reset( const wxRegion& region )
584{
585 m_region = region;
586 ((wxRIRefData*)m_refData)->CreateRects(region);
587 Reset();
588}
589
590bool wxRegionIterator::HaveRects() const
591{
592 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
593}
594
595wxRegionIterator::operator bool () const
596{
597 return HaveRects();
598}
599
600void wxRegionIterator::operator ++ ()
601{
602 if (HaveRects()) ++m_current;
603}
604
605void wxRegionIterator::operator ++ (int)
606{
607 if (HaveRects()) ++m_current;
608}
609
610wxCoord wxRegionIterator::GetX() const
611{
612 if( !HaveRects() ) return 0;
613 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
614}
615
616wxCoord wxRegionIterator::GetY() const
617{
618 if( !HaveRects() ) return 0;
619 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
620}
621
622wxCoord wxRegionIterator::GetW() const
623{
624 if( !HaveRects() ) return -1;
625 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
626}
627
628wxCoord wxRegionIterator::GetH() const
629{
630 if( !HaveRects() ) return -1;
631 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
632}
633
1e6feb95
VZ
634wxRect wxRegionIterator::GetRect() const
635{
636 wxRect r;
3379ed37
VZ
637 if( HaveRects() )
638 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
1e6feb95
VZ
639
640 return r;
641}
642