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