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