]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/pen.cpp
Don't crash when laying out wxGridBagSizer with only hidden elements.
[wxWidgets.git] / src / os2 / pen.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/os2/pen.cpp
3// Purpose: wxPen
4// Author: David Webster
5// Modified by:
6// Created: 10/10/99
7// Copyright: (c) David Webster
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#include "wx/pen.h"
15
16#ifndef WX_PRECOMP
17 #include <stdio.h>
18 #include "wx/list.h"
19 #include "wx/utils.h"
20 #include "wx/app.h"
21 #include "wx/log.h"
22#endif
23
24#include "wx/os2/private.h"
25
26class WXDLLIMPEXP_FWD_CORE wxPen;
27
28// ----------------------------------------------------------------------------
29// wxPenRefData: contains information about an HPEN and its handle
30// ----------------------------------------------------------------------------
31
32class WXDLLEXPORT wxPenRefData: public wxGDIRefData
33{
34 friend class WXDLLIMPEXP_FWD_CORE wxPen;
35public:
36 wxPenRefData();
37 wxPenRefData(const wxPenRefData& rData);
38 wxPenRefData(const wxColour& col, int width, wxPenStyle style);
39 wxPenRefData(const wxBitmap& stipple, int width);
40 virtual ~wxPenRefData();
41
42 bool operator==(const wxPenRefData& data) const
43 {
44 // we intentionally don't compare m_hPen fields here
45 return m_nStyle == data.m_nStyle &&
46 m_nWidth == data.m_nWidth &&
47 m_nJoin == data.m_nJoin &&
48 m_nCap == data.m_nCap &&
49 m_vColour == data.m_vColour &&
50 (m_nStyle != wxPENSTYLE_STIPPLE || m_vStipple.IsSameAs(data.m_vStipple)) &&
51 (m_nStyle != wxPENSTYLE_USER_DASH ||
52 (m_dash == data.m_dash &&
53 memcmp(m_dash, data.m_dash, m_nbDash*sizeof(wxDash)) == 0));
54 }
55
56private:
57 // initialize the fields which have reasonable default values
58 //
59 // doesn't initialize m_width and m_style which must be initialize in ctor
60 void Init()
61 {
62 m_nJoin = wxJOIN_ROUND;
63 m_nCap = wxCAP_ROUND;
64 m_nbDash = 0;
65 m_dash = NULL;
66 m_hPen = 0;
67 }
68
69 int m_nWidth;
70 wxPenStyle m_nStyle;
71 wxPenJoin m_nJoin;
72 wxPenCap m_nCap;
73 wxBitmap m_vStipple;
74 int m_nbDash;
75 wxDash * m_dash;
76 wxColour m_vColour;
77 WXHPEN m_hPen;// in OS/2 GPI this will be the PS the pen is associated with
78
79 wxDECLARE_NO_ASSIGN_CLASS(wxPenRefData);
80};
81
82#define M_PENDATA ((wxPenRefData *)m_refData)
83
84// ----------------------------------------------------------------------------
85// wxPenRefData ctors/dtor
86// ----------------------------------------------------------------------------
87
88wxPenRefData::wxPenRefData()
89{
90 Init();
91
92 m_nStyle = wxPENSTYLE_SOLID;
93 m_nWidth = 1;
94} // end of wxPenRefData::wxPenRefData
95
96wxPenRefData::wxPenRefData(
97 const wxPenRefData& rData
98)
99{
100 m_nStyle = rData.m_nStyle;
101 m_nWidth = rData.m_nWidth;
102 m_nJoin = rData.m_nJoin;
103 m_nCap = rData.m_nCap;
104 m_nbDash = rData.m_nbDash;
105 m_dash = rData.m_dash;
106 m_vColour = rData.m_vColour;
107 m_hPen = 0L;
108} // end of wxPenRefData::wxPenRefData
109
110wxPenRefData::wxPenRefData(const wxColour& col, int width, wxPenStyle style)
111{
112 Init();
113
114 m_nStyle = style;
115 m_nWidth = width;
116
117 m_vColour = col;
118}
119
120wxPenRefData::wxPenRefData(const wxBitmap& stipple, int width)
121{
122 Init();
123
124 m_nStyle = wxPENSTYLE_STIPPLE;
125 m_nWidth = width;
126
127 m_vStipple = stipple;
128}
129
130wxPenRefData::~wxPenRefData()
131{
132} // end of wxPenRefData::~wxPenRefData
133
134// ----------------------------------------------------------------------------
135// wxPen
136// ----------------------------------------------------------------------------
137
138IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
139
140wxPen::wxPen(
141 const wxColour& rColour
142, int nWidth
143, wxPenStyle nStyle
144)
145{
146 m_refData = new wxPenRefData(rColour, nWidth, nStyle);
147
148 RealizeResource();
149} // end of wxPen::wxPen
150
151#if FUTURE_WXWIN_COMPATIBILITY_3_0
152wxPen::wxPen(const wxColour& colour, int width, int style)
153{
154 m_refData = new wxPenRefData(colour, width, (wxPenStyle)style);
155
156 RealizeResource();
157}
158#endif
159
160wxPen::wxPen(
161 const wxBitmap& rStipple
162, int nWidth
163)
164{
165 m_refData = new wxPenRefData (rStipple, nWidth);
166
167 RealizeResource();
168} // end of wxPen::wxPen
169
170bool wxPen::operator==(const wxPen& pen) const
171{
172 const wxPenRefData *
173 penData = static_cast<const wxPenRefData *>(pen.m_refData);
174
175 // an invalid pen is only equal to another invalid pen
176 return m_refData ? penData && *M_PENDATA == *penData : !penData;
177}
178
179int wx2os2PenStyle(
180 wxPenStyle nWxStyle
181);
182
183bool wxPen::RealizeResource()
184{
185 BOOL bOk;
186 ERRORID vError;
187 wxString sError;
188
189 if (M_PENDATA && M_PENDATA->m_hPen == 0L)
190 {
191 SIZEL vSize = {0, 0};
192 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
193 HDC hDC = ::DevOpenDC( vHabmain
194 ,OD_MEMORY
195 ,"*"
196 ,5L
197 ,(PDEVOPENDATA)&vDop
198 ,NULLHANDLE
199 );
200 M_PENDATA->m_hPen = (WXHPEN)::GpiCreatePS( vHabmain
201 ,hDC
202 ,&vSize
203 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
204 );
205 }
206 if (M_PENDATA)
207 {
208 //
209 // Set the color table to RGB mode
210 //
211 if (!::GpiCreateLogColorTable( (HPS)M_PENDATA->m_hPen
212 ,0L
213 ,LCOLF_RGB
214 ,0L
215 ,0L
216 ,NULL
217 ))
218 {
219 vError = ::WinGetLastError(vHabmain);
220 sError = wxPMErrorToStr(vError);
221 wxLogError(wxT("Unable to set current color table to RGB mode. Error: %s\n"), sError.c_str());
222 return false;
223 }
224 if (M_PENDATA->m_nStyle == wxPENSTYLE_TRANSPARENT)
225 {
226 return true;
227 }
228
229 COLORREF vPmColour = 0L;
230 USHORT uLineType = (USHORT)wx2os2PenStyle(M_PENDATA->m_nStyle);
231
232 vPmColour = M_PENDATA->m_vColour.GetPixel();
233
234 USHORT uJoin = 0L;
235
236 switch(M_PENDATA->m_nJoin)
237 {
238 case wxJOIN_BEVEL:
239 uJoin = LINEJOIN_BEVEL;
240 break;
241
242 case wxJOIN_MITER:
243 uJoin = LINEJOIN_MITRE;
244 break;
245
246 case wxJOIN_ROUND:
247 uJoin = LINEJOIN_ROUND;
248 break;
249 }
250
251 USHORT uCap = 0L;
252
253 switch(M_PENDATA->m_nCap)
254 {
255 case wxCAP_PROJECTING:
256 uCap = LINEEND_SQUARE;
257 break;
258
259 case wxCAP_BUTT:
260 uCap = LINEEND_FLAT;
261 break;
262
263 case wxCAP_ROUND:
264 uCap = LINEEND_ROUND;
265 break;
266 }
267 m_vLineBundle.lColor = (LONG)vPmColour;
268 m_vLineBundle.usMixMode = FM_OVERPAINT;
269 if (M_PENDATA->m_nWidth < 1)
270 M_PENDATA->m_nWidth = 1;
271 m_vLineBundle.fxWidth = M_PENDATA->m_nWidth;
272 m_vLineBundle.lGeomWidth = M_PENDATA->m_nWidth;
273 m_vLineBundle.usType = uLineType;
274 m_vLineBundle.usEnd = uCap;
275 m_vLineBundle.usJoin = uJoin;
276
277 bOk = ::GpiSetAttrs( M_PENDATA->m_hPen
278 ,PRIM_LINE
279 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE | LBB_END | LBB_JOIN
280 ,0L
281 ,&m_vLineBundle
282 );
283 if (!bOk)
284 {
285 vError = ::WinGetLastError(vHabmain);
286 sError = wxPMErrorToStr(vError);
287 wxLogError(wxT("Can't set Gpi attributes for a LINEBUNDLE. Error: %s\n"), sError.c_str());
288 return false;
289 }
290
291 ULONG flAttrMask = 0L;
292 ULONG flDefMask = 0L;
293 switch(M_PENDATA->m_nStyle)
294 {
295 case wxPENSTYLE_STIPPLE:
296 ::GpiSetBitmapId( M_PENDATA->m_hPen
297 ,(USHORT)M_PENDATA->m_vStipple.GetHBITMAP()
298 ,(USHORT)M_PENDATA->m_vStipple.GetId()
299 );
300 ::GpiSetPatternSet( M_PENDATA->m_hPen
301 ,(USHORT)M_PENDATA->m_vStipple.GetId()
302 );
303 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SET | ABB_SYMBOL;
304 flDefMask = ABB_REF_POINT;
305 break;
306
307 case wxPENSTYLE_BDIAGONAL_HATCH:
308 m_vAreaBundle.usSymbol = PATSYM_DIAG3;
309 m_vAreaBundle.usSet = LCID_DEFAULT;
310 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
311 flDefMask = ABB_SET | ABB_REF_POINT;
312 break;
313
314 case wxPENSTYLE_CROSSDIAG_HATCH:
315 m_vAreaBundle.usSymbol = PATSYM_DIAGHATCH;
316 m_vAreaBundle.usSet = LCID_DEFAULT;
317 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
318 flDefMask = ABB_SET | ABB_REF_POINT;
319 break;
320
321 case wxPENSTYLE_FDIAGONAL_HATCH:
322 m_vAreaBundle.usSymbol = PATSYM_DIAG1;
323 m_vAreaBundle.usSet = LCID_DEFAULT;
324 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
325 flDefMask = ABB_SET | ABB_REF_POINT;
326 break;
327
328 case wxPENSTYLE_CROSS_HATCH:
329 m_vAreaBundle.usSymbol = PATSYM_HATCH;
330 m_vAreaBundle.usSet = LCID_DEFAULT;
331 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
332 flDefMask = ABB_SET | ABB_REF_POINT;
333 break;
334
335 case wxPENSTYLE_HORIZONTAL_HATCH:
336 m_vAreaBundle.usSymbol = PATSYM_HORIZ;
337 m_vAreaBundle.usSet = LCID_DEFAULT;
338 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
339 flDefMask = ABB_SET | ABB_REF_POINT;
340 break;
341
342 case wxPENSTYLE_VERTICAL_HATCH:
343 m_vAreaBundle.usSymbol = PATSYM_VERT;
344 m_vAreaBundle.usSet = LCID_DEFAULT;
345 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
346 flDefMask = ABB_SET | ABB_REF_POINT;
347 break;
348
349 default:
350 m_vAreaBundle.usSymbol = PATSYM_SOLID;
351 m_vAreaBundle.usSet = LCID_DEFAULT;
352 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
353 flDefMask = ABB_SET | ABB_REF_POINT;
354 break;
355 }
356
357 m_vAreaBundle.lColor = vPmColour;
358 m_vAreaBundle.lBackColor = RGB_WHITE;
359 m_vAreaBundle.usMixMode = FM_OVERPAINT;
360 m_vAreaBundle.usBackMixMode = BM_OVERPAINT;
361
362 bOk = ::GpiSetAttrs( M_PENDATA->m_hPen
363 ,PRIM_AREA
364 ,flAttrMask
365 ,flDefMask
366 ,&m_vAreaBundle
367 );
368 if (!bOk)
369 {
370 vError = ::WinGetLastError(vHabmain);
371 sError = wxPMErrorToStr(vError);
372 wxLogError(wxT("Can't set Gpi attributes for an AREABUNDLE. Error: %s\n"), sError.c_str());
373 }
374
375 return (bool)bOk;
376 }
377 return false;
378} // end of wxPen::RealizeResource
379
380WXHANDLE wxPen::GetResourceHandle() const
381{
382 if (!M_PENDATA)
383 return 0;
384 else
385 return (WXHANDLE)M_PENDATA->m_hPen;
386} // end of wxPen::GetResourceHandle
387
388bool wxPen::FreeResource( bool WXUNUSED(bForce) )
389{
390 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
391 {
392 M_PENDATA->m_hPen = 0;
393 return true;
394 }
395 else return false;
396} // end of wxPen::FreeResource
397
398bool wxPen::IsFree() const
399{
400 return (M_PENDATA && M_PENDATA->m_hPen == 0);
401}
402
403wxGDIRefData* wxPen::CreateGDIRefData() const
404{
405 return new wxPenRefData;
406}
407
408wxGDIRefData* wxPen::CloneGDIRefData(const wxGDIRefData* data) const
409{
410 return new wxPenRefData(*static_cast<const wxPenRefData*>(data));
411}
412
413void wxPen::SetColour( const wxColour& rColour )
414{
415 AllocExclusive();
416 M_PENDATA->m_vColour = rColour;
417 RealizeResource();
418} // end of wxPen::SetColour
419
420void wxPen::SetColour( unsigned char cRed, unsigned char cGreen, unsigned char cBlue)
421{
422 AllocExclusive();
423 M_PENDATA->m_vColour.Set(cRed, cGreen, cBlue);
424 RealizeResource();
425} // end of wxPen::SetColour
426
427void wxPen::SetPS( HPS hPS )
428{
429 AllocExclusive();
430 if (M_PENDATA->m_hPen)
431 ::GpiDestroyPS(M_PENDATA->m_hPen);
432 M_PENDATA->m_hPen = hPS;
433 RealizeResource();
434} // end of WxWinGdi_CPen::SetPS
435
436void wxPen::SetWidth(
437 int nWidth
438)
439{
440 AllocExclusive();
441 M_PENDATA->m_nWidth = nWidth;
442 RealizeResource();
443} // end of wxPen::SetWidth
444
445void wxPen::SetStyle(
446 wxPenStyle nStyle
447)
448{
449 AllocExclusive();
450 M_PENDATA->m_nStyle = nStyle;
451 RealizeResource();
452} // end of wxPen::SetStyle
453
454void wxPen::SetStipple(
455 const wxBitmap& rStipple
456)
457{
458 AllocExclusive();
459 M_PENDATA->m_vStipple = rStipple;
460 M_PENDATA->m_nStyle = wxPENSTYLE_STIPPLE;
461 RealizeResource();
462} // end of wxPen::SetStipple
463
464void wxPen::SetDashes( int WXUNUSED(nNbDashes),
465 const wxDash* WXUNUSED(pDash) )
466{
467 //
468 // Does nothing under OS/2
469 //
470} // end of wxPen::SetDashes
471
472void wxPen::SetJoin(
473 wxPenJoin nJoin
474)
475{
476 AllocExclusive();
477 M_PENDATA->m_nJoin = nJoin;
478 RealizeResource();
479} // end of wxPen::SetJoin
480
481void wxPen::SetCap(
482 wxPenCap nCap
483)
484{
485 AllocExclusive();
486 M_PENDATA->m_nCap = nCap;
487 RealizeResource();
488} // end of wxPen::SetCap
489
490wxColour wxPen::GetColour() const
491{
492 wxCHECK_MSG( IsOk(), wxNullColour, wxT("invalid pen") );
493
494 return M_PENDATA->m_vColour;
495}
496
497int wxPen::GetWidth() const
498{
499 wxCHECK_MSG( IsOk(), -1, wxT("invalid pen") );
500
501 return M_PENDATA->m_nWidth;
502}
503
504wxPenStyle wxPen::GetStyle() const
505{
506 wxCHECK_MSG( IsOk(), wxPENSTYLE_INVALID, wxT("invalid pen") );
507
508 return M_PENDATA->m_nStyle;
509}
510
511wxPenJoin wxPen::GetJoin() const
512{
513 wxCHECK_MSG( IsOk(), wxJOIN_INVALID, wxT("invalid pen") );
514
515 return M_PENDATA->m_nJoin;
516}
517
518wxPenCap wxPen::GetCap() const
519{
520 wxCHECK_MSG( IsOk(), wxCAP_INVALID, wxT("invalid pen") );
521
522 return M_PENDATA->m_nCap;
523}
524
525int wxPen::GetPS() const
526{
527 wxCHECK_MSG( IsOk(), 0, wxT("invalid pen") );
528
529 return M_PENDATA->m_hPen;
530}
531
532int wxPen::GetDashes(wxDash** ptr) const
533{
534 wxCHECK_MSG( IsOk(), -1, wxT("invalid pen") );
535
536 *ptr = M_PENDATA->m_dash;
537 return M_PENDATA->m_nbDash;
538}
539
540wxDash* wxPen::GetDash() const
541{
542 wxCHECK_MSG( IsOk(), NULL, wxT("invalid pen") );
543
544 return M_PENDATA->m_dash;
545}
546
547int wxPen::GetDashCount() const
548{
549 wxCHECK_MSG( IsOk(), -1, wxT("invalid pen") );
550
551 return M_PENDATA->m_nbDash;
552}
553
554wxBitmap* wxPen::GetStipple() const
555{
556 wxCHECK_MSG( IsOk(), NULL, wxT("invalid pen") );
557
558 return &(M_PENDATA->m_vStipple);
559}
560
561int wx2os2PenStyle(
562 wxPenStyle nWxStyle
563)
564{
565 int nPMStyle = 0;
566
567 switch (nWxStyle)
568 {
569 case wxPENSTYLE_DOT:
570 nPMStyle = LINETYPE_DOT;
571 break;
572
573 case wxPENSTYLE_DOT_DASH:
574 nPMStyle = LINETYPE_DASHDOT;
575 break;
576
577 case wxPENSTYLE_SHORT_DASH:
578 nPMStyle = LINETYPE_SHORTDASH;
579 break;
580
581 case wxPENSTYLE_LONG_DASH:
582 nPMStyle = LINETYPE_LONGDASH;
583 break;
584
585 case wxPENSTYLE_TRANSPARENT:
586 nPMStyle = LINETYPE_INVISIBLE;
587 break;
588
589 case wxPENSTYLE_USER_DASH:
590 nPMStyle = LINETYPE_DASHDOUBLEDOT; // We must make a choice... This is mine!
591 break;
592
593 case wxPENSTYLE_SOLID:
594 default:
595 nPMStyle = LINETYPE_SOLID;
596 break;
597 }
598 return nPMStyle;
599} // end of wx2os2PenStyle