]> git.saurik.com Git - wxWidgets.git/blame - src/motif/region.cpp
More Motif additions: mdi and sashtest samples now just about work!
[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
107//-----------------------------------------------------------------------------
108//# Modify region
109//-----------------------------------------------------------------------------
110
111//! Clear current region
112void wxRegion::Clear()
113{
114 UnRef();
115}
116
117//! Combine rectangle (x, y, w, h) with this.
118bool 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
f97c9854
JS
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);
4bb6408c
JS
138
139 int mode = 0; // TODO platform-specific code
140 switch (op)
141 {
142 case wxRGN_AND:
f97c9854 143 XIntersectRegion(M_REGION, rectRegion, M_REGION);
4bb6408c
JS
144 break ;
145 case wxRGN_OR:
f97c9854 146 XUnionRegion(M_REGION, rectRegion, M_REGION);
4bb6408c
JS
147 break ;
148 case wxRGN_XOR:
149 // TODO
150 break ;
151 case wxRGN_DIFF:
152 // TODO
153 break ;
f97c9854 154 case wxRGN_COPY: // Don't have to do this one
4bb6408c
JS
155 default:
156 // TODO
157 break ;
158 }
159
4bb6408c
JS
160 return FALSE;
161}
162
163//! Union /e region with this.
164bool 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:
f97c9854
JS
182 XIntersectRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
183 M_REGION);
4bb6408c
JS
184 break ;
185 case wxRGN_OR:
f97c9854
JS
186 XUnionRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
187 M_REGION);
4bb6408c
JS
188 break ;
189 case wxRGN_XOR:
190 // TODO
191 break ;
192 case wxRGN_DIFF:
193 // TODO
194 break ;
f97c9854 195 case wxRGN_COPY: // Don't have to do this one
4bb6408c
JS
196 default:
197 // TODO
198 break ;
199 }
200
201 // TODO combine region
202
203 return FALSE;
204}
205
206bool 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
216void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
217{
218 if (m_refData) {
f97c9854
JS
219 XRectangle rect;
220 XClipBox(M_REGION, &rect);
221 x = rect.x;
222 y = rect.y;
223 w = rect.width;
224 h = rect.height;
4bb6408c
JS
225 } else {
226 x = y = w = h = 0;
227 }
228}
229
230wxRect 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?
238bool wxRegion::Empty() const
239{
f97c9854 240 return m_refData ? XEmptyRegion(M_REGION) : FALSE;
4bb6408c
JS
241}
242
243//-----------------------------------------------------------------------------
244//# Tests
245//-----------------------------------------------------------------------------
246
247// Does the region contain the point (x,y)?
248wxRegionContain 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?
260wxRegionContain wxRegion::Contains(const wxPoint& pt) const
261{
262 if (!m_refData)
263 return wxOutRegion;
264
f97c9854 265 return XPointInRegion(M_REGION, pt.x, pt.y) ? wxInRegion : wxOutRegion;
4bb6408c
JS
266}
267
268// Does the region contain the rectangle (x, y, w, h)?
269wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
270{
271 if (!m_refData)
272 return wxOutRegion;
273
f97c9854
JS
274 switch (XRectInRegion(M_REGION, x, y, w, h)) {
275 case RectangleIn: return wxInRegion;
276 case RectanglePart: return wxPartRegion;
277 }
278 return wxOutRegion;
4bb6408c
JS
279}
280
281// Does the region contain the rectangle rect
282wxRegionContain 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 */
304wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
305{
306}
307
308wxRegionIterator::~wxRegionIterator()
309{
310 if (m_rects)
311 delete[] m_rects;
312}
313
314/*!
315 * Initialize iterator for region
316 */
317wxRegionIterator::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 */
327void 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 */
350void 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 */
360void wxRegionIterator::operator ++ (int)
361{
362 if (m_current < m_numRects)
363 ++m_current;
364}
365
366long wxRegionIterator::GetX() const
367{
368 if (m_current < m_numRects)
369 return m_rects[m_current].x;
370 return 0;
371}
372
373long wxRegionIterator::GetY() const
374{
375 if (m_current < m_numRects)
376 return m_rects[m_current].y;
377 return 0;
378}
379
380long wxRegionIterator::GetW() const
381{
382 if (m_current < m_numRects)
383 return m_rects[m_current].width ;
384 return 0;
385}
386
387long wxRegionIterator::GetH() const
388{
389 if (m_current < m_numRects)
390 return m_rects[m_current].height;
391 return 0;
392}
393