Include order is wxprec.h=>defs.h=>platform.h=>setup.h so remove explicit setup.h...
[wxWidgets.git] / src / msw / pen.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/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
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include <stdio.h>
21 #include "wx/list.h"
22 #include "wx/utils.h"
23 #include "wx/app.h"
24 #include "wx/pen.h"
25 #endif
26
27 #include "wx/msw/private.h"
28
29 static int wx2msPenStyle(int wx_style);
30
31 IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
32
33 wxPenRefData::wxPenRefData()
34 {
35 m_style = wxSOLID;
36 m_width = 1;
37 m_join = wxJOIN_ROUND ;
38 m_cap = wxCAP_ROUND ;
39 m_nbDash = 0 ;
40 m_dash = (wxDash*)NULL;
41 m_hPen = 0;
42 }
43
44 wxPenRefData::wxPenRefData(const wxPenRefData& data)
45 :wxGDIRefData()
46 {
47 m_style = data.m_style;
48 m_width = data.m_width;
49 m_join = data.m_join;
50 m_cap = data.m_cap;
51 m_nbDash = data.m_nbDash;
52 m_dash = data.m_dash;
53 m_colour = data.m_colour;
54 m_hPen = 0;
55 }
56
57 wxPenRefData::~wxPenRefData()
58 {
59 if ( m_hPen )
60 ::DeleteObject((HPEN) m_hPen);
61 }
62
63 // Pens
64
65 wxPen::wxPen()
66 {
67 }
68
69 wxPen::~wxPen()
70 {
71 }
72
73 // Should implement Create
74 wxPen::wxPen(const wxColour& col, int Width, int Style)
75 {
76 m_refData = new wxPenRefData;
77
78 M_PENDATA->m_colour = col;
79 // M_PENDATA->m_stipple = NULL;
80 M_PENDATA->m_width = Width;
81 M_PENDATA->m_style = Style;
82 M_PENDATA->m_join = wxJOIN_ROUND ;
83 M_PENDATA->m_cap = wxCAP_ROUND ;
84 M_PENDATA->m_nbDash = 0 ;
85 M_PENDATA->m_dash = (wxDash*)NULL;
86 M_PENDATA->m_hPen = 0 ;
87
88 RealizeResource();
89 }
90
91 wxPen::wxPen(const wxBitmap& stipple, int Width)
92 {
93 m_refData = new wxPenRefData;
94
95 // M_PENDATA->m_colour = col;
96 M_PENDATA->m_stipple = stipple;
97 M_PENDATA->m_width = Width;
98 M_PENDATA->m_style = wxSTIPPLE;
99 M_PENDATA->m_join = wxJOIN_ROUND ;
100 M_PENDATA->m_cap = wxCAP_ROUND ;
101 M_PENDATA->m_nbDash = 0 ;
102 M_PENDATA->m_dash = (wxDash*)NULL;
103 M_PENDATA->m_hPen = 0 ;
104
105 RealizeResource();
106 }
107
108 bool wxPen::RealizeResource()
109 {
110 if ( !M_PENDATA || M_PENDATA->m_hPen )
111 return false;
112
113 if (M_PENDATA->m_style==wxTRANSPARENT)
114 {
115 M_PENDATA->m_hPen = (WXHPEN) ::GetStockObject(NULL_PEN);
116 return true;
117 }
118
119 static const int os = wxGetOsVersion();
120 COLORREF ms_colour = M_PENDATA->m_colour.GetPixel();
121
122 // Join style, Cap style, Pen Stippling
123 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
124 // Only NT can display dashed or dotted lines with width > 1
125 if ( os != wxWINDOWS_NT &&
126 (M_PENDATA->m_style == wxDOT ||
127 M_PENDATA->m_style == wxLONG_DASH ||
128 M_PENDATA->m_style == wxSHORT_DASH ||
129 M_PENDATA->m_style == wxDOT_DASH ||
130 M_PENDATA->m_style == wxUSER_DASH) &&
131 M_PENDATA->m_width > 1 )
132 {
133 M_PENDATA->m_width = 1;
134 }
135
136 if (M_PENDATA->m_join==wxJOIN_ROUND &&
137 M_PENDATA->m_cap==wxCAP_ROUND &&
138 M_PENDATA->m_style!=wxUSER_DASH &&
139 M_PENDATA->m_style!=wxSTIPPLE &&
140 M_PENDATA->m_width <= 1)
141 {
142 M_PENDATA->m_hPen =
143 (WXHPEN) CreatePen( wx2msPenStyle(M_PENDATA->m_style),
144 M_PENDATA->m_width,
145 ms_colour );
146 }
147 else
148 {
149 DWORD ms_style = PS_GEOMETRIC | wx2msPenStyle(M_PENDATA->m_style);
150
151 switch(M_PENDATA->m_join)
152 {
153 case wxJOIN_BEVEL: ms_style |= PS_JOIN_BEVEL; break;
154 case wxJOIN_MITER: ms_style |= PS_JOIN_MITER; break;
155 default:
156 case wxJOIN_ROUND: ms_style |= PS_JOIN_ROUND; break;
157 }
158
159 switch(M_PENDATA->m_cap)
160 {
161 case wxCAP_PROJECTING: ms_style |= PS_ENDCAP_SQUARE; break;
162 case wxCAP_BUTT: ms_style |= PS_ENDCAP_FLAT; break;
163 default:
164 case wxCAP_ROUND: ms_style |= PS_ENDCAP_ROUND; break;
165 }
166
167 LOGBRUSH logb;
168
169 switch(M_PENDATA->m_style)
170 {
171 case wxSTIPPLE:
172 logb.lbStyle = BS_PATTERN ;
173 if (M_PENDATA->m_stipple.Ok())
174 logb.lbHatch = (LONG)M_PENDATA->m_stipple.GetHBITMAP();
175 else
176 logb.lbHatch = (LONG)0;
177 break;
178 case wxBDIAGONAL_HATCH:
179 logb.lbStyle = BS_HATCHED;
180 logb.lbHatch = HS_BDIAGONAL;
181 break;
182 case wxCROSSDIAG_HATCH:
183 logb.lbStyle = BS_HATCHED;
184 logb.lbHatch = HS_DIAGCROSS;
185 break;
186 case wxFDIAGONAL_HATCH:
187 logb.lbStyle = BS_HATCHED;
188 logb.lbHatch = HS_FDIAGONAL;
189 break;
190 case wxCROSS_HATCH:
191 logb.lbStyle = BS_HATCHED;
192 logb.lbHatch = HS_CROSS;
193 break;
194 case wxHORIZONTAL_HATCH:
195 logb.lbStyle = BS_HATCHED;
196 logb.lbHatch = HS_HORIZONTAL;
197 break;
198 case wxVERTICAL_HATCH:
199 logb.lbStyle = BS_HATCHED;
200 logb.lbHatch = HS_VERTICAL;
201 break;
202 default:
203 logb.lbStyle = BS_SOLID;
204 #ifdef __WXDEBUG__
205 // this should be unnecessary (it's unused) but suppresses the Purify
206 // messages about uninitialized memory read
207 logb.lbHatch = 0;
208 #endif
209 break;
210 }
211
212 logb.lbColor = ms_colour;
213
214 wxMSWDash *real_dash;
215 if (M_PENDATA->m_style==wxUSER_DASH && M_PENDATA->m_nbDash && M_PENDATA->m_dash)
216 {
217 real_dash = new wxMSWDash[M_PENDATA->m_nbDash];
218 int rw = M_PENDATA->m_width > 1 ? M_PENDATA->m_width : 1;
219 for ( int i = 0; i < M_PENDATA->m_nbDash; i++ )
220 real_dash[i] = M_PENDATA->m_dash[i] * rw;
221 }
222 else
223 {
224 real_dash = (wxMSWDash*)NULL;
225 }
226
227 // Win32s doesn't have ExtCreatePen function...
228 if (os==wxWINDOWS_NT || os==wxWIN95)
229 {
230 M_PENDATA->m_hPen =
231 (WXHPEN) ExtCreatePen( ms_style,
232 M_PENDATA->m_width,
233 &logb,
234 M_PENDATA->m_style == wxUSER_DASH
235 ? M_PENDATA->m_nbDash
236 : 0,
237 (LPDWORD)real_dash );
238 }
239 else
240 {
241 M_PENDATA->m_hPen =
242 (WXHPEN) CreatePen( wx2msPenStyle(M_PENDATA->m_style),
243 M_PENDATA->m_width,
244 ms_colour );
245 }
246
247 delete [] real_dash;
248 }
249 #else // WinCE
250 M_PENDATA->m_hPen =
251 (WXHPEN) CreatePen( wx2msPenStyle(M_PENDATA->m_style),
252 M_PENDATA->m_width,
253 ms_colour );
254 #endif // !WinCE/WinCE
255
256 return true;
257 }
258
259 WXHANDLE wxPen::GetResourceHandle() const
260 {
261 if ( !M_PENDATA )
262 return 0;
263 else
264 return (WXHANDLE)M_PENDATA->m_hPen;
265 }
266
267 bool wxPen::FreeResource(bool WXUNUSED(force))
268 {
269 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
270 {
271 DeleteObject((HPEN) M_PENDATA->m_hPen);
272 M_PENDATA->m_hPen = 0;
273 return true;
274 }
275 else return false;
276 }
277
278 bool wxPen::IsFree() const
279 {
280 return (M_PENDATA && M_PENDATA->m_hPen == 0);
281 }
282
283 void wxPen::Unshare()
284 {
285 // Don't change shared data
286 if (!m_refData)
287 {
288 m_refData = new wxPenRefData();
289 }
290 else
291 {
292 wxPenRefData* ref = new wxPenRefData(*(wxPenRefData*)m_refData);
293 UnRef();
294 m_refData = ref;
295 }
296 }
297
298 void wxPen::SetColour(const wxColour& col)
299 {
300 Unshare();
301
302 M_PENDATA->m_colour = col;
303
304 RealizeResource();
305 }
306
307 void wxPen::SetColour(unsigned char r, unsigned char g, unsigned char b)
308 {
309 Unshare();
310
311 M_PENDATA->m_colour.Set(r, g, b);
312
313 RealizeResource();
314 }
315
316 void wxPen::SetWidth(int Width)
317 {
318 Unshare();
319
320 M_PENDATA->m_width = Width;
321
322 RealizeResource();
323 }
324
325 void wxPen::SetStyle(int Style)
326 {
327 Unshare();
328
329 M_PENDATA->m_style = Style;
330
331 RealizeResource();
332 }
333
334 void wxPen::SetStipple(const wxBitmap& Stipple)
335 {
336 Unshare();
337
338 M_PENDATA->m_stipple = Stipple;
339 M_PENDATA->m_style = wxSTIPPLE;
340
341 RealizeResource();
342 }
343
344 void wxPen::SetDashes(int nb_dashes, const wxDash *Dash)
345 {
346 Unshare();
347
348 M_PENDATA->m_nbDash = nb_dashes;
349 M_PENDATA->m_dash = (wxDash *)Dash;
350
351 RealizeResource();
352 }
353
354 void wxPen::SetJoin(int Join)
355 {
356 Unshare();
357
358 M_PENDATA->m_join = Join;
359
360 RealizeResource();
361 }
362
363 void wxPen::SetCap(int Cap)
364 {
365 Unshare();
366
367 M_PENDATA->m_cap = Cap;
368
369 RealizeResource();
370 }
371
372 int wx2msPenStyle(int wx_style)
373 {
374 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
375 switch (wx_style)
376 {
377 case wxDOT:
378 return PS_DOT;
379
380 case wxDOT_DASH:
381 return PS_DASHDOT;
382
383 case wxSHORT_DASH:
384 case wxLONG_DASH:
385 return PS_DASH;
386
387 case wxTRANSPARENT:
388 return PS_NULL;
389
390 case wxUSER_DASH:
391 // if (wxGetOsVersion()==wxWINDOWS_NT || wxGetOsVersion()==wxWIN95)
392 return PS_USERSTYLE;
393 }
394 #else
395 wxUnusedVar(wx_style);
396 #endif
397 return PS_SOLID;
398 }