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