]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/region.cpp
forced redraw before scrolling
[wxWidgets.git] / src / gtk / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: gtk/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// Unfortunately the new way of implementing the region iterator
20// doesn't work with GTK+ 2.0 or above (can't access a Region in
21// GdkPrivateRegion)
22#ifdef __WXGTK20__
23#define OLDCODE 1
24#else
25#define OLDCODE 0
26#endif
27
28//-----------------------------------------------------------------------------
29// wxRegion
30//-----------------------------------------------------------------------------
31
32class wxRegionRefData: public wxObjectRefData
33{
34public:
35 wxRegionRefData();
36 ~wxRegionRefData();
37
38 GdkRegion *m_region;
39#if OLDCODE
40 wxList m_rects;
41#endif
42};
43
44wxRegionRefData::wxRegionRefData()
45{
46 m_region = (GdkRegion *) NULL;
47}
48
49wxRegionRefData::~wxRegionRefData()
50{
51 if (m_region) gdk_region_destroy( m_region );
52
53#if OLDCODE
54 wxNode *node = m_rects.First();
55 while (node)
56 {
57 wxRect *r = (wxRect*)node->Data();
58 delete r;
59 node = node->Next();
60 }
61#endif
62}
63
64//-----------------------------------------------------------------------------
65
66#define M_REGIONDATA ((wxRegionRefData *)m_refData)
67
68IMPLEMENT_DYNAMIC_CLASS(wxRegion,wxGDIObject);
69
70wxRegion::wxRegion( wxCoord x, wxCoord y, wxCoord w, wxCoord h )
71{
72 m_refData = new wxRegionRefData();
73 GdkRegion *reg = gdk_region_new();
74 GdkRectangle rect;
75 rect.x = x;
76 rect.y = y;
77 rect.width = w;
78 rect.height = h;
79#ifdef __WXGTK20__
80 gdk_region_union_with_rect( reg, &rect );
81 M_REGIONDATA->m_region = reg;
82#else
83 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
84 gdk_region_destroy( reg );
85#endif
86#if OLDCODE
87 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,w,h) );
88#endif
89}
90
91wxRegion::wxRegion( const wxPoint& topLeft, const wxPoint& bottomRight )
92{
93 m_refData = new wxRegionRefData();
94 GdkRegion *reg = gdk_region_new();
95 GdkRectangle rect;
96 rect.x = topLeft.x;
97 rect.y = topLeft.y;
98 rect.width = bottomRight.x - rect.x;
99 rect.height = bottomRight.y - rect.y;
100#ifdef __WXGTK20__
101 gdk_region_union_with_rect( reg, &rect );
102 M_REGIONDATA->m_region = reg;
103#else
104 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
105 gdk_region_destroy( reg );
106#endif
107#if OLDCODE
108 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(topLeft,bottomRight) );
109#endif
110}
111
112wxRegion::wxRegion( const wxRect& rect )
113{
114 m_refData = new wxRegionRefData();
115 GdkRegion *reg = gdk_region_new();
116 GdkRectangle g_rect;
117 g_rect.x = rect.x;
118 g_rect.y = rect.y;
119 g_rect.width = rect.width;
120 g_rect.height = rect.height;
121#ifdef __WXGTK20__
122 gdk_region_union_with_rect( reg, &g_rect );
123 M_REGIONDATA->m_region = reg;
124#else
125 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &g_rect );
126 gdk_region_destroy( reg );
127#endif
128#if OLDCODE
129 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(rect.x,rect.y,rect.width,rect.height) );
130#endif
131}
132
133wxRegion::wxRegion()
134{
135}
136
137wxRegion::~wxRegion()
138{
139}
140
141bool wxRegion::operator == ( const wxRegion& region )
142{
143 return m_refData == region.m_refData;
144}
145
146bool wxRegion::operator != ( const wxRegion& region )
147{
148 return m_refData != region.m_refData;
149}
150
151void wxRegion::Clear()
152{
153 UnRef();
154}
155
156bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
157{
158 GdkRectangle rect;
159 rect.x = x;
160 rect.y = y;
161 rect.width = width;
162 rect.height = height;
163 if (!m_refData)
164 {
165 m_refData = new wxRegionRefData();
166 GdkRegion *reg = gdk_region_new();
167#ifdef __WXGTK20__
168 gdk_region_union_with_rect( reg, &rect );
169 M_REGIONDATA->m_region = reg;
170#else
171 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
172 gdk_region_destroy( reg );
173#endif
174 }
175 else
176 {
177#ifdef __WXGTK20__
178 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
179#else
180 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
181 gdk_region_destroy( M_REGIONDATA->m_region );
182 M_REGIONDATA->m_region = reg;
183#endif
184 }
185
186#if OLDCODE
187 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,width,height) );
188#endif
189
190 return TRUE;
191}
192
193bool wxRegion::Union( const wxRect& rect )
194{
195 return Union( rect.x, rect.y, rect.width, rect.height );
196}
197
198bool wxRegion::Union( const wxRegion& region )
199{
200 if (region.IsNull())
201 return FALSE;
202
203 if (!m_refData)
204 {
205 m_refData = new wxRegionRefData();
206 M_REGIONDATA->m_region = gdk_region_new();
207 }
208
209#ifdef __WXGTK20__
210 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
211#else
212 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
213 gdk_region_destroy( M_REGIONDATA->m_region );
214 M_REGIONDATA->m_region = reg;
215#endif
216
217#if OLDCODE
218 wxNode *node = region.GetRectList()->First();
219 while (node)
220 {
221 wxRect *r = (wxRect*)node->Data();
222 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
223 node = node->Next();
224 }
225#endif
226
227 return TRUE;
228}
229
230bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
231{
232 if (!m_refData)
233 {
234 m_refData = new wxRegionRefData();
235 M_REGIONDATA->m_region = gdk_region_new();
236 }
237
238 wxRegion reg( x, y, width, height );
239 Intersect( reg );
240 return TRUE;
241}
242
243bool wxRegion::Intersect( const wxRect& rect )
244{
245 if (!m_refData)
246 {
247 m_refData = new wxRegionRefData();
248 M_REGIONDATA->m_region = gdk_region_new();
249 }
250
251 wxRegion reg( rect );
252 Intersect( reg );
253 return TRUE;
254}
255
256bool wxRegion::Intersect( const wxRegion& region )
257{
258 if (region.IsNull())
259 return FALSE;
260
261 if (!m_refData)
262 {
263 m_refData = new wxRegionRefData();
264 M_REGIONDATA->m_region = gdk_region_new();
265 return TRUE;
266 }
267
268#ifdef __WXGTK20__
269 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
270#else
271 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
272 gdk_region_destroy( M_REGIONDATA->m_region );
273 M_REGIONDATA->m_region = reg;
274#endif
275 return TRUE;
276}
277
278bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
279{
280 if (!m_refData)
281 {
282 m_refData = new wxRegionRefData();
283 M_REGIONDATA->m_region = gdk_region_new();
284 }
285
286 wxRegion reg( x, y, width, height );
287 Subtract( reg );
288 return TRUE;
289}
290
291bool wxRegion::Subtract( const wxRect& rect )
292{
293 if (!m_refData)
294 {
295 m_refData = new wxRegionRefData();
296 M_REGIONDATA->m_region = gdk_region_new();
297 }
298
299 wxRegion reg( rect );
300 Subtract( reg );
301 return TRUE;
302}
303
304bool wxRegion::Subtract( const wxRegion& region )
305{
306 if (region.IsNull())
307 return FALSE;
308
309 if (!m_refData)
310 {
311 m_refData = new wxRegionRefData();
312 M_REGIONDATA->m_region = gdk_region_new();
313 }
314
315#ifdef __WXGTK20__
316 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
317#else
318 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
319 gdk_region_destroy( M_REGIONDATA->m_region );
320 M_REGIONDATA->m_region = reg;
321#endif
322 return TRUE;
323}
324
325bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
326{
327 if (!m_refData)
328 {
329 m_refData = new wxRegionRefData();
330 M_REGIONDATA->m_region = gdk_region_new();
331 }
332
333 wxRegion reg( x, y, width, height );
334 Xor( reg );
335 return TRUE;
336}
337
338bool wxRegion::Xor( const wxRect& rect )
339{
340 if (!m_refData)
341 {
342 m_refData = new wxRegionRefData();
343 M_REGIONDATA->m_region = gdk_region_new();
344 }
345
346 wxRegion reg( rect );
347 Xor( reg );
348 return TRUE;
349}
350
351bool wxRegion::Xor( const wxRegion& region )
352{
353 if (region.IsNull())
354 return FALSE;
355
356 if (!m_refData)
357 {
358 m_refData = new wxRegionRefData();
359 M_REGIONDATA->m_region = gdk_region_new();
360 }
361
362#ifdef __WXGTK20__
363 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
364#else
365 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
366 gdk_region_destroy( M_REGIONDATA->m_region );
367 M_REGIONDATA->m_region = reg;
368#endif
369
370#if OLDCODE
371 wxNode *node = region.GetRectList()->First();
372 while (node)
373 {
374 wxRect *r = (wxRect*)node->Data();
375 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
376 node = node->Next();
377 }
378#endif
379
380 return TRUE;
381}
382
383void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
384{
385 x = 0;
386 y = 0;
387 w = -1;
388 h = -1;
389 if (!m_refData)
390 return;
391
392 GdkRectangle rect;
393 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
394 x = rect.x;
395 y = rect.y;
396 w = rect.width;
397 h = rect.height;
398}
399
400wxRect wxRegion::GetBox() const
401{
402 wxCoord x = 0;
403 wxCoord y = 0;
404 wxCoord w = -1;
405 wxCoord h = -1;
406 GetBox( x, y, w, h );
407 return wxRect( x, y, w, h );
408}
409
410bool wxRegion::Empty() const
411{
412 if (!m_refData)
413 return TRUE;
414
415 return gdk_region_empty( M_REGIONDATA->m_region );
416}
417
418wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
419{
420 if (!m_refData)
421 return wxOutRegion;
422
423 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
424 return wxInRegion;
425 else
426 return wxOutRegion;
427}
428
429wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
430{
431 if (!m_refData)
432 return wxOutRegion;
433
434 GdkRectangle rect;
435 rect.x = x;
436 rect.y = y;
437 rect.width = w;
438 rect.height = h;
439 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
440 switch (res)
441 {
442 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
443 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
444 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
445 }
446 return wxOutRegion;
447}
448
449wxRegionContain wxRegion::Contains(const wxPoint& pt) const
450{
451 return Contains( pt.x, pt.y );
452}
453
454wxRegionContain wxRegion::Contains(const wxRect& rect) const
455{
456 return Contains( rect.x, rect.y, rect.width, rect.height );
457}
458
459GdkRegion *wxRegion::GetRegion() const
460{
461 if (!m_refData)
462 return (GdkRegion*) NULL;
463
464 return M_REGIONDATA->m_region;
465}
466
467wxList *wxRegion::GetRectList() const
468{
469#if OLDCODE
470 if (!m_refData)
471 return (wxList*) NULL;
472
473 return &(M_REGIONDATA->m_rects);
474#else
475 return (wxList*) NULL;
476#endif
477}
478
479//-----------------------------------------------------------------------------
480// wxRegionIterator
481//-----------------------------------------------------------------------------
482
483#if OLDCODE
484
485IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
486
487wxRegionIterator::wxRegionIterator()
488{
489 Reset();
490}
491
492wxRegionIterator::wxRegionIterator( const wxRegion& region )
493{
494 Reset(region);
495}
496
497void wxRegionIterator::Reset( const wxRegion& region )
498{
499 m_region = region;
500 Reset();
501}
502
503wxRegionIterator::operator bool () const
504{
505 return m_region.GetRectList() && m_current < (size_t)m_region.GetRectList()->Number();
506}
507
508bool wxRegionIterator::HaveRects() const
509{
510 return m_region.GetRectList() && m_current < (size_t)m_region.GetRectList()->Number();
511}
512
513void wxRegionIterator::operator ++ ()
514{
515 if (HaveRects()) ++m_current;
516}
517
518void wxRegionIterator::operator ++ (int)
519{
520 if (HaveRects()) ++m_current;
521}
522
523wxCoord wxRegionIterator::GetX() const
524{
525 wxNode *node = m_region.GetRectList()->Nth( m_current );
526 if (!node) return 0;
527 wxRect *r = (wxRect*)node->Data();
528 return r->x;
529}
530
531wxCoord wxRegionIterator::GetY() const
532{
533 wxNode *node = m_region.GetRectList()->Nth( m_current );
534 if (!node) return 0;
535 wxRect *r = (wxRect*)node->Data();
536 return r->y;
537}
538
539wxCoord wxRegionIterator::GetW() const
540{
541 wxNode *node = m_region.GetRectList()->Nth( m_current );
542 if (!node) return 0;
543 wxRect *r = (wxRect*)node->Data();
544 return r->width;
545}
546
547wxCoord wxRegionIterator::GetH() const
548{
549 wxNode *node = m_region.GetRectList()->Nth( m_current );
550 if (!node) return 0;
551 wxRect *r = (wxRect*)node->Data();
552 return r->height;
553}
554
555#else
556
557// the following structures must match the private structures
558// in X11 region code ( xc/lib/X11/region.h )
559
560// this makes the Region type transparent
561// and we have access to the region rectangles
562
563struct _XBox {
564 short x1, x2, y1, y2;
565};
566
567struct _XRegion {
568 long size , numRects;
569 _XBox *rects, extents;
570};
571
572class wxRIRefData: public wxObjectRefData
573{
574public:
575
576 wxRIRefData() : m_rects(0), m_numRects(0){}
577 ~wxRIRefData();
578
579 wxRect *m_rects;
580 size_t m_numRects;
581
582 void CreateRects( const wxRegion& r );
583};
584
585wxRIRefData::~wxRIRefData()
586{
587 delete m_rects;
588}
589
590#include <gdk/gdkprivate.h>
591
592void wxRIRefData::CreateRects( const wxRegion& region )
593{
594 if( m_rects )
595 delete m_rects;
596 m_rects = 0;
597 m_numRects= 0;
598 GdkRegion *gdkregion= region.GetRegion();
599 if( gdkregion ){
600 Region r= ((GdkRegionPrivate *)gdkregion)->xregion;
601 if( r ){
602 m_numRects= r->numRects;
603 if( m_numRects )
604 {
605 m_rects= new wxRect[m_numRects];
606 for( size_t i=0; i<m_numRects; ++i )
607 {
608 _XBox &xr= r->rects[i];
609 wxRect&wr= m_rects[i];
610 wr.x = xr.x1;
611 wr.y = xr.y1;
612 wr.width = xr.x2-xr.x1;
613 wr.height= xr.y2-xr.y1;
614 }
615 }
616 }
617 }
618}
619
620IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
621
622wxRegionIterator::wxRegionIterator()
623{
624 m_refData = new wxRIRefData();
625 Reset();
626}
627
628wxRegionIterator::wxRegionIterator( const wxRegion& region )
629{
630 m_refData = new wxRIRefData();
631 Reset(region);
632}
633
634void wxRegionIterator::Reset( const wxRegion& region )
635{
636 m_region = region;
637 ((wxRIRefData*)m_refData)->CreateRects(region);
638 Reset();
639}
640
641bool wxRegionIterator::HaveRects() const
642{
643 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
644}
645
646wxRegionIterator::operator bool () const
647{
648 return HaveRects();
649}
650
651void wxRegionIterator::operator ++ ()
652{
653 if (HaveRects()) ++m_current;
654}
655
656void wxRegionIterator::operator ++ (int)
657{
658 if (HaveRects()) ++m_current;
659}
660
661wxCoord wxRegionIterator::GetX() const
662{
663 if( !HaveRects() ) return 0;
664 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
665}
666
667wxCoord wxRegionIterator::GetY() const
668{
669 if( !HaveRects() ) return 0;
670 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
671}
672
673wxCoord wxRegionIterator::GetW() const
674{
675 if( !HaveRects() ) return -1;
676 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
677}
678
679wxCoord wxRegionIterator::GetH() const
680{
681 if( !HaveRects() ) return -1;
682 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
683}
684
685#endif
686