]> git.saurik.com Git - wxWidgets.git/blob - src/os2/brush.cpp
Don't crash when laying out wxGridBagSizer with only hidden elements.
[wxWidgets.git] / src / os2 / brush.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/brush.cpp
3 // Purpose: wxBrush
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/13/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 #ifndef WX_PRECOMP
15 #include <stdio.h>
16 #include "wx/list.h"
17 #include "wx/utils.h"
18 #include "wx/app.h"
19 #include "wx/brush.h"
20 #include "wx/log.h"
21 #endif
22
23 #include "wx/os2/private.h"
24
25 class WXDLLEXPORT wxBrushRefData: public wxGDIRefData
26 {
27 friend class WXDLLIMPEXP_FWD_CORE wxBrush;
28 public:
29 wxBrushRefData(const wxColour& colour = wxNullColour, wxBrushStyle style = wxBRUSHSTYLE_SOLID);
30 wxBrushRefData(const wxBitmap& stipple);
31 wxBrushRefData(const wxBrushRefData& rData);
32 virtual ~wxBrushRefData();
33
34 bool operator == (const wxBrushRefData& data) const
35 {
36 return (m_nStyle == data.m_nStyle &&
37 m_vStipple.IsSameAs(data.m_vStipple) &&
38 m_vColour == data.m_vColour);
39 }
40
41 protected:
42 wxBrushStyle m_nStyle;
43 wxBitmap m_vStipple;
44 wxColour m_vColour;
45 WXHBRUSH m_hBrush; // in OS/2 GPI this will be the PS the pen is associated with
46 AREABUNDLE m_vBundle;
47 };
48
49 #define M_BRUSHDATA ((wxBrushRefData *)m_refData)
50
51 // ============================================================================
52 // wxBrushRefData implementation
53 // ============================================================================
54
55 IMPLEMENT_DYNAMIC_CLASS(wxBrush, wxGDIObject)
56
57 // ----------------------------------------------------------------------------
58 // wxBrushRefData ctors/dtor
59 // ----------------------------------------------------------------------------
60
61 wxBrushRefData::wxBrushRefData(const wxColour& colour, wxBrushStyle style)
62 : m_vColour(colour)
63 {
64 m_nStyle = style;
65 m_hBrush = 0;
66 memset(&m_vBundle, '\0', sizeof(AREABUNDLE));
67 } // end of wxBrushRefData::wxBrushRefData
68
69 wxBrushRefData::wxBrushRefData(const wxBitmap& stipple)
70 {
71 m_vStipple = stipple;
72 m_nStyle = stipple.GetMask() ? wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE
73 : wxBRUSHSTYLE_STIPPLE;
74
75 m_hBrush = NULL;
76 memset(&m_vBundle, '\0', sizeof(AREABUNDLE));
77 }
78
79 wxBrushRefData::wxBrushRefData(const wxBrushRefData& rData)
80 : wxGDIRefData(),
81 m_vStipple(rData.m_vStipple),
82 m_vColour(rData.m_vColour)
83 {
84 m_nStyle = rData.m_nStyle;
85 m_hBrush = 0;
86 memcpy(&m_vBundle, &rData.m_vBundle, sizeof(AREABUNDLE));
87 } // end of wxBrushRefData::wxBrushRefData
88
89 wxBrushRefData::~wxBrushRefData()
90 {
91 } // end of wxBrushRefData::~wxBrushRefData
92
93 // ============================================================================
94 // wxBrush implementation
95 // ============================================================================
96
97 // ----------------------------------------------------------------------------
98 // wxBrush ctors/dtor
99 // ----------------------------------------------------------------------------
100
101 wxBrush::wxBrush()
102 {
103 } // end of wxBrush::wxBrush
104
105 wxBrush::~wxBrush()
106 {
107 } // end of wxBrush::~wxBrush
108
109 wxBrush::wxBrush(
110 const wxColour& rColour
111 , wxBrushStyle nStyle
112 )
113 {
114 m_refData = new wxBrushRefData(rColour, nStyle);
115
116 RealizeResource();
117 } // end of wxBrush::wxBrush
118
119 #if FUTURE_WXWIN_COMPATIBILITY_3_0
120 wxBrush::wxBrush(const wxColour& col, int style)
121 {
122 m_refData = new wxBrushRefData(col, (wxBrushStyle)style);
123
124 RealizeResource();
125 }
126 #endif
127
128 wxBrush::wxBrush(const wxBitmap& rStipple)
129 {
130 m_refData = new wxBrushRefData(rStipple);
131
132 RealizeResource();
133 } // end of wxBrush::wxBrush
134
135 bool wxBrush::RealizeResource()
136 {
137 bool bOk;
138 ERRORID vError;
139 wxString sError;
140
141 if (M_BRUSHDATA && M_BRUSHDATA->m_hBrush == 0L)
142 {
143 SIZEL vSize = {0, 0};
144 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
145 HDC hDC = ::DevOpenDC( vHabmain
146 ,OD_MEMORY
147 ,"*"
148 ,5L
149 ,(PDEVOPENDATA)&vDop
150 ,NULLHANDLE
151 );
152 M_BRUSHDATA->m_hBrush = (WXHPEN)::GpiCreatePS( vHabmain
153 ,hDC
154 ,&vSize
155 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
156 );
157 }
158 if (M_BRUSHDATA)
159 {
160 //
161 // Set the color table to RGB mode
162 //
163 if (!::GpiCreateLogColorTable( (HPS)M_BRUSHDATA->m_hBrush
164 ,0L
165 ,LCOLF_RGB
166 ,0L
167 ,0L
168 ,NULL
169 ))
170 {
171 vError = ::WinGetLastError(vHabmain);
172 sError = wxPMErrorToStr(vError);
173 wxLogError(wxT("Unable to set current color table to RGB mode. Error: %s\n"), sError.c_str());
174 return false;
175 }
176
177 if (M_BRUSHDATA->m_nStyle==wxTRANSPARENT)
178 {
179 return true;
180 }
181 COLORREF vPmColour = 0L;
182
183 vPmColour = M_BRUSHDATA->m_vColour.GetPixel() ;
184
185 M_BRUSHDATA->m_vBundle.usSet = LCID_DEFAULT;
186 switch (M_BRUSHDATA->m_nStyle)
187 {
188 case wxTRANSPARENT:
189 M_BRUSHDATA->m_hBrush = NULL; // Must always select a suitable background brush
190 break; // - could choose white always for a quick solution
191
192 case wxBDIAGONAL_HATCH:
193 M_BRUSHDATA->m_vBundle.usSymbol = PATSYM_DIAG3;
194 break;
195
196 case wxCROSSDIAG_HATCH:
197 M_BRUSHDATA->m_vBundle.usSymbol = PATSYM_DIAGHATCH;
198 break;
199
200 case wxFDIAGONAL_HATCH:
201 M_BRUSHDATA->m_vBundle.usSymbol = PATSYM_DIAG1;
202 break;
203
204 case wxCROSS_HATCH:
205 M_BRUSHDATA->m_vBundle.usSymbol = PATSYM_HATCH;
206 break;
207
208 case wxHORIZONTAL_HATCH:
209 M_BRUSHDATA->m_vBundle.usSymbol = PATSYM_HORIZ;
210 break;
211
212 case wxVERTICAL_HATCH:
213 M_BRUSHDATA->m_vBundle.usSymbol = PATSYM_VERT;
214 break;
215
216 case wxSTIPPLE:
217 if (M_BRUSHDATA->m_vStipple.IsOk())
218 {
219 ::GpiSetBitmapId( M_BRUSHDATA->m_hBrush
220 ,(USHORT)M_BRUSHDATA->m_vStipple.GetHBITMAP()
221 ,(USHORT)M_BRUSHDATA->m_vStipple.GetId()
222 );
223 ::GpiSetPatternSet( M_BRUSHDATA->m_hBrush
224 ,(USHORT)M_BRUSHDATA->m_vStipple.GetId()
225 );
226 }
227 else
228 M_BRUSHDATA->m_vBundle.usSymbol = PATSYM_SOLID;
229 break ;
230
231 case wxSOLID:
232 default:
233 M_BRUSHDATA->m_vBundle.usSymbol = PATSYM_SOLID;
234 break;
235 }
236 #ifdef WXDEBUG_CREATE
237 if (M_BRUSHDATA->m_hBrush==NULL) wxError("Cannot create brush","Internal error") ;
238 #endif
239 M_BRUSHDATA->m_vBundle.lColor = vPmColour;
240 M_BRUSHDATA->m_vBundle.lBackColor = RGB_WHITE;
241 M_BRUSHDATA->m_vBundle.usMixMode = FM_OVERPAINT;
242 M_BRUSHDATA->m_vBundle.usBackMixMode = BM_OVERPAINT;
243
244 bOk = (bool)::GpiSetAttrs( M_BRUSHDATA->m_hBrush
245 ,PRIM_AREA
246 ,ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE |
247 ABB_SET | ABB_SYMBOL | ABB_REF_POINT
248 ,ABB_SET | ABB_SYMBOL | ABB_REF_POINT
249 ,&M_BRUSHDATA->m_vBundle
250 );
251 if (!bOk)
252 {
253 vError = ::WinGetLastError(vHabmain);
254 sError = wxPMErrorToStr(vError);
255 wxLogError(wxT("Can't set Gpi attributes for an AREABUNDLE. Error: %s\n"), sError.c_str());
256 }
257 return bOk;
258 }
259 return false;
260 } // end of wxBrush::RealizeResource
261
262 // ----------------------------------------------------------------------------
263 // wxBrush accessors
264 // ----------------------------------------------------------------------------
265
266 wxColour wxBrush::GetColour() const
267 {
268 wxCHECK_MSG( IsOk(), wxNullColour, wxT("invalid brush") );
269
270 return M_BRUSHDATA->m_vColour;
271 }
272
273 wxBrushStyle wxBrush::GetStyle() const
274 {
275 wxCHECK_MSG( IsOk(), wxBRUSHSTYLE_INVALID, wxT("invalid brush") );
276
277 return M_BRUSHDATA->m_nStyle;
278 }
279
280 wxBitmap *wxBrush::GetStipple() const
281 {
282 wxCHECK_MSG( IsOk(), NULL, wxT("invalid brush") );
283
284 return &(M_BRUSHDATA->m_vStipple);
285 }
286
287 int wxBrush::GetPS() const
288 {
289 wxCHECK_MSG( IsOk(), 0, wxT("invalid brush") );
290
291 return M_BRUSHDATA->m_hBrush;
292 }
293
294 WXHANDLE wxBrush::GetResourceHandle() const
295 {
296 wxCHECK_MSG( IsOk(), 0, wxT("invalid brush") );
297
298 return (WXHANDLE)M_BRUSHDATA->m_hBrush;
299 } // end of wxBrush::GetResourceHandle
300
301 bool wxBrush::FreeResource( bool WXUNUSED(bForce) )
302 {
303 if (M_BRUSHDATA && (M_BRUSHDATA->m_hBrush != 0))
304 {
305 M_BRUSHDATA->m_hBrush = 0;
306 return true;
307 }
308 else return false;
309 } // end of wxBrush::FreeResource
310
311 bool wxBrush::IsFree() const
312 {
313 return (M_BRUSHDATA && (M_BRUSHDATA->m_hBrush == 0));
314 } // end of wxBrush::IsFree
315
316 // ----------------------------------------------------------------------------
317 // wxBrush setters
318 // ----------------------------------------------------------------------------
319
320 void wxBrush::SetColour( const wxColour& rColour )
321 {
322 AllocExclusive();
323 M_BRUSHDATA->m_vColour = rColour;
324 RealizeResource();
325 }
326
327 void wxBrush::SetColour(unsigned char cRed, unsigned char cGreen, unsigned char cBlue)
328 {
329 AllocExclusive();
330 M_BRUSHDATA->m_vColour.Set( cRed, cGreen, cBlue );
331 RealizeResource();
332 } // end of wxBrush::SetColour
333
334 void wxBrush::SetStyle(wxBrushStyle nStyle)
335 {
336 AllocExclusive();
337 M_BRUSHDATA->m_nStyle = nStyle;
338 RealizeResource();
339 } // end of wxBrush::SetStyle
340
341 void wxBrush::SetStipple(
342 const wxBitmap& rStipple
343 )
344 {
345 AllocExclusive();
346 M_BRUSHDATA->m_vStipple = rStipple;
347 RealizeResource();
348 } // end of wxBrush::SetStipple
349
350 void wxBrush::SetPS(
351 HPS hPS
352 )
353 {
354 AllocExclusive();
355 if (M_BRUSHDATA->m_hBrush)
356 ::GpiDestroyPS(M_BRUSHDATA->m_hBrush);
357 M_BRUSHDATA->m_hBrush = hPS;
358 RealizeResource();
359 } // end of WxWinGdi_CPen::SetPS
360
361 // ----------------------------------------------------------------------------
362 // wxBrush house keeping stuff
363 // ----------------------------------------------------------------------------
364
365 bool wxBrush::operator == (
366 const wxBrush& brush
367 ) const
368 {
369 if (m_refData == brush.m_refData) return true;
370
371 if (!m_refData || !brush.m_refData) return false;
372
373 return ( *(wxBrushRefData*)m_refData == *(wxBrushRefData*)brush.m_refData );
374 } // end of wxBrush::operator ==
375
376 wxGDIRefData *wxBrush::CreateGDIRefData() const
377 {
378 return new wxBrushRefData;
379 }
380
381 wxGDIRefData *wxBrush::CloneGDIRefData(const wxGDIRefData *data) const
382 {
383 return new wxBrushRefData(*(const wxBrushRefData *)data);
384 }