Initialize m_cocoaDash to NULL in copy constructor
[wxWidgets.git] / src / cocoa / pen.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/pen.mm
3 // Purpose:     wxPen
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2003/08/02
7 // RCS-ID:      $Id$
8 // Copyright:   (c) 2003 David Elliott
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/setup.h"
13 #include "wx/pen.h"
14 #include "wx/bitmap.h"
15 #include "wx/colour.h"
16
17 #import <AppKit/NSColor.h>
18
19 // ========================================================================
20 // wxPenRefData
21 // ========================================================================
22 class WXDLLEXPORT wxPenRefData: public wxGDIRefData
23 {
24     friend class WXDLLEXPORT wxPen;
25 public:
26     wxPenRefData(const wxColour& colour = wxNullColour,
27         int width = 1, int style = wxSOLID,
28         const wxBitmap& stipple = wxNullBitmap);
29     wxPenRefData(const wxPenRefData& data);
30     ~wxPenRefData() { FreeCocoaNSColor(); FreeCocoaDash(); }
31
32     void SetWidth(int Width) { m_width = Width; }
33     void SetStyle(int Style)
34     {   FreeCocoaNSColor();
35         FreeCocoaDash();
36         m_style = Style;
37     }
38     void SetJoin(int Join) { m_join = Join; }
39     void SetCap(int Cap) { m_cap = Cap; }
40     void SetColour(const wxColour& col) { FreeCocoaNSColor(); m_colour = col; }
41     void SetDashes(int nb_dashes, const wxDash *Dash)
42     {
43         FreeCocoaDash();
44         m_nbDash = nb_dashes;
45         m_dash = (wxDash *)Dash;
46     }
47     void SetStipple(const wxBitmap& Stipple)
48     {
49         FreeCocoaNSColor();
50         m_stipple = Stipple;
51         m_style = wxSTIPPLE;
52     }
53     WX_NSColor GetNSColor();
54     int GetCocoaLineDash(const float **pattern);
55 protected:
56     void FreeCocoaNSColor();
57     void FreeCocoaDash();
58
59     int             m_width;
60     int             m_style;
61     int             m_join;
62     int             m_cap;
63     wxColour        m_colour;
64     int             m_nbDash;
65     wxDash         *m_dash;
66     wxBitmap        m_stipple;
67     WX_NSColor      m_cocoaNSColor;
68     float          *m_cocoaDash;
69
70     // Predefined dash patterns
71     static const int scm_countDot;
72     static const float scm_patternDot[];
73     static const int scm_countLongDash;
74     static const float scm_patternLongDash[];
75     static const int scm_countShortDash;
76     static const float scm_patternShortDash[];
77     static const int scm_countDotDash;
78     static const float scm_patternDotDash[];
79 private:
80     // Don't allow assignment
81     wxPenRefData& operator=(const wxPenRefData& data);
82 };
83
84 const int wxPenRefData::scm_countDot = 1;
85 const float wxPenRefData::scm_patternDot[] = {
86     1.0
87 };
88 const int wxPenRefData::scm_countLongDash = 1;
89 const float wxPenRefData::scm_patternLongDash[] = {
90     10.0
91 };
92 const int wxPenRefData::scm_countShortDash = 1;
93 const float wxPenRefData::scm_patternShortDash[] = {
94     5.0
95 };
96 const int wxPenRefData::scm_countDotDash = 4;
97 const float wxPenRefData::scm_patternDotDash[] = {
98     1.0
99 ,   1.0
100 ,   5.0
101 ,   1.0
102 };
103
104 #define M_PENDATA ((wxPenRefData *)m_refData)
105
106 inline wxPenRefData::wxPenRefData(const wxColour& colour,
107         int width, int style, const wxBitmap& stipple)
108 {
109     m_width = width;
110     m_style = style;
111     m_join = wxJOIN_ROUND;
112     m_cap = wxCAP_ROUND;
113     m_colour = colour;
114     m_nbDash = 0;
115     m_dash = 0;
116     m_stipple = stipple;
117     m_cocoaNSColor = nil;
118     m_cocoaDash = NULL;
119 }
120
121 inline wxPenRefData::wxPenRefData(const wxPenRefData& data)
122 {
123     m_width = data.m_width;
124     m_style = data.m_style;
125     m_join = data.m_join;
126     m_cap = data.m_cap;
127     m_colour = data.m_colour;
128     m_nbDash = data.m_nbDash;
129     m_dash = data.m_dash;
130     m_stipple = data.m_stipple;
131     m_cocoaNSColor = [data.m_cocoaNSColor retain];
132     m_cocoaDash = NULL;
133 }
134
135 inline void wxPenRefData::FreeCocoaNSColor()
136 {
137     [m_cocoaNSColor release];
138     m_cocoaNSColor = nil;
139 }
140
141 inline void wxPenRefData::FreeCocoaDash()
142 {
143     delete m_cocoaDash;
144     m_cocoaDash = NULL;
145 }
146
147 inline WX_NSColor wxPenRefData::GetNSColor()
148 {
149     if(!m_cocoaNSColor)
150     {
151         switch( m_style )
152         {
153         case wxTRANSPARENT:
154             m_cocoaNSColor = [[NSColor clearColor] retain];
155             break;
156         case wxSTIPPLE:
157 //  wxBitmap isn't implemented yet
158 //            m_cocoaNSColor = [[NSColor colorWithPatternImage: m_stipple.GetNSImage()] retain];
159 //            break;
160         // The hatch brushes are going to be tricky
161         case wxBDIAGONAL_HATCH:
162         case wxCROSSDIAG_HATCH:
163         case wxFDIAGONAL_HATCH:
164         case wxCROSS_HATCH:
165         case wxHORIZONTAL_HATCH:
166         case wxVERTICAL_HATCH:
167         default:
168         // Dot/dashed pens use solid colors
169         case wxDOT:
170         case wxLONG_DASH:
171         case wxSHORT_DASH:
172         case wxDOT_DASH:
173         case wxUSER_DASH:
174         case wxSOLID:
175             NSColor *colour_NSColor = m_colour.GetNSColor();
176             if(!colour_NSColor)
177                 colour_NSColor = [NSColor clearColor];
178             m_cocoaNSColor = [colour_NSColor copyWithZone:nil];
179             break;
180         }
181     }
182     return m_cocoaNSColor;
183 }
184
185 int wxPenRefData::GetCocoaLineDash(const float **pattern)
186 {
187     int count;
188     switch( m_style )
189     {
190     case wxDOT:
191         count = scm_countDot;
192         if(pattern)
193             *pattern = scm_patternDot;
194         break;
195     case wxLONG_DASH:
196         count = scm_countLongDash;
197         if(pattern)
198             *pattern = scm_patternLongDash;
199         break;
200     case wxSHORT_DASH:
201         count = scm_countShortDash;
202         if(pattern)
203             *pattern = scm_patternShortDash;
204         break;
205     case wxDOT_DASH:
206         count = scm_countDotDash;
207         if(pattern)
208             *pattern = scm_patternDotDash;
209         break;
210     case wxUSER_DASH:
211         count = m_nbDash;
212         if(pattern)
213         {
214             if(!m_cocoaDash)
215             {
216                 m_cocoaDash = new float[count];
217                 for(int i=0; i<count; i++)
218                     m_cocoaDash[i] = m_dash[i];
219             }
220             *pattern = m_cocoaDash;
221         }
222         break;
223     case wxTRANSPARENT:
224     case wxSTIPPLE:
225     case wxBDIAGONAL_HATCH:
226     case wxCROSSDIAG_HATCH:
227     case wxFDIAGONAL_HATCH:
228     case wxCROSS_HATCH:
229     case wxHORIZONTAL_HATCH:
230     case wxVERTICAL_HATCH:
231     case wxSOLID:
232     default:
233         count = 0;
234         if(pattern)
235             *pattern = NULL;
236     }
237     return count;
238 }
239
240 // ========================================================================
241 // wxPen
242 // ========================================================================
243 IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
244
245 wxPen::wxPen()
246 {
247 }
248
249 wxPen::~wxPen()
250 {
251 }
252
253 // Should implement Create
254 wxPen::wxPen(const wxColour& colour, int width, int style)
255 {
256     m_refData = new wxPenRefData(colour,width,style);
257 }
258
259 wxPen::wxPen(const wxBitmap& stipple, int width)
260 {
261     m_refData = new wxPenRefData(wxNullColour,width,wxSTIPPLE,stipple);
262 }
263
264 wxObjectRefData *wxPen::CreateRefData() const
265 {
266     return new wxPenRefData;
267 }
268
269 wxObjectRefData *wxPen::CloneRefData(const wxObjectRefData *data) const
270 {
271     return new wxPenRefData(*(wxPenRefData *)data);
272 }
273
274 void wxPen::SetWidth(int Width)
275 {
276     AllocExclusive();
277     M_PENDATA->SetWidth(Width);
278 }
279
280 void wxPen::SetStyle(int Style)
281 {
282     AllocExclusive();
283     M_PENDATA->SetStyle(Style);
284 }
285
286 void wxPen::SetJoin(int Join)
287 {
288     AllocExclusive();
289     M_PENDATA->SetJoin(Join);
290 }
291
292 void wxPen::SetCap(int Cap)
293 {
294     AllocExclusive();
295     M_PENDATA->SetCap(Cap);
296 }
297
298 void wxPen::SetColour(const wxColour& col)
299 {
300     AllocExclusive();
301     M_PENDATA->SetColour(col);
302 }
303
304 void wxPen::SetColour(unsigned char r, unsigned char g, unsigned char b)
305 {
306     AllocExclusive();
307     M_PENDATA->SetColour(wxColour(r, g, b));
308 }
309
310 void wxPen::SetDashes(int nb_dashes, const wxDash *Dash)
311 {
312     AllocExclusive();
313     M_PENDATA->SetDashes(nb_dashes, Dash);
314 }
315
316 void wxPen::SetStipple(const wxBitmap& Stipple)
317 {
318     AllocExclusive();
319     M_PENDATA->SetStipple(Stipple);
320 }
321
322 wxColour& wxPen::GetColour() const
323 {
324     return (M_PENDATA ? M_PENDATA->m_colour : wxNullColour); 
325 }
326
327 int wxPen::GetWidth() const
328 {
329     return (M_PENDATA ? M_PENDATA->m_width : 0); 
330 }
331
332 int wxPen::GetStyle() const
333 {
334     return (M_PENDATA ? M_PENDATA->m_style : 0); 
335 }
336
337 int wxPen::GetJoin() const
338 {
339     return (M_PENDATA ? M_PENDATA->m_join : 0); 
340 }
341
342 int wxPen::GetCap() const
343 {
344     return (M_PENDATA ? M_PENDATA->m_cap : 0); 
345 }
346
347 int wxPen::GetDashes(wxDash **ptr) const
348 {
349     *ptr = (M_PENDATA ? M_PENDATA->m_dash : (wxDash*) NULL); return (M_PENDATA ? M_PENDATA->m_nbDash : 0);
350 }
351
352 wxBitmap *wxPen::GetStipple() const
353 {
354     return (M_PENDATA ? (& M_PENDATA->m_stipple) : (wxBitmap*) NULL); 
355 }
356
357 WX_NSColor wxPen::GetNSColor()
358 {
359     return (M_PENDATA ? M_PENDATA->GetNSColor() : nil);
360 }
361
362 int wxPen::GetCocoaLineDash(const float **pattern)
363 {
364     if(M_PENDATA)
365         return M_PENDATA->GetCocoaLineDash(pattern);
366     if(pattern)
367         *pattern = NULL;
368     return 0;
369 }
370