]> git.saurik.com Git - wxWidgets.git/blame - src/motif/region.cpp
Stupid bug in GAddress initialization prevented BCC to work. (I still
[wxWidgets.git] / src / motif / region.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// File: region.cpp
3// Purpose: Region class
f97c9854 4// Author: Markus Holzem/Julian Smart
4bb6408c 5// Created: Fri Oct 24 10:46:34 MET 1997
dfe1eee3 6// RCS-ID: $Id$
f97c9854 7// Copyright: (c) 1997 Markus Holzem/Julian Smart
4bb6408c
JS
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
f97c9854
JS
18#include <Xm/Xm.h>
19// #include "wx/motif/private.h"
20
4bb6408c 21#if !USE_SHARED_LIBRARY
dfe1eee3
VZ
22 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
23 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
4bb6408c
JS
24#endif
25
25f47127
JS
26// ----------------------------------------------------------------------------
27// list types
28// ----------------------------------------------------------------------------
29
30#include "wx/listimpl.cpp"
31
32WX_DEFINE_LIST(wxRectList);
33
4bb6408c
JS
34//-----------------------------------------------------------------------------
35// wxRegionRefData implementation
36//-----------------------------------------------------------------------------
37
38class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
39public:
dfe1eee3
VZ
40 wxRegionRefData()
41 {
42 m_region = XCreateRegion();
25f47127
JS
43 m_usingRects = FALSE;
44 m_rects = (wxRect*) NULL;
45 m_rectCount = 0;
dfe1eee3
VZ
46 }
47
48 wxRegionRefData(const wxRegionRefData& data)
49 {
50 m_region = XCreateRegion();
25f47127
JS
51 m_rects = (wxRect*) NULL;
52 m_rectCount = 0;
dfe1eee3 53 XUnionRegion(m_region, data.m_region, m_region);
25f47127
JS
54
55 SetRects(data.m_rectCount, data.m_rects);
dfe1eee3
VZ
56 }
57
58 ~wxRegionRefData()
59 {
60 XDestroyRegion(m_region);
25f47127 61 DeleteRects();
dfe1eee3 62 }
25f47127
JS
63
64 wxRect* GetRects() { return m_rects; };
65 void SetRects(const wxRectList& rectList);
66 void SetRects(int count, const wxRect* rects);
67 bool UsingRects() const { return m_usingRects; }
68 int GetRectCount() const { return m_rectCount; }
69
70 void DeleteRects();
71
72 Region m_region;
73 wxRect* m_rects;
74 int m_rectCount;
75 bool m_usingRects; // TRUE if we're using the above.
4bb6408c
JS
76};
77
25f47127
JS
78void wxRegionRefData::SetRects(const wxRectList& rectList)
79{
80 DeleteRects();
81 m_usingRects = (rectList.Number() > 0);
82 if (m_usingRects)
83 {
84 m_rectCount = rectList.Number();
85 m_rects = new wxRect[m_rectCount];
86 }
87
88 wxRectList::Node* node = rectList.GetFirst();
89 int i = 0;
90 while (node) {
91 wxRect* rect = node->GetData();
92 m_rects[i] = * rect;
93 node = node->GetNext();
94 i ++;
95 }
96}
97
98void wxRegionRefData::SetRects(int count, const wxRect* rects)
99{
100 DeleteRects();
101 m_usingRects = (count > 0);
102 if (m_usingRects)
103 {
104 m_rectCount = count;
105 m_rects = new wxRect[m_rectCount];
106 int i;
107 for (i = 0; i < m_rectCount; i++)
108 m_rects[i] = rects[i];
109 }
110}
111
112void wxRegionRefData::DeleteRects()
113{
114 if (m_rects)
115 {
116 delete[] m_rects;
117 m_rects = (wxRect*) NULL;
118 }
119 m_rectCount = 0;
120 m_usingRects = FALSE;
121 }
122
f97c9854 123#define M_REGION (((wxRegionRefData*)m_refData)->m_region)
4bb6408c
JS
124
125//-----------------------------------------------------------------------------
126// wxRegion
127//-----------------------------------------------------------------------------
128
129/*!
130 * Create an empty region.
131 */
132wxRegion::wxRegion()
133{
4bb6408c
JS
134}
135
136wxRegion::wxRegion(long x, long y, long w, long h)
137{
138 m_refData = new wxRegionRefData;
f97c9854 139
dfe1eee3
VZ
140 XRectangle rect;
141 rect.x = x;
142 rect.y = y;
143 rect.width = w;
144 rect.height = h;
145 XUnionRectWithRegion(&rect, M_REGION, M_REGION);
4bb6408c
JS
146}
147
148wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
149{
150 m_refData = new wxRegionRefData;
f97c9854 151
dfe1eee3
VZ
152 XRectangle rect;
153 rect.x = topLeft.x;
154 rect.y = topLeft.y;
155 rect.width = bottomRight.x - topLeft.x;
156 rect.height = bottomRight.y - topLeft.y;
157 XUnionRectWithRegion(&rect, M_REGION, M_REGION);
4bb6408c
JS
158}
159
160wxRegion::wxRegion(const wxRect& rect)
161{
162 m_refData = new wxRegionRefData;
f97c9854
JS
163
164 XRectangle rect1;
dfe1eee3
VZ
165 rect1.x = rect.x;
166 rect1.y = rect.y;
167 rect1.width = rect.width;
f97c9854
JS
168 rect1.height = rect.height;
169 XUnionRectWithRegion(&rect1, M_REGION, M_REGION);
4bb6408c
JS
170}
171
172/*!
173 * Destroy the region.
174 */
175wxRegion::~wxRegion()
176{
177 // m_refData unrefed in ~wxObject
178}
179
55acd85e 180// Get the internal region handle
45d49251 181WXRegion wxRegion::GetXRegion() const
55acd85e
JS
182{
183 wxASSERT( m_refData !=NULL );
184
185 return (WXRegion) ((wxRegionRefData*)m_refData)->m_region;
186}
187
4bb6408c
JS
188//-----------------------------------------------------------------------------
189//# Modify region
190//-----------------------------------------------------------------------------
191
192//! Clear current region
193void wxRegion::Clear()
194{
195 UnRef();
196}
197
198//! Combine rectangle (x, y, w, h) with this.
199bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op)
200{
dfe1eee3
VZ
201 // Don't change shared data
202 if (!m_refData) {
203 m_refData = new wxRegionRefData();
204 } else if (m_refData->GetRefCount() > 1) {
205 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
206 UnRef();
207 m_refData = new wxRegionRefData(*ref);
208 }
4bb6408c
JS
209 // If ref count is 1, that means it's 'ours' anyway so no action.
210
f97c9854
JS
211 Region rectRegion = XCreateRegion();
212
dfe1eee3
VZ
213 XRectangle rect;
214 rect.x = x;
215 rect.y = y;
216 rect.width = width;
217 rect.height = height;
218 XUnionRectWithRegion(&rect, rectRegion, rectRegion);
4bb6408c 219
4bb6408c
JS
220 switch (op)
221 {
222 case wxRGN_AND:
dfe1eee3 223 XIntersectRegion(M_REGION, rectRegion, M_REGION);
4bb6408c
JS
224 break ;
225 case wxRGN_OR:
dfe1eee3 226 XUnionRegion(M_REGION, rectRegion, M_REGION);
4bb6408c
JS
227 break ;
228 case wxRGN_XOR:
229 // TODO
230 break ;
231 case wxRGN_DIFF:
232 // TODO
233 break ;
f97c9854 234 case wxRGN_COPY: // Don't have to do this one
4bb6408c
JS
235 default:
236 // TODO
237 break ;
238 }
239
4bb6408c
JS
240 return FALSE;
241}
242
243//! Union /e region with this.
244bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
245{
dfe1eee3
VZ
246 if (region.Empty())
247 return FALSE;
248
249 // Don't change shared data
250 if (!m_refData) {
251 m_refData = new wxRegionRefData();
252 } else if (m_refData->GetRefCount() > 1) {
253 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
254 UnRef();
255 m_refData = new wxRegionRefData(*ref);
256 }
257
4bb6408c
JS
258 switch (op)
259 {
260 case wxRGN_AND:
dfe1eee3
VZ
261 XIntersectRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
262 M_REGION);
4bb6408c
JS
263 break ;
264 case wxRGN_OR:
dfe1eee3
VZ
265 XUnionRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
266 M_REGION);
4bb6408c
JS
267 break ;
268 case wxRGN_XOR:
269 // TODO
270 break ;
271 case wxRGN_DIFF:
272 // TODO
273 break ;
f97c9854 274 case wxRGN_COPY: // Don't have to do this one
4bb6408c
JS
275 default:
276 // TODO
277 break ;
278 }
279
a724d789 280 return FALSE;
4bb6408c
JS
281}
282
283bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
284{
285 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
286}
287
288//-----------------------------------------------------------------------------
289//# Information on region
290//-----------------------------------------------------------------------------
291
292// Outer bounds of region
293void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
294{
dfe1eee3
VZ
295 if (m_refData) {
296 XRectangle rect;
297 XClipBox(M_REGION, &rect);
298 x = rect.x;
299 y = rect.y;
300 w = rect.width;
301 h = rect.height;
302 } else {
303 x = y = w = h = 0;
304 }
4bb6408c
JS
305}
306
307wxRect wxRegion::GetBox() const
308{
309 long x, y, w, h;
310 GetBox(x, y, w, h);
311 return wxRect(x, y, w, h);
312}
313
314// Is region empty?
315bool wxRegion::Empty() const
316{
dfe1eee3 317 return m_refData ? XEmptyRegion(M_REGION) : TRUE;
4bb6408c
JS
318}
319
320//-----------------------------------------------------------------------------
321//# Tests
322//-----------------------------------------------------------------------------
323
324// Does the region contain the point (x,y)?
af111fc3 325wxRegionContain wxRegion::Contains(long WXUNUSED(x), long WXUNUSED(y)) const
4bb6408c 326{
dfe1eee3
VZ
327 if (!m_refData)
328 return wxOutRegion;
4bb6408c
JS
329
330 // TODO. Return wxInRegion if within region.
331 if (0)
332 return wxInRegion;
333 return wxOutRegion;
334}
335
336// Does the region contain the point pt?
337wxRegionContain wxRegion::Contains(const wxPoint& pt) const
338{
dfe1eee3
VZ
339 if (!m_refData)
340 return wxOutRegion;
4bb6408c 341
dfe1eee3 342 return XPointInRegion(M_REGION, pt.x, pt.y) ? wxInRegion : wxOutRegion;
4bb6408c
JS
343}
344
345// Does the region contain the rectangle (x, y, w, h)?
346wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
347{
dfe1eee3
VZ
348 if (!m_refData)
349 return wxOutRegion;
350
351 switch (XRectInRegion(M_REGION, x, y, w, h)) {
352 case RectangleIn: return wxInRegion;
353 case RectanglePart: return wxPartRegion;
354 }
355 return wxOutRegion;
4bb6408c
JS
356}
357
358// Does the region contain the rectangle rect
359wxRegionContain wxRegion::Contains(const wxRect& rect) const
360{
dfe1eee3
VZ
361 if (!m_refData)
362 return wxOutRegion;
4bb6408c
JS
363
364 long x, y, w, h;
365 x = rect.x;
366 y = rect.y;
367 w = rect.GetWidth();
368 h = rect.GetHeight();
369 return Contains(x, y, w, h);
370}
371
25f47127
JS
372bool wxRegion::UsingRects() const
373{
374 return ((wxRegionRefData*)m_refData)->UsingRects();
375}
376
377/*
378wxRectList& wxRegion::GetRectList()
379{
380 return ((wxRegionRefData*)m_refData)->GetRectList();
381}
382*/
383
384wxRect* wxRegion::GetRects()
385{
386 return ((wxRegionRefData*)m_refData)->GetRects();
387}
388
389int wxRegion::GetRectCount() const
390{
391 return ((wxRegionRefData*)m_refData)->GetRectCount();
392}
393
394void wxRegion::SetRects(const wxRectList& rectList)
395{
396 ((wxRegionRefData*)m_refData)->SetRects(rectList);
397}
398
399void wxRegion::SetRects(int count, const wxRect* rects)
400{
401 ((wxRegionRefData*)m_refData)->SetRects(count, rects);
402}
403
4bb6408c 404///////////////////////////////////////////////////////////////////////////////
dfe1eee3
VZ
405// //
406// wxRegionIterator //
407// //
4bb6408c
JS
408///////////////////////////////////////////////////////////////////////////////
409
410/*!
411 * Initialize empty iterator
412 */
413wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
414{
415}
416
417wxRegionIterator::~wxRegionIterator()
418{
419 if (m_rects)
420 delete[] m_rects;
421}
422
423/*!
424 * Initialize iterator for region
425 */
426wxRegionIterator::wxRegionIterator(const wxRegion& region)
427{
428 m_rects = NULL;
429
dfe1eee3 430 Reset(region);
4bb6408c
JS
431}
432
433/*!
434 * Reset iterator for a new /e region.
435 */
436void wxRegionIterator::Reset(const wxRegion& region)
437{
dfe1eee3
VZ
438 m_current = 0;
439 m_region = region;
4bb6408c
JS
440
441 if (m_rects)
442 delete[] m_rects;
443
444 m_rects = NULL;
445
dfe1eee3
VZ
446 if (m_region.Empty())
447 m_numRects = 0;
448 else
4bb6408c 449 {
25f47127
JS
450 // Create m_rects and fill with rectangles for this region.
451 // Since we can't find the rectangles in a region, we cheat
452 // by retrieving the rectangles explicitly set in wxPaintDC::wxPaintDC
453 // (dcclient.cpp).
454 if (m_region.UsingRects())
455 {
456 wxRect* rects = m_region.GetRects();
457 int count = m_region.GetRectCount();
458 m_numRects = count;
459 m_rects = new wxRect[m_numRects];
460
461 int i = 0;
462 for (i = 0; i < m_numRects; i++)
463 m_rects[i] = rects[i];
464
465 /*
466 int i = 0;
467 wxRectList::Node* node = rectList.GetFirst();
468 while (node) {
469 wxRect* rect = node->GetData();
470 m_rects[i] = * rect;
471 node = node->GetNext();
472 i ++;
473 }
474 */
475 }
476 else
477 {
478 // For now, fudge by getting the whole bounding box.
479 m_rects = new wxRect[1];
480 m_numRects = 1;
481 m_rects[0] = m_region.GetBox();
482 }
4bb6408c
JS
483 }
484}
485
486/*!
487 * Increment iterator. The rectangle returned is the one after the
488 * incrementation.
489 */
490void wxRegionIterator::operator ++ ()
491{
dfe1eee3
VZ
492 if (m_current < m_numRects)
493 ++m_current;
4bb6408c
JS
494}
495
496/*!
497 * Increment iterator. The rectangle returned is the one before the
498 * incrementation.
499 */
500void wxRegionIterator::operator ++ (int)
501{
dfe1eee3
VZ
502 if (m_current < m_numRects)
503 ++m_current;
4bb6408c
JS
504}
505
506long wxRegionIterator::GetX() const
507{
dfe1eee3
VZ
508 if (m_current < m_numRects)
509 return m_rects[m_current].x;
510 return 0;
4bb6408c
JS
511}
512
513long wxRegionIterator::GetY() const
514{
dfe1eee3
VZ
515 if (m_current < m_numRects)
516 return m_rects[m_current].y;
517 return 0;
4bb6408c
JS
518}
519
520long wxRegionIterator::GetW() const
521{
dfe1eee3
VZ
522 if (m_current < m_numRects)
523 return m_rects[m_current].width ;
524 return 0;
4bb6408c
JS
525}
526
527long wxRegionIterator::GetH() const
528{
dfe1eee3
VZ
529 if (m_current < m_numRects)
530 return m_rects[m_current].height;
531 return 0;
4bb6408c
JS
532}
533