]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/x11/region.cpp
generate key events for Space/Enter in addition to the activate events, as wxMSW...
[wxWidgets.git] / src / x11 / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// File: region.cpp
3// Purpose: Region class
4// Author: Markus Holzem, Julian Smart, Robert Roebling
5// Created: Fri Oct 24 10:46:34 MET 1997
6// RCS-ID: $Id$
7// Copyright: (c) 1997 Markus Holzem, Julian Smart, Robert Roebling
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifdef __GNUG__
12#pragma implementation "region.h"
13#endif
14
15#include "wx/region.h"
16#include "wx/gdicmn.h"
17#include "wx/log.h"
18
19#ifdef __VMS__
20#pragma message disable nosimpint
21#endif
22#include "wx/x11/private.h"
23#include "X11/Xutil.h"
24#ifdef __VMS__
25#pragma message enable nosimpint
26#endif
27
28// ----------------------------------------------------------------------------
29// wxRegionRefData: private class containing the information about the region
30// ----------------------------------------------------------------------------
31
32class wxRegionRefData : public wxObjectRefData
33{
34public:
35 wxRegionRefData()
36 {
37 m_region = NULL;
38 }
39
40 wxRegionRefData(const wxRegionRefData& refData)
41 {
42 m_region = XCreateRegion();
43 XUnionRegion( refData.m_region, m_region, m_region );
44 }
45
46 ~wxRegionRefData()
47 {
48 if (m_region)
49 XDestroyRegion( m_region );
50 }
51
52 Region m_region;
53};
54
55// ----------------------------------------------------------------------------
56// macros
57// ----------------------------------------------------------------------------
58
59#define M_REGIONDATA ((wxRegionRefData *)m_refData)
60#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
61
62IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject);
63IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
64
65// ----------------------------------------------------------------------------
66// wxRegion construction
67// ----------------------------------------------------------------------------
68
69#define M_REGIONDATA ((wxRegionRefData *)m_refData)
70
71void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
72{
73 XRectangle rect;
74 rect.x = x;
75 rect.y = y;
76 rect.width = w;
77 rect.height = h;
78
79 m_refData = new wxRegionRefData();
80
81 M_REGIONDATA->m_region = XCreateRegion();
82 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
83}
84
85wxRegion::wxRegion( size_t n, const wxPoint *points, int fillStyle )
86{
87#if 0
88 XPoint *xpoints = new XPoint[n];
89 for ( size_t i = 0 ; i < n ; i++ )
90 {
91 xpoints[i].x = points[i].x;
92 xpoints[i].y = points[i].y;
93 }
94
95 m_refData = new wxRegionRefData();
96
97 Region* reg = gdk_region_polygon
98 (
99 gdkpoints,
100 n,
101 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
102 : GDK_EVEN_ODD_RULE
103 );
104
105 M_REGIONDATA->m_region = reg;
106
107 delete [] xpoints;
108#endif
109}
110
111wxRegion::~wxRegion()
112{
113 // m_refData unrefed in ~wxObject
114}
115
116wxObjectRefData *wxRegion::CreateRefData() const
117{
118 return new wxRegionRefData;
119}
120
121wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
122{
123 return new wxRegionRefData(*(wxRegionRefData *)data);
124}
125
126// ----------------------------------------------------------------------------
127// wxRegion comparison
128// ----------------------------------------------------------------------------
129
130bool wxRegion::operator==( const wxRegion& region )
131{
132 if (m_refData == region.m_refData) return TRUE;
133
134 if (!m_refData || !region.m_refData) return FALSE;
135
136 // compare the regions themselves, not the pointers to ref data!
137 return XEqualRegion( M_REGIONDATA->m_region,
138 M_REGIONDATA_OF(region)->m_region );
139}
140
141// ----------------------------------------------------------------------------
142// wxRegion operations
143// ----------------------------------------------------------------------------
144
145void wxRegion::Clear()
146{
147 UnRef();
148}
149
150bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
151{
152 XRectangle rect;
153 rect.x = x;
154 rect.y = y;
155 rect.width = width;
156 rect.height = height;
157
158 if (!m_refData)
159 {
160 m_refData = new wxRegionRefData();
161 M_REGIONDATA->m_region = XCreateRegion();
162 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
163 }
164 else
165 {
166 AllocExclusive();
167
168 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
169 }
170
171 return TRUE;
172}
173
174bool wxRegion::Union( const wxRect& rect )
175{
176 return Union( rect.x, rect.y, rect.width, rect.height );
177}
178
179bool wxRegion::Union( const wxRegion& region )
180{
181 if (region.IsNull())
182 return FALSE;
183
184 if (!m_refData)
185 {
186 m_refData = new wxRegionRefData();
187 M_REGIONDATA->m_region = XCreateRegion();
188 }
189 else
190 {
191 AllocExclusive();
192 }
193
194 XUnionRegion( M_REGIONDATA->m_region,
195 M_REGIONDATA_OF(region)->m_region,
196 M_REGIONDATA->m_region );
197
198 return TRUE;
199}
200
201bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
202{
203 wxRegion reg( x, y, width, height );
204
205 return Intersect( reg );
206}
207
208bool wxRegion::Intersect( const wxRect& rect )
209{
210 wxRegion reg( rect );
211
212 return Intersect( reg );
213}
214
215bool wxRegion::Intersect( const wxRegion& region )
216{
217 if (region.IsNull())
218 return FALSE;
219
220 if (!m_refData)
221 {
222 m_refData = new wxRegionRefData();
223 M_REGIONDATA->m_region = XCreateRegion();
224
225 // leave here
226 return TRUE;
227 }
228 else
229 {
230 AllocExclusive();
231 }
232
233 XIntersectRegion( M_REGIONDATA->m_region,
234 M_REGIONDATA_OF(region)->m_region,
235 M_REGIONDATA->m_region );
236
237 return TRUE;
238}
239
240bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
241{
242 wxRegion reg( x, y, width, height );
243 return Subtract( reg );
244}
245
246bool wxRegion::Subtract( const wxRect& rect )
247{
248 wxRegion reg( rect );
249 return Subtract( reg );
250}
251
252bool wxRegion::Subtract( const wxRegion& region )
253{
254 if (region.IsNull())
255 return FALSE;
256
257 if (!m_refData)
258 {
259 m_refData = new wxRegionRefData();
260 M_REGIONDATA->m_region = XCreateRegion();
261 }
262 else
263 {
264 AllocExclusive();
265 }
266
267 XSubtractRegion( M_REGIONDATA->m_region,
268 M_REGIONDATA_OF(region)->m_region,
269 M_REGIONDATA->m_region );
270
271 return TRUE;
272}
273
274bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
275{
276 wxRegion reg( x, y, width, height );
277 return Xor( reg );
278}
279
280bool wxRegion::Xor( const wxRect& rect )
281{
282 wxRegion reg( rect );
283 return Xor( reg );
284}
285
286bool wxRegion::Xor( const wxRegion& region )
287{
288 if (region.IsNull())
289 return FALSE;
290
291 if (!m_refData)
292 {
293 m_refData = new wxRegionRefData();
294 M_REGIONDATA->m_region = XCreateRegion();
295 }
296 else
297 {
298 AllocExclusive();
299 }
300
301 XXorRegion( M_REGIONDATA->m_region,
302 M_REGIONDATA_OF(region)->m_region,
303 M_REGIONDATA->m_region );
304
305 return TRUE;
306}
307
308// ----------------------------------------------------------------------------
309// wxRegion tests
310// ----------------------------------------------------------------------------
311
312void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
313{
314 if (m_refData)
315 {
316 XRectangle rect;
317 XClipBox( M_REGIONDATA->m_region, &rect );
318 x = rect.x;
319 y = rect.y;
320 w = rect.width;
321 h = rect.height;
322 }
323 else
324 {
325 x = 0;
326 y = 0;
327 w = -1;
328 h = -1;
329 }
330}
331
332wxRect wxRegion::GetBox() const
333{
334 wxCoord x, y, w, h;
335 GetBox( x, y, w, h );
336 return wxRect( x, y, w, h );
337}
338
339bool wxRegion::Offset( wxCoord x, wxCoord y )
340{
341 if (!m_refData)
342 return FALSE;
343
344 AllocExclusive();
345
346 XOffsetRegion( M_REGIONDATA->m_region, x, y );
347
348 return TRUE;
349}
350
351bool wxRegion::Empty() const
352{
353 if (!m_refData)
354 return TRUE;
355
356 return XEmptyRegion( M_REGIONDATA->m_region );
357}
358
359wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
360{
361 if (!m_refData)
362 return wxOutRegion;
363
364 if (XPointInRegion( M_REGIONDATA->m_region, x, y ))
365 return wxInRegion;
366 else
367 return wxOutRegion;
368}
369
370wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
371{
372 if (!m_refData)
373 return wxOutRegion;
374
375 int res = XRectInRegion( M_REGIONDATA->m_region, x, y, w, h );
376 switch (res)
377 {
378 case RectangleIn: return wxInRegion;
379 case RectangleOut: return wxOutRegion;
380 case RectanglePart: return wxPartRegion;
381 }
382 return wxOutRegion;
383}
384
385wxRegionContain wxRegion::Contains(const wxPoint& pt) const
386{
387 return Contains( pt.x, pt.y );
388}
389
390wxRegionContain wxRegion::Contains(const wxRect& rect) const
391{
392 return Contains( rect.x, rect.y, rect.width, rect.height );
393}
394
395WXRegion *wxRegion::GetX11Region() const
396{
397 if (!m_refData)
398 return (WXRegion*) NULL;
399
400 return (WXRegion*) M_REGIONDATA->m_region;
401}
402
403// ----------------------------------------------------------------------------
404// wxRegionIterator
405// ----------------------------------------------------------------------------
406
407// the following structures must match the private structures
408// in X11 region code ( xc/lib/X11/region.h )
409
410// this makes the Region type transparent
411// and we have access to the region rectangles
412
413struct _XBox {
414 short x1, x2, y1, y2;
415};
416
417struct _XRegion {
418 long size , numRects;
419 _XBox *rects, extents;
420};
421
422class wxRIRefData: public wxObjectRefData
423{
424public:
425
426 wxRIRefData() : m_rects(0), m_numRects(0){}
427 ~wxRIRefData();
428
429 wxRect *m_rects;
430 size_t m_numRects;
431
432 void CreateRects( const wxRegion& r );
433};
434
435wxRIRefData::~wxRIRefData()
436{
437 delete [] m_rects;
438}
439
440void wxRIRefData::CreateRects( const wxRegion& region )
441{
442 if (m_rects)
443 delete [] m_rects;
444
445 m_rects = 0;
446 m_numRects = 0;
447
448 if (region.IsEmpty()) return;
449
450 Region r = (Region) region.GetX11Region();
451 if (r)
452 {
453#if wxUSE_NANOX
454 GR_RECT rect;
455 GrGetRegionBox(r, & rect);
456 m_numRects = 1;
457 m_rects = new wxRect[1];
458 m_rects[0].x = rect.x;
459 m_rects[0].y = rect.y;
460 m_rects[0].width = rect.width;
461 m_rects[0].height = rect.height;
462#else
463 m_numRects = r->numRects;
464 if (m_numRects)
465 {
466 m_rects = new wxRect[m_numRects];
467 for (size_t i=0; i < m_numRects; ++i)
468 {
469 _XBox &xr = r->rects[i];
470 wxRect &wr = m_rects[i];
471 wr.x = xr.x1;
472 wr.y = xr.y1;
473 wr.width = xr.x2-xr.x1;
474 wr.height = xr.y2-xr.y1;
475 }
476 }
477#endif
478 }
479}
480
481wxRegionIterator::wxRegionIterator()
482{
483 m_refData = new wxRIRefData();
484 Reset();
485}
486
487wxRegionIterator::wxRegionIterator( const wxRegion& region )
488{
489 m_refData = new wxRIRefData();
490 Reset(region);
491}
492
493void wxRegionIterator::Reset( const wxRegion& region )
494{
495 m_region = region;
496 ((wxRIRefData*)m_refData)->CreateRects(region);
497 Reset();
498}
499
500bool wxRegionIterator::HaveRects() const
501{
502 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
503}
504
505wxRegionIterator::operator bool () const
506{
507 return HaveRects();
508}
509
510void wxRegionIterator::operator ++ ()
511{
512 if (HaveRects()) ++m_current;
513}
514
515void wxRegionIterator::operator ++ (int)
516{
517 if (HaveRects()) ++m_current;
518}
519
520wxCoord wxRegionIterator::GetX() const
521{
522 if( !HaveRects() ) return 0;
523 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
524}
525
526wxCoord wxRegionIterator::GetY() const
527{
528 if( !HaveRects() ) return 0;
529 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
530}
531
532wxCoord wxRegionIterator::GetW() const
533{
534 if( !HaveRects() ) return -1;
535 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
536}
537
538wxCoord wxRegionIterator::GetH() const
539{
540 if( !HaveRects() ) return -1;
541 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
542}
543
544wxRect wxRegionIterator::GetRect() const
545{
546 wxRect r;
547 if( HaveRects() )
548 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
549
550 return r;
551}
552