]> git.saurik.com Git - wxWidgets.git/blame - src/motif/region.cpp
thread fixes for MSW (samples doesn't compile currently under !MSW, will
[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
JS
5// Created: Fri Oct 24 10:46:34 MET 1997
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
JS
21#if !USE_SHARED_LIBRARY
22 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
23 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
24#endif
25
26//-----------------------------------------------------------------------------
27// wxRegionRefData implementation
28//-----------------------------------------------------------------------------
29
30class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
31public:
32 wxRegionRefData()
33 {
f97c9854 34 m_region = XCreateRegion();
4bb6408c
JS
35 }
36
37 wxRegionRefData(const wxRegionRefData& data)
38 {
f97c9854
JS
39 m_region = XCreateRegion();
40 XUnionRegion(m_region, data.m_region, m_region);
4bb6408c
JS
41 }
42
43 ~wxRegionRefData()
44 {
f97c9854 45 XDestroyRegion(m_region);
4bb6408c 46 }
f97c9854 47 Region m_region;
4bb6408c
JS
48};
49
f97c9854 50#define M_REGION (((wxRegionRefData*)m_refData)->m_region)
4bb6408c
JS
51
52//-----------------------------------------------------------------------------
53// wxRegion
54//-----------------------------------------------------------------------------
55
56/*!
57 * Create an empty region.
58 */
59wxRegion::wxRegion()
60{
4bb6408c
JS
61}
62
63wxRegion::wxRegion(long x, long y, long w, long h)
64{
65 m_refData = new wxRegionRefData;
f97c9854
JS
66
67 XRectangle rect;
68 rect.x = x;
69 rect.y = y;
70 rect.width = w;
71 rect.height = h;
72 XUnionRectWithRegion(&rect, M_REGION, M_REGION);
4bb6408c
JS
73}
74
75wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
76{
77 m_refData = new wxRegionRefData;
f97c9854
JS
78
79 XRectangle rect;
80 rect.x = topLeft.x;
81 rect.y = topLeft.y;
82 rect.width = bottomRight.x - topLeft.x;
83 rect.height = bottomRight.y - topLeft.y;
84 XUnionRectWithRegion(&rect, M_REGION, M_REGION);
4bb6408c
JS
85}
86
87wxRegion::wxRegion(const wxRect& rect)
88{
89 m_refData = new wxRegionRefData;
f97c9854
JS
90
91 XRectangle rect1;
92 rect1.x = rect.x;
93 rect1.y = rect.y;
94 rect1.width = rect.width;
95 rect1.height = rect.height;
96 XUnionRectWithRegion(&rect1, M_REGION, M_REGION);
4bb6408c
JS
97}
98
99/*!
100 * Destroy the region.
101 */
102wxRegion::~wxRegion()
103{
104 // m_refData unrefed in ~wxObject
105}
106
55acd85e 107// Get the internal region handle
45d49251 108WXRegion wxRegion::GetXRegion() const
55acd85e
JS
109{
110 wxASSERT( m_refData !=NULL );
111
112 return (WXRegion) ((wxRegionRefData*)m_refData)->m_region;
113}
114
4bb6408c
JS
115//-----------------------------------------------------------------------------
116//# Modify region
117//-----------------------------------------------------------------------------
118
119//! Clear current region
120void wxRegion::Clear()
121{
122 UnRef();
123}
124
125//! Combine rectangle (x, y, w, h) with this.
126bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op)
127{
128 // Don't change shared data
129 if (!m_refData) {
130 m_refData = new wxRegionRefData();
131 } else if (m_refData->GetRefCount() > 1) {
132 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
133 UnRef();
134 m_refData = new wxRegionRefData(*ref);
135 }
136 // If ref count is 1, that means it's 'ours' anyway so no action.
137
f97c9854
JS
138 Region rectRegion = XCreateRegion();
139
140 XRectangle rect;
141 rect.x = x;
142 rect.y = y;
143 rect.width = width;
144 rect.height = height;
145 XUnionRectWithRegion(&rect, rectRegion, rectRegion);
4bb6408c
JS
146
147 int mode = 0; // TODO platform-specific code
148 switch (op)
149 {
150 case wxRGN_AND:
f97c9854 151 XIntersectRegion(M_REGION, rectRegion, M_REGION);
4bb6408c
JS
152 break ;
153 case wxRGN_OR:
f97c9854 154 XUnionRegion(M_REGION, rectRegion, M_REGION);
4bb6408c
JS
155 break ;
156 case wxRGN_XOR:
157 // TODO
158 break ;
159 case wxRGN_DIFF:
160 // TODO
161 break ;
f97c9854 162 case wxRGN_COPY: // Don't have to do this one
4bb6408c
JS
163 default:
164 // TODO
165 break ;
166 }
167
4bb6408c
JS
168 return FALSE;
169}
170
171//! Union /e region with this.
172bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
173{
174 if (region.Empty())
175 return FALSE;
176
177 // Don't change shared data
178 if (!m_refData) {
179 m_refData = new wxRegionRefData();
180 } else if (m_refData->GetRefCount() > 1) {
181 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
182 UnRef();
183 m_refData = new wxRegionRefData(*ref);
184 }
185
186 int mode = 0; // TODO platform-specific code
187 switch (op)
188 {
189 case wxRGN_AND:
f97c9854
JS
190 XIntersectRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
191 M_REGION);
4bb6408c
JS
192 break ;
193 case wxRGN_OR:
f97c9854
JS
194 XUnionRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
195 M_REGION);
4bb6408c
JS
196 break ;
197 case wxRGN_XOR:
198 // TODO
199 break ;
200 case wxRGN_DIFF:
201 // TODO
202 break ;
f97c9854 203 case wxRGN_COPY: // Don't have to do this one
4bb6408c
JS
204 default:
205 // TODO
206 break ;
207 }
208
a724d789 209 return FALSE;
4bb6408c
JS
210}
211
212bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
213{
214 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
215}
216
217//-----------------------------------------------------------------------------
218//# Information on region
219//-----------------------------------------------------------------------------
220
221// Outer bounds of region
222void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
223{
224 if (m_refData) {
f97c9854
JS
225 XRectangle rect;
226 XClipBox(M_REGION, &rect);
227 x = rect.x;
228 y = rect.y;
229 w = rect.width;
230 h = rect.height;
4bb6408c
JS
231 } else {
232 x = y = w = h = 0;
233 }
234}
235
236wxRect wxRegion::GetBox() const
237{
238 long x, y, w, h;
239 GetBox(x, y, w, h);
240 return wxRect(x, y, w, h);
241}
242
243// Is region empty?
244bool wxRegion::Empty() const
245{
55acd85e 246 return m_refData ? XEmptyRegion(M_REGION) : TRUE;
4bb6408c
JS
247}
248
249//-----------------------------------------------------------------------------
250//# Tests
251//-----------------------------------------------------------------------------
252
253// Does the region contain the point (x,y)?
254wxRegionContain wxRegion::Contains(long x, long y) const
255{
256 if (!m_refData)
257 return wxOutRegion;
258
259 // TODO. Return wxInRegion if within region.
260 if (0)
261 return wxInRegion;
262 return wxOutRegion;
263}
264
265// Does the region contain the point pt?
266wxRegionContain wxRegion::Contains(const wxPoint& pt) const
267{
268 if (!m_refData)
269 return wxOutRegion;
270
f97c9854 271 return XPointInRegion(M_REGION, pt.x, pt.y) ? wxInRegion : wxOutRegion;
4bb6408c
JS
272}
273
274// Does the region contain the rectangle (x, y, w, h)?
275wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
276{
277 if (!m_refData)
278 return wxOutRegion;
279
f97c9854
JS
280 switch (XRectInRegion(M_REGION, x, y, w, h)) {
281 case RectangleIn: return wxInRegion;
282 case RectanglePart: return wxPartRegion;
283 }
284 return wxOutRegion;
4bb6408c
JS
285}
286
287// Does the region contain the rectangle rect
288wxRegionContain wxRegion::Contains(const wxRect& rect) const
289{
290 if (!m_refData)
291 return wxOutRegion;
292
293 long x, y, w, h;
294 x = rect.x;
295 y = rect.y;
296 w = rect.GetWidth();
297 h = rect.GetHeight();
298 return Contains(x, y, w, h);
299}
300
301///////////////////////////////////////////////////////////////////////////////
302// //
303// wxRegionIterator //
304// //
305///////////////////////////////////////////////////////////////////////////////
306
307/*!
308 * Initialize empty iterator
309 */
310wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
311{
312}
313
314wxRegionIterator::~wxRegionIterator()
315{
316 if (m_rects)
317 delete[] m_rects;
318}
319
320/*!
321 * Initialize iterator for region
322 */
323wxRegionIterator::wxRegionIterator(const wxRegion& region)
324{
325 m_rects = NULL;
326
327 Reset(region);
328}
329
330/*!
331 * Reset iterator for a new /e region.
332 */
333void wxRegionIterator::Reset(const wxRegion& region)
334{
335 m_current = 0;
336 m_region = region;
337
338 if (m_rects)
339 delete[] m_rects;
340
341 m_rects = NULL;
342
343 if (m_region.Empty())
344 m_numRects = 0;
345 else
346 {
347 // TODO create m_rects and fill with rectangles for this region
348 m_numRects = 0;
349 }
350}
351
352/*!
353 * Increment iterator. The rectangle returned is the one after the
354 * incrementation.
355 */
356void wxRegionIterator::operator ++ ()
357{
358 if (m_current < m_numRects)
359 ++m_current;
360}
361
362/*!
363 * Increment iterator. The rectangle returned is the one before the
364 * incrementation.
365 */
366void wxRegionIterator::operator ++ (int)
367{
368 if (m_current < m_numRects)
369 ++m_current;
370}
371
372long wxRegionIterator::GetX() const
373{
374 if (m_current < m_numRects)
375 return m_rects[m_current].x;
376 return 0;
377}
378
379long wxRegionIterator::GetY() const
380{
381 if (m_current < m_numRects)
382 return m_rects[m_current].y;
383 return 0;
384}
385
386long wxRegionIterator::GetW() const
387{
388 if (m_current < m_numRects)
389 return m_rects[m_current].width ;
390 return 0;
391}
392
393long wxRegionIterator::GetH() const
394{
395 if (m_current < m_numRects)
396 return m_rects[m_current].height;
397 return 0;
398}
399