]> git.saurik.com Git - wxWidgets.git/blob - src/motif/region.cpp
OnEnter/OnDragOver API update (compiles, links, somewhat runs under wxGTK)
[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 switch (op)
148 {
149 case wxRGN_AND:
150 XIntersectRegion(M_REGION, rectRegion, M_REGION);
151 break ;
152 case wxRGN_OR:
153 XUnionRegion(M_REGION, rectRegion, M_REGION);
154 break ;
155 case wxRGN_XOR:
156 // TODO
157 break ;
158 case wxRGN_DIFF:
159 // TODO
160 break ;
161 case wxRGN_COPY: // Don't have to do this one
162 default:
163 // TODO
164 break ;
165 }
166
167 return FALSE;
168 }
169
170 //! Union /e region with this.
171 bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
172 {
173 if (region.Empty())
174 return FALSE;
175
176 // Don't change shared data
177 if (!m_refData) {
178 m_refData = new wxRegionRefData();
179 } else if (m_refData->GetRefCount() > 1) {
180 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
181 UnRef();
182 m_refData = new wxRegionRefData(*ref);
183 }
184
185 switch (op)
186 {
187 case wxRGN_AND:
188 XIntersectRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
189 M_REGION);
190 break ;
191 case wxRGN_OR:
192 XUnionRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
193 M_REGION);
194 break ;
195 case wxRGN_XOR:
196 // TODO
197 break ;
198 case wxRGN_DIFF:
199 // TODO
200 break ;
201 case wxRGN_COPY: // Don't have to do this one
202 default:
203 // TODO
204 break ;
205 }
206
207 return FALSE;
208 }
209
210 bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
211 {
212 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
213 }
214
215 //-----------------------------------------------------------------------------
216 //# Information on region
217 //-----------------------------------------------------------------------------
218
219 // Outer bounds of region
220 void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
221 {
222 if (m_refData) {
223 XRectangle rect;
224 XClipBox(M_REGION, &rect);
225 x = rect.x;
226 y = rect.y;
227 w = rect.width;
228 h = rect.height;
229 } else {
230 x = y = w = h = 0;
231 }
232 }
233
234 wxRect wxRegion::GetBox() const
235 {
236 long x, y, w, h;
237 GetBox(x, y, w, h);
238 return wxRect(x, y, w, h);
239 }
240
241 // Is region empty?
242 bool wxRegion::Empty() const
243 {
244 return m_refData ? XEmptyRegion(M_REGION) : TRUE;
245 }
246
247 //-----------------------------------------------------------------------------
248 //# Tests
249 //-----------------------------------------------------------------------------
250
251 // Does the region contain the point (x,y)?
252 wxRegionContain wxRegion::Contains(long x, long y) const
253 {
254 if (!m_refData)
255 return wxOutRegion;
256
257 // TODO. Return wxInRegion if within region.
258 if (0)
259 return wxInRegion;
260 return wxOutRegion;
261 }
262
263 // Does the region contain the point pt?
264 wxRegionContain wxRegion::Contains(const wxPoint& pt) const
265 {
266 if (!m_refData)
267 return wxOutRegion;
268
269 return XPointInRegion(M_REGION, pt.x, pt.y) ? wxInRegion : wxOutRegion;
270 }
271
272 // Does the region contain the rectangle (x, y, w, h)?
273 wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
274 {
275 if (!m_refData)
276 return wxOutRegion;
277
278 switch (XRectInRegion(M_REGION, x, y, w, h)) {
279 case RectangleIn: return wxInRegion;
280 case RectanglePart: return wxPartRegion;
281 }
282 return wxOutRegion;
283 }
284
285 // Does the region contain the rectangle rect
286 wxRegionContain wxRegion::Contains(const wxRect& rect) const
287 {
288 if (!m_refData)
289 return wxOutRegion;
290
291 long x, y, w, h;
292 x = rect.x;
293 y = rect.y;
294 w = rect.GetWidth();
295 h = rect.GetHeight();
296 return Contains(x, y, w, h);
297 }
298
299 ///////////////////////////////////////////////////////////////////////////////
300 // //
301 // wxRegionIterator //
302 // //
303 ///////////////////////////////////////////////////////////////////////////////
304
305 /*!
306 * Initialize empty iterator
307 */
308 wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
309 {
310 }
311
312 wxRegionIterator::~wxRegionIterator()
313 {
314 if (m_rects)
315 delete[] m_rects;
316 }
317
318 /*!
319 * Initialize iterator for region
320 */
321 wxRegionIterator::wxRegionIterator(const wxRegion& region)
322 {
323 m_rects = NULL;
324
325 Reset(region);
326 }
327
328 /*!
329 * Reset iterator for a new /e region.
330 */
331 void wxRegionIterator::Reset(const wxRegion& region)
332 {
333 m_current = 0;
334 m_region = region;
335
336 if (m_rects)
337 delete[] m_rects;
338
339 m_rects = NULL;
340
341 if (m_region.Empty())
342 m_numRects = 0;
343 else
344 {
345 // TODO create m_rects and fill with rectangles for this region
346 m_numRects = 0;
347 }
348 }
349
350 /*!
351 * Increment iterator. The rectangle returned is the one after the
352 * incrementation.
353 */
354 void wxRegionIterator::operator ++ ()
355 {
356 if (m_current < m_numRects)
357 ++m_current;
358 }
359
360 /*!
361 * Increment iterator. The rectangle returned is the one before the
362 * incrementation.
363 */
364 void wxRegionIterator::operator ++ (int)
365 {
366 if (m_current < m_numRects)
367 ++m_current;
368 }
369
370 long wxRegionIterator::GetX() const
371 {
372 if (m_current < m_numRects)
373 return m_rects[m_current].x;
374 return 0;
375 }
376
377 long wxRegionIterator::GetY() const
378 {
379 if (m_current < m_numRects)
380 return m_rects[m_current].y;
381 return 0;
382 }
383
384 long wxRegionIterator::GetW() const
385 {
386 if (m_current < m_numRects)
387 return m_rects[m_current].width ;
388 return 0;
389 }
390
391 long wxRegionIterator::GetH() const
392 {
393 if (m_current < m_numRects)
394 return m_rects[m_current].height;
395 return 0;
396 }
397