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