]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/region.cpp
corrected scrolling problems for controls, switched to separate wxSpinCtrl implementa...
[wxWidgets.git] / src / os2 / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// File: region.cpp
3// Purpose: Region class
4// Author: David Webster
5// Modified by:
6// Created: 10/15/99
7// RCS-ID: $Id$
8// Copyright: (c) Davdi Webster
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#include "wx/app.h"
16#include "wx/os2/region.h"
17#include "wx/gdicmn.h"
18
19#include "wx/window.h"
20#include "wx/os2/private.h"
21
22 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
23 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
24
25//-----------------------------------------------------------------------------
26// wxRegionRefData implementation
27//-----------------------------------------------------------------------------
28
29class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
30public:
31 wxRegionRefData()
32 {
33 m_hRegion = 0;
34 m_hPS = 0;
35 }
36
37 wxRegionRefData(const wxRegionRefData& rData)
38 {
39 RGNRECT vRgnData;
40 PRECTL pRect = NULL;
41
42 if (::GpiQueryRegionRects( rData.m_hPS // Pres space
43 ,rData.m_hRegion // Handle of region to query
44 ,NULL // Return all RECTs
45 ,&vRgnData // Will contain number or RECTs in region
46 ,NULL // NULL to return number of RECTs
47 ))
48 {
49 pRect = new RECTL[vRgnData.crcReturned];
50 vRgnData.crc = vRgnData.crcReturned;
51 vRgnData.ircStart = 1;
52 if (::GpiQueryRegionRects( rData.m_hPS // Pres space of source
53 ,rData.m_hRegion // Handle of source region
54 ,NULL // Return all RECTs
55 ,&vRgnData // Operations set to return rects
56 ,pRect // Will contain the actual RECTS
57 ))
58 {
59 m_hRegion = ::GpiCreateRegion( rData.m_hPS
60 ,vRgnData.crcReturned
61 ,pRect
62 );
63 m_hPS = rData.m_hPS;
64 }
65 delete [] pRect;
66 }
67 }
68
69 ~wxRegionRefData()
70 {
71 ::GpiDestroyRegion(m_hPS, m_hRegion);
72 }
73
74 HRGN m_hRegion;
75 HPS m_hPS;
76};
77
78#define M_REGION (((wxRegionRefData*)m_refData)->m_hRegion)
79#define M_REGION_OF(rgn) (((wxRegionRefData*)(rgn.m_refData))->m_hRegion)
80
81//-----------------------------------------------------------------------------
82// wxRegion
83//-----------------------------------------------------------------------------
84
85/*!
86 * Create an empty region.
87 */
88wxRegion::wxRegion()
89{
90 m_refData = new wxRegionRefData;
91} // end of wxRegion::wxRegion
92
93wxRegion::wxRegion(
94 WXHRGN hRegion,
95 WXHDC hPS
96)
97{
98 m_refData = new wxRegionRefData;
99 M_REGION = (HRGN) hRegion;
100 (((wxRegionRefData*)m_refData)->m_hPS) = hPS;
101} // end of wxRegion::wxRegion
102
103wxRegion::wxRegion(
104 wxCoord x
105, wxCoord y
106, wxCoord vWidth
107, wxCoord vHeight
108)
109{
110 RECTL vRect;
111 SIZEL vSize = {0, 0};
112 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
113 HDC hDC = ::DevOpenDC( vHabmain
114 ,OD_MEMORY
115 ,"*"
116 ,5L
117 ,(PDEVOPENDATA)&vDop
118 ,NULLHANDLE
119 );
120
121
122 vRect.xLeft = x;
123 vRect.xRight = x + vWidth;
124 vRect.yBottom = y;
125 vRect.yTop = y + vHeight;
126
127 m_refData = new wxRegionRefData;
128
129 //
130 // Need a PS to create a Region
131 //
132 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
133 ,hDC
134 ,&vSize
135 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
136 );
137 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
138 ,1
139 ,&vRect
140 );
141} // end of wxRegion::wxRegion
142
143wxRegion::wxRegion(
144 const wxPoint& rTopLeft
145, const wxPoint& rBottomRight
146)
147{
148 RECTL vRect;
149 SIZEL vSize = {0, 0};
150 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
151 HDC hDC = ::DevOpenDC( vHabmain
152 ,OD_MEMORY
153 ,"*"
154 ,5L
155 ,(PDEVOPENDATA)&vDop
156 ,NULLHANDLE
157 );
158
159 vRect.xLeft = rTopLeft.x;
160 vRect.xRight = rBottomRight.x;
161 vRect.yBottom = rBottomRight.y;
162 vRect.yTop = rTopLeft.y;
163
164 m_refData = new wxRegionRefData;
165
166 //
167 // Need a PS to create a Region
168 //
169 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
170 ,hDC
171 ,&vSize
172 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
173 );
174 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
175 ,1
176 ,&vRect
177 );
178} // end of wxRegion::wxRegion
179
180wxRegion::wxRegion(
181 const wxRect& rRect
182)
183{
184 RECTL vRect;
185 SIZEL vSize = {0, 0};
186 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
187 HDC hDC = ::DevOpenDC( vHabmain
188 ,OD_MEMORY
189 ,"*"
190 ,5L
191 ,(PDEVOPENDATA)&vDop
192 ,NULLHANDLE
193 );
194
195
196 vRect.xLeft = rRect.x;
197 vRect.xRight = rRect.x + rRect.width;
198 vRect.yBottom = rRect.y;
199 vRect.yTop = rRect.y + rRect.height;
200
201 m_refData = new wxRegionRefData;
202
203 //
204 // Need a PS to create a Region
205 //
206 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
207 ,hDC
208 ,&vSize
209 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
210 );
211 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
212 ,1
213 ,&vRect
214 );
215} // end of wxRegion::wxRegion
216
217//
218// Destroy the region.
219//
220wxRegion::~wxRegion()
221{
222} // end of wxRegion::~wxRegion
223
224wxObjectRefData *wxRegion::CreateData() const
225{
226 return new wxRegionRefData;
227}
228
229wxObjectRefData *wxRegion::CloneData(const wxObjectRefData *data) const
230{
231 return new wxRegionRefData(*(wxRegionRefData *)data);
232}
233
234//-----------------------------------------------------------------------------
235//# Modify region
236//-----------------------------------------------------------------------------
237
238bool wxRegion::Offset(
239 wxCoord x
240, wxCoord y
241)
242{
243 if ( !x && !y )
244 {
245 // nothing to do
246 return TRUE;
247 }
248
249 AllocExclusive();
250
251#if 0
252 if ( ::OffsetRgn(GetHrgn(), x, y) == ERROR )
253 {
254 wxLogLastError(_T("OffsetRgn"));
255
256 return FALSE;
257 }
258#endif
259 return TRUE;
260}
261
262//
263// Clear current region
264//
265void wxRegion::Clear()
266{
267 UnRef();
268} // end of wxRegion::Clear
269
270//
271// Combine rectangle (x, y, w, h) with this.
272//
273bool wxRegion::Combine(
274 wxCoord x
275, wxCoord y
276, wxCoord vWidth
277, wxCoord vHeight
278, wxRegionOp eOp
279)
280{
281 return Combine(wxRegion(x, y, vWidth, vHeight), eOp);
282} // end of wxRegion::Combine
283
284//
285// Union region with this.
286//
287bool wxRegion::Combine(
288 const wxRegion& rRegion
289, wxRegionOp eOp
290)
291{
292 //
293 // We can't use the API functions if we don't have a valid region handle
294 //
295 if (!m_refData)
296 {
297 // combining with an empty/invalid region works differently depending
298 // on the operation
299 switch (eOp)
300 {
301 case wxRGN_COPY:
302 case wxRGN_OR:
303 case wxRGN_XOR:
304 *this = rRegion;
305 break;
306
307 default:
308 wxFAIL_MSG( _T("unknown region operation") );
309 // fall through
310
311 case wxRGN_AND:
312 case wxRGN_DIFF:
313 // leave empty/invalid
314 return FALSE;
315 }
316 }
317 else // we have a valid region
318 {
319
320 LONG lMode = 0;
321
322 switch (eOp)
323 {
324 case wxRGN_AND:
325 lMode = CRGN_AND;
326 break;
327
328 case wxRGN_OR:
329 lMode = CRGN_OR;
330 break;
331
332 case wxRGN_XOR:
333 lMode = CRGN_XOR;
334 break;
335
336 case wxRGN_DIFF:
337 lMode = CRGN_DIFF;
338 break;
339
340 case wxRGN_COPY:
341 default:
342 lMode = CRGN_COPY;
343 break;
344 }
345 return (::GpiCombineRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
346 ,M_REGION
347 ,M_REGION
348 ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion
349 ,lMode
350 ) != RGN_ERROR);
351 }
352 return TRUE;
353} // end of wxRegion::Combine
354
355bool wxRegion::Combine(
356 const wxRect& rRect
357, wxRegionOp eOp
358)
359{
360 return Combine( rRect.GetLeft()
361 ,rRect.GetTop()
362 ,rRect.GetWidth()
363 ,rRect.GetHeight()
364 ,eOp
365 );
366} // end of wxRegion::Combine
367
368//-----------------------------------------------------------------------------
369//# Information on region
370//-----------------------------------------------------------------------------
371
372//
373// Outer bounds of region
374//
375void wxRegion::GetBox(
376 wxCoord& x
377, wxCoord& y
378, wxCoord& vWidth
379, wxCoord& vHeight
380) const
381{
382 if (m_refData)
383 {
384 RECTL vRect;
385 APIRET rc;
386
387 rc = ::GpiQueryRegionBox( ((wxRegionRefData*)m_refData)->m_hPS
388 ,M_REGION
389 ,&vRect
390 );
391 x = vRect.xLeft;
392 y = vRect.yBottom;
393 vWidth = vRect.xRight - vRect.xLeft;
394 vHeight = vRect.yTop - vRect.yBottom;
395 }
396 else
397 {
398 x = y = vWidth = vHeight = 0L;
399 }
400} // end of wxRegion::GetBox
401
402wxRect wxRegion::GetBox() const
403{
404 wxCoord x, y, w, h;
405 GetBox(x, y, w, h);
406 return wxRect(x, y, w, h);
407}
408
409//
410// Is region empty?
411//
412bool wxRegion::Empty() const
413{
414 wxCoord x;
415 wxCoord y;
416 wxCoord vWidth;
417 wxCoord vHeight;
418
419 if (M_REGION == 0)
420 return TRUE;
421
422 GetBox( x
423 ,y
424 ,vWidth
425 ,vHeight
426 );
427 return ((vWidth == 0) && (vHeight == 0));
428} // end of wxRegion::Empty
429
430//-----------------------------------------------------------------------------
431// Tests
432//-----------------------------------------------------------------------------
433
434//
435// Does the region contain the point (x,y)?
436wxRegionContain wxRegion::Contains(
437 wxCoord x
438, wxCoord y
439) const
440{
441 bool bOK = FALSE;
442 POINTL vPoint;
443
444 vPoint.x = x;
445 vPoint.y = y;
446
447 if (!m_refData)
448 return wxOutRegion;
449
450 LONG lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS
451 ,M_REGION
452 ,&vPoint
453 );
454 if (lInside == PRGN_INSIDE)
455 return wxInRegion;
456 return wxOutRegion;
457} // end of wxRegion::Contains
458
459//
460// Does the region contain the point pt?
461//
462wxRegionContain wxRegion::Contains(
463 const wxPoint& rPoint
464) const
465{
466 POINTL vPoint = { rPoint.x, rPoint.y };
467
468 if (!m_refData)
469 return wxOutRegion;
470
471 LONG lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS
472 ,M_REGION
473 ,&vPoint
474 );
475 if (lInside == PRGN_INSIDE)
476 return wxInRegion;
477 else
478 return wxOutRegion;
479} // end of wxRegion::Contains
480
481//
482// Does the region contain the rectangle (x, y, w, h)?
483//
484wxRegionContain wxRegion::Contains(
485 wxCoord x
486, wxCoord y
487, wxCoord vWidth
488, wxCoord vHeight
489) const
490{
491 RECTL vRect;
492
493 if (!m_refData)
494 return wxOutRegion;
495
496 vRect.xLeft = x;
497 vRect.yTop = y;
498 vRect.xRight = x + vWidth;
499 vRect.yBottom = y + vHeight;
500
501 if (PRGN_INSIDE == ::GpiRectInRegion( ((wxRegionRefData*)m_refData)->m_hPS
502 ,M_REGION
503 ,&vRect
504 ))
505 return wxInRegion;
506 else
507 return wxOutRegion;
508} // end of wxRegion::Contains
509
510//
511// Does the region contain the rectangle rect
512//
513wxRegionContain wxRegion::Contains(
514 const wxRect& rRect
515) const
516{
517 if (!m_refData)
518 return wxOutRegion;
519
520 wxCoord x;
521 wxCoord y;
522 wxCoord vWidth;
523 wxCoord vHeight;
524
525 x = rRect.x;
526 y = rRect.y;
527 vWidth = rRect.GetWidth();
528 vHeight = rRect.GetHeight();
529 return Contains( x
530 ,y
531 ,vWidth
532 ,vHeight
533 );
534} // end of wxRegion::Contains
535
536//
537// Get internal region handle
538//
539WXHRGN wxRegion::GetHRGN() const
540{
541 if (!m_refData)
542 return (WXHRGN) 0;
543 return (WXHRGN) M_REGION;
544}
545
546//
547// Set a new PS, this means we have to recreate the old region in the new
548// PS
549//
550void wxRegion::SetPS(
551 HPS hPS
552)
553{
554 RGNRECT vRgnData;
555 PRECTL pRect = NULL;
556
557 if (::GpiQueryRegionRects( ((wxRegionRefData*)m_refData)->m_hPS
558 ,((wxRegionRefData*)m_refData)->m_hRegion
559 ,NULL
560 ,&vRgnData
561 ,NULL
562 ))
563 {
564 pRect = new RECTL[vRgnData.crcReturned];
565 vRgnData.crc = vRgnData.crcReturned;
566 vRgnData.ircStart = 1;
567 if (::GpiQueryRegionRects( ((wxRegionRefData*)m_refData)->m_hPS
568 ,((wxRegionRefData*)m_refData)->m_hRegion
569 ,NULL
570 ,&vRgnData
571 ,pRect
572 ))
573 {
574 //
575 // First destroy the region out of the old PS
576 // and then create it in the new and set the new to current
577 //
578 ::GpiDestroyRegion( ((wxRegionRefData*)m_refData)->m_hPS
579 ,M_REGION
580 );
581 ((wxRegionRefData*)m_refData)->m_hRegion = ::GpiCreateRegion( hPS
582 ,vRgnData.crcReturned
583 ,pRect
584 );
585 ((wxRegionRefData*)m_refData)->m_hPS = hPS;
586 }
587 delete [] pRect;
588 }
589} // end of wxRegion::SetPS
590
591///////////////////////////////////////////////////////////////////////////////
592// //
593// wxRegionIterator //
594// //
595///////////////////////////////////////////////////////////////////////////////
596
597//
598// Initialize empty iterator
599//
600wxRegionIterator::wxRegionIterator()
601: m_lCurrent(0)
602, m_lNumRects(0)
603, m_pRects(NULL)
604{
605} // end of wxRegionIterator::wxRegionIterator
606
607wxRegionIterator::~wxRegionIterator()
608{
609 if (m_pRects)
610 delete[] m_pRects;
611} // end of wxRegionIterator::~wxRegionIterator
612
613//
614// Initialize iterator for region
615//
616wxRegionIterator::wxRegionIterator(
617 const wxRegion& rRegion
618)
619{
620 m_pRects = NULL;
621 Reset(rRegion);
622} // end of wxRegionIterator::wxRegionIterator
623
624//
625// Reset iterator for a new /e region.
626//
627void wxRegionIterator::Reset(
628 const wxRegion& rRegion
629)
630{
631 m_lCurrent = 0;
632 m_vRegion = rRegion;
633
634 if (m_pRects)
635 delete[] m_pRects;
636
637 m_pRects = NULL;
638
639 if (m_vRegion.Empty())
640 m_lNumRects = 0;
641 else
642 {
643 RGNRECT vRgnData;
644 PRECTL pRect;
645
646 if (::GpiQueryRegionRects( ((wxRegionRefData*)rRegion.m_refData)->m_hPS // Pres space
647 ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion // Handle of region to query
648 ,NULL // Return all RECTs
649 ,&vRgnData // Will contain number or RECTs in region
650 ,NULL // NULL to return number of RECTs
651 ))
652 {
653 pRect = new RECTL[vRgnData.crcReturned];
654 m_pRects = new wxRect[vRgnData.crcReturned];
655 vRgnData.crc = vRgnData.crcReturned;
656 m_lNumRects = vRgnData.crcReturned;
657 vRgnData.ircStart = 1;
658 if (::GpiQueryRegionRects( ((wxRegionRefData*)rRegion.m_refData)->m_hPS // Pres space of source
659 ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion // Handle of source region
660 ,NULL // Return all RECTs
661 ,&vRgnData // Operations set to return rects
662 ,pRect // Will contain the actual RECTS
663 ))
664 {
665 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
666 ,vRgnData.crcReturned
667 ,pRect
668 );
669 for( LONG i = 0; i < m_lNumRects; i++)
670 {
671 m_pRects[i].x = pRect[i].xLeft;
672 m_pRects[i].width = pRect[i].xRight - pRect[i].xLeft;
673 m_pRects[i].y = pRect[i].yBottom;
674 m_pRects[i].height = pRect[i].yTop - pRect[i].yBottom;
675 }
676 ((wxRegionRefData*)m_refData)->m_hPS = ((wxRegionRefData*)rRegion.m_refData)->m_hPS;
677 }
678 }
679 }
680} // end of wxRegionIterator::Reset
681
682//
683// Increment iterator. The rectangle returned is the one after the
684// incrementation.
685//
686void wxRegionIterator::operator++ ()
687{
688 if (m_lCurrent < m_lNumRects)
689 ++m_lCurrent;
690} // end of wxRegionIterator::operator ++
691
692//
693// Increment iterator. The rectangle returned is the one before the
694// incrementation.
695//
696void wxRegionIterator::operator++ (int)
697{
698 if (m_lCurrent < m_lNumRects)
699 ++m_lCurrent;
700} // end of wxRegionIterator::operator++
701
702wxCoord wxRegionIterator::GetX() const
703{
704 if (m_lCurrent < m_lNumRects)
705 return m_pRects[m_lCurrent].x;
706 return 0L;
707} // end of wxRegionIterator::GetX
708
709wxCoord wxRegionIterator::GetY() const
710{
711 if (m_lCurrent < m_lNumRects)
712 return m_pRects[m_lCurrent].y;
713 return 0L;
714} // end of wxRegionIterator::GetY
715
716wxCoord wxRegionIterator::GetW() const
717{
718 if (m_lCurrent < m_lNumRects)
719 return m_pRects[m_lCurrent].width ;
720 return 0L;
721} // end of wxRegionIterator::GetW
722
723wxCoord wxRegionIterator::GetH() const
724{
725 if (m_lCurrent < m_lNumRects)
726 return m_pRects[m_lCurrent].height;
727 return 0L;
728} // end of wxRegionIterator::GetH
729