Sorry, I went and removed consts as per the style guide :-)
[wxWidgets.git] / src / msw / pen.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: pen.cpp
3 // Purpose: wxPen
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "pen.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include <stdio.h>
25 #include "wx/setup.h"
26 #include "wx/list.h"
27 #include "wx/utils.h"
28 #include "wx/app.h"
29 #include "wx/pen.h"
30 #endif
31
32 #include "wx/msw/private.h"
33 #include "assert.h"
34
35 #if !USE_SHARED_LIBRARIES
36 IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
37 #endif
38
39 wxPenRefData::wxPenRefData(void)
40 {
41 // m_stipple = NULL ;
42 m_style = wxSOLID;
43 m_width = 1;
44 m_join = wxJOIN_ROUND ;
45 m_cap = wxCAP_ROUND ;
46 m_nbDash = 0 ;
47 m_dash = 0 ;
48 m_hPen = 0;
49 }
50
51 wxPenRefData::~wxPenRefData(void)
52 {
53 if ( m_hPen )
54 ::DeleteObject((HPEN) m_hPen);
55 }
56
57 // Pens
58
59 wxPen::wxPen(void)
60 {
61 if ( wxThePenList )
62 wxThePenList->AddPen(this);
63 }
64
65 wxPen::~wxPen()
66 {
67 if (wxThePenList)
68 wxThePenList->RemovePen(this);
69 }
70
71 // Should implement Create
72 wxPen::wxPen(const wxColour& col, int Width, int Style)
73 {
74 m_refData = new wxPenRefData;
75
76 M_PENDATA->m_colour = col;
77 // M_PENDATA->m_stipple = NULL;
78 M_PENDATA->m_width = Width;
79 M_PENDATA->m_style = Style;
80 M_PENDATA->m_join = wxJOIN_ROUND ;
81 M_PENDATA->m_cap = wxCAP_ROUND ;
82 M_PENDATA->m_nbDash = 0 ;
83 M_PENDATA->m_dash = 0 ;
84 M_PENDATA->m_hPen = 0 ;
85
86 #ifndef __WIN32__
87 // In Windows, only a pen of width = 1 can be dotted or dashed!
88 if ((Style == wxDOT) || (Style == wxLONG_DASH) ||
89 (Style == wxSHORT_DASH) || (Style == wxDOT_DASH) ||
90 (Style == wxUSER_DASH))
91 M_PENDATA->m_width = 1;
92 #else
93 /***
94 DWORD vers = GetVersion() ;
95 WORD high = HIWORD(vers) ; // high bit=0 for NT, 1 for Win32s
96 // Win32s doesn't support wide dashed pens
97
98 if ((high&0x8000)!=0)
99 ***/
100 if (wxGetOsVersion()==wxWIN32S)
101 {
102 // In Windows, only a pen of width = 1 can be dotted or dashed!
103 if ((Style == wxDOT) || (Style == wxLONG_DASH) ||
104 (Style == wxSHORT_DASH) || (Style == wxDOT_DASH) ||
105 (Style == wxUSER_DASH))
106 M_PENDATA->m_width = 1;
107 }
108 #endif
109 RealizeResource();
110
111 if ( wxThePenList )
112 wxThePenList->AddPen(this);
113 }
114
115 wxPen::wxPen(const wxBitmap& stipple, int Width)
116 {
117 m_refData = new wxPenRefData;
118
119 // M_PENDATA->m_colour = col;
120 M_PENDATA->m_stipple = stipple;
121 M_PENDATA->m_width = Width;
122 M_PENDATA->m_style = wxSTIPPLE;
123 M_PENDATA->m_join = wxJOIN_ROUND ;
124 M_PENDATA->m_cap = wxCAP_ROUND ;
125 M_PENDATA->m_nbDash = 0 ;
126 M_PENDATA->m_dash = 0 ;
127 M_PENDATA->m_hPen = 0 ;
128
129 RealizeResource();
130
131 if ( wxThePenList )
132 wxThePenList->AddPen(this);
133 }
134
135 wxPen::wxPen(const wxString& col, int Width, int Style)
136 {
137 m_refData = new wxPenRefData;
138
139 M_PENDATA->m_colour = col;
140 // M_PENDATA->m_stipple = NULL ;
141 M_PENDATA->m_width = Width;
142 M_PENDATA->m_style = Style;
143 M_PENDATA->m_join = wxJOIN_ROUND ;
144 M_PENDATA->m_cap = wxCAP_ROUND ;
145 M_PENDATA->m_nbDash = 0 ;
146 M_PENDATA->m_dash = 0 ;
147 M_PENDATA->m_hPen = 0 ;
148
149 RealizeResource();
150
151 if ( wxThePenList )
152 wxThePenList->AddPen(this);
153 }
154
155 bool wxPen::RealizeResource(void)
156 {
157 if (M_PENDATA && (M_PENDATA->m_hPen == 0))
158 {
159 if (M_PENDATA->m_style==wxTRANSPARENT)
160 {
161 M_PENDATA->m_hPen = (WXHPEN) ::GetStockObject(NULL_PEN);
162 return TRUE;
163 }
164
165 COLORREF ms_colour = 0 ;
166 ms_colour = M_PENDATA->m_colour.GetPixel() ;
167
168 // Join style, Cap style, Pen Stippling only on Win32.
169 // Currently no time to find equivalent on Win3.1, sorry
170 // [if such equiv exist!!]
171 #ifdef __WIN32__
172 if (M_PENDATA->m_join==wxJOIN_ROUND &&
173 M_PENDATA->m_cap==wxCAP_ROUND &&
174 M_PENDATA->m_style!=wxUSER_DASH &&
175 M_PENDATA->m_style!=wxSTIPPLE &&
176 M_PENDATA->m_width <= 1
177 )
178 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
179 else
180 {
181 DWORD ms_style = PS_GEOMETRIC|wx2msPenStyle(M_PENDATA->m_style) ;
182
183 LOGBRUSH logb ;
184
185 switch(M_PENDATA->m_join)
186 {
187 case wxJOIN_BEVEL: ms_style |= PS_JOIN_BEVEL ; break ;
188 case wxJOIN_MITER: ms_style |= PS_JOIN_MITER ; break ;
189 default:
190 case wxJOIN_ROUND: ms_style |= PS_JOIN_ROUND ; break ;
191 }
192
193 switch(M_PENDATA->m_cap)
194 {
195 case wxCAP_PROJECTING: ms_style |= PS_ENDCAP_SQUARE ; break ;
196 case wxCAP_BUTT: ms_style |= PS_ENDCAP_FLAT ; break ;
197 default:
198 case wxCAP_ROUND: ms_style |= PS_ENDCAP_ROUND ; break ;
199 }
200
201 switch(M_PENDATA->m_style)
202 {
203 case wxSTIPPLE:
204 logb.lbStyle = BS_PATTERN ;
205 if (M_PENDATA->m_stipple.Ok())
206 logb.lbHatch = (LONG)M_PENDATA->m_stipple.GetHBITMAP() ;
207 else
208 logb.lbHatch = (LONG)0 ;
209 break ;
210 case wxBDIAGONAL_HATCH:
211 logb.lbStyle = BS_HATCHED ;
212 logb.lbHatch = HS_BDIAGONAL ;
213 break ;
214 case wxCROSSDIAG_HATCH:
215 logb.lbStyle = BS_HATCHED ;
216 logb.lbHatch = HS_DIAGCROSS ;
217 break ;
218 case wxFDIAGONAL_HATCH:
219 logb.lbStyle = BS_HATCHED ;
220 logb.lbHatch = HS_FDIAGONAL ;
221 break ;
222 case wxCROSS_HATCH:
223 logb.lbStyle = BS_HATCHED ;
224 logb.lbHatch = HS_CROSS ;
225 break ;
226 case wxHORIZONTAL_HATCH:
227 logb.lbStyle = BS_HATCHED ;
228 logb.lbHatch = HS_HORIZONTAL ;
229 break ;
230 case wxVERTICAL_HATCH:
231 logb.lbStyle = BS_HATCHED ;
232 logb.lbHatch = HS_VERTICAL ;
233 break ;
234 default:
235 logb.lbStyle = BS_SOLID ;
236 break ;
237 }
238 logb.lbColor = ms_colour ;
239 wxDash *real_dash ;
240 if (M_PENDATA->m_style==wxUSER_DASH && M_PENDATA->m_nbDash && M_PENDATA->m_dash)
241 {
242 real_dash = new wxDash[M_PENDATA->m_nbDash] ;
243 int i;
244 for (i=0;i<M_PENDATA->m_nbDash;i++)
245 real_dash[i] = M_PENDATA->m_dash[i] * M_PENDATA->m_width ;
246 }
247 else
248 real_dash = 0 ;
249
250 // Win32s doesn't have ExtCreatePen function...
251 if (wxGetOsVersion()==wxWINDOWS_NT || wxGetOsVersion()==wxWIN95)
252 M_PENDATA->m_hPen = (WXHPEN) ExtCreatePen(ms_style,M_PENDATA->m_width,&logb,
253 M_PENDATA->m_style==wxUSER_DASH ? M_PENDATA->m_nbDash:0, (const DWORD *)real_dash);
254 else
255 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
256
257 if (real_dash)
258 delete [] real_dash ;
259 }
260 #else
261 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
262 #endif
263 #ifdef DEBUG_CREATE
264 if (M_PENDATA->m_hPen==0)
265 wxError("Cannot create pen","Internal error") ;
266 #endif
267 return TRUE;
268 }
269 return FALSE;
270 }
271
272 WXHANDLE wxPen::GetResourceHandle(void)
273 {
274 if ( !M_PENDATA )
275 return 0;
276 else
277 return (WXHANDLE)M_PENDATA->m_hPen;
278 }
279
280 bool wxPen::FreeResource(bool force)
281 {
282 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
283 {
284 DeleteObject((HPEN) M_PENDATA->m_hPen);
285 M_PENDATA->m_hPen = 0;
286 return TRUE;
287 }
288 else return FALSE;
289 }
290
291 /*
292 bool wxPen::UseResource(void)
293 {
294 IncrementResourceUsage();
295 return TRUE;
296 }
297
298 bool wxPen::ReleaseResource(void)
299 {
300 DecrementResourceUsage();
301 return TRUE;
302 }
303 */
304
305 bool wxPen::IsFree(void)
306 {
307 return (M_PENDATA && M_PENDATA->m_hPen == 0);
308 }
309
310 void wxPen::SetColour(const wxColour& col)
311 {
312 if ( !M_PENDATA )
313 m_refData = new wxPenRefData;
314
315 M_PENDATA->m_colour = col;
316
317 if (FreeResource())
318 RealizeResource();
319 }
320
321 void wxPen::SetColour(const wxString& col)
322 {
323 if ( !M_PENDATA )
324 m_refData = new wxPenRefData;
325
326 M_PENDATA->m_colour = col;
327
328 if (FreeResource())
329 RealizeResource();
330 }
331
332 void wxPen::SetColour(const unsigned char r, const unsigned char g, const unsigned char b)
333 {
334 if ( !M_PENDATA )
335 m_refData = new wxPenRefData;
336
337 M_PENDATA->m_colour.Set(r, g, b);
338
339 if (FreeResource())
340 RealizeResource();
341 }
342
343 void wxPen::SetWidth(int Width)
344 {
345 if ( !M_PENDATA )
346 m_refData = new wxPenRefData;
347
348 M_PENDATA->m_width = Width;
349
350 if (FreeResource())
351 RealizeResource();
352 }
353
354 void wxPen::SetStyle(int Style)
355 {
356 if ( !M_PENDATA )
357 m_refData = new wxPenRefData;
358
359 M_PENDATA->m_style = Style;
360
361 if (FreeResource())
362 RealizeResource();
363 }
364
365 void wxPen::SetStipple(const wxBitmap& Stipple)
366 {
367 if ( !M_PENDATA )
368 m_refData = new wxPenRefData;
369
370 M_PENDATA->m_stipple = Stipple;
371 M_PENDATA->m_style = wxSTIPPLE;
372
373 if (FreeResource())
374 RealizeResource();
375 }
376
377 void wxPen::SetDashes(int nb_dashes, const wxDash *Dash)
378 {
379 if ( !M_PENDATA )
380 m_refData = new wxPenRefData;
381
382 M_PENDATA->m_nbDash = nb_dashes;
383 M_PENDATA->m_dash = (wxDash *)Dash;
384
385 if (FreeResource())
386 RealizeResource();
387 }
388
389 void wxPen::SetJoin(int Join)
390 {
391 if ( !M_PENDATA )
392 m_refData = new wxPenRefData;
393
394 M_PENDATA->m_join = Join;
395
396 if (FreeResource())
397 RealizeResource();
398 }
399
400 void wxPen::SetCap(int Cap)
401 {
402 if ( !M_PENDATA )
403 m_refData = new wxPenRefData;
404
405 M_PENDATA->m_cap = Cap;
406
407 if (FreeResource())
408 RealizeResource();
409 }
410
411 int wx2msPenStyle(int wx_style)
412 {
413 int cstyle;
414 /***
415 #ifdef __WIN32__
416 DWORD vers = GetVersion() ;
417 WORD high = HIWORD(vers) ; // high bit=0 for NT, 1 for Win32s
418 #endif
419 ***/
420 switch (wx_style)
421 {
422 case wxDOT:
423 cstyle = PS_DOT;
424 break;
425 case wxSHORT_DASH:
426 case wxLONG_DASH:
427 cstyle = PS_DASH;
428 break;
429 case wxTRANSPARENT:
430 cstyle = PS_NULL;
431 break;
432 case wxUSER_DASH:
433 // User dash style not supported on Win3.1, sorry...
434 #ifdef __WIN32__
435 // Win32s doesn't have PS_USERSTYLE
436 /***
437 if ((high&0x8000)==0)
438 ***/
439 if (wxGetOsVersion()==wxWINDOWS_NT)
440 cstyle = PS_USERSTYLE ;
441 else
442 cstyle = PS_DOT ; // We must make a choice... This is mine!
443 #else
444 cstyle = PS_DASH ;
445 #endif
446 break ;
447 case wxSOLID:
448 default:
449 cstyle = PS_SOLID;
450 break;
451 }
452 return cstyle;
453 }
454