diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm | 265 |
1 files changed, 151 insertions, 114 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index a70ba3749f..91fb52eb6d 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -128,14 +128,18 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) - (void)finishOffWithCode:(NSInteger)code; @end -@implementation QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) +QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); -- (id)initWithDialogHelper: - (QCocoaFontDialogHelper *)helper +@implementation QNSFontPanelDelegate + +- (id)init { self = [super init]; mFontPanel = [NSFontPanel sharedFontPanel]; - mHelper = helper; + mHelper = 0; + mStolenContentView = 0; + mOkButton = 0; + mCancelButton = 0; mResultCode = NSCancelButton; mDialogIsExecuting = false; mResultSet = false; @@ -145,13 +149,32 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) [mFontPanel setRestorable:NO]; #endif + [mFontPanel setDelegate:self]; + [[NSFontManager sharedFontManager] setDelegate:self]; + + [mFontPanel retain]; + return self; +} + +- (void)dealloc +{ + [self restoreOriginalContentView]; + [mFontPanel setDelegate:nil]; + [[NSFontManager sharedFontManager] setDelegate:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [super dealloc]; +} + +- (void)setDialogHelper:(QCocoaFontDialogHelper *)helper +{ + mHelper = helper; + [mFontPanel setTitle:QCFString::toNSString(helper->options()->windowTitle())]; if (mHelper->options()->testOption(QFontDialogOptions::NoButtons)) { - mStolenContentView = 0; - mOkButton = 0; - mCancelButton = 0; - } else { + [self restoreOriginalContentView]; + } else if (!mStolenContentView) { // steal the font panel's contents view mStolenContentView = [mFontPanel contentView]; [mStolenContentView retain]; @@ -176,14 +199,22 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) [mCancelButton setAction:@selector(onCancelClicked)]; [mCancelButton setTarget:self]; } +} - [mFontPanel retain]; - return self; +- (void)closePanel +{ + [mFontPanel close]; } -- (void)dealloc +- (void)windowDidResize:(NSNotification *)notification { - if (mOkButton) { + Q_UNUSED(notification); + [self relayout]; +} + +- (void)restoreOriginalContentView +{ + if (mStolenContentView) { NSView *ourContentView = [mFontPanel contentView]; // return stolen stuff to its rightful owner @@ -192,28 +223,17 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) [mOkButton release]; [mCancelButton release]; [ourContentView release]; + mOkButton = 0; + mCancelButton = 0; + mStolenContentView = 0; } - - [mFontPanel setDelegate:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - [super dealloc]; -} - -- (void)closePanel -{ - [mFontPanel close]; -} - -- (void)windowDidResize:(NSNotification *)notification -{ - Q_UNUSED(notification); - if (mOkButton) - [self relayout]; } - (void)relayout { + if (!mOkButton) + return; + [self relayoutToContentSize:[[mStolenContentView superview] frame].size]; } @@ -289,30 +309,32 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) NSFont *panelFont = [fontManager convertFont:selectedFont]; mQtFont = qfontForCocoaFont(panelFont, mQtFont); - emit mHelper->currentFontChanged(mQtFont); + if (mHelper) + emit mHelper->currentFontChanged(mQtFont); } - (void)showModelessPanel { mDialogIsExecuting = false; + mResultSet = false; [mFontPanel makeKeyAndOrderFront:mFontPanel]; } - (BOOL)runApplicationModalPanel { mDialogIsExecuting = true; - [mFontPanel setDelegate:self]; // Call processEvents in case the event dispatcher has been interrupted, and needs to do // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will // close down during the cleanup. qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); [NSApp runModalForWindow:mFontPanel]; + mDialogIsExecuting = false; return (mResultCode == NSOKButton); } -- (QT_PREPEND_NAMESPACE(QPlatformDialogHelper::DialogCode))dialogResultCode +- (QPlatformDialogHelper::DialogCode)dialogResultCode { - return (mResultCode == NSOKButton) ? QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Accepted) : QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Rejected); + return (mResultCode == NSOKButton) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected; } - (BOOL)windowShouldClose:(id)window @@ -324,7 +346,8 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) [self finishOffWithCode:NSCancelButton]; } else { mResultSet = true; - emit mHelper->reject(); + if (mHelper) + emit mHelper->reject(); } return true; } @@ -359,27 +382,101 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) QT_BEGIN_NAMESPACE -QCocoaFontDialogHelper::QCocoaFontDialogHelper() : - mDelegate(0) +class QCocoaFontPanel +{ +public: + QCocoaFontPanel() + { + mDelegate = [[QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) alloc] init]; + } + + ~QCocoaFontPanel() + { + [mDelegate release]; + } + + void init(QCocoaFontDialogHelper *helper) + { + [mDelegate setDialogHelper:helper]; + } + + void cleanup(QCocoaFontDialogHelper *helper) + { + if (mDelegate->mHelper == helper) + mDelegate->mHelper = 0; + } + + bool exec() + { + // Note: If NSApp is not running (which is the case if e.g a top-most + // QEventLoop has been interrupted, and the second-most event loop has not + // yet been reactivated (regardless if [NSApp run] is still on the stack)), + // showing a native modal dialog will fail. + return [mDelegate runApplicationModalPanel]; + } + + bool show(Qt::WindowModality windowModality, QWindow *parent) + { + Q_UNUSED(parent); + if (windowModality != Qt::WindowModal) + [mDelegate showModelessPanel]; + // no need to show a Qt::WindowModal dialog here, because it's necessary to call exec() in that case + return true; + } + + void hide() + { + [mDelegate closePanel]; + } + + QFont currentFont() const + { + return mDelegate->mQtFont; + } + + void setCurrentFont(const QFont &font) + { + NSFontManager *mgr = [NSFontManager sharedFontManager]; + const NSFont *nsFont = 0; + + int weight = 5; + NSFontTraitMask mask = 0; + if (font.style() == QFont::StyleItalic) { + mask |= NSItalicFontMask; + } + if (font.weight() == QFont::Bold) { + weight = 9; + mask |= NSBoldFontMask; + } + + QFontInfo fontInfo(font); + nsFont = [mgr fontWithFamily:QCFString::toNSString(fontInfo.family()) + traits:mask + weight:weight + size:fontInfo.pointSize()]; + + [mgr setSelectedFont:const_cast<NSFont *>(nsFont) isMultiple:NO]; + mDelegate->mQtFont = font; + } + +private: + QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *mDelegate; +}; + +Q_GLOBAL_STATIC(QCocoaFontPanel, sharedFontPanel) + +QCocoaFontDialogHelper::QCocoaFontDialogHelper() { } QCocoaFontDialogHelper::~QCocoaFontDialogHelper() { - if (!mDelegate) - return; - [reinterpret_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate) release]; - mDelegate = 0; + sharedFontPanel()->cleanup(this); } void QCocoaFontDialogHelper::exec() { - // Note: If NSApp is not running (which is the case if e.g a top-most - // QEventLoop has been interrupted, and the second-most event loop has not - // yet been reactivated (regardless if [NSApp run] is still on the stack)), - // showing a native modal dialog will fail. - QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate); - if ([delegate runApplicationModalPanel]) + if (sharedFontPanel()->exec()) emit accept(); else emit reject(); @@ -387,86 +484,26 @@ void QCocoaFontDialogHelper::exec() bool QCocoaFontDialogHelper::show(Qt::WindowFlags, Qt::WindowModality windowModality, QWindow *parent) { - if (windowModality == Qt::WindowModal) { - // Cocoa's shared font panel cannot be shown as a sheet - return false; - } - return showCocoaFontPanel(windowModality, parent); + if (windowModality == Qt::WindowModal) + windowModality = Qt::ApplicationModal; + sharedFontPanel()->init(this); + return sharedFontPanel()->show(windowModality, parent); } void QCocoaFontDialogHelper::hide() { - if (!mDelegate) - return; - [reinterpret_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate)->mFontPanel close]; + sharedFontPanel()->hide(); } void QCocoaFontDialogHelper::setCurrentFont(const QFont &font) { - NSFontManager *mgr = [NSFontManager sharedFontManager]; - const NSFont *nsFont = 0; - - int weight = 5; - NSFontTraitMask mask = 0; - if (font.style() == QFont::StyleItalic) { - mask |= NSItalicFontMask; - } - if (font.weight() == QFont::Bold) { - weight = 9; - mask |= NSBoldFontMask; - } - - QFontInfo fontInfo(font); - nsFont = [mgr fontWithFamily:QCFString::toNSString(fontInfo.family()) - traits:mask - weight:weight - size:fontInfo.pointSize()]; - - if (!mDelegate) - createNSFontPanelDelegate(); - - [mgr setSelectedFont:const_cast<NSFont *>(nsFont) isMultiple:NO]; - static_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate)->mQtFont = font; + sharedFontPanel()->init(this); + sharedFontPanel()->setCurrentFont(font); } QFont QCocoaFontDialogHelper::currentFont() const { - if (!mDelegate) - return QFont(); - return reinterpret_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate)->mQtFont; -} - -void QCocoaFontDialogHelper::createNSFontPanelDelegate() -{ - if (mDelegate) - return; - - QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) alloc] - initWithDialogHelper:this]; - - mDelegate = delegate; -} - -bool QCocoaFontDialogHelper::showCocoaFontPanel(Qt::WindowModality windowModality, QWindow *parent) -{ - Q_UNUSED(parent); - createNSFontPanelDelegate(); - QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate); - if (windowModality == Qt::NonModal) - [delegate showModelessPanel]; - // no need to show a Qt::ApplicationModal dialog here, since it will be done in _q_platformRunNativeAppModalPanel() - return true; -} - -bool QCocoaFontDialogHelper::hideCocoaFontPanel() -{ - if (!mDelegate){ - return false; - } else { - QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate); - [delegate closePanel]; - return true; - } + return sharedFontPanel()->currentFont(); } QT_END_NAMESPACE |