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