]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/fontdlgosx.mm
making implementation independent of a wx-peer of that control
[wxWidgets.git] / src / mac / carbon / fontdlgosx.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: fontdlg.cpp
3 // Purpose: wxFontDialog class.
4 // Author: Ryan Norton
5 // Modified by:
6 // Created: 2004-10-03
7 // RCS-ID: $Id$
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 #include "wx/cmndata.h"
21 #include "wx/fontdlg.h"
22 #include "wx/fontutil.h"
23 #include "wx/log.h"
24
25 // ============================================================================
26 // implementation
27 // ============================================================================
28
29 //Mac OSX 10.2+ only
30 #if USE_NATIVE_FONT_DIALOG_FOR_MACOSX
31
32 #if !USE_SHARED_LIBRARY
33 IMPLEMENT_DYNAMIC_CLASS(wxFontDialog, wxDialog)
34 #endif
35
36 // Cocoa headers
37 #include "wx/cocoa/autorelease.h"
38 #include "wx/cocoa/string.h"
39
40 #import <AppKit/NSFont.h>
41 #import <AppKit/NSFontManager.h>
42 #import <AppKit/NSFontPanel.h>
43 #import <AppKit/NSColor.h>
44 #import <AppKit/NSColorPanel.h>
45
46 // ---------------------------------------------------------------------------
47 // wxWCDelegate - Window Closed delegate
48 // ---------------------------------------------------------------------------
49
50 @interface wxWCDelegate : NSObject
51 {
52 bool m_bIsClosed;
53 }
54
55 // Delegate methods
56 - (id)init;
57 - (BOOL)windowShouldClose:(id)sender;
58 - (BOOL)isClosed;
59 @end // interface wxNSFontPanelDelegate : NSObject
60
61 @implementation wxWCDelegate : NSObject
62
63 - (id)init
64 {
65 [super init];
66 m_bIsClosed = false;
67
68 return self;
69 }
70
71 - (BOOL)windowShouldClose:(id)sender
72 {
73 m_bIsClosed = true;
74
75 [NSApp abortModal];
76 [NSApp stopModal];
77 return YES;
78 }
79
80 - (BOOL)isClosed
81 {
82 return m_bIsClosed;
83 }
84
85 @end // wxNSFontPanelDelegate
86
87 // ---------------------------------------------------------------------------
88 // wxWCODelegate - Window Closed or Open delegate
89 // ---------------------------------------------------------------------------
90
91 @interface wxWCODelegate : NSObject
92 {
93 bool m_bIsClosed;
94 bool m_bIsOpen;
95 }
96
97 // Delegate methods
98 - (id)init;
99 - (BOOL)windowShouldClose:(id)sender;
100 - (void)windowDidUpdate:(NSNotification *)aNotification;
101 - (BOOL)isClosed;
102 - (BOOL)isOpen;
103 @end // interface wxNSFontPanelDelegate : NSObject
104
105 @implementation wxWCODelegate : NSObject
106
107 - (id)init
108 {
109 [super init];
110 m_bIsClosed = false;
111 m_bIsOpen = false;
112
113 return self;
114 }
115
116 - (BOOL)windowShouldClose:(id)sender
117 {
118 m_bIsClosed = true;
119 m_bIsOpen = false;
120
121 [NSApp abortModal];
122 [NSApp stopModal];
123 return YES;
124 }
125
126 - (void)windowDidUpdate:(NSNotification *)aNotification
127 {
128 if (m_bIsOpen == NO)
129 {
130 m_bIsClosed = false;
131 m_bIsOpen = true;
132
133 [NSApp abortModal];
134 [NSApp stopModal];
135 }
136 }
137
138 - (BOOL)isClosed
139 {
140 return m_bIsClosed;
141 }
142
143 - (BOOL)isOpen
144 {
145 return m_bIsOpen;
146 }
147
148 @end // wxNSFontPanelDelegate
149
150 // ---------------------------------------------------------------------------
151 // wxFontDialog
152 // ---------------------------------------------------------------------------
153
154 wxFontDialog::wxFontDialog()
155 {
156 }
157
158 wxFontDialog::wxFontDialog(wxWindow *parent, const wxFontData& data)
159 {
160 Create(parent, data);
161 }
162
163 wxFontDialog::~wxFontDialog()
164 {
165 }
166
167 bool wxFontDialog::Create(wxWindow *parent, const wxFontData& data)
168 {
169 m_fontData = data;
170
171 //
172 // This is the key call - this initializes
173 // events and window stuff for cocoa for carbon
174 // applications.
175 //
176 // This is also the only call here that is
177 // 10.2+ specific (the rest is OSX only),
178 // which, ironically, the carbon font
179 // panel requires.
180 //
181 bool bOK = NSApplicationLoad();
182
183 //autorelease pool - req'd for carbon
184 NSAutoreleasePool *thePool;
185 thePool = [[NSAutoreleasePool alloc] init];
186
187 //Get the initial wx font
188 wxFont& thewxfont = m_fontData.m_initialFont;
189
190 //if the font is valid set the default (selected) font of the
191 //NSFontDialog to that font
192 if (thewxfont.Ok())
193 {
194 NSFontTraitMask theMask = 0;
195
196 if(thewxfont.GetStyle() == wxFONTSTYLE_ITALIC)
197 theMask |= NSItalicFontMask;
198
199 if(thewxfont.IsFixedWidth())
200 theMask |= NSFixedPitchFontMask;
201
202 NSFont* theDefaultFont =
203 [[NSFontManager sharedFontManager] fontWithFamily:
204 wxNSStringWithWxString(thewxfont.GetFaceName())
205 traits:theMask
206 weight:thewxfont.GetWeight() == wxBOLD ? 9 :
207 thewxfont.GetWeight() == wxLIGHT ? 0 : 5
208 size: (float)(thewxfont.GetPointSize())
209 ];
210
211 wxASSERT_MSG(theDefaultFont, wxT("Invalid default font for wxCocoaFontDialog!"));
212
213 //Apple docs say to call NSFontManager::setSelectedFont
214 //However, 10.3 doesn't seem to create the font panel
215 //is this is done, so create it ourselves
216 [[NSFontPanel sharedFontPanel] setPanelFont:theDefaultFont isMultiple:NO];
217
218 }
219
220 if(m_fontData.m_fontColour.Ok())
221 [[NSColorPanel sharedColorPanel] setColor:
222 [NSColor colorWithCalibratedRed:m_fontData.m_fontColour.Red() / 255.0
223 green:m_fontData.m_fontColour.Green() / 255.0
224 blue:m_fontData.m_fontColour.Blue() / 255.0
225 alpha:1.0]
226 ];
227 else
228 [[NSColorPanel sharedColorPanel] setColor:[NSColor blackColor]];
229
230 //We're done - free up the pool
231 [thePool release];
232
233 return bOK;
234 }
235
236 int wxFontDialog::ShowModal()
237 {
238 //Start the pool. Required for carbon interaction
239 //(For those curious, the only thing that happens
240 //if you don't do this is a bunch of error
241 //messages about leaks on the console,
242 //with no windows shown or anything).
243 NSAutoreleasePool *thePool;
244 thePool = [[NSAutoreleasePool alloc] init];
245
246 //Get the shared color and font panel
247 NSFontPanel* theFontPanel = [NSFontPanel sharedFontPanel];
248 NSColorPanel* theColorPanel = [NSColorPanel sharedColorPanel];
249
250 //Create and assign the delegates (cocoa event handlers) so
251 //we can tell if a window has closed/open or not
252 wxWCDelegate* theFPDelegate = [[wxWCDelegate alloc] init];
253 [theFontPanel setDelegate:theFPDelegate];
254
255 wxWCODelegate* theCPDelegate = [[wxWCODelegate alloc] init];
256 [theColorPanel setDelegate:theCPDelegate];
257
258 //
259 // Begin the modal loop for the font and color panels
260 //
261 // The idea is that we first make the font panel modal,
262 // but if the color panel is opened, unless we stop the
263 // modal loop the color panel opens behind the font panel
264 // with no input acceptable to it - which makes it useless.
265 //
266 // So we set up delegates for both the color and font panels,
267 // and the if the font panel opens the color panel, we
268 // stop the modal loop, and start a seperate modal loop for
269 // the color panel until the color panel closes, switching
270 // back to the font panel modal loop once it does close.
271 //
272 do
273 {
274 //
275 // Start the font panel modal loop
276 //
277 NSModalSession session = [NSApp beginModalSessionForWindow:theFontPanel];
278 for (;;)
279 {
280 [NSApp runModalSession:session];
281
282 //If the font panel is closed or the font panel
283 //opened the color panel, break
284 if ([theFPDelegate isClosed] || [theCPDelegate isOpen])
285 break;
286 }
287 [NSApp endModalSession:session];
288
289 //is the color panel open?
290 if ([theCPDelegate isOpen])
291 {
292 //
293 // Start the color panel modal loop
294 //
295 NSModalSession session = [NSApp beginModalSessionForWindow:theColorPanel];
296 for (;;)
297 {
298 [NSApp runModalSession:session];
299
300 //If the color panel is closed, return the font panel modal loop
301 if ([theCPDelegate isClosed])
302 break;
303 }
304 [NSApp endModalSession:session];
305 }
306 //If the font panel is still alive (I.E. we broke
307 //out of its modal loop because the color panel was
308 //opened) return the font panel modal loop
309 }while([theFPDelegate isClosed] == NO);
310
311 //free up the memory for the delegates - we don't need them anymore
312 [theFPDelegate release];
313 [theCPDelegate release];
314
315 //Get the font the user selected
316 NSFont* theFont = [theFontPanel panelConvertFont:[NSFont userFontOfSize:0]];
317
318 //Get more information about the user's chosen font
319 NSFontTraitMask theTraits = [[NSFontManager sharedFontManager] traitsOfFont:theFont];
320 int theFontWeight = [[NSFontManager sharedFontManager] weightOfFont:theFont];
321 int theFontSize = (int) [theFont pointSize];
322
323 //Set the wx font to the appropriate data
324 if(theTraits & NSFixedPitchFontMask)
325 m_fontData.m_chosenFont.SetFamily(wxTELETYPE);
326
327 m_fontData.m_chosenFont.SetFaceName(wxStringWithNSString([theFont familyName]));
328 m_fontData.m_chosenFont.SetPointSize(theFontSize);
329 m_fontData.m_chosenFont.SetStyle(theTraits & NSItalicFontMask ? wxFONTSTYLE_ITALIC : 0);
330 m_fontData.m_chosenFont.SetWeight(theFontWeight < 5 ? wxLIGHT :
331 theFontWeight >= 9 ? wxBOLD : wxNORMAL);
332
333 //Get the shared color panel along with the chosen color and set the chosen color
334 NSColor* theColor = [[theColorPanel color] colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
335
336 m_fontData.m_fontColour.Set((unsigned char) ([theColor redComponent] * 255.0),
337 (unsigned char) ([theColor greenComponent] * 255.0),
338 (unsigned char) ([theColor blueComponent] * 255.0));
339
340 //Friendly debug stuff
341 #ifdef FONTDLGDEBUG
342 wxPrintf(wxT("---Font Panel---\n--NS--\nSize:%f\nWeight:%i\nTraits:%i\n--WX--\nFaceName:%s\nPointSize:%i\nStyle:%i\nWeight:%i\nColor:%i,%i,%i\n---END Font Panel---\n"),
343
344 (float) theFontSize,
345 theFontWeight,
346 theTraits,
347
348 m_fontData.m_chosenFont.GetFaceName().c_str(),
349 m_fontData.m_chosenFont.GetPointSize(),
350 m_fontData.m_chosenFont.GetStyle(),
351 m_fontData.m_chosenFont.GetWeight(),
352 m_fontData.m_fontColour.Red(),
353 m_fontData.m_fontColour.Green(),
354 m_fontData.m_fontColour.Blue() );
355 #endif
356
357 //Release the pool, we're done :)
358 [thePool release];
359
360 //Return ID_OK - there are no "apply" buttons or the like
361 //on either the font or color panel
362 return wxID_OK;
363 }
364
365 //old api stuff (REMOVE ME)
366 bool wxFontDialog::IsShown() const
367 {
368 return false;
369 }
370
371 #endif // 10.2+