]> git.saurik.com Git - wxWidgets.git/blame - src/motif/region.cpp
wxSize/wxPoint/wxRect versions of functions added to wxMSW, wxMotif;
[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
JS
107// Get the internal region handle
108WXRegion wxRegion::GetXRegion()
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
209 // TODO combine region
210
211 return FALSE;
212}
213
214bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
215{
216 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
217}
218
219//-----------------------------------------------------------------------------
220//# Information on region
221//-----------------------------------------------------------------------------
222
223// Outer bounds of region
224void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
225{
226 if (m_refData) {
f97c9854
JS
227 XRectangle rect;
228 XClipBox(M_REGION, &rect);
229 x = rect.x;
230 y = rect.y;
231 w = rect.width;
232 h = rect.height;
4bb6408c
JS
233 } else {
234 x = y = w = h = 0;
235 }
236}
237
238wxRect wxRegion::GetBox() const
239{
240 long x, y, w, h;
241 GetBox(x, y, w, h);
242 return wxRect(x, y, w, h);
243}
244
245// Is region empty?
246bool wxRegion::Empty() const
247{
55acd85e 248 return m_refData ? XEmptyRegion(M_REGION) : TRUE;
4bb6408c
JS
249}
250
251//-----------------------------------------------------------------------------
252//# Tests
253//-----------------------------------------------------------------------------
254
255// Does the region contain the point (x,y)?
256wxRegionContain wxRegion::Contains(long x, long y) const
257{
258 if (!m_refData)
259 return wxOutRegion;
260
261 // TODO. Return wxInRegion if within region.
262 if (0)
263 return wxInRegion;
264 return wxOutRegion;
265}
266
267// Does the region contain the point pt?
268wxRegionContain wxRegion::Contains(const wxPoint& pt) const
269{
270 if (!m_refData)
271 return wxOutRegion;
272
f97c9854 273 return XPointInRegion(M_REGION, pt.x, pt.y) ? wxInRegion : wxOutRegion;
4bb6408c
JS
274}
275
276// Does the region contain the rectangle (x, y, w, h)?
277wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
278{
279 if (!m_refData)
280 return wxOutRegion;
281
f97c9854
JS
282 switch (XRectInRegion(M_REGION, x, y, w, h)) {
283 case RectangleIn: return wxInRegion;
284 case RectanglePart: return wxPartRegion;
285 }
286 return wxOutRegion;
4bb6408c
JS
287}
288
289// Does the region contain the rectangle rect
290wxRegionContain wxRegion::Contains(const wxRect& rect) const
291{
292 if (!m_refData)
293 return wxOutRegion;
294
295 long x, y, w, h;
296 x = rect.x;
297 y = rect.y;
298 w = rect.GetWidth();
299 h = rect.GetHeight();
300 return Contains(x, y, w, h);
301}
302
303///////////////////////////////////////////////////////////////////////////////
304// //
305// wxRegionIterator //
306// //
307///////////////////////////////////////////////////////////////////////////////
308
309/*!
310 * Initialize empty iterator
311 */
312wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
313{
314}
315
316wxRegionIterator::~wxRegionIterator()
317{
318 if (m_rects)
319 delete[] m_rects;
320}
321
322/*!
323 * Initialize iterator for region
324 */
325wxRegionIterator::wxRegionIterator(const wxRegion& region)
326{
327 m_rects = NULL;
328
329 Reset(region);
330}
331
332/*!
333 * Reset iterator for a new /e region.
334 */
335void wxRegionIterator::Reset(const wxRegion& region)
336{
337 m_current = 0;
338 m_region = region;
339
340 if (m_rects)
341 delete[] m_rects;
342
343 m_rects = NULL;
344
345 if (m_region.Empty())
346 m_numRects = 0;
347 else
348 {
349 // TODO create m_rects and fill with rectangles for this region
350 m_numRects = 0;
351 }
352}
353
354/*!
355 * Increment iterator. The rectangle returned is the one after the
356 * incrementation.
357 */
358void wxRegionIterator::operator ++ ()
359{
360 if (m_current < m_numRects)
361 ++m_current;
362}
363
364/*!
365 * Increment iterator. The rectangle returned is the one before the
366 * incrementation.
367 */
368void wxRegionIterator::operator ++ (int)
369{
370 if (m_current < m_numRects)
371 ++m_current;
372}
373
374long wxRegionIterator::GetX() const
375{
376 if (m_current < m_numRects)
377 return m_rects[m_current].x;
378 return 0;
379}
380
381long wxRegionIterator::GetY() const
382{
383 if (m_current < m_numRects)
384 return m_rects[m_current].y;
385 return 0;
386}
387
388long wxRegionIterator::GetW() const
389{
390 if (m_current < m_numRects)
391 return m_rects[m_current].width ;
392 return 0;
393}
394
395long wxRegionIterator::GetH() const
396{
397 if (m_current < m_numRects)
398 return m_rects[m_current].height;
399 return 0;
400}
401