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