src/gui/dialogs/qfontdialog_mac.mm
changeset 30 5dc02b23752f
parent 18 2f34d5167611
child 37 758a864f9613
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    56 
    56 
    57 #if !CGFLOAT_DEFINED
    57 #if !CGFLOAT_DEFINED
    58 typedef float CGFloat;  // Should only not be defined on 32-bit platforms
    58 typedef float CGFloat;  // Should only not be defined on 32-bit platforms
    59 #endif
    59 #endif
    60 
    60 
       
    61 QT_BEGIN_NAMESPACE
       
    62 
       
    63 extern void macStartInterceptNSPanelCtor();
       
    64 extern void macStopInterceptNSPanelCtor();
       
    65 extern NSButton *macCreateButton(const char *text, NSView *superview);
       
    66 extern bool qt_mac_is_macsheet(const QWidget *w); // qwidget_mac.mm
       
    67 
       
    68 QT_END_NAMESPACE
    61 QT_USE_NAMESPACE
    69 QT_USE_NAMESPACE
    62 
    70 
    63 // should a priori be kept in sync with qcolordialog_mac.mm
    71 // should a priori be kept in sync with qcolordialog_mac.mm
    64 const CGFloat ButtonMinWidth = 78.0;
    72 const CGFloat ButtonMinWidth = 78.0;
    65 const CGFloat ButtonMinHeight = 32.0;
    73 const CGFloat ButtonMinHeight = 32.0;
    72 const CGFloat DialogTopMargin = 7.0;
    80 const CGFloat DialogTopMargin = 7.0;
    73 const CGFloat DialogSideMargin = 9.0;
    81 const CGFloat DialogSideMargin = 9.0;
    74 
    82 
    75 const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask;
    83 const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask;
    76 
    84 
    77 @class QCocoaFontPanelDelegate;
    85 @class QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate);
    78 
    86 
    79 
    87 
    80 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
    88 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
    81 
    89 
    82 @protocol NSWindowDelegate <NSObject>
    90 @protocol NSWindowDelegate <NSObject>
    83 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
    91 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
    84 @end
    92 @end
    85 
    93 
    86 #endif
    94 #endif
    87 
    95 
    88 @interface QCocoaFontPanelDelegate : NSObject <NSWindowDelegate> {
    96 @interface QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) : NSObject <NSWindowDelegate> {
    89     NSFontPanel *mFontPanel;
    97     NSFontPanel *mFontPanel;
    90     NSView *mStolenContentView;
    98     NSView *mStolenContentView;
    91     NSButton *mOkButton;
    99     NSButton *mOkButton;
    92     NSButton *mCancelButton;
   100     NSButton *mCancelButton;
    93     QFontDialogPrivate *mPriv;
   101     QFontDialogPrivate *mPriv;
    94     QFont *mQtFont;
   102     QFont *mQtFont;
    95     BOOL mPanelHackedWithButtons;
   103     BOOL mPanelHackedWithButtons;
    96     CGFloat mDialogExtraWidth;
   104     CGFloat mDialogExtraWidth;
    97     CGFloat mDialogExtraHeight;
   105     CGFloat mDialogExtraHeight;
    98     NSModalSession mModalSession;
   106     int mReturnCode;
       
   107     BOOL mAppModal;
    99 }
   108 }
   100 - (id)initWithFontPanel:(NSFontPanel *)panel
   109 - (id)initWithFontPanel:(NSFontPanel *)panel
   101       stolenContentView:(NSView *)stolenContentView
   110       stolenContentView:(NSView *)stolenContentView
   102                okButton:(NSButton *)okButton
   111                okButton:(NSButton *)okButton
   103            cancelButton:(NSButton *)cancelButton
   112            cancelButton:(NSButton *)cancelButton
   104                    priv:(QFontDialogPrivate *)priv
   113                    priv:(QFontDialogPrivate *)priv
   105              extraWidth:(CGFloat)extraWidth
   114              extraWidth:(CGFloat)extraWidth
   106             extraHeight:(CGFloat)extraHeight;
   115             extraHeight:(CGFloat)extraHeight;
       
   116 - (void)showModelessPanel;
       
   117 - (void)showWindowModalSheet:(QWidget *)docWidget;
       
   118 - (void)runApplicationModalPanel;
   107 - (void)changeFont:(id)sender;
   119 - (void)changeFont:(id)sender;
   108 - (void)changeAttributes:(id)sender;
   120 - (void)changeAttributes:(id)sender;
   109 - (void)setModalSession:(NSModalSession)session;
       
   110 - (BOOL)windowShouldClose:(id)window;
   121 - (BOOL)windowShouldClose:(id)window;
   111 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
   122 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
   112 - (void)relayout;
   123 - (void)relayout;
   113 - (void)relayoutToContentSize:(NSSize)frameSize;
   124 - (void)relayoutToContentSize:(NSSize)frameSize;
   114 - (void)onOkClicked;
   125 - (void)onOkClicked;
   143 
   154 
   144     }
   155     }
   145     return newFont;
   156     return newFont;
   146 }
   157 }
   147 
   158 
   148 @implementation QCocoaFontPanelDelegate
   159 @implementation QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate)
   149 - (id)initWithFontPanel:(NSFontPanel *)panel
   160 - (id)initWithFontPanel:(NSFontPanel *)panel
   150        stolenContentView:(NSView *)stolenContentView
   161        stolenContentView:(NSView *)stolenContentView
   151                 okButton:(NSButton *)okButton
   162                 okButton:(NSButton *)okButton
   152             cancelButton:(NSButton *)cancelButton
   163             cancelButton:(NSButton *)cancelButton
   153                     priv:(QFontDialogPrivate *)priv
   164                     priv:(QFontDialogPrivate *)priv
   161     mCancelButton = cancelButton;
   172     mCancelButton = cancelButton;
   162     mPriv = priv;
   173     mPriv = priv;
   163     mPanelHackedWithButtons = (okButton != 0);
   174     mPanelHackedWithButtons = (okButton != 0);
   164     mDialogExtraWidth = extraWidth;
   175     mDialogExtraWidth = extraWidth;
   165     mDialogExtraHeight = extraHeight;
   176     mDialogExtraHeight = extraHeight;
   166     mModalSession = 0;
   177     mReturnCode = -1;
       
   178     mAppModal = false;
   167 
   179 
   168     if (mPanelHackedWithButtons) {
   180     if (mPanelHackedWithButtons) {
   169         [self relayout];
   181         [self relayout];
   170 
   182 
   171         [okButton setAction:@selector(onOkClicked)];
   183         [okButton setAction:@selector(onOkClicked)];
   172         [okButton setTarget:self];
   184         [okButton setTarget:self];
   173 
   185 
   174         [cancelButton setAction:@selector(onCancelClicked)];
   186         [cancelButton setAction:@selector(onCancelClicked)];
   175         [cancelButton setTarget:self];
   187         [cancelButton setTarget:self];
   176     }
   188     }
       
   189 
       
   190 #ifdef QT_MAC_USE_COCOA
       
   191     // Stack the native dialog in front of its parent, if any:
       
   192     QFontDialog *q = mPriv->fontDialog();
       
   193     if (!qt_mac_is_macsheet(q)) {
       
   194         if (QWidget *parent = q->parentWidget()) {
       
   195             if (parent->isWindow()) {
       
   196                 [qt_mac_window_for(parent)
       
   197                     addChildWindow:[mStolenContentView window] ordered:NSWindowAbove];
       
   198             }
       
   199         }
       
   200     }
       
   201 #endif
       
   202 
   177     mQtFont = new QFont();
   203     mQtFont = new QFont();
   178     return self;
   204     return self;
   179 }
   205 }
   180 
   206 
   181 - (void)dealloc
   207 - (void)dealloc
   182 {
   208 {
   183     delete mQtFont;
   209     delete mQtFont;
   184     [super dealloc];
   210     [super dealloc];
       
   211 }
       
   212 
       
   213 - (void)showModelessPanel
       
   214 {
       
   215     mAppModal = false;
       
   216     NSWindow *ourPanel = [mStolenContentView window];
       
   217     [ourPanel makeKeyAndOrderFront:self];
       
   218 }
       
   219 
       
   220 - (void)runApplicationModalPanel
       
   221 {
       
   222     QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
       
   223     mAppModal = true;
       
   224     NSWindow *ourPanel = [mStolenContentView window];
       
   225     [NSApp runModalForWindow:ourPanel];
       
   226     QAbstractEventDispatcher::instance()->interrupt();
       
   227 
       
   228     if (mReturnCode == NSOKButton)
       
   229         mPriv->fontDialog()->accept();
       
   230     else
       
   231         mPriv->fontDialog()->reject();
       
   232 }
       
   233 
       
   234 - (void)showWindowModalSheet:(QWidget *)docWidget
       
   235 {
       
   236 #ifdef QT_MAC_USE_COCOA
       
   237     NSWindow *window = qt_mac_window_for(docWidget);
       
   238 #else
       
   239     WindowRef hiwindowRef = qt_mac_window_for(docWidget);
       
   240     NSWindow *window = [[NSWindow alloc] initWithWindowRef:hiwindowRef];
       
   241     CFRetain(hiwindowRef);
       
   242 #endif
       
   243 
       
   244     mAppModal = false;
       
   245     NSWindow *ourPanel = [mStolenContentView window];
       
   246     [NSApp beginSheet:ourPanel
       
   247         modalForWindow:window
       
   248         modalDelegate:0
       
   249         didEndSelector:0
       
   250         contextInfo:0 ];
       
   251 
       
   252 #ifndef QT_MAC_USE_COCOA
       
   253     CFRelease(hiwindowRef);
       
   254 #endif
   185 }
   255 }
   186 
   256 
   187 - (void)changeFont:(id)sender
   257 - (void)changeFont:(id)sender
   188 {
   258 {
   189     NSFont *dummyFont = [NSFont userFontOfSize:12.0];
   259     NSFont *dummyFont = [NSFont userFontOfSize:12.0];
   212         }
   282         }
   213     }
   283     }
   214 
   284 
   215     if (mPriv)
   285     if (mPriv)
   216         mPriv->updateSampleFont(*mQtFont);
   286         mPriv->updateSampleFont(*mQtFont);
   217 }
       
   218 
       
   219 - (void)setModalSession:(NSModalSession)session
       
   220 {
       
   221     Q_ASSERT(!mModalSession);
       
   222     mModalSession = session;
       
   223 }
   287 }
   224 
   288 
   225 - (BOOL)windowShouldClose:(id)window
   289 - (BOOL)windowShouldClose:(id)window
   226 {
   290 {
   227     Q_UNUSED(window);
   291     Q_UNUSED(window);
   280 
   344 
   281     [mCancelButton sizeToFit];
   345     [mCancelButton sizeToFit];
   282     NSSize cancelSizeHint = [mCancelButton frame].size;
   346     NSSize cancelSizeHint = [mCancelButton frame].size;
   283 
   347 
   284     const CGFloat ButtonWidth = qMin(qMax(ButtonMinWidth,
   348     const CGFloat ButtonWidth = qMin(qMax(ButtonMinWidth,
   285                                           qMax(okSizeHint.width, cancelSizeHint.width)),
   349                 qMax(okSizeHint.width, cancelSizeHint.width)),
   286                                      CGFloat((frameSize.width - 2.0 * ButtonSideMargin
   350             CGFloat((frameSize.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5));
   287                                               - ButtonSpacing) * 0.5));
       
   288     const CGFloat ButtonHeight = qMax(ButtonMinHeight,
   351     const CGFloat ButtonHeight = qMax(ButtonMinHeight,
   289                                      qMax(okSizeHint.height, cancelSizeHint.height));
   352                                      qMax(okSizeHint.height, cancelSizeHint.height));
   290 
   353 
   291     const CGFloat X = DialogSideMargin;
   354     const CGFloat X = DialogSideMargin;
   292     const CGFloat Y = ButtonBottomMargin + ButtonHeight + ButtonTopMargin;
   355     const CGFloat Y = ButtonBottomMargin + ButtonHeight + ButtonTopMargin;
   315 {
   378 {
   316     Q_ASSERT(mPanelHackedWithButtons);
   379     Q_ASSERT(mPanelHackedWithButtons);
   317     NSFontManager *fontManager = [NSFontManager sharedFontManager];
   380     NSFontManager *fontManager = [NSFontManager sharedFontManager];
   318     [self setQtFont:qfontForCocoaFont([fontManager convertFont:[fontManager selectedFont]],
   381     [self setQtFont:qfontForCocoaFont([fontManager convertFont:[fontManager selectedFont]],
   319                                       *mQtFont)];
   382                                       *mQtFont)];
   320     [[mStolenContentView window] close];
       
   321     [self finishOffWithCode:NSOKButton];
   383     [self finishOffWithCode:NSOKButton];
   322 }
   384 }
   323 
   385 
   324 - (void)onCancelClicked
   386 - (void)onCancelClicked
   325 {
   387 {
   326     Q_ASSERT(mPanelHackedWithButtons);
   388     Q_ASSERT(mPanelHackedWithButtons);
   327     [[mStolenContentView window] close];
       
   328     [self finishOffWithCode:NSCancelButton];
   389     [self finishOffWithCode:NSCancelButton];
   329 }
   390 }
   330 
   391 
   331 - (NSFontPanel *)fontPanel
   392 - (NSFontPanel *)fontPanel
   332 {
   393 {
   366     return *mQtFont;
   427     return *mQtFont;
   367 }
   428 }
   368 
   429 
   369 - (void)finishOffWithCode:(NSInteger)code
   430 - (void)finishOffWithCode:(NSInteger)code
   370 {
   431 {
   371     if (mPriv) {
   432 #ifdef QT_MAC_USE_COCOA
   372         if (mModalSession) {
   433     QFontDialog *q = mPriv->fontDialog();
   373             [NSApp endModalSession:mModalSession];
   434     if (QWidget *parent = q->parentWidget()) {
   374             mModalSession = 0;
   435         if (parent->isWindow()) {
       
   436             [qt_mac_window_for(parent) removeChildWindow:[mStolenContentView window]];
   375         }
   437         }
   376         // Hack alert!
   438     }
   377         // Since this code path was never intended to be followed when starting from exec
   439 #endif
   378         // we need to force the dialog to communicate the new font, otherwise the signal
   440 
   379         // won't get emitted.
   441     if(code == NSOKButton)
   380         if(code == NSOKButton)
   442         mPriv->sampleEdit->setFont([self qtFont]);
   381             mPriv->sampleEdit->setFont([self qtFont]);
   443 
   382         mPriv->done((code == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
   444     if (mAppModal) {
       
   445         mReturnCode = code;
       
   446         [NSApp stopModalWithCode:code];
   383     } else {
   447     } else {
   384         [NSApp stopModalWithCode:code];
   448         if (code == NSOKButton)
       
   449             mPriv->fontDialog()->accept();
       
   450         else
       
   451             mPriv->fontDialog()->reject();
   385     }
   452     }
   386 }
   453 }
   387 
   454 
   388 - (void)cleanUpAfterMyself
   455 - (void)cleanUpAfterMyself
   389 {
   456 {
   406 }
   473 }
   407 @end
   474 @end
   408 
   475 
   409 QT_BEGIN_NAMESPACE
   476 QT_BEGIN_NAMESPACE
   410 
   477 
   411 extern void macStartInterceptNSPanelCtor();
   478 void QFontDialogPrivate::closeCocoaFontPanel()
   412 extern void macStopInterceptNSPanelCtor();
   479 {
   413 extern NSButton *macCreateButton(const char *text, NSView *superview);
       
   414 
       
   415 void *QFontDialogPrivate::openCocoaFontPanel(const QFont &initial,
       
   416         QWidget *parent, const QString &title, QFontDialog::FontDialogOptions options,
       
   417         QFontDialogPrivate *priv)
       
   418 {
       
   419     Q_UNUSED(parent);   // we would use the parent if only NSFontPanel could be a sheet
       
   420     QMacCocoaAutoReleasePool pool;
   480     QMacCocoaAutoReleasePool pool;
   421 
   481     QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *theDelegate = static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate);
   422     /*
       
   423         The standard Cocoa font panel has no OK or Cancel button and
       
   424         is created as a utility window. For strange reasons (which seem
       
   425         to stem from the fact that the font panel is based on a NIB
       
   426         file), the approach we use for the color panel doesn't work for
       
   427         the font panel (and, inversely, the approach we use here doesn't
       
   428         quite work for color panel, and crashed last time I tried). So
       
   429         instead, we take the following steps:
       
   430 
       
   431          1. Constructs a plain NSPanel that looks the way we want it
       
   432             to look. Specifically, if the NoButtons option is off, we
       
   433             construct a panel without the NSUtilityWindowMask flag
       
   434             and with buttons (OK and Cancel).
       
   435 
       
   436          2. Steal the content view from the shared NSFontPanel and
       
   437             put it inside our new NSPanel's content view, together
       
   438             with the OK and Cancel buttons.
       
   439 
       
   440          3. Lay out the original content view and the buttons when
       
   441             the font panel is shown and whenever it is resized.
       
   442 
       
   443          4. Clean up after ourselves.
       
   444 
       
   445          PS. Some customization is also done in QCocoaApplication
       
   446          validModesForFontPanel:.
       
   447     */
       
   448 
       
   449     Qt::WindowModality modality = Qt::ApplicationModal;
       
   450     if (priv)
       
   451         modality = priv->fontDialog()->windowModality();
       
   452 
       
   453     bool needButtons = !(options & QFontDialog::NoButtons);
       
   454     // don't need our own panel if the title bar isn't visible anyway (in a sheet)
       
   455     bool needOwnPanel = (needButtons && modality != Qt::WindowModal);
       
   456 
       
   457     bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
       
   458     NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
       
   459     [sharedFontPanel setHidesOnDeactivate:false];
       
   460 
       
   461     // hack to ensure that QCocoaApplication's validModesForFontPanel:
       
   462     // implementation is honored
       
   463     if (!sharedFontPanelExisted && needOwnPanel) {
       
   464         [sharedFontPanel makeKeyAndOrderFront:sharedFontPanel];
       
   465         [sharedFontPanel close];
       
   466     }
       
   467 
       
   468     NSPanel *ourPanel = 0;
       
   469     NSView *stolenContentView = 0;
       
   470     NSButton *okButton = 0;
       
   471     NSButton *cancelButton = 0;
       
   472 
       
   473     CGFloat dialogExtraWidth = 0.0;
       
   474     CGFloat dialogExtraHeight = 0.0;
       
   475 
       
   476     if (!needOwnPanel) {
       
   477         // we can reuse the NSFontPanel unchanged
       
   478         ourPanel = sharedFontPanel;
       
   479     } else {
       
   480         // compute dialogExtra{Width,Height}
       
   481         dialogExtraWidth = 2.0 * DialogSideMargin;
       
   482         dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight
       
   483                             + ButtonBottomMargin;
       
   484 
       
   485         // compute initial contents rectangle
       
   486         NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]];
       
   487         contentRect.size.width += dialogExtraWidth;
       
   488         contentRect.size.height += dialogExtraHeight;
       
   489 
       
   490         // create the new panel
       
   491         ourPanel = [[NSPanel alloc] initWithContentRect:contentRect
       
   492                                               styleMask:StyleMask
       
   493                                                 backing:NSBackingStoreBuffered
       
   494                                                   defer:YES];
       
   495         [ourPanel setReleasedWhenClosed:YES];
       
   496     }
       
   497 
       
   498     stolenContentView = [sharedFontPanel contentView];
       
   499 
       
   500     if (needButtons) {
       
   501         // steal the font panel's contents view
       
   502         [stolenContentView retain];
       
   503         [sharedFontPanel setContentView:0];
       
   504 
       
   505         // create a new content view and add the stolen one as a subview
       
   506         NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } };
       
   507         NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect];
       
   508         [ourContentView addSubview:stolenContentView];
       
   509 
       
   510         // create OK and Cancel buttons and add these as subviews
       
   511         okButton = macCreateButton("&OK", ourContentView);
       
   512         cancelButton = macCreateButton("Cancel", ourContentView);
       
   513 
       
   514         [ourPanel setContentView:ourContentView];
       
   515         [ourPanel setDefaultButtonCell:[okButton cell]];
       
   516     }
       
   517 
       
   518     // create a delegate and set it
       
   519     QCocoaFontPanelDelegate *delegate =
       
   520             [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
       
   521                                              stolenContentView:stolenContentView
       
   522                                                       okButton:okButton
       
   523                                                   cancelButton:cancelButton
       
   524                                                           priv:priv
       
   525                                                     extraWidth:dialogExtraWidth
       
   526                                                    extraHeight:dialogExtraHeight];
       
   527     [ourPanel setDelegate:delegate];
       
   528     [[NSFontManager sharedFontManager] setDelegate:delegate];
       
   529 #ifdef QT_MAC_USE_COCOA
       
   530     [[NSFontManager sharedFontManager] setTarget:delegate];
       
   531 #endif
       
   532     setFont(delegate, initial);
       
   533 
       
   534     // hack to get correct initial layout
       
   535     NSRect frameRect = [ourPanel frame];
       
   536     frameRect.size.width += 1.0;
       
   537     [ourPanel setFrame:frameRect display:NO];
       
   538     frameRect.size.width -= 1.0;
       
   539     frameRect.size = [delegate windowWillResize:ourPanel toSize:frameRect.size];
       
   540     [ourPanel setFrame:frameRect display:NO];
       
   541     [ourPanel center];
       
   542 
       
   543     [ourPanel setTitle:(NSString*)(CFStringRef)QCFString(title)];
       
   544 
       
   545     if (priv) {
       
   546         switch (modality) {
       
   547         case Qt::WindowModal:
       
   548             if (parent) {
       
   549 #ifndef QT_MAC_USE_COCOA
       
   550                 WindowRef hiwindowRef = qt_mac_window_for(parent);
       
   551                 NSWindow *window =
       
   552                     [[NSWindow alloc] initWithWindowRef:hiwindowRef];
       
   553                 // Cocoa docs say I should retain the Carbon ref.
       
   554                 CFRetain(hiwindowRef);
       
   555 #else
       
   556                 NSWindow *window = qt_mac_window_for(parent);
       
   557 #endif
       
   558                 [NSApp beginSheet:ourPanel
       
   559                    modalForWindow:window
       
   560                     modalDelegate:0
       
   561                    didEndSelector:0
       
   562                       contextInfo:0];
       
   563 #ifndef QT_MAC_USE_COCOA
       
   564                 [window release];
       
   565 #endif
       
   566                 break;
       
   567             }
       
   568             // fallthrough
       
   569         case Qt::ApplicationModal:
       
   570             [delegate setModalSession:[NSApp beginModalSessionForWindow:ourPanel]];
       
   571             break;
       
   572         default:
       
   573             [ourPanel makeKeyAndOrderFront:ourPanel];
       
   574         }
       
   575     }
       
   576     return delegate;
       
   577 }
       
   578 
       
   579 void QFontDialogPrivate::closeCocoaFontPanel(void *delegate)
       
   580 {
       
   581     QMacCocoaAutoReleasePool pool;
       
   582     QCocoaFontPanelDelegate *theDelegate = static_cast<QCocoaFontPanelDelegate *>(delegate);
       
   583     NSWindow *ourPanel = [theDelegate actualPanel];
   482     NSWindow *ourPanel = [theDelegate actualPanel];
   584     [ourPanel close];
   483     [ourPanel close];
   585     [theDelegate cleanUpAfterMyself];
   484     [theDelegate cleanUpAfterMyself];
   586     [theDelegate autorelease];
   485     [theDelegate release];
   587 }
   486     this->delegate = 0;
   588 
   487     sharedFontPanelAvailable = true;
   589 QFont QFontDialogPrivate::execCocoaFontPanel(bool *ok, const QFont &initial,
       
   590         QWidget *parent, const QString &title, QFontDialog::FontDialogOptions options)
       
   591 {
       
   592     QMacCocoaAutoReleasePool pool;
       
   593     QCocoaFontPanelDelegate *delegate =
       
   594             static_cast<QCocoaFontPanelDelegate *>(
       
   595                 openCocoaFontPanel(initial, parent, title, options));
       
   596     NSWindow *ourPanel = [delegate actualPanel];
       
   597     [ourPanel retain];
       
   598     int rval = [NSApp runModalForWindow:ourPanel];
       
   599     QFont font([delegate qtFont]);
       
   600     [ourPanel release];
       
   601     [delegate cleanUpAfterMyself];
       
   602     [delegate release];
       
   603     bool isOk = ((options & QFontDialog::NoButtons) || rval == NSOKButton);
       
   604     if (ok)
       
   605         *ok = isOk;
       
   606     if (isOk) {
       
   607         return font;
       
   608     } else {
       
   609         return initial;
       
   610     }
       
   611 }
   488 }
   612 
   489 
   613 void QFontDialogPrivate::setFont(void *delegate, const QFont &font)
   490 void QFontDialogPrivate::setFont(void *delegate, const QFont &font)
   614 {
   491 {
   615     QMacCocoaAutoReleasePool pool;
   492     QMacCocoaAutoReleasePool pool;
   640             weight:weight
   517             weight:weight
   641             size:fontInfo.pointSize()];
   518             size:fontInfo.pointSize()];
   642     }
   519     }
   643 
   520 
   644     [mgr setSelectedFont:nsFont isMultiple:NO];
   521     [mgr setSelectedFont:nsFont isMultiple:NO];
   645     [static_cast<QCocoaFontPanelDelegate *>(delegate) setQtFont:font];
   522     [static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate) setQtFont:font];
   646 }
   523 }
   647 
   524 
   648 void *QFontDialogPrivate::_q_constructNativePanel()
   525 void QFontDialogPrivate::createNSFontPanelDelegate()
   649 {
   526 {
       
   527     if (delegate)
       
   528         return;
       
   529 
       
   530     sharedFontPanelAvailable = false;
   650     QMacCocoaAutoReleasePool pool;
   531     QMacCocoaAutoReleasePool pool;
   651 
       
   652     bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
   532     bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
   653     NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
   533     NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
   654     [sharedFontPanel setHidesOnDeactivate:false];
   534     [sharedFontPanel setHidesOnDeactivate:false];
   655 
   535 
   656     // hack to ensure that QCocoaApplication's validModesForFontPanel:
   536     // hack to ensure that QCocoaApplication's validModesForFontPanel:
   668     CGFloat dialogExtraWidth = 0.0;
   548     CGFloat dialogExtraWidth = 0.0;
   669     CGFloat dialogExtraHeight = 0.0;
   549     CGFloat dialogExtraHeight = 0.0;
   670 
   550 
   671     // compute dialogExtra{Width,Height}
   551     // compute dialogExtra{Width,Height}
   672     dialogExtraWidth = 2.0 * DialogSideMargin;
   552     dialogExtraWidth = 2.0 * DialogSideMargin;
   673     dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight
   553     dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight + ButtonBottomMargin;
   674                         + ButtonBottomMargin;
       
   675 
   554 
   676     // compute initial contents rectangle
   555     // compute initial contents rectangle
   677     NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]];
   556     NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]];
   678     contentRect.size.width += dialogExtraWidth;
   557     contentRect.size.width += dialogExtraWidth;
   679     contentRect.size.height += dialogExtraHeight;
   558     contentRect.size.height += dialogExtraHeight;
   682     ourPanel = [[NSPanel alloc] initWithContentRect:contentRect
   561     ourPanel = [[NSPanel alloc] initWithContentRect:contentRect
   683                 styleMask:StyleMask
   562                 styleMask:StyleMask
   684                     backing:NSBackingStoreBuffered
   563                     backing:NSBackingStoreBuffered
   685                         defer:YES];
   564                         defer:YES];
   686     [ourPanel setReleasedWhenClosed:YES];
   565     [ourPanel setReleasedWhenClosed:YES];
   687 
       
   688     stolenContentView = [sharedFontPanel contentView];
   566     stolenContentView = [sharedFontPanel contentView];
   689 
   567 
   690     // steal the font panel's contents view
   568     // steal the font panel's contents view
   691     [stolenContentView retain];
   569     [stolenContentView retain];
   692     [sharedFontPanel setContentView:0];
   570     [sharedFontPanel setContentView:0];
   702         cancelButton = macCreateButton("Cancel", ourContentView);
   580         cancelButton = macCreateButton("Cancel", ourContentView);
   703 
   581 
   704         [ourPanel setContentView:ourContentView];
   582         [ourPanel setContentView:ourContentView];
   705         [ourPanel setDefaultButtonCell:[okButton cell]];
   583         [ourPanel setDefaultButtonCell:[okButton cell]];
   706     }
   584     }
   707     // create a delegate and set it
   585 
   708     QCocoaFontPanelDelegate *delegate =
   586     // create the delegate and set it
   709             [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
   587     QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *del = [[QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) alloc] initWithFontPanel:sharedFontPanel
   710                                              stolenContentView:stolenContentView
   588                                              stolenContentView:stolenContentView
   711                                                       okButton:okButton
   589                                                       okButton:okButton
   712                                                   cancelButton:cancelButton
   590                                                   cancelButton:cancelButton
   713                                                           priv:this
   591                                                           priv:this
   714                                                     extraWidth:dialogExtraWidth
   592                                                     extraWidth:dialogExtraWidth
   715                                                    extraHeight:dialogExtraHeight];
   593                                                    extraHeight:dialogExtraHeight];
   716     [ourPanel setDelegate:delegate];
   594     delegate = del;
   717     [[NSFontManager sharedFontManager] setDelegate:delegate];
   595     [ourPanel setDelegate:del];
       
   596 
       
   597     [[NSFontManager sharedFontManager] setDelegate:del];
   718 #ifdef QT_MAC_USE_COCOA
   598 #ifdef QT_MAC_USE_COCOA
   719     [[NSFontManager sharedFontManager] setTarget:delegate];
   599     [[NSFontManager sharedFontManager] setTarget:del];
   720 #endif
   600 #endif
   721     setFont(delegate, QApplication::font());
   601     setFont(del, q_func()->currentFont());
   722 
   602 
   723     {
   603     {
   724         // hack to get correct initial layout
   604         // hack to get correct initial layout
   725         NSRect frameRect = [ourPanel frame];
   605         NSRect frameRect = [ourPanel frame];
   726         frameRect.size.width += 1.0;
   606         frameRect.size.width += 1.0;
   727         [ourPanel setFrame:frameRect display:NO];
   607         [ourPanel setFrame:frameRect display:NO];
   728         frameRect.size.width -= 1.0;
   608         frameRect.size.width -= 1.0;
   729         frameRect.size = [delegate windowWillResize:ourPanel toSize:frameRect.size];
   609         frameRect.size = [del windowWillResize:ourPanel toSize:frameRect.size];
   730         [ourPanel setFrame:frameRect display:NO];
   610         [ourPanel setFrame:frameRect display:NO];
   731         [ourPanel center];
   611         [ourPanel center];
   732     }
   612     }
   733     NSString *title = @"Select font";
   613     NSString *title = @"Select font";
   734     [ourPanel setTitle:title];
   614     [ourPanel setTitle:title];
   735 
       
   736     [delegate setModalSession:[NSApp beginModalSessionForWindow:ourPanel]];
       
   737     return delegate;
       
   738 }
   615 }
   739 
   616 
   740 void QFontDialogPrivate::mac_nativeDialogModalHelp()
   617 void QFontDialogPrivate::mac_nativeDialogModalHelp()
   741 {
   618 {
   742     // Copied from QFileDialogPrivate
   619     // Copied from QFileDialogPrivate
   757 // offer a proper dialog, but a panel (i.e. without Ok and Cancel buttons).
   634 // offer a proper dialog, but a panel (i.e. without Ok and Cancel buttons).
   758 // This means we need to "construct" a native dialog by taking the panel
   635 // This means we need to "construct" a native dialog by taking the panel
   759 // and "adding" the buttons.
   636 // and "adding" the buttons.
   760 void QFontDialogPrivate::_q_macRunNativeAppModalPanel()
   637 void QFontDialogPrivate::_q_macRunNativeAppModalPanel()
   761 {
   638 {
   762     QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
   639     createNSFontPanelDelegate();
       
   640     QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *del = static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate);
       
   641     [del runApplicationModalPanel];
       
   642 }
       
   643 
       
   644 bool QFontDialogPrivate::showCocoaFontPanel()
       
   645 {
       
   646     if (!sharedFontPanelAvailable)
       
   647         return false;
       
   648 
   763     Q_Q(QFontDialog);
   649     Q_Q(QFontDialog);
   764     QCocoaFontPanelDelegate *delegate = (QCocoaFontPanelDelegate *)_q_constructNativePanel();
   650     QMacCocoaAutoReleasePool pool;
   765     NSWindow *ourPanel = [delegate actualPanel];
   651     createNSFontPanelDelegate();
   766     [ourPanel retain];
   652     QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *del = static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate);
   767     int rval = [NSApp runModalForWindow:ourPanel];
   653     if (qt_mac_is_macsheet(q))
   768     QAbstractEventDispatcher::instance()->interrupt();
   654         [del showWindowModalSheet:q->parentWidget()];
   769     [ourPanel release];
       
   770     [delegate cleanUpAfterMyself];
       
   771     [delegate release];
       
   772     bool isOk = (rval == NSOKButton);
       
   773     if(isOk)
       
   774         rescode = QDialog::Accepted;
       
   775     else
   655     else
   776         rescode = QDialog::Rejected;
   656         [del showModelessPanel];
   777 }
   657     return true;
   778 
   658 }
       
   659 
       
   660 bool QFontDialogPrivate::hideCocoaFontPanel()
       
   661 {
       
   662     if (!delegate){
       
   663         // Nothing to do. We return false to leave the question
       
   664         // open regarding whether or not to go native:
       
   665         return false;
       
   666     } else {
       
   667         closeCocoaFontPanel();
       
   668         // Even when we hide it, we are still using a
       
   669         // native dialog, so return true:
       
   670         return true;
       
   671     }
       
   672 }
   779 bool QFontDialogPrivate::setVisible_sys(bool visible)
   673 bool QFontDialogPrivate::setVisible_sys(bool visible)
   780 {
   674 {
   781     Q_Q(QFontDialog);
   675     Q_Q(QFontDialog);
   782     if (!visible == q->isHidden())
   676     if (!visible == q->isHidden())
   783         return false;
   677         return false;
   784     return visible;
   678 
       
   679     return visible ? showCocoaFontPanel() : hideCocoaFontPanel();
   785 }
   680 }
   786 
   681 
   787 QT_END_NAMESPACE
   682 QT_END_NAMESPACE
   788 
   683 
   789 #endif
   684 #endif