added some wxMSW stuff
[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, const int Width, const 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, const 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, const int Width, const 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 // In Windows, only a pen of width = 1 can be dotted or dashed!
150 if ((Style == wxDOT) || (Style == wxLONG_DASH) || (Style == wxSHORT_DASH) || (Style == wxDOT_DASH))
151 M_PENDATA->m_width = 1;
152
153 RealizeResource();
154
155 if ( wxThePenList )
156 wxThePenList->AddPen(this);
157 }
158
159 bool wxPen::RealizeResource(void)
160 {
161 if (M_PENDATA && (M_PENDATA->m_hPen == 0))
162 {
163 if (M_PENDATA->m_style==wxTRANSPARENT)
164 {
165 M_PENDATA->m_hPen = (WXHPEN) ::GetStockObject(NULL_PEN);
166 return TRUE;
167 }
168
169 COLORREF ms_colour = 0 ;
170 ms_colour = M_PENDATA->m_colour.GetPixel() ;
171
172 // Join style, Cap style, Pen Stippling only on Win32.
173 // Currently no time to find equivalent on Win3.1, sorry
174 // [if such equiv exist!!]
175 #ifdef __WIN32__
176 if (M_PENDATA->m_join==wxJOIN_ROUND &&
177 M_PENDATA->m_cap==wxCAP_ROUND &&
178 M_PENDATA->m_style!=wxUSER_DASH &&
179 M_PENDATA->m_style!=wxSTIPPLE
180 )
181 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
182 else
183 {
184 DWORD ms_style = PS_GEOMETRIC|wx2msPenStyle(M_PENDATA->m_style) ;
185
186 LOGBRUSH logb ;
187
188 switch(M_PENDATA->m_join)
189 {
190 case wxJOIN_BEVEL: ms_style |= PS_JOIN_BEVEL ; break ;
191 case wxJOIN_MITER: ms_style |= PS_JOIN_MITER ; break ;
192 default:
193 case wxJOIN_ROUND: ms_style |= PS_JOIN_ROUND ; break ;
194 }
195
196 switch(M_PENDATA->m_cap)
197 {
198 case wxCAP_PROJECTING: ms_style |= PS_ENDCAP_SQUARE ; break ;
199 case wxCAP_BUTT: ms_style |= PS_ENDCAP_FLAT ; break ;
200 default:
201 case wxCAP_ROUND: ms_style |= PS_ENDCAP_ROUND ; break ;
202 }
203
204 switch(M_PENDATA->m_style)
205 {
206 case wxSTIPPLE:
207 logb.lbStyle = BS_PATTERN ;
208 if (M_PENDATA->m_stipple.Ok())
209 logb.lbHatch = (LONG)M_PENDATA->m_stipple.GetHBITMAP() ;
210 else
211 logb.lbHatch = (LONG)0 ;
212 break ;
213 case wxBDIAGONAL_HATCH:
214 logb.lbStyle = BS_HATCHED ;
215 logb.lbHatch = HS_BDIAGONAL ;
216 break ;
217 case wxCROSSDIAG_HATCH:
218 logb.lbStyle = BS_HATCHED ;
219 logb.lbHatch = HS_DIAGCROSS ;
220 break ;
221 case wxFDIAGONAL_HATCH:
222 logb.lbStyle = BS_HATCHED ;
223 logb.lbHatch = HS_FDIAGONAL ;
224 break ;
225 case wxCROSS_HATCH:
226 logb.lbStyle = BS_HATCHED ;
227 logb.lbHatch = HS_CROSS ;
228 break ;
229 case wxHORIZONTAL_HATCH:
230 logb.lbStyle = BS_HATCHED ;
231 logb.lbHatch = HS_HORIZONTAL ;
232 break ;
233 case wxVERTICAL_HATCH:
234 logb.lbStyle = BS_HATCHED ;
235 logb.lbHatch = HS_VERTICAL ;
236 break ;
237 default:
238 logb.lbStyle = BS_SOLID ;
239 break ;
240 }
241 logb.lbColor = ms_colour ;
242 wxDash *real_dash ;
243 if (M_PENDATA->m_style==wxUSER_DASH && M_PENDATA->m_nbDash && M_PENDATA->m_dash)
244 {
245 real_dash = new wxDash[M_PENDATA->m_nbDash] ;
246 int i;
247 for (i=0;i<M_PENDATA->m_nbDash;i++)
248 real_dash[i] = M_PENDATA->m_dash[i] * M_PENDATA->m_width ;
249 }
250 else
251 real_dash = 0 ;
252
253 // Win32s doesn't have ExtCreatePen function...
254 if (wxGetOsVersion()==wxWINDOWS_NT || wxGetOsVersion()==wxWIN95)
255 M_PENDATA->m_hPen = (WXHPEN) ExtCreatePen(ms_style,M_PENDATA->m_width,&logb,
256 M_PENDATA->m_style==wxUSER_DASH ? M_PENDATA->m_nbDash:0, (const DWORD *)real_dash);
257 else
258 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
259
260 if (real_dash)
261 delete [] real_dash ;
262 }
263 #else
264 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
265 #endif
266 #ifdef DEBUG_CREATE
267 if (M_PENDATA->m_hPen==0)
268 wxError("Cannot create pen","Internal error") ;
269 #endif
270 return TRUE;
271 }
272 return FALSE;
273 }
274
275 WXHANDLE wxPen::GetResourceHandle(void)
276 {
277 if ( !M_PENDATA )
278 return 0;
279 else
280 return (WXHANDLE)M_PENDATA->m_hPen;
281 }
282
283 bool wxPen::FreeResource(bool force)
284 {
285 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
286 {
287 DeleteObject((HPEN) M_PENDATA->m_hPen);
288 M_PENDATA->m_hPen = 0;
289 return TRUE;
290 }
291 else return FALSE;
292 }
293
294 /*
295 bool wxPen::UseResource(void)
296 {
297 IncrementResourceUsage();
298 return TRUE;
299 }
300
301 bool wxPen::ReleaseResource(void)
302 {
303 DecrementResourceUsage();
304 return TRUE;
305 }
306 */
307
308 bool wxPen::IsFree(void)
309 {
310 return (M_PENDATA && M_PENDATA->m_hPen == 0);
311 }
312
313 void wxPen::SetColour(const wxColour& col)
314 {
315 if ( !M_PENDATA )
316 m_refData = new wxPenRefData;
317
318 M_PENDATA->m_colour = col;
319
320 if (FreeResource())
321 RealizeResource();
322 }
323
324 void wxPen::SetColour(const wxString& col)
325 {
326 if ( !M_PENDATA )
327 m_refData = new wxPenRefData;
328
329 M_PENDATA->m_colour = col;
330
331 if (FreeResource())
332 RealizeResource();
333 }
334
335 void wxPen::SetColour(const unsigned char r, const unsigned char g, const unsigned char b)
336 {
337 if ( !M_PENDATA )
338 m_refData = new wxPenRefData;
339
340 M_PENDATA->m_colour.Set(r, g, b);
341
342 if (FreeResource())
343 RealizeResource();
344 }
345
346 void wxPen::SetWidth(const int Width)
347 {
348 if ( !M_PENDATA )
349 m_refData = new wxPenRefData;
350
351 M_PENDATA->m_width = Width;
352
353 if (FreeResource())
354 RealizeResource();
355 }
356
357 void wxPen::SetStyle(const int Style)
358 {
359 if ( !M_PENDATA )
360 m_refData = new wxPenRefData;
361
362 M_PENDATA->m_style = Style;
363
364 if (FreeResource())
365 RealizeResource();
366 }
367
368 void wxPen::SetStipple(const wxBitmap& Stipple)
369 {
370 if ( !M_PENDATA )
371 m_refData = new wxPenRefData;
372
373 M_PENDATA->m_stipple = Stipple;
374 M_PENDATA->m_style = wxSTIPPLE;
375
376 if (FreeResource())
377 RealizeResource();
378 }
379
380 void wxPen::SetDashes(const int nb_dashes, const wxDash *Dash)
381 {
382 if ( !M_PENDATA )
383 m_refData = new wxPenRefData;
384
385 M_PENDATA->m_nbDash = nb_dashes;
386 M_PENDATA->m_dash = (wxDash *)Dash;
387
388 if (FreeResource())
389 RealizeResource();
390 }
391
392 void wxPen::SetJoin(const int Join)
393 {
394 if ( !M_PENDATA )
395 m_refData = new wxPenRefData;
396
397 M_PENDATA->m_join = Join;
398
399 if (FreeResource())
400 RealizeResource();
401 }
402
403 void wxPen::SetCap(const int Cap)
404 {
405 if ( !M_PENDATA )
406 m_refData = new wxPenRefData;
407
408 M_PENDATA->m_cap = Cap;
409
410 if (FreeResource())
411 RealizeResource();
412 }
413
414 int wx2msPenStyle(int wx_style)
415 {
416 int cstyle;
417 /***
418 #ifdef __WIN32__
419 DWORD vers = GetVersion() ;
420 WORD high = HIWORD(vers) ; // high bit=0 for NT, 1 for Win32s
421 #endif
422 ***/
423 switch (wx_style)
424 {
425 case wxDOT:
426 cstyle = PS_DOT;
427 break;
428 case wxSHORT_DASH:
429 case wxLONG_DASH:
430 cstyle = PS_DASH;
431 break;
432 case wxTRANSPARENT:
433 cstyle = PS_NULL;
434 break;
435 case wxUSER_DASH:
436 // User dash style not supported on Win3.1, sorry...
437 #ifdef __WIN32__
438 // Win32s doesn't have PS_USERSTYLE
439 /***
440 if ((high&0x8000)==0)
441 ***/
442 if (wxGetOsVersion()==wxWINDOWS_NT)
443 cstyle = PS_USERSTYLE ;
444 else
445 cstyle = PS_DOT ; // We must make a choice... This is mine!
446 #else
447 cstyle = PS_DASH ;
448 #endif
449 break ;
450 case wxSOLID:
451 default:
452 cstyle = PS_SOLID;
453 break;
454 }
455 return cstyle;
456 }
457