]> git.saurik.com Git - wxWidgets.git/blob - src/motif/region.cpp
wxWindow::Fit() infinite loop bug fixed
[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 // Get the internal region handle
108 WXRegion wxRegion::GetXRegion() const
109 {
110 wxASSERT( m_refData !=NULL );
111
112 return (WXRegion) ((wxRegionRefData*)m_refData)->m_region;
113 }
114
115 //-----------------------------------------------------------------------------
116 //# Modify region
117 //-----------------------------------------------------------------------------
118
119 //! Clear current region
120 void wxRegion::Clear()
121 {
122 UnRef();
123 }
124
125 //! Combine rectangle (x, y, w, h) with this.
126 bool 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
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);
146
147 int mode = 0; // TODO platform-specific code
148 switch (op)
149 {
150 case wxRGN_AND:
151 XIntersectRegion(M_REGION, rectRegion, M_REGION);
152 break ;
153 case wxRGN_OR:
154 XUnionRegion(M_REGION, rectRegion, M_REGION);
155 break ;
156 case wxRGN_XOR:
157 // TODO
158 break ;
159 case wxRGN_DIFF:
160 // TODO
161 break ;
162 case wxRGN_COPY: // Don't have to do this one
163 default:
164 // TODO
165 break ;
166 }
167
168 return FALSE;
169 }
170
171 //! Union /e region with this.
172 bool 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:
190 XIntersectRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
191 M_REGION);
192 break ;
193 case wxRGN_OR:
194 XUnionRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
195 M_REGION);
196 break ;
197 case wxRGN_XOR:
198 // TODO
199 break ;
200 case wxRGN_DIFF:
201 // TODO
202 break ;
203 case wxRGN_COPY: // Don't have to do this one
204 default:
205 // TODO
206 break ;
207 }
208
209 return FALSE;
210 }
211
212 bool 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
222 void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
223 {
224 if (m_refData) {
225 XRectangle rect;
226 XClipBox(M_REGION, &rect);
227 x = rect.x;
228 y = rect.y;
229 w = rect.width;
230 h = rect.height;
231 } else {
232 x = y = w = h = 0;
233 }
234 }
235
236 wxRect 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?
244 bool wxRegion::Empty() const
245 {
246 return m_refData ? XEmptyRegion(M_REGION) : TRUE;
247 }
248
249 //-----------------------------------------------------------------------------
250 //# Tests
251 //-----------------------------------------------------------------------------
252
253 // Does the region contain the point (x,y)?
254 wxRegionContain 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?
266 wxRegionContain wxRegion::Contains(const wxPoint& pt) const
267 {
268 if (!m_refData)
269 return wxOutRegion;
270
271 return XPointInRegion(M_REGION, pt.x, pt.y) ? wxInRegion : wxOutRegion;
272 }
273
274 // Does the region contain the rectangle (x, y, w, h)?
275 wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
276 {
277 if (!m_refData)
278 return wxOutRegion;
279
280 switch (XRectInRegion(M_REGION, x, y, w, h)) {
281 case RectangleIn: return wxInRegion;
282 case RectanglePart: return wxPartRegion;
283 }
284 return wxOutRegion;
285 }
286
287 // Does the region contain the rectangle rect
288 wxRegionContain 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 */
310 wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
311 {
312 }
313
314 wxRegionIterator::~wxRegionIterator()
315 {
316 if (m_rects)
317 delete[] m_rects;
318 }
319
320 /*!
321 * Initialize iterator for region
322 */
323 wxRegionIterator::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 */
333 void 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 */
356 void 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 */
366 void wxRegionIterator::operator ++ (int)
367 {
368 if (m_current < m_numRects)
369 ++m_current;
370 }
371
372 long wxRegionIterator::GetX() const
373 {
374 if (m_current < m_numRects)
375 return m_rects[m_current].x;
376 return 0;
377 }
378
379 long wxRegionIterator::GetY() const
380 {
381 if (m_current < m_numRects)
382 return m_rects[m_current].y;
383 return 0;
384 }
385
386 long wxRegionIterator::GetW() const
387 {
388 if (m_current < m_numRects)
389 return m_rects[m_current].width ;
390 return 0;
391 }
392
393 long wxRegionIterator::GetH() const
394 {
395 if (m_current < m_numRects)
396 return m_rects[m_current].height;
397 return 0;
398 }
399