src/gui/dialogs/qfontdialog_mac.mm
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qfontdialog_p.h"
       
    43 #if !defined(QT_NO_FONTDIALOG) && defined(Q_WS_MAC)
       
    44 #include <qapplication.h>
       
    45 #include <qdialogbuttonbox.h>
       
    46 #include <qlineedit.h>
       
    47 #include <private/qapplication_p.h>
       
    48 #include <private/qfont_p.h>
       
    49 #include <private/qfontengine_p.h>
       
    50 #include <private/qt_cocoa_helpers_mac_p.h>
       
    51 #include <private/qt_mac_p.h>
       
    52 #include <qdebug.h>
       
    53 #import <AppKit/AppKit.h>
       
    54 #import <Foundation/Foundation.h>
       
    55 
       
    56 #if !CGFLOAT_DEFINED
       
    57 typedef float CGFloat;  // Should only not be defined on 32-bit platforms
       
    58 #endif
       
    59 
       
    60 QT_USE_NAMESPACE
       
    61 
       
    62 // should a priori be kept in sync with qcolordialog_mac.mm
       
    63 const CGFloat ButtonMinWidth = 78.0;
       
    64 const CGFloat ButtonMinHeight = 32.0;
       
    65 const CGFloat ButtonSpacing = 0.0;
       
    66 const CGFloat ButtonTopMargin = 0.0;
       
    67 const CGFloat ButtonBottomMargin = 7.0;
       
    68 const CGFloat ButtonSideMargin = 9.0;
       
    69 
       
    70 // looks better with some margins
       
    71 const CGFloat DialogTopMargin = 7.0;
       
    72 const CGFloat DialogSideMargin = 9.0;
       
    73 
       
    74 const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask;
       
    75 
       
    76 @class QCocoaFontPanelDelegate;
       
    77 
       
    78 
       
    79 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
       
    80 
       
    81 @protocol NSWindowDelegate <NSObject>
       
    82 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
       
    83 @end
       
    84 
       
    85 #endif
       
    86 
       
    87 @interface QCocoaFontPanelDelegate : NSObject <NSWindowDelegate> {
       
    88     NSFontPanel *mFontPanel;
       
    89     NSView *mStolenContentView;
       
    90     NSButton *mOkButton;
       
    91     NSButton *mCancelButton;
       
    92     QFontDialogPrivate *mPriv;
       
    93     QFont *mQtFont;
       
    94     BOOL mPanelHackedWithButtons;
       
    95     CGFloat mDialogExtraWidth;
       
    96     CGFloat mDialogExtraHeight;
       
    97     NSModalSession mModalSession;
       
    98 }
       
    99 - (id)initWithFontPanel:(NSFontPanel *)panel
       
   100       stolenContentView:(NSView *)stolenContentView
       
   101                okButton:(NSButton *)okButton
       
   102            cancelButton:(NSButton *)cancelButton
       
   103                    priv:(QFontDialogPrivate *)priv
       
   104              extraWidth:(CGFloat)extraWidth
       
   105             extraHeight:(CGFloat)extraHeight;
       
   106 - (void)changeFont:(id)sender;
       
   107 - (void)changeAttributes:(id)sender;
       
   108 - (void)setModalSession:(NSModalSession)session;
       
   109 - (BOOL)windowShouldClose:(id)window;
       
   110 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
       
   111 - (void)relayout;
       
   112 - (void)relayoutToContentSize:(NSSize)frameSize;
       
   113 - (void)onOkClicked;
       
   114 - (void)onCancelClicked;
       
   115 - (NSFontPanel *)fontPanel;
       
   116 - (NSWindow *)actualPanel;
       
   117 - (NSSize)dialogExtraSize;
       
   118 - (void)setQtFont:(const QFont &)newFont;
       
   119 - (QFont)qtFont;
       
   120 - (void)finishOffWithCode:(NSInteger)result;
       
   121 - (void)cleanUpAfterMyself;
       
   122 @end
       
   123 
       
   124 static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
       
   125 {
       
   126     QFont newFont;
       
   127     if (cocoaFont) {
       
   128         int pSize = qRound([cocoaFont pointSize]);
       
   129         QString family(qt_mac_NSStringToQString([cocoaFont familyName]));
       
   130         QString typeface(qt_mac_NSStringToQString([cocoaFont fontName]));
       
   131 
       
   132         int hyphenPos = typeface.indexOf(QLatin1Char('-'));
       
   133         if (hyphenPos != -1) {
       
   134             typeface.remove(0, hyphenPos + 1);
       
   135         } else {
       
   136             typeface = QLatin1String("Normal");
       
   137         }
       
   138 
       
   139         newFont = QFontDatabase().font(family, typeface, pSize);
       
   140         newFont.setUnderline(resolveFont.underline());
       
   141         newFont.setStrikeOut(resolveFont.strikeOut());
       
   142 
       
   143     }
       
   144     return newFont;
       
   145 }
       
   146 
       
   147 @implementation QCocoaFontPanelDelegate
       
   148 - (id)initWithFontPanel:(NSFontPanel *)panel
       
   149        stolenContentView:(NSView *)stolenContentView
       
   150                 okButton:(NSButton *)okButton
       
   151             cancelButton:(NSButton *)cancelButton
       
   152                     priv:(QFontDialogPrivate *)priv
       
   153               extraWidth:(CGFloat)extraWidth
       
   154              extraHeight:(CGFloat)extraHeight
       
   155 {
       
   156     self = [super init];
       
   157     mFontPanel = panel;
       
   158     mStolenContentView = stolenContentView;
       
   159     mOkButton = okButton;
       
   160     mCancelButton = cancelButton;
       
   161     mPriv = priv;
       
   162     mPanelHackedWithButtons = (okButton != 0);
       
   163     mDialogExtraWidth = extraWidth;
       
   164     mDialogExtraHeight = extraHeight;
       
   165     mModalSession = 0;
       
   166 
       
   167     if (mPanelHackedWithButtons) {
       
   168         [self relayout];
       
   169 
       
   170         [okButton setAction:@selector(onOkClicked)];
       
   171         [okButton setTarget:self];
       
   172 
       
   173         [cancelButton setAction:@selector(onCancelClicked)];
       
   174         [cancelButton setTarget:self];
       
   175     }
       
   176     mQtFont = new QFont();
       
   177     return self;
       
   178 }
       
   179 
       
   180 - (void)dealloc
       
   181 {
       
   182     delete mQtFont;
       
   183     [super dealloc];
       
   184 }
       
   185 
       
   186 - (void)changeFont:(id)sender
       
   187 {
       
   188     NSFont *dummyFont = [NSFont userFontOfSize:12.0];
       
   189     [self setQtFont:qfontForCocoaFont([sender convertFont:dummyFont], *mQtFont)];
       
   190     if (mPriv)
       
   191         mPriv->updateSampleFont(*mQtFont);
       
   192 }
       
   193 
       
   194 - (void)changeAttributes:(id)sender
       
   195 {
       
   196     NSDictionary *dummyAttribs = [NSDictionary dictionary];
       
   197     NSDictionary *attribs = [sender convertAttributes:dummyAttribs];
       
   198 
       
   199 #ifdef QT_MAC_USE_COCOA
       
   200     for (id key in attribs) {
       
   201 #else
       
   202     NSEnumerator *enumerator = [attribs keyEnumerator];
       
   203     id key;
       
   204     while((key = [enumerator nextObject])) {
       
   205 #endif
       
   206         NSNumber *number = static_cast<NSNumber *>([attribs objectForKey:key]);
       
   207         if ([key isEqual:NSUnderlineStyleAttributeName]) {
       
   208             mQtFont->setUnderline([number intValue] != NSUnderlineStyleNone);
       
   209         } else if ([key isEqual:NSStrikethroughStyleAttributeName]) {
       
   210             mQtFont->setStrikeOut([number intValue] != NSUnderlineStyleNone);
       
   211         }
       
   212     }
       
   213 
       
   214     if (mPriv)
       
   215         mPriv->updateSampleFont(*mQtFont);
       
   216 }
       
   217 
       
   218 - (void)setModalSession:(NSModalSession)session
       
   219 {
       
   220     Q_ASSERT(!mModalSession);
       
   221     mModalSession = session;
       
   222 }
       
   223 
       
   224 - (BOOL)windowShouldClose:(id)window
       
   225 {
       
   226     Q_UNUSED(window);
       
   227     if (mPanelHackedWithButtons) {
       
   228         [self onCancelClicked];
       
   229     } else {
       
   230         [self finishOffWithCode:NSCancelButton];
       
   231     }
       
   232     return true;
       
   233 }
       
   234 
       
   235 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
       
   236 {
       
   237     if (mFontPanel == window) {
       
   238         proposedFrameSize = [static_cast<id <NSWindowDelegate> >(mFontPanel) windowWillResize:mFontPanel toSize:proposedFrameSize];
       
   239     } else {
       
   240         /*
       
   241             Ugly hack: NSFontPanel rearranges the layout of its main
       
   242             component in windowWillResize:toSize:. So we temporarily
       
   243             restore the stolen content view to its rightful owner,
       
   244             call windowWillResize:toSize:, and steal the content view
       
   245             again.
       
   246         */
       
   247         [mStolenContentView removeFromSuperview];
       
   248         [mFontPanel setContentView:mStolenContentView];
       
   249         NSSize extraSize = [self dialogExtraSize];
       
   250         proposedFrameSize.width -= extraSize.width;
       
   251         proposedFrameSize.height -= extraSize.height;
       
   252         proposedFrameSize = [static_cast<id <NSWindowDelegate> >(mFontPanel) windowWillResize:mFontPanel toSize:proposedFrameSize];
       
   253         NSRect frameRect = { { 0.0, 0.0 }, proposedFrameSize };
       
   254         [mFontPanel setFrame:frameRect display:NO];
       
   255         [mFontPanel setContentView:0];
       
   256         [[window contentView] addSubview:mStolenContentView];
       
   257         proposedFrameSize.width += extraSize.width;
       
   258         proposedFrameSize.height += extraSize.height;
       
   259     }
       
   260     if (mPanelHackedWithButtons) {
       
   261         NSRect frameRect = { { 0.0, 0.0 }, proposedFrameSize };
       
   262         NSRect contentRect = [NSWindow contentRectForFrameRect:frameRect styleMask:[window styleMask]];
       
   263         [self relayoutToContentSize:contentRect.size];
       
   264     }
       
   265     return proposedFrameSize;
       
   266 }
       
   267 
       
   268 - (void)relayout
       
   269 {
       
   270     [self relayoutToContentSize:[[mStolenContentView superview] frame].size];
       
   271 }
       
   272 
       
   273 - (void)relayoutToContentSize:(NSSize)frameSize;
       
   274 {
       
   275     Q_ASSERT(mPanelHackedWithButtons);
       
   276 
       
   277     [mOkButton sizeToFit];
       
   278     NSSize okSizeHint = [mOkButton frame].size;
       
   279 
       
   280     [mCancelButton sizeToFit];
       
   281     NSSize cancelSizeHint = [mCancelButton frame].size;
       
   282 
       
   283     const CGFloat ButtonWidth = qMin(qMax(ButtonMinWidth,
       
   284                                           qMax(okSizeHint.width, cancelSizeHint.width)),
       
   285                                      CGFloat((frameSize.width - 2.0 * ButtonSideMargin
       
   286                                               - ButtonSpacing) * 0.5));
       
   287     const CGFloat ButtonHeight = qMax(ButtonMinHeight,
       
   288                                      qMax(okSizeHint.height, cancelSizeHint.height));
       
   289 
       
   290     const CGFloat X = DialogSideMargin;
       
   291     const CGFloat Y = ButtonBottomMargin + ButtonHeight + ButtonTopMargin;
       
   292 
       
   293     NSRect okRect = { { frameSize.width - ButtonSideMargin - ButtonWidth,
       
   294                         ButtonBottomMargin },
       
   295                       { ButtonWidth, ButtonHeight } };
       
   296     [mOkButton setFrame:okRect];
       
   297     [mOkButton setNeedsDisplay:YES];
       
   298 
       
   299     NSRect cancelRect = { { okRect.origin.x - ButtonSpacing - ButtonWidth,
       
   300                             ButtonBottomMargin },
       
   301                             { ButtonWidth, ButtonHeight } };
       
   302     [mCancelButton setFrame:cancelRect];
       
   303     [mCancelButton setNeedsDisplay:YES];
       
   304 
       
   305     NSRect stolenCVRect = { { X, Y },
       
   306                             { frameSize.width - X - X, frameSize.height - Y - DialogTopMargin } };
       
   307     [mStolenContentView setFrame:stolenCVRect];
       
   308     [mStolenContentView setNeedsDisplay:YES];
       
   309 
       
   310     [[mStolenContentView superview] setNeedsDisplay:YES];
       
   311 }
       
   312 
       
   313 - (void)onOkClicked
       
   314 {
       
   315     Q_ASSERT(mPanelHackedWithButtons);
       
   316     NSFontManager *fontManager = [NSFontManager sharedFontManager];
       
   317     [self setQtFont:qfontForCocoaFont([fontManager convertFont:[fontManager selectedFont]],
       
   318                                       *mQtFont)];
       
   319     [[mStolenContentView window] close];
       
   320     [self finishOffWithCode:NSOKButton];
       
   321 }
       
   322 
       
   323 - (void)onCancelClicked
       
   324 {
       
   325     Q_ASSERT(mPanelHackedWithButtons);
       
   326     [[mStolenContentView window] close];
       
   327     [self finishOffWithCode:NSCancelButton];
       
   328 }
       
   329 
       
   330 - (NSFontPanel *)fontPanel
       
   331 {
       
   332     return mFontPanel;
       
   333 }
       
   334 
       
   335 - (NSWindow *)actualPanel
       
   336 {
       
   337     return [mStolenContentView window];
       
   338 }
       
   339 
       
   340 - (NSSize)dialogExtraSize
       
   341 {
       
   342     // this must be recomputed each time, because sometimes the
       
   343     // NSFontPanel has the NSDocModalWindowMask flag set, and sometimes
       
   344     // not -- which affects the frame rect vs. content rect measurements
       
   345 
       
   346     // take the different frame rectangles into account for dialogExtra{Width,Height}
       
   347     NSRect someRect = { { 0.0, 0.0 }, { 100000.0, 100000.0 } };
       
   348     NSRect sharedFontPanelContentRect = [mFontPanel contentRectForFrameRect:someRect];
       
   349     NSRect ourPanelContentRect = [NSWindow contentRectForFrameRect:someRect styleMask:StyleMask];
       
   350 
       
   351     NSSize result = { mDialogExtraWidth, mDialogExtraHeight };
       
   352     result.width -= ourPanelContentRect.size.width - sharedFontPanelContentRect.size.width;
       
   353     result.height -= ourPanelContentRect.size.height - sharedFontPanelContentRect.size.height;
       
   354     return result;
       
   355 }
       
   356 
       
   357 - (void)setQtFont:(const QFont &)newFont
       
   358 {
       
   359     delete mQtFont;
       
   360     mQtFont = new QFont(newFont);
       
   361 }
       
   362 
       
   363 - (QFont)qtFont
       
   364 {
       
   365     return *mQtFont;
       
   366 }
       
   367 
       
   368 - (void)finishOffWithCode:(NSInteger)code
       
   369 {
       
   370     if (mPriv) {
       
   371         if (mModalSession) {
       
   372             [NSApp endModalSession:mModalSession];
       
   373             mModalSession = 0;
       
   374         }
       
   375 
       
   376         mPriv->done((code == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
       
   377     } else {
       
   378         [NSApp stopModalWithCode:code];
       
   379     }
       
   380 }
       
   381 
       
   382 - (void)cleanUpAfterMyself
       
   383 {
       
   384     if (mPanelHackedWithButtons) {
       
   385         NSView *ourContentView = [mFontPanel contentView];
       
   386 
       
   387         // return stolen stuff to its rightful owner
       
   388         [mStolenContentView removeFromSuperview];
       
   389         [mFontPanel setContentView:mStolenContentView];
       
   390 
       
   391         [mOkButton release];
       
   392         [mCancelButton release];
       
   393         [ourContentView release];
       
   394     }
       
   395     [mFontPanel setDelegate:nil];
       
   396     [[NSFontManager sharedFontManager] setDelegate:nil];
       
   397     [[NSFontManager sharedFontManager] setTarget:nil];
       
   398 }
       
   399 @end
       
   400 
       
   401 QT_BEGIN_NAMESPACE
       
   402 
       
   403 extern void macStartInterceptNSPanelCtor();
       
   404 extern void macStopInterceptNSPanelCtor();
       
   405 extern NSButton *macCreateButton(const char *text, NSView *superview);
       
   406 
       
   407 void *QFontDialogPrivate::openCocoaFontPanel(const QFont &initial,
       
   408         QWidget *parent, const QString &title, QFontDialog::FontDialogOptions options,
       
   409         QFontDialogPrivate *priv)
       
   410 {
       
   411     Q_UNUSED(parent);   // we would use the parent if only NSFontPanel could be a sheet
       
   412     QMacCocoaAutoReleasePool pool;
       
   413 
       
   414     /*
       
   415         The standard Cocoa font panel has no OK or Cancel button and
       
   416         is created as a utility window. For strange reasons (which seem
       
   417         to stem from the fact that the font panel is based on a NIB
       
   418         file), the approach we use for the color panel doesn't work for
       
   419         the font panel (and, inversely, the approach we use here doesn't
       
   420         quite work for color panel, and crashed last time I tried). So
       
   421         instead, we take the following steps:
       
   422 
       
   423          1. Constructs a plain NSPanel that looks the way we want it
       
   424             to look. Specifically, if the NoButtons option is off, we
       
   425             construct a panel without the NSUtilityWindowMask flag
       
   426             and with buttons (OK and Cancel).
       
   427 
       
   428          2. Steal the content view from the shared NSFontPanel and
       
   429             put it inside our new NSPanel's content view, together
       
   430             with the OK and Cancel buttons.
       
   431 
       
   432          3. Lay out the original content view and the buttons when
       
   433             the font panel is shown and whenever it is resized.
       
   434 
       
   435          4. Clean up after ourselves.
       
   436 
       
   437          PS. Some customization is also done in QCocoaApplication
       
   438          validModesForFontPanel:.
       
   439     */
       
   440 
       
   441     Qt::WindowModality modality = Qt::ApplicationModal;
       
   442     if (priv)
       
   443         modality = priv->fontDialog()->windowModality();
       
   444 
       
   445     bool needButtons = !(options & QFontDialog::NoButtons);
       
   446     // don't need our own panel if the title bar isn't visible anyway (in a sheet)
       
   447     bool needOwnPanel = (needButtons && modality != Qt::WindowModal);
       
   448 
       
   449     bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
       
   450     NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
       
   451     [sharedFontPanel setHidesOnDeactivate:false];
       
   452 
       
   453     // hack to ensure that QCocoaApplication's validModesForFontPanel:
       
   454     // implementation is honored
       
   455     if (!sharedFontPanelExisted && needOwnPanel) {
       
   456         [sharedFontPanel makeKeyAndOrderFront:sharedFontPanel];
       
   457         [sharedFontPanel close];
       
   458     }
       
   459 
       
   460     NSPanel *ourPanel = 0;
       
   461     NSView *stolenContentView = 0;
       
   462     NSButton *okButton = 0;
       
   463     NSButton *cancelButton = 0;
       
   464 
       
   465     CGFloat dialogExtraWidth = 0.0;
       
   466     CGFloat dialogExtraHeight = 0.0;
       
   467 
       
   468     if (!needOwnPanel) {
       
   469         // we can reuse the NSFontPanel unchanged
       
   470         ourPanel = sharedFontPanel;
       
   471     } else {
       
   472         // compute dialogExtra{Width,Height}
       
   473         dialogExtraWidth = 2.0 * DialogSideMargin;
       
   474         dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight
       
   475                             + ButtonBottomMargin;
       
   476 
       
   477         // compute initial contents rectangle
       
   478         NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]];
       
   479         contentRect.size.width += dialogExtraWidth;
       
   480         contentRect.size.height += dialogExtraHeight;
       
   481 
       
   482         // create the new panel
       
   483         ourPanel = [[NSPanel alloc] initWithContentRect:contentRect
       
   484                                               styleMask:StyleMask
       
   485                                                 backing:NSBackingStoreBuffered
       
   486                                                   defer:YES];
       
   487         [ourPanel setReleasedWhenClosed:YES];
       
   488     }
       
   489 
       
   490     stolenContentView = [sharedFontPanel contentView];
       
   491 
       
   492     if (needButtons) {
       
   493         // steal the font panel's contents view
       
   494         [stolenContentView retain];
       
   495         [sharedFontPanel setContentView:0];
       
   496 
       
   497         // create a new content view and add the stolen one as a subview
       
   498         NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } };
       
   499         NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect];
       
   500         [ourContentView addSubview:stolenContentView];
       
   501 
       
   502         // create OK and Cancel buttons and add these as subviews
       
   503         okButton = macCreateButton("&OK", ourContentView);
       
   504         cancelButton = macCreateButton("Cancel", ourContentView);
       
   505 
       
   506         [ourPanel setContentView:ourContentView];
       
   507         [ourPanel setDefaultButtonCell:[okButton cell]];
       
   508     }
       
   509 
       
   510     // create a delegate and set it
       
   511     QCocoaFontPanelDelegate *delegate =
       
   512             [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
       
   513                                              stolenContentView:stolenContentView
       
   514                                                       okButton:okButton
       
   515                                                   cancelButton:cancelButton
       
   516                                                           priv:priv
       
   517                                                     extraWidth:dialogExtraWidth
       
   518                                                    extraHeight:dialogExtraHeight];
       
   519     [ourPanel setDelegate:delegate];
       
   520     [[NSFontManager sharedFontManager] setDelegate:delegate];
       
   521     [[NSFontManager sharedFontManager] setTarget:delegate];
       
   522     setFont(delegate, initial);
       
   523 
       
   524     // hack to get correct initial layout
       
   525     NSRect frameRect = [ourPanel frame];
       
   526     frameRect.size.width += 1.0;
       
   527     [ourPanel setFrame:frameRect display:NO];
       
   528     frameRect.size.width -= 1.0;
       
   529     frameRect.size = [delegate windowWillResize:ourPanel toSize:frameRect.size];
       
   530     [ourPanel setFrame:frameRect display:NO];
       
   531     [ourPanel center];
       
   532 
       
   533     [ourPanel setTitle:(NSString*)(CFStringRef)QCFString(title)];
       
   534 
       
   535     if (priv) {
       
   536         switch (modality) {
       
   537         case Qt::WindowModal:
       
   538             if (parent) {
       
   539 #ifndef QT_MAC_USE_COCOA
       
   540                 WindowRef hiwindowRef = qt_mac_window_for(parent);
       
   541                 NSWindow *window =
       
   542                     [[NSWindow alloc] initWithWindowRef:hiwindowRef];
       
   543                 // Cocoa docs say I should retain the Carbon ref.
       
   544                 CFRetain(hiwindowRef);
       
   545 #else
       
   546                 NSWindow *window = qt_mac_window_for(parent);
       
   547 #endif
       
   548                 [NSApp beginSheet:ourPanel
       
   549                    modalForWindow:window
       
   550                     modalDelegate:0
       
   551                    didEndSelector:0
       
   552                       contextInfo:0];
       
   553 #ifndef QT_MAC_USE_COCOA
       
   554                 [window release];
       
   555 #endif
       
   556                 break;
       
   557             }
       
   558             // fallthrough
       
   559         case Qt::ApplicationModal:
       
   560             [delegate setModalSession:[NSApp beginModalSessionForWindow:ourPanel]];
       
   561             break;
       
   562         default:
       
   563             [ourPanel makeKeyAndOrderFront:ourPanel];
       
   564         }
       
   565     }
       
   566 
       
   567     return delegate;
       
   568 }
       
   569 
       
   570 void QFontDialogPrivate::closeCocoaFontPanel(void *delegate)
       
   571 {
       
   572     QMacCocoaAutoReleasePool pool;
       
   573     QCocoaFontPanelDelegate *theDelegate = static_cast<QCocoaFontPanelDelegate *>(delegate);
       
   574     NSWindow *ourPanel = [theDelegate actualPanel];
       
   575     [ourPanel close];
       
   576     [theDelegate cleanUpAfterMyself];
       
   577     [theDelegate autorelease];
       
   578 }
       
   579 
       
   580 QFont QFontDialogPrivate::execCocoaFontPanel(bool *ok, const QFont &initial,
       
   581         QWidget *parent, const QString &title, QFontDialog::FontDialogOptions options)
       
   582 {
       
   583     QMacCocoaAutoReleasePool pool;
       
   584     QCocoaFontPanelDelegate *delegate =
       
   585             static_cast<QCocoaFontPanelDelegate *>(
       
   586                 openCocoaFontPanel(initial, parent, title, options));
       
   587     NSWindow *ourPanel = [delegate actualPanel];
       
   588     [ourPanel retain];
       
   589     int rval = [NSApp runModalForWindow:ourPanel];
       
   590     QFont font([delegate qtFont]);
       
   591     [ourPanel release];
       
   592     [delegate cleanUpAfterMyself];
       
   593     [delegate release];
       
   594     bool isOk = ((options & QFontDialog::NoButtons) || rval == NSOKButton);
       
   595     if (ok)
       
   596         *ok = isOk;
       
   597     if (isOk) {
       
   598         return font;
       
   599     } else {
       
   600         return initial;
       
   601     }
       
   602 }
       
   603 
       
   604 void QFontDialogPrivate::setFont(void *delegate, const QFont &font)
       
   605 {
       
   606     QMacCocoaAutoReleasePool pool;
       
   607     QFontEngine *fe = font.d->engineForScript(QUnicodeTables::Common);
       
   608     NSFontManager *mgr = [NSFontManager sharedFontManager];
       
   609     NSFont *nsFont = 0;
       
   610 
       
   611 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
       
   612     if (qstrcmp(fe->name(), "CoreText") == 0) {
       
   613         nsFont = reinterpret_cast<const NSFont *>(static_cast<QCoreTextFontEngineMulti *>(fe)->ctfont);
       
   614     } else
       
   615 #endif
       
   616     {
       
   617         int weight = 5;
       
   618         NSFontTraitMask mask = 0;
       
   619         if (font.style() == QFont::StyleItalic) {
       
   620             mask |= NSItalicFontMask;
       
   621         }
       
   622         if (font.weight() == QFont::Bold) {
       
   623             weight = 9;
       
   624             mask |= NSBoldFontMask;
       
   625         }
       
   626 
       
   627         NSFontManager *mgr = [NSFontManager sharedFontManager];
       
   628         nsFont = [mgr fontWithFamily:qt_mac_QStringToNSString(font.family())
       
   629             traits:mask
       
   630             weight:weight
       
   631             size:QFontInfo(font).pointSize()];
       
   632     }
       
   633 
       
   634     [mgr setSelectedFont:nsFont isMultiple:NO];
       
   635     [static_cast<QCocoaFontPanelDelegate *>(delegate) setQtFont:font];
       
   636 }
       
   637 
       
   638 QT_END_NAMESPACE
       
   639 
       
   640 #endif