]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/region.cpp
generate key events for Space/Enter in addition to the activate events, as wxMSW...
[wxWidgets.git] / src / mgl / region.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: region.cpp
3 // Purpose: Region handling for wxWindows/MGL
4 // Author: Vaclav Slavik
5 // RCS-ID: $Id$
6 // Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "region.h"
12 #endif
13
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #include "wx/region.h"
22 #include "wx/gdicmn.h"
23 #include "wx/thread.h"
24
25 #include <mgraph.hpp>
26
27 #include "wx/listimpl.cpp"
28 WX_DEFINE_LIST(wxRegionRectList)
29
30 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
31 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
32
33 //-----------------------------------------------------------------------------
34 // wxRegionRefData implementation
35 //-----------------------------------------------------------------------------
36
37 class WXDLLEXPORT wxRegionRefData : public wxGDIRefData
38 {
39 public:
40 wxRegionRefData() {}
41
42 wxRegionRefData(const wxRegionRefData& data)
43 {
44 m_region = data.m_region;
45 }
46
47 ~wxRegionRefData() {}
48
49 MGLRegion m_region;
50 };
51
52 #define M_REGION (((wxRegionRefData*)m_refData)->m_region)
53 #define M_REGION_OF(r) (((wxRegionRefData*)(r.m_refData))->m_region)
54
55 //-----------------------------------------------------------------------------
56 // wxRegion
57 //-----------------------------------------------------------------------------
58
59 wxObjectRefData *wxRegion::CreateRefData() const
60 {
61 return new wxRegionRefData;
62 }
63
64 wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
65 {
66 return new wxRegionRefData(*(wxRegionRefData *)data);
67 }
68
69 /*
70 * Create an empty region.
71 */
72 wxRegion::wxRegion()
73 {
74 m_refData = NULL;
75 }
76
77 wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
78 {
79 m_refData = new wxRegionRefData;
80 MGLRect rect(x, y, x + w, y + h);
81 M_REGION = rect;
82 }
83
84 wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
85 {
86 m_refData = new wxRegionRefData;
87 MGLRect rect(topLeft.x, topLeft.y, bottomRight.x+1, bottomRight.y+1);
88 M_REGION = rect;
89 }
90
91 wxRegion::wxRegion(const wxRect& r)
92 {
93 m_refData = new wxRegionRefData;
94 MGLRect rect(r.GetLeft(), r.GetTop(), r.GetRight()+1, r.GetBottom()+1);
95 M_REGION = rect;
96 }
97
98 wxRegion::wxRegion(const MGLRegion& region)
99 {
100 m_refData = new wxRegionRefData;
101 M_REGION = region;
102 }
103
104 wxRegion::~wxRegion()
105 {
106 // m_refData unrefed in ~wxObject
107 }
108
109 const MGLRegion& wxRegion::GetMGLRegion() const
110 {
111 return M_REGION;
112 }
113
114 //-----------------------------------------------------------------------------
115 // Modify region
116 //-----------------------------------------------------------------------------
117
118 // Clear current region
119 void wxRegion::Clear()
120 {
121 UnRef();
122 }
123
124
125 //-----------------------------------------------------------------------------
126 // Information on region
127 //-----------------------------------------------------------------------------
128
129 // Outer bounds of region
130 void wxRegion::GetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
131 {
132 if (m_refData)
133 {
134 rect_t rect;
135 rect = M_REGION.getBounds();
136 x = rect.left;
137 y = rect.top;
138 w = rect.right - rect.left;
139 h = rect.bottom - rect.top;
140 }
141 else
142 {
143 x = y = w = h = 0;
144 }
145 }
146
147 wxRect wxRegion::GetBox() const
148 {
149 wxCoord x, y, w, h;
150 GetBox(x, y, w, h);
151 return wxRect(x, y, w, h);
152 }
153
154 // Is region empty?
155 bool wxRegion::Empty() const
156 {
157 if (!m_refData) return TRUE;
158 return M_REGION.isEmpty();
159 }
160
161 //-----------------------------------------------------------------------------
162 // Modifications
163 //-----------------------------------------------------------------------------
164
165 bool wxRegion::Offset(wxCoord x, wxCoord y)
166 {
167 AllocExclusive();
168 M_REGION.offset(x, y);
169 return TRUE;
170 }
171
172 // Union rectangle or region with this.
173 bool wxRegion::Union(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
174 {
175 AllocExclusive();
176 M_REGION += MGLRect(x, y, x + width, y + height);
177 return TRUE;
178 }
179
180 bool wxRegion::Union(const wxRegion& region)
181 {
182 AllocExclusive();
183 M_REGION += M_REGION_OF(region);
184 return TRUE;
185 }
186
187 // Intersect rectangle or region with this.
188 bool wxRegion::Intersect(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
189 {
190 AllocExclusive();
191 M_REGION &= MGLRect(x, y, x + width, y + height);
192 return TRUE;
193 }
194
195 bool wxRegion::Intersect(const wxRegion& region)
196 {
197 AllocExclusive();
198 M_REGION &= M_REGION_OF(region);
199 return TRUE;
200 }
201
202 // Subtract rectangle or region from this:
203 // Combines the parts of 'this' that are not part of the second region.
204 bool wxRegion::Subtract(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
205 {
206 AllocExclusive();
207 M_REGION -= MGLRect(x, y, x + width, y + height);
208 return TRUE;
209 }
210
211 bool wxRegion::Subtract(const wxRegion& region)
212 {
213 AllocExclusive();
214 M_REGION -= M_REGION_OF(region);
215 return TRUE;
216 }
217
218 // XOR: the union of two combined regions except for any overlapping areas.
219 bool wxRegion::Xor(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
220 {
221 AllocExclusive();
222 MGLRect rect(x, y, x + width, y + height);
223 MGLRegion rg1 = M_REGION + rect,
224 rg2 = M_REGION & rect;
225 M_REGION = rg1 - rg2;
226 return TRUE;
227 }
228
229 bool wxRegion::Xor(const wxRegion& region)
230 {
231 AllocExclusive();
232 MGLRegion rg1 = M_REGION + M_REGION_OF(region),
233 rg2 = M_REGION & M_REGION_OF(region);
234 M_REGION = rg1 - rg2;
235 return TRUE;
236 }
237
238
239 //-----------------------------------------------------------------------------
240 // Tests
241 //-----------------------------------------------------------------------------
242
243 // Does the region contain the point (x,y)?
244 wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y) const
245 {
246 if (!m_refData)
247 return wxOutRegion;
248
249 if (M_REGION.includes((int)x, (int)y))
250 return wxInRegion;
251 else
252 return wxOutRegion;
253 }
254
255 // Does the region contain the point pt?
256 wxRegionContain wxRegion::Contains(const wxPoint& pt) const
257 {
258 return Contains(pt.x, pt.y);
259 }
260
261 // Does the region contain the rectangle (x, y, w, h)?
262 wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y, wxCoord w, wxCoord h) const
263 {
264 if (!m_refData)
265 return wxOutRegion;
266
267 MGLRect rect(x, y, x + w, y + h);
268 MGLRegion rg;
269
270 // 1) is the rectangle entirely covered by the region?
271 rg = MGLRegion(rect) - M_REGION;
272 if (rg.isEmpty()) return wxInRegion;
273
274 // 2) is the rectangle completely outside the region?
275 rg = M_REGION & rect; // intersection
276 if (rg.isEmpty()) return wxOutRegion;
277
278 // 3) neither case happened => it is partially covered:
279 return wxPartRegion;
280 }
281
282 // Does the region contain the rectangle rect
283 wxRegionContain wxRegion::Contains(const wxRect& rect) const
284 {
285 return Contains(rect.x, rect.y, rect.width, rect.height);
286 }
287
288
289 ///////////////////////////////////////////////////////////////////////////////
290 // wxRegionIterator //
291 ///////////////////////////////////////////////////////////////////////////////
292
293 /*
294 * Initialize empty iterator
295 */
296 wxRegionIterator::wxRegionIterator() : m_currentNode(NULL)
297 {
298 m_rects.DeleteContents(TRUE);
299 }
300
301 wxRegionIterator::~wxRegionIterator()
302 {
303 }
304
305 /*
306 * Initialize iterator for region
307 */
308 wxRegionIterator::wxRegionIterator(const wxRegion& region)
309 {
310 m_rects.DeleteContents(TRUE);
311 Reset(region);
312 }
313
314 /*
315 * Reset iterator for a new /e region.
316 */
317
318
319 static wxRegionRectList *gs_rectList;
320
321 static void MGLAPI wxMGL_region_callback(const rect_t *r)
322 {
323 gs_rectList->Append(new wxRect(r->left, r->top,
324 r->right - r->left, r->bottom - r->top));
325 }
326
327 void wxRegionIterator::Reset(const wxRegion& region)
328 {
329 m_currentNode = NULL;
330 m_rects.Clear();
331
332 if (!region.Empty())
333 {
334 wxMutexGuiEnter();
335 gs_rectList = &m_rects;
336 M_REGION_OF(region).traverse(wxMGL_region_callback);
337 wxMutexGuiLeave();
338 m_currentNode = m_rects.GetFirst();
339 }
340 }
341
342 /*
343 * Increment iterator. The rectangle returned is the one after the
344 * incrementation.
345 */
346 void wxRegionIterator::operator ++ ()
347 {
348 if (m_currentNode)
349 m_currentNode = m_currentNode->GetNext();
350 }
351
352 /*
353 * Increment iterator. The rectangle returned is the one before the
354 * incrementation.
355 */
356 void wxRegionIterator::operator ++ (int)
357 {
358 if (m_currentNode)
359 m_currentNode = m_currentNode->GetNext();
360 }
361
362 wxCoord wxRegionIterator::GetX() const
363 {
364 if (m_currentNode)
365 return m_currentNode->GetData()->x;
366 else
367 return 0;
368 }
369
370 wxCoord wxRegionIterator::GetY() const
371 {
372 if (m_currentNode)
373 return m_currentNode->GetData()->y;
374 else
375 return 0;
376 }
377
378 wxCoord wxRegionIterator::GetW() const
379 {
380 if (m_currentNode)
381 return m_currentNode->GetData()->width;
382 else
383 return 0;
384 }
385
386 wxCoord wxRegionIterator::GetH() const
387 {
388 if (m_currentNode)
389 return m_currentNode->GetData()->height;
390 else
391 return 0;
392 }