| /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| /* |
| * This file is part of the Collabora Office project. |
| * |
| * This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| * |
| * This file incorporates work covered by the following license notice: |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed |
| * with this work for additional information regarding copyright |
| * ownership. The ASF licenses this file to you under the Apache |
| * License, Version 2.0 (the "License"); you may not use this file |
| * except in compliance with the License. You may obtain a copy of |
| * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
| */ |
| |
| #include <sal/config.h> |
| #include <sal/log.hxx> |
| |
| #include <i18nlangtag/languagetag.hxx> |
| #include <o3tl/string_view.hxx> |
| #include <rtl/ustrbuf.hxx> |
| #include <vcl/print.hxx> |
| #include <vcl/image.hxx> |
| #include <vcl/virdev.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/unohelp.hxx> |
| #include <vcl/settings.hxx> |
| |
| #include <osx/printview.h> |
| #include <osx/salinst.h> |
| #include <quartz/utils.h> |
| |
| #include <svdata.hxx> |
| #include <strings.hrc> |
| #include <printaccessoryview.hrc> |
| |
| #include <com/sun/star/i18n/XBreakIterator.hpp> |
| #include <com/sun/star/i18n/WordType.hpp> |
| |
| #include <map> |
| #include <string_view> |
| #include <utility> |
| |
| using namespace vcl; |
| using namespace com::sun::star; |
| using namespace com::sun::star::beans; |
| using namespace com::sun::star::uno; |
| |
| namespace { |
| |
| class ControllerProperties; |
| |
| } |
| |
| @interface ControlTarget : NSObject |
| { |
| ControllerProperties* mpController; |
| } |
| -(id)initWithControllerMap: (ControllerProperties*)pController; |
| -(void)triggered:(id)pSender; |
| -(void)triggeredNumeric:(id)pSender; |
| -(void)dealloc; |
| @end |
| |
| @interface AquaPrintPanelAccessoryController : NSViewController< NSPrintPanelAccessorizing > |
| { |
| NSPrintOperation *mpPrintOperation; |
| vcl::PrinterController *mpPrinterController; |
| PrintAccessoryViewState *mpViewState; |
| } |
| |
| -(void)forPrintOperation:(NSPrintOperation*)pPrintOp; |
| -(void)withPrinterController:(vcl::PrinterController*)pController; |
| -(void)withViewState:(PrintAccessoryViewState*)pState; |
| |
| -(NSPrintOperation*)printOperation; |
| -(vcl::PrinterController*)printerController; |
| -(PrintAccessoryViewState*)viewState; |
| |
| -(NSSet*)keyPathsForValuesAffectingPreview; |
| -(NSArray*)localizedSummaryItems; |
| |
| -(sal_Int32)updatePrintOperation:(sal_Int32)pLastPageCount; |
| -(sal_Int32)updatePrintOperation:(sal_Int32)pLastPageCount forceRestart:(BOOL)bForceRestart; |
| |
| @end |
| |
| @implementation AquaPrintPanelAccessoryController |
| |
| -(void)forPrintOperation:(NSPrintOperation*)pPrintOp |
| { mpPrintOperation = pPrintOp; } |
| |
| -(void)withPrinterController:(vcl::PrinterController*)pController |
| { mpPrinterController = pController; } |
| |
| -(void)withViewState:(PrintAccessoryViewState*)pState |
| { mpViewState = pState; } |
| |
| -(NSPrintOperation*)printOperation |
| { return mpPrintOperation; } |
| |
| -(vcl::PrinterController*)printerController |
| { return mpPrinterController; } |
| |
| -(PrintAccessoryViewState*)viewState |
| { return mpViewState; } |
| |
| -(NSSet*)keyPathsForValuesAffectingPreview |
| { |
| return [ NSSet setWithObject:@"updatePrintOperation" ]; |
| } |
| |
| -(NSArray*)localizedSummaryItems |
| { |
| return [ NSArray arrayWithObject: |
| [ NSDictionary dictionary ] ]; |
| } |
| |
| -(sal_Int32)updatePrintOperation:(sal_Int32)pLastPageCount |
| { |
| return [self updatePrintOperation: pLastPageCount forceRestart: NO]; |
| } |
| |
| -(sal_Int32)updatePrintOperation:(sal_Int32)pLastPageCount forceRestart:(BOOL)bForceRestart |
| { |
| // page range may be changed by option choice |
| sal_Int32 nPages = mpPrinterController->getFilteredPageCount(); |
| |
| mpViewState->bNeedRestart = false; |
| if( bForceRestart || nPages != pLastPageCount ) |
| { |
| #if OSL_DEBUG_LEVEL > 1 |
| if( nPages != pLastPageCount ) |
| { |
| SAL_INFO( "vcl.osx.print", "number of pages changed" << |
| " from " << pLastPageCount << " to " << nPages ); |
| } |
| #endif |
| mpViewState->bNeedRestart = true; |
| } |
| |
| NSTabView* pTabView = [[[self view] subviews] objectAtIndex:0]; |
| NSTabViewItem* pItem = [pTabView selectedTabViewItem]; |
| if( pItem ) |
| mpViewState->nLastPage = [pTabView indexOfTabViewItem: pItem]; |
| else |
| mpViewState->nLastPage = 0; |
| |
| if( mpViewState->bNeedRestart ) |
| { |
| // AppKit does not give a chance of changing the page count |
| // and don't let cancel the dialog either |
| // hack: send a cancel message to the modal window displaying views |
| NSWindow* pNSWindow = [NSApp modalWindow]; |
| if( pNSWindow ) |
| { |
| [pNSWindow cancelOperation: nil]; |
| [pNSWindow close]; |
| [NSApp abortModal]; |
| } |
| [mpPrintOperation setShowsProgressPanel: NO]; |
| [[mpPrintOperation printInfo] setJobDisposition: NSPrintCancelJob]; |
| } |
| |
| return nPages; |
| } |
| |
| @end |
| |
| namespace { |
| |
| class ControllerProperties |
| { |
| std::map< int, OUString > maTagToPropertyName; |
| std::map< int, sal_Int32 > maTagToValueInt; |
| std::map< NSView*, NSView* > maViewPairMap; |
| std::vector< NSObject* > maViews; |
| int mnNextTag; |
| sal_Int32 mnLastPageCount; |
| AquaPrintPanelAccessoryController* mpAccessoryController; |
| |
| public: |
| ControllerProperties( AquaPrintPanelAccessoryController* i_pAccessoryController ) |
| : mnNextTag( 0 ) |
| , mnLastPageCount( [i_pAccessoryController printerController]->getFilteredPageCount() ) |
| , mpAccessoryController( i_pAccessoryController ) |
| { |
| static_assert( SAL_N_ELEMENTS(SV_PRINT_NATIVE_STRINGS) == 5, "resources not found" ); |
| } |
| |
| static OUString getMoreString() |
| { |
| return VclResId(SV_PRINT_NATIVE_STRINGS[3]); |
| } |
| |
| static OUString getPrintSelectionString() |
| { |
| return VclResId(SV_PRINT_NATIVE_STRINGS[4]); |
| } |
| |
| int addNameTag( const OUString& i_rPropertyName ) |
| { |
| int nNewTag = mnNextTag++; |
| maTagToPropertyName[ nNewTag ] = i_rPropertyName; |
| return nNewTag; |
| } |
| |
| int addNameAndValueTag( const OUString& i_rPropertyName, sal_Int32 i_nValue ) |
| { |
| int nNewTag = mnNextTag++; |
| maTagToPropertyName[ nNewTag ] = i_rPropertyName; |
| maTagToValueInt[ nNewTag ] = i_nValue; |
| return nNewTag; |
| } |
| |
| void addObservedControl( NSObject* i_pView ) |
| { |
| maViews.push_back( i_pView ); |
| } |
| |
| void addViewPair( NSView* i_pLeft, NSView* i_pRight ) |
| { |
| maViewPairMap[ i_pLeft ] = i_pRight; |
| maViewPairMap[ i_pRight ] = i_pLeft; |
| } |
| |
| NSView* getPair( NSView* i_pLeft ) const |
| { |
| NSView* pRight = nil; |
| std::map< NSView*, NSView* >::const_iterator it = maViewPairMap.find( i_pLeft ); |
| if( it != maViewPairMap.end() ) |
| pRight = it->second; |
| return pRight; |
| } |
| |
| void changePropertyWithIntValue( int i_nTag ) |
| { |
| std::map< int, OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); |
| std::map< int, sal_Int32 >::const_iterator value_it = maTagToValueInt.find( i_nTag ); |
| if( name_it != maTagToPropertyName.end() && value_it != maTagToValueInt.end() ) |
| { |
| vcl::PrinterController * mpController = [mpAccessoryController printerController]; |
| PropertyValue* pVal = mpController->getValue( name_it->second ); |
| if( pVal ) |
| { |
| pVal->Value <<= value_it->second; |
| mnLastPageCount = [mpAccessoryController updatePrintOperation: mnLastPageCount]; |
| } |
| } |
| } |
| |
| void changePropertyWithIntValue( int i_nTag, sal_Int64 i_nValue ) |
| { |
| std::map< int, OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); |
| if( name_it != maTagToPropertyName.end() ) |
| { |
| vcl::PrinterController * mpController = [mpAccessoryController printerController]; |
| PropertyValue* pVal = mpController->getValue( name_it->second ); |
| if( pVal ) |
| { |
| pVal->Value <<= i_nValue; |
| mnLastPageCount = [mpAccessoryController updatePrintOperation: mnLastPageCount]; |
| } |
| } |
| } |
| |
| void changePropertyWithBoolValue( int i_nTag, bool i_bValue ) |
| { |
| std::map< int, OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); |
| if( name_it != maTagToPropertyName.end() ) |
| { |
| vcl::PrinterController * mpController = [mpAccessoryController printerController]; |
| PropertyValue* pVal = mpController->getValue( name_it->second ); |
| if( pVal ) |
| { |
| // ugly |
| bool bPrintContent = name_it->second == "PrintContent"; |
| if( bPrintContent ) |
| pVal->Value <<= i_bValue ? sal_Int32(2) : sal_Int32(0); |
| else |
| pVal->Value <<= i_bValue; |
| |
| // Related: tdf#163126 if the "print selection only" checkbox |
| // is changed when the content is only a single page, calling |
| // -[AquaPrintPanelAccessoryController updatePrintOperation:] |
| // won't restart the print job so force the print job to |
| // restart. |
| mnLastPageCount = [mpAccessoryController updatePrintOperation: mnLastPageCount forceRestart: bPrintContent]; |
| } |
| } |
| } |
| |
| void changePropertyWithStringValue( int i_nTag, const OUString& i_rValue ) |
| { |
| std::map< int, OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); |
| if( name_it != maTagToPropertyName.end() ) |
| { |
| vcl::PrinterController * mpController = [mpAccessoryController printerController]; |
| PropertyValue* pVal = mpController->getValue( name_it->second ); |
| if( pVal ) |
| { |
| pVal->Value <<= i_rValue; |
| mnLastPageCount = [mpAccessoryController updatePrintOperation: mnLastPageCount]; |
| } |
| } |
| } |
| |
| void updateEnableState() |
| { |
| for( std::vector< NSObject* >::iterator it = maViews.begin(); it != maViews.end(); ++it ) |
| { |
| NSObject* pObj = *it; |
| NSControl* pCtrl = nil; |
| NSCell* pCell = nil; |
| if( [pObj isKindOfClass: [NSControl class]] ) |
| pCtrl = static_cast<NSControl*>(pObj); |
| else if( [pObj isKindOfClass: [NSCell class]] ) |
| pCell = static_cast<NSCell*>(pObj); |
| |
| int nTag = pCtrl ? [pCtrl tag] : |
| pCell ? [pCell tag] : |
| -1; |
| |
| std::map< int, OUString >::const_iterator name_it = maTagToPropertyName.find( nTag ); |
| if( name_it != maTagToPropertyName.end() && name_it->second != "PrintContent" ) |
| { |
| vcl::PrinterController * mpController = [mpAccessoryController printerController]; |
| bool bEnabled = mpController->isUIOptionEnabled( name_it->second ) ? YES : NO; |
| if( pCtrl ) |
| { |
| [pCtrl setEnabled: bEnabled]; |
| NSView* pOther = getPair( pCtrl ); |
| if( pOther && [pOther isKindOfClass: [NSControl class]] ) |
| [static_cast<NSControl*>(pOther) setEnabled: bEnabled]; |
| } |
| else if( pCell ) |
| [pCell setEnabled: bEnabled]; |
| } |
| } |
| } |
| |
| }; |
| |
| } |
| |
| static OUString filterAccelerator( OUString const & rText ) |
| { |
| OUStringBuffer aBuf( rText.getLength() ); |
| for( sal_Int32 nIndex = 0; nIndex != -1; ) |
| aBuf.append( o3tl::getToken( rText, 0, '~', nIndex ) ); |
| return aBuf.makeStringAndClear(); |
| } |
| |
| @implementation ControlTarget |
| |
| -(id)initWithControllerMap: (ControllerProperties*)pController |
| { |
| if( (self = [super init]) ) |
| { |
| mpController = pController; |
| } |
| return self; |
| } |
| |
| -(void)triggered:(id)pSender |
| { |
| if( [pSender isMemberOfClass: [NSPopUpButton class]] ) |
| { |
| NSPopUpButton* pBtn = static_cast<NSPopUpButton*>(pSender); |
| NSMenuItem* pSelected = [pBtn selectedItem]; |
| if( pSelected ) |
| { |
| int nTag = [pSelected tag]; |
| mpController->changePropertyWithIntValue( nTag ); |
| } |
| } |
| else if( [pSender isMemberOfClass: [NSButton class]] ) |
| { |
| NSButton* pBtn = static_cast<NSButton*>(pSender); |
| int nTag = [pBtn tag]; |
| mpController->changePropertyWithBoolValue( nTag, [pBtn state] == NSControlStateValueOn ); |
| } |
| else if( [pSender isMemberOfClass: [NSMatrix class]] ) |
| { |
| NSObject* pObj = [static_cast<NSMatrix*>(pSender) selectedCell]; |
| if( [pObj isMemberOfClass: [NSButtonCell class]] ) |
| { |
| NSButtonCell* pCell = static_cast<NSButtonCell*>(pObj); |
| int nTag = [pCell tag]; |
| mpController->changePropertyWithIntValue( nTag ); |
| } |
| } |
| else if( [pSender isMemberOfClass: [NSTextField class]] ) |
| { |
| NSTextField* pField = static_cast<NSTextField*>(pSender); |
| int nTag = [pField tag]; |
| OUString aValue = GetOUString( [pSender stringValue] ); |
| mpController->changePropertyWithStringValue( nTag, aValue ); |
| } |
| else |
| { |
| SAL_INFO( "vcl.osx.print", "Unsupported class" << |
| ( [pSender class] ? [NSStringFromClass([pSender class]) UTF8String] : "nil" ) ); |
| } |
| mpController->updateEnableState(); |
| } |
| |
| -(void)triggeredNumeric:(id)pSender |
| { |
| if( [pSender isMemberOfClass: [NSTextField class]] ) |
| { |
| NSTextField* pField = static_cast<NSTextField*>(pSender); |
| int nTag = [pField tag]; |
| sal_Int64 nValue = [pField intValue]; |
| |
| NSView* pOther = mpController->getPair( pField ); |
| if( pOther ) |
| [static_cast<NSControl*>(pOther) setIntValue: nValue]; |
| |
| mpController->changePropertyWithIntValue( nTag, nValue ); |
| } |
| else if( [pSender isMemberOfClass: [NSStepper class]] ) |
| { |
| NSStepper* pStep = static_cast<NSStepper*>(pSender); |
| int nTag = [pStep tag]; |
| sal_Int64 nValue = [pStep intValue]; |
| |
| NSView* pOther = mpController->getPair( pStep ); |
| if( pOther ) |
| [static_cast<NSControl*>(pOther) setIntValue: nValue]; |
| |
| mpController->changePropertyWithIntValue( nTag, nValue ); |
| } |
| else |
| { |
| SAL_INFO( "vcl.osx.print", "Unsupported class" << |
| ([pSender class] ? [NSStringFromClass([pSender class]) UTF8String] : "nil") ); |
| } |
| mpController->updateEnableState(); |
| } |
| |
| -(void)dealloc |
| { |
| delete mpController; |
| [super dealloc]; |
| } |
| |
| @end |
| |
| namespace { |
| |
| struct ColumnItem |
| { |
| NSControl* pControl; |
| CGFloat nOffset; |
| NSControl* pSubControl; |
| |
| ColumnItem( NSControl* i_pControl = nil, CGFloat i_nOffset = 0, NSControl* i_pSub = nil ) |
| : pControl( i_pControl ) |
| , nOffset( i_nOffset ) |
| , pSubControl( i_pSub ) |
| {} |
| |
| CGFloat getWidth() const |
| { |
| CGFloat nWidth = 0; |
| if( pControl ) |
| { |
| NSRect aCtrlRect = [pControl frame]; |
| nWidth = aCtrlRect.size.width; |
| nWidth += nOffset; |
| if( pSubControl ) |
| { |
| NSRect aSubRect = [pSubControl frame]; |
| nWidth += aSubRect.size.width; |
| nWidth += aSubRect.origin.x - (aCtrlRect.origin.x + aCtrlRect.size.width); |
| } |
| } |
| return nWidth; |
| } |
| }; |
| |
| } |
| |
| static void adjustViewAndChildren( NSView* pNSView, NSSize& rMaxSize, |
| std::vector< ColumnItem >& rLeftColumn, |
| std::vector< ColumnItem >& rRightColumn |
| ) |
| { |
| // balance columns |
| |
| // first get overall column widths |
| CGFloat nLeftWidth = 0; |
| CGFloat nRightWidth = 0; |
| for( size_t i = 0; i < rLeftColumn.size(); i++ ) |
| { |
| CGFloat nW = rLeftColumn[i].getWidth(); |
| if( nW > nLeftWidth ) |
| nLeftWidth = nW; |
| } |
| for( size_t i = 0; i < rRightColumn.size(); i++ ) |
| { |
| CGFloat nW = rRightColumn[i].getWidth(); |
| if( nW > nRightWidth ) |
| nRightWidth = nW; |
| } |
| |
| // right align left column |
| for( size_t i = 0; i < rLeftColumn.size(); i++ ) |
| { |
| if( rLeftColumn[i].pControl ) |
| { |
| NSRect aCtrlRect = [rLeftColumn[i].pControl frame]; |
| CGFloat nX = nLeftWidth - aCtrlRect.size.width; |
| if( rLeftColumn[i].pSubControl ) |
| { |
| NSRect aSubRect = [rLeftColumn[i].pSubControl frame]; |
| nX -= aSubRect.size.width + (aSubRect.origin.x - (aCtrlRect.origin.x + aCtrlRect.size.width)); |
| aSubRect.origin.x = nLeftWidth - aSubRect.size.width; |
| [rLeftColumn[i].pSubControl setFrame: aSubRect]; |
| } |
| aCtrlRect.origin.x = nX; |
| [rLeftColumn[i].pControl setFrame: aCtrlRect]; |
| } |
| } |
| |
| // left align right column |
| for( size_t i = 0; i < rRightColumn.size(); i++ ) |
| { |
| if( rRightColumn[i].pControl ) |
| { |
| NSRect aCtrlRect = [rRightColumn[i].pControl frame]; |
| CGFloat nX = nLeftWidth + 3; |
| if( rRightColumn[i].pSubControl ) |
| { |
| NSRect aSubRect = [rRightColumn[i].pSubControl frame]; |
| aSubRect.origin.x = nX + aSubRect.origin.x - aCtrlRect.origin.x; |
| [rRightColumn[i].pSubControl setFrame: aSubRect]; |
| } |
| aCtrlRect.origin.x = nX; |
| [rRightColumn[i].pControl setFrame: aCtrlRect]; |
| } |
| } |
| |
| NSArray* pSubViews = [pNSView subviews]; |
| unsigned int nViews = [pSubViews count]; |
| NSRect aUnion = NSZeroRect; |
| |
| // get the combined frame of all subviews |
| for( unsigned int n = 0; n < nViews; n++ ) |
| { |
| aUnion = NSUnionRect( aUnion, [[pSubViews objectAtIndex: n] frame] ); |
| } |
| |
| // move everything so it will fit |
| for( unsigned int n = 0; n < nViews; n++ ) |
| { |
| NSView* pCurSubView = [pSubViews objectAtIndex: n]; |
| NSRect aFrame = [pCurSubView frame]; |
| aFrame.origin.x -= aUnion.origin.x - 5; |
| aFrame.origin.y -= aUnion.origin.y - 5; |
| [pCurSubView setFrame: aFrame]; |
| } |
| |
| // resize the view itself |
| aUnion.size.height += 10; |
| aUnion.size.width += 20; |
| [pNSView setFrameSize: aUnion.size]; |
| |
| if( aUnion.size.width > rMaxSize.width ) |
| rMaxSize.width = aUnion.size.width; |
| if( aUnion.size.height > rMaxSize.height ) |
| rMaxSize.height = aUnion.size.height; |
| } |
| |
| static void adjustTabViews( NSTabView* pTabView, NSSize aTabSize ) |
| { |
| // loop over all contained tab pages |
| NSArray* pTabbedViews = [pTabView tabViewItems]; |
| int nViews = [pTabbedViews count]; |
| for( int i = 0; i < nViews; i++ ) |
| { |
| NSTabViewItem* pItem = static_cast<NSTabViewItem*>([pTabbedViews objectAtIndex: i]); |
| NSView* pNSView = [pItem view]; |
| if( pNSView ) |
| { |
| NSRect aRect = [pNSView frame]; |
| double nDiff = aTabSize.height - aRect.size.height; |
| aRect.size = aTabSize; |
| [pNSView setFrame: aRect]; |
| |
| NSArray* pSubViews = [pNSView subviews]; |
| unsigned int nSubViews = [pSubViews count]; |
| |
| // move everything up |
| for( unsigned int n = 0; n < nSubViews; n++ ) |
| { |
| NSView* pCurSubView = [pSubViews objectAtIndex: n]; |
| NSRect aFrame = [pCurSubView frame]; |
| aFrame.origin.y += nDiff; |
| // give separators the correct width |
| // separators are currently the only NSBoxes we use |
| if( [pCurSubView isMemberOfClass: [NSBox class]] ) |
| { |
| aFrame.size.width = aTabSize.width - aFrame.origin.x - 10; |
| } |
| [pCurSubView setFrame: aFrame]; |
| } |
| } |
| } |
| } |
| |
| static NSControl* createLabel( const OUString& i_rText ) |
| { |
| NSString* pText = CreateNSString( i_rText ); |
| NSRect aTextRect = { NSZeroPoint, {20, 15} }; |
| NSTextField* pTextView = [[NSTextField alloc] initWithFrame: aTextRect]; |
| [pTextView setFont: [NSFont controlContentFontOfSize: 0]]; |
| [pTextView setEditable: NO]; |
| [pTextView setSelectable: NO]; |
| [pTextView setDrawsBackground: NO]; |
| [pTextView setBordered: NO]; |
| [pTextView setStringValue: pText]; |
| [pTextView sizeToFit]; |
| [pText release]; |
| return pTextView; |
| } |
| |
| static sal_Int32 findBreak( const OUString& i_rText, sal_Int32 i_nPos ) |
| { |
| sal_Int32 nRet = i_rText.getLength(); |
| Reference< i18n::XBreakIterator > xBI( vcl::unohelper::CreateBreakIterator() ); |
| if( xBI.is() ) |
| { |
| i18n::Boundary aBoundary = |
| xBI->getWordBoundary( i_rText, i_nPos, |
| Application::GetSettings().GetLanguageTag().getLocale(), |
| i18n::WordType::ANYWORD_IGNOREWHITESPACES, |
| true ); |
| nRet = aBoundary.endPos; |
| } |
| return nRet; |
| } |
| |
| static void linebreakCell( NSCell* pBtn, const OUString& i_rText ) |
| { |
| NSString* pText = CreateNSString( i_rText ); |
| [pBtn setTitle: pText]; |
| [pText release]; |
| NSSize aSize = [pBtn cellSize]; |
| if( aSize.width > 280 ) |
| { |
| // need two lines |
| sal_Int32 nLen = i_rText.getLength(); |
| sal_Int32 nIndex = nLen / 2; |
| nIndex = findBreak( i_rText, nIndex ); |
| if( nIndex < nLen ) |
| { |
| OUStringBuffer aBuf( i_rText ); |
| aBuf[nIndex] = '\n'; |
| pText = CreateNSString( aBuf.makeStringAndClear() ); |
| [pBtn setTitle: pText]; |
| [pText release]; |
| } |
| } |
| } |
| |
| static void addSubgroup( NSView* pCurParent, CGFloat& rCurY, const OUString& rText ) |
| { |
| NSControl* pTextView = createLabel( rText ); |
| [pCurParent addSubview: [pTextView autorelease]]; |
| NSRect aTextRect = [pTextView frame]; |
| // move to nCurY |
| aTextRect.origin.y = rCurY - aTextRect.size.height; |
| [pTextView setFrame: aTextRect]; |
| |
| NSRect aSepRect = { { aTextRect.size.width + 1, aTextRect.origin.y }, { 100, 6 } }; |
| NSBox* pBox = [[NSBox alloc] initWithFrame: aSepRect]; |
| [pBox setBoxType: NSBoxSeparator]; |
| [pCurParent addSubview: [pBox autorelease]]; |
| |
| // update nCurY |
| rCurY = aTextRect.origin.y - 5; |
| } |
| |
| static void addBool( NSView* pCurParent, CGFloat rCurX, CGFloat& rCurY, CGFloat nAttachOffset, |
| const OUString& rText, bool bEnabled, |
| const OUString& rProperty, bool bValue, |
| std::vector<ColumnItem >& rRightColumn, |
| ControllerProperties* pControllerProperties, |
| ControlTarget* pCtrlTarget |
| ) |
| { |
| NSRect aCheckRect = { { rCurX + nAttachOffset, 0 }, { 0, 15 } }; |
| NSButton* pBtn = [[NSButton alloc] initWithFrame: aCheckRect]; |
| [pBtn setButtonType: NSButtonTypeSwitch]; |
| [pBtn setState: bValue ? NSControlStateValueOn : NSControlStateValueOff]; |
| if( ! bEnabled ) |
| [pBtn setEnabled: NO]; |
| linebreakCell( [pBtn cell], rText ); |
| [pBtn sizeToFit]; |
| |
| rRightColumn.push_back( ColumnItem( pBtn ) ); |
| |
| // connect target |
| [pBtn setTarget: pCtrlTarget]; |
| [pBtn setAction: @selector(triggered:)]; |
| int nTag = pControllerProperties->addNameTag( rProperty ); |
| pControllerProperties->addObservedControl( pBtn ); |
| [pBtn setTag: nTag]; |
| |
| aCheckRect = [pBtn frame]; |
| // #i115837# add a murphy factor; it can apparently occasionally happen |
| // that sizeToFit does not a perfect job and that the button linebreaks again |
| // if - and only if - there is already a '\n' contained in the text and the width |
| // is minimally of |
| aCheckRect.size.width += 1; |
| |
| // move to rCurY |
| aCheckRect.origin.y = rCurY - aCheckRect.size.height; |
| [pBtn setFrame: aCheckRect]; |
| |
| [pCurParent addSubview: [pBtn autorelease]]; |
| |
| // update rCurY |
| rCurY = aCheckRect.origin.y - 5; |
| } |
| |
| static void addRadio( NSView* pCurParent, CGFloat rCurX, CGFloat& rCurY, CGFloat nAttachOffset, |
| const OUString& rText, |
| const OUString& rProperty, Sequence<OUString> const & rChoices, sal_Int32 nSelectValue, |
| std::vector<ColumnItem >& rLeftColumn, |
| std::vector<ColumnItem >& rRightColumn, |
| ControllerProperties* pControllerProperties, |
| ControlTarget* pCtrlTarget |
| ) |
| { |
| CGFloat nOff = 0; |
| if( rText.getLength() ) |
| { |
| // add a label |
| NSControl* pTextView = createLabel( rText ); |
| NSRect aTextRect = [pTextView frame]; |
| aTextRect.origin.x = rCurX + nAttachOffset; |
| [pCurParent addSubview: [pTextView autorelease]]; |
| |
| rLeftColumn.push_back( ColumnItem( pTextView ) ); |
| |
| // move to nCurY |
| aTextRect.origin.y = rCurY - aTextRect.size.height; |
| [pTextView setFrame: aTextRect]; |
| |
| // update nCurY |
| rCurY = aTextRect.origin.y - 5; |
| |
| // indent the radio group relative to the text |
| // nOff = 20; |
| } |
| |
| // setup radio matrix |
| NSButtonCell* pProto = [[NSButtonCell alloc] init]; |
| |
| NSRect aRadioRect = { { rCurX + nOff, 0 }, |
| { 280 - rCurX, |
| static_cast<CGFloat>(5*rChoices.getLength()) } }; |
| [pProto setTitle: @"RadioButtonGroup"]; |
| [pProto setButtonType: NSButtonTypeRadio]; |
| NSMatrix* pMatrix = [[NSMatrix alloc] initWithFrame: aRadioRect |
| mode: NSRadioModeMatrix |
| prototype: static_cast<NSCell*>(pProto) |
| numberOfRows: rChoices.getLength() |
| numberOfColumns: 1]; |
| // set individual titles |
| NSArray* pCells = [pMatrix cells]; |
| for( sal_Int32 m = 0; m < rChoices.getLength(); m++ ) |
| { |
| NSCell* pCell = [pCells objectAtIndex: m]; |
| linebreakCell( pCell, filterAccelerator( rChoices[m] ) ); |
| // connect target and action |
| [pCell setTarget: pCtrlTarget]; |
| [pCell setAction: @selector(triggered:)]; |
| int nTag = pControllerProperties->addNameAndValueTag( rProperty, m ); |
| pControllerProperties->addObservedControl( pCell ); |
| [pCell setTag: nTag]; |
| // set current selection |
| if( nSelectValue == m ) |
| [pMatrix selectCellAtRow: m column: 0]; |
| } |
| [pMatrix sizeToFit]; |
| aRadioRect = [pMatrix frame]; |
| |
| // move it down, so it comes to the correct position |
| aRadioRect.origin.y = rCurY - aRadioRect.size.height; |
| [pMatrix setFrame: aRadioRect]; |
| [pCurParent addSubview: [pMatrix autorelease]]; |
| |
| rRightColumn.push_back( ColumnItem( pMatrix ) ); |
| |
| // update nCurY |
| rCurY = aRadioRect.origin.y - 5; |
| |
| [pProto release]; |
| } |
| |
| static void addList( NSView* pCurParent, CGFloat& rCurX, CGFloat& rCurY, CGFloat /*nAttachOffset*/, |
| const OUString& rText, |
| const OUString& rProperty, Sequence<OUString> const & rChoices, sal_Int32 nSelectValue, |
| std::vector<ColumnItem >& rLeftColumn, |
| std::vector<ColumnItem >& rRightColumn, |
| ControllerProperties* pControllerProperties, |
| ControlTarget* pCtrlTarget |
| ) |
| { |
| // don't indent attached lists, looks bad in the existing cases |
| NSControl* pTextView = createLabel( rText ); |
| [pCurParent addSubview: [pTextView autorelease]]; |
| rLeftColumn.push_back( ColumnItem( pTextView ) ); |
| NSRect aTextRect = [pTextView frame]; |
| aTextRect.origin.x = rCurX /* + nAttachOffset*/; |
| |
| // don't indent attached lists, looks bad in the existing cases |
| NSRect aBtnRect = { { rCurX /*+ nAttachOffset*/ + aTextRect.size.width, 0 }, { 0, 15 } }; |
| NSPopUpButton* pBtn = [[NSPopUpButton alloc] initWithFrame: aBtnRect pullsDown: NO]; |
| |
| // iterate options |
| for( sal_Int32 m = 0; m < rChoices.getLength(); m++ ) |
| { |
| NSString* pItemText = CreateNSString( rChoices[m] ); |
| [pBtn addItemWithTitle: pItemText]; |
| NSMenuItem* pItem = [pBtn itemWithTitle: pItemText]; |
| int nTag = pControllerProperties->addNameAndValueTag( rProperty, m ); |
| [pItem setTag: nTag]; |
| [pItemText release]; |
| } |
| |
| [pBtn selectItemAtIndex: nSelectValue]; |
| |
| // add the button to observed controls for enabled state changes |
| // also add a tag just for this purpose |
| pControllerProperties->addObservedControl( pBtn ); |
| [pBtn setTag: pControllerProperties->addNameTag( rProperty )]; |
| |
| [pBtn sizeToFit]; |
| [pCurParent addSubview: [pBtn autorelease]]; |
| |
| rRightColumn.push_back( ColumnItem( pBtn ) ); |
| |
| // connect target and action |
| [pBtn setTarget: pCtrlTarget]; |
| [pBtn setAction: @selector(triggered:)]; |
| |
| // move to nCurY |
| aBtnRect = [pBtn frame]; |
| aBtnRect.origin.y = rCurY - aBtnRect.size.height; |
| [pBtn setFrame: aBtnRect]; |
| |
| // align label |
| aTextRect.origin.y = aBtnRect.origin.y + (aBtnRect.size.height - aTextRect.size.height)/2; |
| [pTextView setFrame: aTextRect]; |
| |
| // update rCurY |
| rCurY = aBtnRect.origin.y - 5; |
| } |
| |
| static void addEdit( NSView* pCurParent, CGFloat rCurX, CGFloat& rCurY, CGFloat nAttachOffset, |
| std::u16string_view rCtrlType, |
| const OUString& rText, |
| const OUString& rProperty, const PropertyValue* pValue, |
| sal_Int64 nMinValue, sal_Int64 nMaxValue, |
| std::vector<ColumnItem >& rLeftColumn, |
| std::vector<ColumnItem >& rRightColumn, |
| ControllerProperties* pControllerProperties, |
| ControlTarget* pCtrlTarget |
| ) |
| { |
| CGFloat nOff = 0; |
| if( rText.getLength() ) |
| { |
| // add a label |
| NSControl* pTextView = createLabel( rText ); |
| [pCurParent addSubview: [pTextView autorelease]]; |
| |
| rLeftColumn.push_back( ColumnItem( pTextView ) ); |
| |
| // move to nCurY |
| NSRect aTextRect = [pTextView frame]; |
| aTextRect.origin.x = rCurX + nAttachOffset; |
| aTextRect.origin.y = rCurY - aTextRect.size.height; |
| [pTextView setFrame: aTextRect]; |
| |
| // update nCurY |
| rCurY = aTextRect.origin.y - 5; |
| |
| // and set the offset for the real edit field |
| nOff = aTextRect.size.width + 5; |
| } |
| |
| NSRect aFieldRect = { { rCurX + nOff + nAttachOffset, 0 }, { 100, 25 } }; |
| NSTextField* pFieldView = [[NSTextField alloc] initWithFrame: aFieldRect]; |
| [pFieldView setEditable: YES]; |
| [pFieldView setSelectable: YES]; |
| [pFieldView setDrawsBackground: YES]; |
| [pFieldView sizeToFit]; // FIXME: this does nothing |
| [pCurParent addSubview: [pFieldView autorelease]]; |
| |
| rRightColumn.push_back( ColumnItem( pFieldView ) ); |
| |
| // add the field to observed controls for enabled state changes |
| // also add a tag just for this purpose |
| pControllerProperties->addObservedControl( pFieldView ); |
| int nTag = pControllerProperties->addNameTag( rProperty ); |
| [pFieldView setTag: nTag]; |
| // pControllerProperties->addNamedView( pFieldView, aPropertyName ); |
| |
| // move to nCurY |
| aFieldRect.origin.y = rCurY - aFieldRect.size.height; |
| [pFieldView setFrame: aFieldRect]; |
| |
| if( rCtrlType == u"Range" ) |
| { |
| // add a stepper control |
| NSRect aStepFrame = { { aFieldRect.origin.x + aFieldRect.size.width + 5, |
| aFieldRect.origin.y }, |
| { 15, aFieldRect.size.height } }; |
| NSStepper* pStep = [[NSStepper alloc] initWithFrame: aStepFrame]; |
| [pStep setIncrement: 1]; |
| [pStep setValueWraps: NO]; |
| [pStep setTag: nTag]; |
| [pCurParent addSubview: [pStep autorelease]]; |
| |
| rRightColumn.back().pSubControl = pStep; |
| |
| pControllerProperties->addObservedControl( pStep ); |
| [pStep setTarget: pCtrlTarget]; |
| [pStep setAction: @selector(triggered:)]; |
| |
| // constrain the text field to decimal numbers |
| NSNumberFormatter* pFormatter = [[NSNumberFormatter alloc] init]; |
| [pFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4]; |
| [pFormatter setNumberStyle: NSNumberFormatterDecimalStyle]; |
| [pFormatter setAllowsFloats: NO]; |
| [pFormatter setMaximumFractionDigits: 0]; |
| if( nMinValue != nMaxValue ) |
| { |
| [pFormatter setMinimum: [NSNumber numberWithInt: nMinValue]]; |
| [pStep setMinValue: nMinValue]; |
| [pFormatter setMaximum: [NSNumber numberWithInt: nMaxValue]]; |
| [pStep setMaxValue: nMaxValue]; |
| } |
| [pFieldView setFormatter: [pFormatter autorelease]]; |
| |
| sal_Int64 nSelectVal = 0; |
| if( pValue && pValue->Value.hasValue() ) |
| pValue->Value >>= nSelectVal; |
| |
| [pFieldView setIntValue: nSelectVal]; |
| [pStep setIntValue: nSelectVal]; |
| |
| pControllerProperties->addViewPair( pFieldView, pStep ); |
| // connect target and action |
| [pFieldView setTarget: pCtrlTarget]; |
| [pFieldView setAction: @selector(triggeredNumeric:)]; |
| [pStep setTarget: pCtrlTarget]; |
| [pStep setAction: @selector(triggeredNumeric:)]; |
| } |
| else |
| { |
| // connect target and action |
| [pFieldView setTarget: pCtrlTarget]; |
| [pFieldView setAction: @selector(triggered:)]; |
| |
| if( pValue && pValue->Value.hasValue() ) |
| { |
| OUString aValue; |
| pValue->Value >>= aValue; |
| if( aValue.getLength() ) |
| { |
| NSString* pText = CreateNSString( aValue ); |
| [pFieldView setStringValue: pText]; |
| [pText release]; |
| } |
| } |
| } |
| |
| // update nCurY |
| rCurY = aFieldRect.origin.y - 5; |
| } |
| |
| @implementation AquaPrintAccessoryView |
| |
| +(NSObject*)setupPrinterPanel: (NSPrintOperation*)pOp |
| withController: (vcl::PrinterController*)pController |
| withState: (PrintAccessoryViewState*)pState |
| { |
| const Sequence< PropertyValue >& rOptions( pController->getUIOptions() ); |
| if( rOptions.getLength() == 0 ) |
| return nil; |
| |
| NSRect aViewFrame = { NSZeroPoint, { 600, 400 } }; |
| NSRect aTabViewFrame = aViewFrame; |
| |
| NSView* pAccessoryView = [[NSView alloc] initWithFrame: aViewFrame]; |
| NSTabView* pTabView = [[NSTabView alloc] initWithFrame: aTabViewFrame]; |
| [pAccessoryView addSubview: [pTabView autorelease]]; |
| |
| // create the accessory controller |
| AquaPrintPanelAccessoryController* pAccessoryController = |
| [[AquaPrintPanelAccessoryController alloc] initWithNibName: nil bundle: nil]; |
| [pAccessoryController setView: [pAccessoryView autorelease]]; |
| [pAccessoryController forPrintOperation: pOp]; |
| [pAccessoryController withPrinterController: pController]; |
| [pAccessoryController withViewState: pState]; |
| |
| NSView* pCurParent = nullptr; |
| CGFloat nCurY = 0; |
| CGFloat nCurX = 0; |
| NSSize aMaxTabSize = NSZeroSize; |
| |
| ControllerProperties* pControllerProperties = new ControllerProperties( pAccessoryController ); |
| ControlTarget* pCtrlTarget = [[ControlTarget alloc] initWithControllerMap: pControllerProperties]; |
| |
| std::vector< ColumnItem > aLeftColumn, aRightColumn; |
| |
| // ugly: |
| // prepend a "selection" checkbox if the properties have such a selection in PrintContent |
| bool bAddSelectionCheckBox = false, bSelectionBoxEnabled = false, bSelectionBoxChecked = false; |
| |
| for( const PropertyValue & prop : rOptions ) |
| { |
| Sequence< beans::PropertyValue > aOptProp; |
| prop.Value >>= aOptProp; |
| |
| OUString aCtrlType; |
| OUString aPropertyName; |
| Sequence< OUString > aChoices; |
| Sequence< sal_Bool > aChoicesDisabled; |
| sal_Int32 aSelectionChecked = 0; |
| for( const beans::PropertyValue& rEntry : aOptProp ) |
| { |
| if( rEntry.Name == "ControlType" ) |
| { |
| rEntry.Value >>= aCtrlType; |
| } |
| else if( rEntry.Name == "Choices" ) |
| { |
| rEntry.Value >>= aChoices; |
| } |
| else if( rEntry.Name == "ChoicesDisabled" ) |
| { |
| rEntry.Value >>= aChoicesDisabled; |
| } |
| else if( rEntry.Name == "Property" ) |
| { |
| PropertyValue aVal; |
| rEntry.Value >>= aVal; |
| aPropertyName = aVal.Name; |
| if( aPropertyName == "PrintContent" ) |
| aVal.Value >>= aSelectionChecked; |
| } |
| } |
| if( aCtrlType == "Radio" && |
| aPropertyName == "PrintContent" && |
| aChoices.getLength() > 2 ) |
| { |
| // Related: tdf#163126 the "print selection only" checkbox would |
| // remain unchecked after checking it had restarted the print |
| // job so load the checkbox state from where it was updated in |
| // ControllerProperties::changePropertyWithBoolValue(). |
| const PropertyValue* pVal = pController->getValue( "PrintSelectionOnly" ); |
| if( pVal ) |
| { |
| bool bPrintSelectionOnly; |
| pVal->Value >>= bPrintSelectionOnly; |
| aSelectionChecked = bPrintSelectionOnly ? 2 : 0; |
| } |
| else |
| { |
| pVal = pController->getValue( "PrintContent" ); |
| if( pVal ) |
| pVal->Value >>= aSelectionChecked; |
| } |
| |
| bAddSelectionCheckBox = true; |
| bSelectionBoxEnabled = aChoicesDisabled.getLength() < 2 || ! aChoicesDisabled[2]; |
| bSelectionBoxChecked = (aSelectionChecked==2); |
| break; |
| } |
| } |
| |
| for( const PropertyValue & prop : rOptions ) |
| { |
| Sequence< beans::PropertyValue > aOptProp; |
| prop.Value >>= aOptProp; |
| |
| // extract ui element |
| OUString aCtrlType; |
| OUString aText; |
| OUString aPropertyName; |
| OUString aGroupHint; |
| Sequence< OUString > aChoices; |
| sal_Int64 nMinValue = 0, nMaxValue = 0; |
| CGFloat nAttachOffset = 0; |
| bool bIgnore = false; |
| |
| for( const beans::PropertyValue& rEntry : aOptProp ) |
| { |
| if( rEntry.Name == "Text" ) |
| { |
| rEntry.Value >>= aText; |
| aText = filterAccelerator( aText ); |
| } |
| else if( rEntry.Name == "ControlType" ) |
| { |
| rEntry.Value >>= aCtrlType; |
| } |
| else if( rEntry.Name == "Choices" ) |
| { |
| rEntry.Value >>= aChoices; |
| } |
| else if( rEntry.Name == "Property" ) |
| { |
| PropertyValue aVal; |
| rEntry.Value >>= aVal; |
| aPropertyName = aVal.Name; |
| } |
| else if( rEntry.Name == "MinValue" ) |
| { |
| rEntry.Value >>= nMinValue; |
| } |
| else if( rEntry.Name == "MaxValue" ) |
| { |
| rEntry.Value >>= nMaxValue; |
| } |
| else if( rEntry.Name == "AttachToDependency" ) |
| { |
| nAttachOffset = 20; |
| } |
| else if( rEntry.Name == "InternalUIOnly" ) |
| { |
| bool bValue = false; |
| rEntry.Value >>= bValue; |
| bIgnore = bValue; |
| } |
| else if( rEntry.Name == "GroupingHint" ) |
| { |
| rEntry.Value >>= aGroupHint; |
| } |
| } |
| |
| if( aCtrlType == "Group" || |
| aCtrlType == "Subgroup" || |
| aCtrlType == "Radio" || |
| aCtrlType == "List" || |
| aCtrlType == "Edit" || |
| aCtrlType == "Range" || |
| aCtrlType == "Bool" ) |
| { |
| bool bIgnoreSubgroup = false; |
| |
| // with `setAccessoryView' method only one accessory view can be set |
| // so create this single accessory view as tabbed for grouping |
| if( aCtrlType == "Group" |
| || ! pCurParent |
| || ( aCtrlType == "Subgroup" && nCurY < -250 && ! bIgnore ) |
| ) |
| { |
| OUString aGroupTitle( aText ); |
| if( aCtrlType == "Subgroup" ) |
| aGroupTitle = ControllerProperties::getMoreString(); |
| |
| // set size of current parent |
| if( pCurParent ) |
| adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn ); |
| |
| // new tab item |
| if( ! aText.getLength() ) |
| aText = "OOo"; |
| NSString* pLabel = CreateNSString( aGroupTitle ); |
| NSTabViewItem* pItem = [[NSTabViewItem alloc] initWithIdentifier: pLabel ]; |
| [pItem setLabel: pLabel]; |
| [pTabView addTabViewItem: [pItem autorelease]]; |
| pCurParent = [[NSView alloc] initWithFrame: aTabViewFrame]; |
| [pItem setView: [pCurParent autorelease]]; |
| [pLabel release]; |
| |
| nCurX = 20; // reset indent |
| nCurY = 0; // reset Y |
| // clear columns |
| aLeftColumn.clear(); |
| aRightColumn.clear(); |
| |
| if( bAddSelectionCheckBox ) |
| { |
| addBool( pCurParent, nCurX, nCurY, 0, |
| ControllerProperties::getPrintSelectionString(), bSelectionBoxEnabled, |
| "PrintContent", bSelectionBoxChecked, |
| aRightColumn, pControllerProperties, pCtrlTarget ); |
| bAddSelectionCheckBox = false; |
| } |
| } |
| |
| if( aCtrlType == "Subgroup" && pCurParent ) |
| { |
| bIgnoreSubgroup = bIgnore; |
| if( bIgnore ) |
| continue; |
| |
| addSubgroup( pCurParent, nCurY, aText ); |
| } |
| else if( bIgnoreSubgroup || bIgnore ) |
| { |
| continue; |
| } |
| else if( aCtrlType == "Bool" && pCurParent ) |
| { |
| bool bVal = false; |
| PropertyValue* pVal = pController->getValue( aPropertyName ); |
| if( pVal ) |
| pVal->Value >>= bVal; |
| addBool( pCurParent, nCurX, nCurY, nAttachOffset, |
| aText, true, aPropertyName, bVal, |
| aRightColumn, pControllerProperties, pCtrlTarget ); |
| } |
| else if( aCtrlType == "Radio" && pCurParent ) |
| { |
| // get currently selected value |
| sal_Int32 nSelectVal = 0; |
| PropertyValue* pVal = pController->getValue( aPropertyName ); |
| if( pVal && pVal->Value.hasValue() ) |
| pVal->Value >>= nSelectVal; |
| |
| addRadio( pCurParent, nCurX, nCurY, nAttachOffset, |
| aText, aPropertyName, aChoices, nSelectVal, |
| aLeftColumn, aRightColumn, |
| pControllerProperties, pCtrlTarget ); |
| } |
| else if( aCtrlType == "List" && pCurParent ) |
| { |
| PropertyValue* pVal = pController->getValue( aPropertyName ); |
| sal_Int32 aSelectVal = 0; |
| if( pVal && pVal->Value.hasValue() ) |
| pVal->Value >>= aSelectVal; |
| |
| addList( pCurParent, nCurX, nCurY, nAttachOffset, |
| aText, aPropertyName, aChoices, aSelectVal, |
| aLeftColumn, aRightColumn, |
| pControllerProperties, pCtrlTarget ); |
| } |
| else if( (aCtrlType == "Edit" |
| || aCtrlType == "Range") && pCurParent ) |
| { |
| // current value |
| PropertyValue* pVal = pController->getValue( aPropertyName ); |
| addEdit( pCurParent, nCurX, nCurY, nAttachOffset, |
| aCtrlType, aText, aPropertyName, pVal, |
| nMinValue, nMaxValue, |
| aLeftColumn, aRightColumn, |
| pControllerProperties, pCtrlTarget ); |
| } |
| } |
| else |
| { |
| SAL_INFO( "vcl.osx.print", "Unsupported UI option \"" << aCtrlType << "\""); |
| } |
| } |
| |
| pControllerProperties->updateEnableState(); |
| adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn ); |
| |
| // now reposition everything again so it is upper bound |
| adjustTabViews( pTabView, aMaxTabSize ); |
| |
| // find the minimum needed tab size |
| NSSize aTabCtrlSize = [pTabView minimumSize]; |
| aTabCtrlSize.height += aMaxTabSize.height + 10; |
| if( aTabCtrlSize.width < aMaxTabSize.width + 10 ) |
| aTabCtrlSize.width = aMaxTabSize.width + 10; |
| [pTabView setFrameSize: aTabCtrlSize]; |
| aViewFrame.size.width = aTabCtrlSize.width + aTabViewFrame.origin.x; |
| aViewFrame.size.height = aTabCtrlSize.height + aTabViewFrame.origin.y; |
| [pAccessoryView setFrameSize: aViewFrame.size]; |
| |
| // get the print panel |
| NSPrintPanel* pPrintPanel = [pOp printPanel]; |
| [pPrintPanel setOptions: [pPrintPanel options] | NSPrintPanelShowsPreview]; |
| // add the accessory controller to the panel |
| [pPrintPanel addAccessoryController: [pAccessoryController autorelease]]; |
| |
| // set the current selected tab item |
| if( pState->nLastPage >= 0 && pState->nLastPage < [pTabView numberOfTabViewItems] ) |
| [pTabView selectTabViewItemAtIndex: pState->nLastPage]; |
| |
| return pCtrlTarget; |
| } |
| |
| @end |
| |
| /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |