1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
22 #include "tools/resary.hxx"
24 #include "vcl/print.hxx"
25 #include "vcl/image.hxx"
26 #include "vcl/virdev.hxx"
27 #include "vcl/svapp.hxx"
28 #include "vcl/unohelp.hxx"
29 #include <vcl/settings.hxx>
31 #include "osx/printview.h"
32 #include "osx/salinst.h"
33 #include "quartz/utils.h"
38 #include "com/sun/star/i18n/XBreakIterator.hpp"
39 #include "com/sun/star/i18n/WordType.hpp"
44 using namespace com::sun::star;
45 using namespace com::sun::star::beans;
46 using namespace com::sun::star::uno;
48 /* Note: the accesory view as implemented here is already deprecated in Leopard. Unfortunately
49 as long as our baseline is Tiger we cannot gain the advantages over multiple accessory views
50 as well havs having accessory views AND a preview (as long as you are linked vs. 10.4 libraries
51 the preview insists on not being present. This is unfortunate.
54 class ControllerProperties;
56 @interface ControlTarget : NSObject
58 ControllerProperties* mpController;
60 -(id)initWithControllerMap: (ControllerProperties*)pController;
61 -(void)triggered:(id)pSender;
62 -(void)triggeredNumeric:(id)pSender;
63 -(void)triggeredPreview:(id)pSender;
68 class ControllerProperties
70 vcl::PrinterController* mpController;
71 std::map< int, rtl::OUString > maTagToPropertyName;
72 std::map< int, sal_Int32 > maTagToValueInt;
73 std::map< NSView*, NSView* > maViewPairMap;
74 std::vector< NSObject* > maViews;
76 sal_Int32 mnLastPageCount;
77 PrintAccessoryViewState* mpState;
78 NSPrintOperation* mpOp;
79 NSView* mpAccessoryView;
82 NSImageView* mpPreview;
83 NSTextField* mpPageEdit;
85 NSTextView* mpPagesLabel;
86 ResStringArray maLocalizedStrings;
89 ControllerProperties( vcl::PrinterController* i_pController,
90 NSPrintOperation* i_pOp,
91 NSView* i_pAccessoryView,
92 NSTabView* i_pTabView,
93 PrintAccessoryViewState* i_pState )
94 : mpController( i_pController ),
96 mnLastPageCount( i_pController->getFilteredPageCount() ),
99 mpAccessoryView( i_pAccessoryView ),
100 mpTabView( i_pTabView ),
106 maLocalizedStrings( VclResId( SV_PRINT_NATIVE_STRINGS ) )
108 mpState->bNeedRestart = false;
109 DBG_ASSERT( maLocalizedStrings.Count() >= 5, "resources not found !" );
112 rtl::OUString getMoreString()
114 return maLocalizedStrings.Count() >= 4
115 ? OUString( maLocalizedStrings.GetString( 3 ) )
116 : OUString( "More" );
119 rtl::OUString getPrintSelectionString()
121 return maLocalizedStrings.Count() >= 5
122 ? OUString( maLocalizedStrings.GetString( 4 ) )
123 : OUString( "Print selection only" );
126 void updatePrintJob()
128 // TODO: refresh page count etc from mpController
130 // page range may have changed depending on options
131 sal_Int32 nPages = mpController->getFilteredPageCount();
132 #if OSL_DEBUG_LEVEL > 1
133 if( nPages != mnLastPageCount )
134 fprintf( stderr, "trouble: number of pages changed from %ld to %ld !\n", mnLastPageCount, nPages );
136 mpState->bNeedRestart = (nPages != mnLastPageCount);
137 NSTabViewItem* pItem = [mpTabView selectedTabViewItem];
139 mpState->nLastPage = [mpTabView indexOfTabViewItem: pItem];
141 mpState->nLastPage = 0;
142 mnLastPageCount = nPages;
143 if( mpState->bNeedRestart )
145 // Warning: bad hack ahead
146 // Apple does not give us a chance of changing the page count,
147 // and they don't let us cancel the dialog either
148 // hack: send a cancel message to the window displaying our views.
150 NSWindow* pNSWindow = [NSApp modalWindow];
152 [pNSWindow cancelOperation: nil];
153 [[mpOp printInfo] setJobDisposition: NSPrintCancelJob];
157 sal_Int32 nPage = [mpStepper intValue];
158 updatePreviewImage( nPage-1 );
162 int addNameTag( const rtl::OUString& i_rPropertyName )
164 int nNewTag = mnNextTag++;
165 maTagToPropertyName[ nNewTag ] = i_rPropertyName;
169 int addNameAndValueTag( const rtl::OUString& i_rPropertyName, sal_Int32 i_nValue )
171 int nNewTag = mnNextTag++;
172 maTagToPropertyName[ nNewTag ] = i_rPropertyName;
173 maTagToValueInt[ nNewTag ] = i_nValue;
177 void addObservedControl( NSObject* i_pView )
179 maViews.push_back( i_pView );
182 void addViewPair( NSView* i_pLeft, NSView* i_pRight )
184 maViewPairMap[ i_pLeft ] = i_pRight;
185 maViewPairMap[ i_pRight ] = i_pLeft;
188 NSView* getPair( NSView* i_pLeft ) const
190 NSView* pRight = nil;
191 std::map< NSView*, NSView* >::const_iterator it = maViewPairMap.find( i_pLeft );
192 if( it != maViewPairMap.end() )
197 void changePropertyWithIntValue( int i_nTag )
199 std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag );
200 std::map< int, sal_Int32 >::const_iterator value_it = maTagToValueInt.find( i_nTag );
201 if( name_it != maTagToPropertyName.end() && value_it != maTagToValueInt.end() )
203 PropertyValue* pVal = mpController->getValue( name_it->second );
206 pVal->Value <<= value_it->second;
212 void changePropertyWithIntValue( int i_nTag, sal_Int64 i_nValue )
214 std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag );
215 if( name_it != maTagToPropertyName.end() )
217 PropertyValue* pVal = mpController->getValue( name_it->second );
220 pVal->Value <<= i_nValue;
226 void changePropertyWithBoolValue( int i_nTag, bool i_bValue )
228 std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag );
229 if( name_it != maTagToPropertyName.end() )
231 PropertyValue* pVal = mpController->getValue( name_it->second );
235 if( name_it->second.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) )
236 pVal->Value <<= i_bValue ? sal_Int32(2) : sal_Int32(0);
238 pVal->Value <<= i_bValue;
244 void changePropertyWithStringValue( int i_nTag, const rtl::OUString& i_rValue )
246 std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag );
247 if( name_it != maTagToPropertyName.end() )
249 PropertyValue* pVal = mpController->getValue( name_it->second );
252 pVal->Value <<= i_rValue;
258 void updateEnableState()
260 for( std::vector< NSObject* >::iterator it = maViews.begin(); it != maViews.end(); ++it )
262 NSObject* pObj = *it;
263 NSControl* pCtrl = nil;
265 if( [pObj isKindOfClass: [NSControl class]] )
266 pCtrl = (NSControl*)pObj;
267 else if( [pObj isKindOfClass: [NSCell class]] )
268 pCell = (NSCell*)pObj;
270 int nTag = pCtrl ? [pCtrl tag] :
271 pCell ? [pCell tag] :
274 std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( nTag );
275 if( name_it != maTagToPropertyName.end() && ! name_it->second.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) )
277 BOOL bEnabled = mpController->isUIOptionEnabled( name_it->second ) ? YES : NO;
280 [pCtrl setEnabled: bEnabled];
281 NSView* pOther = getPair( pCtrl );
282 if( pOther && [pOther isKindOfClass: [NSControl class]] )
283 [(NSControl*)pOther setEnabled: bEnabled];
286 [pCell setEnabled: bEnabled];
292 void updatePreviewImage( sal_Int32 i_nPage )
294 sal_Int32 nPages = mpController->getFilteredPageCount();
295 NSRect aViewFrame = [mpPreview frame];
296 Size aPixelSize( static_cast<long>(aViewFrame.size.width),
297 static_cast<long>(aViewFrame.size.height) );
298 if( i_nPage >= 0 && nPages > i_nPage )
301 PrinterController::PageSize aPageSize( mpController->getFilteredPageFile( i_nPage, aMtf, false ) );
302 auto aDev(VclPtr<VirtualDevice>::Create());
303 if( mpController->getPrinter()->GetPrinterOptions().IsConvertToGreyscales() )
304 aDev->SetDrawMode( aDev->GetDrawMode() | ( DrawModeFlags::GrayLine | DrawModeFlags::GrayFill | DrawModeFlags::GrayText |
305 DrawModeFlags::GrayBitmap | DrawModeFlags::GrayGradient ) );
306 // see salprn.cxx, currently we pretend to be a 720dpi device on printers
307 aDev->SetReferenceDevice( 720, 720 );
308 aDev->EnableOutput( TRUE );
309 Size aLogicSize( aDev->PixelToLogic( aPixelSize, MapMode( MAP_100TH_MM ) ) );
310 double fScaleX = double(aLogicSize.Width())/double(aPageSize.aSize.Width());
311 double fScaleY = double(aLogicSize.Height())/double(aPageSize.aSize.Height());
312 double fScale = (fScaleX < fScaleY) ? fScaleX : fScaleY;
313 // #i104784# if we render the page too small then rounding issues result in
314 // layout artifacts looking really bad. So scale the page unto a device that is not
315 // full page size but not too small either. This also results in much better visual
316 // quality of the preview, e.g. when its height approaches the number of text lines
320 aMtf.Scale( fScale, fScale );
322 aLogicSize.Width() = long(double(aPageSize.aSize.Width()) * fScale);
323 aLogicSize.Height() = long(double(aPageSize.aSize.Height()) * fScale);
324 aPixelSize = aDev->LogicToPixel( aLogicSize, MapMode( MAP_100TH_MM ) );
325 aDev->SetOutputSizePixel( aPixelSize );
327 aDev->SetMapMode( MapMode( MAP_100TH_MM ) );
328 aMtf.Play( aDev.get(), Point( 0, 0 ), aLogicSize );
329 aDev->EnableMapMode( FALSE );
330 Image aImage( aDev->GetBitmap( Point( 0, 0 ), aPixelSize ) );
331 NSImage* pImage = CreateNSImage( aImage );
332 [mpPreview setImage: [pImage autorelease]];
335 [mpPreview setImage: nil];
338 void setupPreview( ControlTarget* i_pCtrlTarget )
340 if( maLocalizedStrings.Count() < 3 )
343 // get the preview control
344 NSRect aPreviewFrame = [mpAccessoryView frame];
345 aPreviewFrame.origin.x = 0;
346 aPreviewFrame.origin.y = 5;
347 aPreviewFrame.size.width = 190;
348 aPreviewFrame.size.height -= 7;
350 // create a box to put the preview controls in
351 mpPreviewBox = [[NSBox alloc] initWithFrame: aPreviewFrame];
352 [mpPreviewBox setTitle: [CreateNSString( maLocalizedStrings.GetString( 0 ) ) autorelease]];
353 [mpAccessoryView addSubview: [mpPreviewBox autorelease]];
355 // now create the image view of the preview
356 NSSize aMargins = [mpPreviewBox contentViewMargins];
357 aPreviewFrame.origin.x = 0;
358 aPreviewFrame.origin.y = 34;
359 aPreviewFrame.size.width -= 2*(aMargins.width+1);
360 aPreviewFrame.size.height -= 61;
361 mpPreview = [[NSImageView alloc] initWithFrame: aPreviewFrame];
362 [mpPreview setImageScaling: NSImageScaleProportionallyDown];
363 [mpPreview setImageAlignment: NSImageAlignCenter];
364 [mpPreview setImageFrameStyle: NSImageFrameNone];
365 [mpPreviewBox addSubview: [mpPreview autorelease]];
368 sal_Int32 nPages = mpController->getFilteredPageCount();
369 rtl::OUStringBuffer aBuf( 16 );
370 aBuf.appendAscii( "/ " );
371 aBuf.append( rtl::OUString::number( nPages ) );
373 NSString* pText = CreateNSString( aBuf.makeStringAndClear() );
374 NSRect aTextRect = { { 100, 5 }, { 100, 22 } };
375 mpPagesLabel = [[NSTextView alloc] initWithFrame: aTextRect];
376 [mpPagesLabel setFont: [NSFont controlContentFontOfSize: 0]];
377 [mpPagesLabel setEditable: NO];
378 [mpPagesLabel setSelectable: NO];
379 [mpPagesLabel setDrawsBackground: NO];
380 [mpPagesLabel setString: [pText autorelease]];
381 [mpPagesLabel setToolTip: [CreateNSString( maLocalizedStrings.GetString( 2 ) ) autorelease]];
382 [mpPreviewBox addSubview: [mpPagesLabel autorelease]];
384 NSRect aFieldRect = { { 45, 5 }, { 35, 25 } };
385 mpPageEdit = [[NSTextField alloc] initWithFrame: aFieldRect];
386 [mpPageEdit setEditable: YES];
387 [mpPageEdit setSelectable: YES];
388 [mpPageEdit setDrawsBackground: YES];
389 [mpPageEdit setToolTip: [CreateNSString( maLocalizedStrings.GetString( 1 ) ) autorelease]];
390 [mpPreviewBox addSubview: [mpPageEdit autorelease]];
392 // add a stepper control
393 NSRect aStepFrame = { { 85, 5 }, { 15, 25 } };
394 mpStepper = [[NSStepper alloc] initWithFrame: aStepFrame];
395 [mpStepper setIncrement: 1];
396 [mpStepper setValueWraps: NO];
397 [mpPreviewBox addSubview: [mpStepper autorelease]];
399 // constrain the text field to decimal numbers
400 NSNumberFormatter* pFormatter = [[NSNumberFormatter alloc] init];
401 [pFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4];
402 [pFormatter setMinimum: [[NSNumber numberWithInt: 1] autorelease]];
403 [pFormatter setMaximum: [[NSNumber numberWithInt: nPages] autorelease]];
404 [pFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
405 [pFormatter setAllowsFloats: NO];
406 [pFormatter setMaximumFractionDigits: 0];
407 [mpPageEdit setFormatter: pFormatter];
408 [mpStepper setMinValue: 1];
409 [mpStepper setMaxValue: nPages];
411 [mpPageEdit setIntValue: 1];
412 [mpStepper setIntValue: 1];
414 // connect target and action
415 [mpStepper setTarget: i_pCtrlTarget];
416 [mpStepper setAction: @selector(triggeredPreview:)];
417 [mpPageEdit setTarget: i_pCtrlTarget];
418 [mpPageEdit setAction: @selector(triggeredPreview:)];
420 // set first preview image
421 updatePreviewImage( 0 );
424 void changePreview( NSObject* i_pSender )
426 if( [i_pSender isMemberOfClass: [NSTextField class]] )
428 NSTextField* pField = (NSTextField*)i_pSender;
429 if( pField == mpPageEdit ) // sanity check
431 sal_Int32 nPage = [pField intValue];
432 [mpStepper setIntValue: nPage];
433 updatePreviewImage( nPage-1 );
436 else if( [i_pSender isMemberOfClass: [NSStepper class]] )
438 NSStepper* pStepper = (NSStepper*)i_pSender;
439 if( pStepper == mpStepper ) // sanity check
441 sal_Int32 nPage = [pStepper intValue];
442 [mpPageEdit setIntValue: nPage];
443 updatePreviewImage( nPage-1 );
449 static OUString filterAccelerator( rtl::OUString const & rText )
451 rtl::OUStringBuffer aBuf( rText.getLength() );
452 for( sal_Int32 nIndex = 0; nIndex != -1; )
453 aBuf.append( rText.getToken( 0, '~', nIndex ) );
454 return aBuf.makeStringAndClear();
457 @implementation ControlTarget
458 -(id)initWithControllerMap: (ControllerProperties*)pController
460 if( (self = [super init]) )
462 mpController = pController;
466 -(void)triggered:(id)pSender
468 if( [pSender isMemberOfClass: [NSPopUpButton class]] )
470 NSPopUpButton* pBtn = (NSPopUpButton*)pSender;
471 NSMenuItem* pSelected = [pBtn selectedItem];
474 int nTag = [pSelected tag];
475 mpController->changePropertyWithIntValue( nTag );
478 else if( [pSender isMemberOfClass: [NSButton class]] )
480 NSButton* pBtn = (NSButton*)pSender;
481 int nTag = [pBtn tag];
482 mpController->changePropertyWithBoolValue( nTag, [pBtn state] == NSOnState );
484 else if( [pSender isMemberOfClass: [NSMatrix class]] )
486 NSObject* pObj = [(NSMatrix*)pSender selectedCell];
487 if( [pObj isMemberOfClass: [NSButtonCell class]] )
489 NSButtonCell* pCell = (NSButtonCell*)pObj;
490 int nTag = [pCell tag];
491 mpController->changePropertyWithIntValue( nTag );
494 else if( [pSender isMemberOfClass: [NSTextField class]] )
496 NSTextField* pField = (NSTextField*)pSender;
497 int nTag = [pField tag];
498 rtl::OUString aValue = GetOUString( [pSender stringValue] );
499 mpController->changePropertyWithStringValue( nTag, aValue );
503 SAL_INFO( "vcl.osx.print", "Unsupported class" << ([pSender class] ? [NSStringFromClass([pSender class]) UTF8String] : "nil"));
505 mpController->updateEnableState();
507 -(void)triggeredNumeric:(id)pSender
509 if( [pSender isMemberOfClass: [NSTextField class]] )
511 NSTextField* pField = (NSTextField*)pSender;
512 int nTag = [pField tag];
513 sal_Int64 nValue = [pField intValue];
515 NSView* pOther = mpController->getPair( pField );
517 [(NSControl*)pOther setIntValue: nValue];
519 mpController->changePropertyWithIntValue( nTag, nValue );
521 else if( [pSender isMemberOfClass: [NSStepper class]] )
523 NSStepper* pStep = (NSStepper*)pSender;
524 int nTag = [pStep tag];
525 sal_Int64 nValue = [pStep intValue];
527 NSView* pOther = mpController->getPair( pStep );
529 [(NSControl*)pOther setIntValue: nValue];
531 mpController->changePropertyWithIntValue( nTag, nValue );
535 SAL_INFO( "vcl.osx.print", "Unsupported class" << ([pSender class] ? [NSStringFromClass([pSender class]) UTF8String] : "nil"));
537 mpController->updateEnableState();
539 -(void)triggeredPreview:(id)pSender
541 mpController->changePreview( pSender );
554 NSControl* pSubControl;
556 ColumnItem( NSControl* i_pControl = nil, long i_nOffset = 0, NSControl* i_pSub = nil )
557 : pControl( i_pControl )
558 , nOffset( i_nOffset )
559 , pSubControl( i_pSub )
562 long getWidth() const
567 NSRect aCtrlRect = [pControl frame];
568 nWidth = aCtrlRect.size.width;
572 NSRect aSubRect = [pSubControl frame];
573 nWidth += aSubRect.size.width;
574 nWidth += aSubRect.origin.x - (aCtrlRect.origin.x + aCtrlRect.size.width);
581 static void adjustViewAndChildren( NSView* pNSView, NSSize& rMaxSize,
582 std::vector< ColumnItem >& rLeftColumn,
583 std::vector< ColumnItem >& rRightColumn
588 // first get overall column widths
590 long nRightWidth = 0;
591 for( size_t i = 0; i < rLeftColumn.size(); i++ )
593 long nW = rLeftColumn[i].getWidth();
594 if( nW > nLeftWidth )
597 for( size_t i = 0; i < rRightColumn.size(); i++ )
599 long nW = rRightColumn[i].getWidth();
600 if( nW > nRightWidth )
604 // right align left column
605 for( size_t i = 0; i < rLeftColumn.size(); i++ )
607 if( rLeftColumn[i].pControl )
609 NSRect aCtrlRect = [rLeftColumn[i].pControl frame];
610 long nX = nLeftWidth - aCtrlRect.size.width;
611 if( rLeftColumn[i].pSubControl )
613 NSRect aSubRect = [rLeftColumn[i].pSubControl frame];
614 nX -= aSubRect.size.width + (aSubRect.origin.x - (aCtrlRect.origin.x + aCtrlRect.size.width));
615 aSubRect.origin.x = nLeftWidth - aSubRect.size.width;
616 [rLeftColumn[i].pSubControl setFrame: aSubRect];
618 aCtrlRect.origin.x = nX;
619 [rLeftColumn[i].pControl setFrame: aCtrlRect];
623 // left align right column
624 for( size_t i = 0; i < rRightColumn.size(); i++ )
626 if( rRightColumn[i].pControl )
628 NSRect aCtrlRect = [rRightColumn[i].pControl frame];
629 long nX = nLeftWidth + 3;
630 if( rRightColumn[i].pSubControl )
632 NSRect aSubRect = [rRightColumn[i].pSubControl frame];
633 aSubRect.origin.x = nX + aSubRect.origin.x - aCtrlRect.origin.x;
634 [rRightColumn[i].pSubControl setFrame: aSubRect];
636 aCtrlRect.origin.x = nX;
637 [rRightColumn[i].pControl setFrame: aCtrlRect];
641 NSArray* pSubViews = [pNSView subviews];
642 unsigned int nViews = [pSubViews count];
643 NSRect aUnion = NSZeroRect;
645 // get the combined frame of all subviews
646 for( unsigned int n = 0; n < nViews; n++ )
648 aUnion = NSUnionRect( aUnion, [[pSubViews objectAtIndex: n] frame] );
651 // move everything so it will fit
652 for( unsigned int n = 0; n < nViews; n++ )
654 NSView* pCurSubView = [pSubViews objectAtIndex: n];
655 NSRect aFrame = [pCurSubView frame];
656 aFrame.origin.x -= aUnion.origin.x - 5;
657 aFrame.origin.y -= aUnion.origin.y - 5;
658 [pCurSubView setFrame: aFrame];
661 // resize the view itself
662 aUnion.size.height += 10;
663 aUnion.size.width += 20;
664 [pNSView setFrameSize: aUnion.size];
666 if( aUnion.size.width > rMaxSize.width )
667 rMaxSize.width = aUnion.size.width;
668 if( aUnion.size.height > rMaxSize.height )
669 rMaxSize.height = aUnion.size.height;
672 static void adjustTabViews( NSTabView* pTabView, NSSize aTabSize )
674 // loop over all contained tab pages
675 NSArray* pTabbedViews = [pTabView tabViewItems];
676 int nViews = [pTabbedViews count];
677 for( int i = 0; i < nViews; i++ )
679 NSTabViewItem* pItem = (NSTabViewItem*)[pTabbedViews objectAtIndex: i];
680 NSView* pNSView = [pItem view];
683 NSRect aRect = [pNSView frame];
684 double nDiff = aTabSize.height - aRect.size.height;
685 aRect.size = aTabSize;
686 [pNSView setFrame: aRect];
688 NSArray* pSubViews = [pNSView subviews];
689 unsigned int nSubViews = [pSubViews count];
691 // move everything up
692 for( unsigned int n = 0; n < nSubViews; n++ )
694 NSView* pCurSubView = [pSubViews objectAtIndex: n];
695 NSRect aFrame = [pCurSubView frame];
696 aFrame.origin.y += nDiff;
697 // give separators the correct width
698 // separators are currently the only NSBoxes we use
699 if( [pCurSubView isMemberOfClass: [NSBox class]] )
701 aFrame.size.width = aTabSize.width - aFrame.origin.x - 10;
703 [pCurSubView setFrame: aFrame];
709 static NSControl* createLabel( const rtl::OUString& i_rText )
711 NSString* pText = CreateNSString( i_rText );
712 NSRect aTextRect = { NSZeroPoint, {20, 15} };
713 NSTextField* pTextView = [[NSTextField alloc] initWithFrame: aTextRect];
714 [pTextView setFont: [NSFont controlContentFontOfSize: 0]];
715 [pTextView setEditable: NO];
716 [pTextView setSelectable: NO];
717 [pTextView setDrawsBackground: NO];
718 [pTextView setBordered: NO];
719 [pTextView setStringValue: pText];
720 [pTextView sizeToFit];
725 static sal_Int32 findBreak( const rtl::OUString& i_rText, sal_Int32 i_nPos )
727 sal_Int32 nRet = i_rText.getLength();
728 Reference< i18n::XBreakIterator > xBI( vcl::unohelper::CreateBreakIterator() );
731 i18n::Boundary aBoundary = xBI->getWordBoundary( i_rText, i_nPos,
732 Application::GetSettings().GetLanguageTag().getLocale(),
733 i18n::WordType::ANYWORD_IGNOREWHITESPACES,
735 nRet = aBoundary.endPos;
740 static void linebreakCell( NSCell* pBtn, const rtl::OUString& i_rText )
742 NSString* pText = CreateNSString( i_rText );
743 [pBtn setTitle: pText];
745 NSSize aSize = [pBtn cellSize];
746 if( aSize.width > 280 )
749 sal_Int32 nLen = i_rText.getLength();
750 sal_Int32 nIndex = nLen / 2;
751 nIndex = findBreak( i_rText, nIndex );
754 rtl::OUStringBuffer aBuf( i_rText );
756 pText = CreateNSString( aBuf.makeStringAndClear() );
757 [pBtn setTitle: pText];
763 static void addSubgroup( NSView* pCurParent, long& rCurY, const rtl::OUString& rText )
765 NSControl* pTextView = createLabel( rText );
766 [pCurParent addSubview: [pTextView autorelease]];
767 NSRect aTextRect = [pTextView frame];
769 aTextRect.origin.y = rCurY - aTextRect.size.height;
770 [pTextView setFrame: aTextRect];
772 NSRect aSepRect = { { aTextRect.size.width + 1, aTextRect.origin.y }, { 100, 6 } };
773 NSBox* pBox = [[NSBox alloc] initWithFrame: aSepRect];
774 [pBox setBoxType: NSBoxSeparator];
775 [pCurParent addSubview: [pBox autorelease]];
778 rCurY = aTextRect.origin.y - 5;
781 static void addBool( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset,
782 const rtl::OUString& rText, bool bEnabled,
783 const rtl::OUString& rProperty, bool bValue,
784 std::vector<ColumnItem >& rRightColumn,
785 ControllerProperties* pControllerProperties,
786 ControlTarget* pCtrlTarget
789 NSRect aCheckRect = { { static_cast<CGFloat>(rCurX + nAttachOffset), 0 }, { 0, 15 } };
790 NSButton* pBtn = [[NSButton alloc] initWithFrame: aCheckRect];
791 [pBtn setButtonType: NSSwitchButton];
792 [pBtn setState: bValue ? NSOnState : NSOffState];
794 [pBtn setEnabled: NO];
795 linebreakCell( [pBtn cell], rText );
798 rRightColumn.push_back( ColumnItem( pBtn ) );
801 [pBtn setTarget: pCtrlTarget];
802 [pBtn setAction: @selector(triggered:)];
803 int nTag = pControllerProperties->addNameTag( rProperty );
804 pControllerProperties->addObservedControl( pBtn );
807 aCheckRect = [pBtn frame];
808 // #i115837# add a murphy factor; it can apparently occasionally happen
809 // that sizeToFit does not a perfect job and that the button linebreaks again
810 // if - and only if - there is already a '\n' contained in the text and the width
812 aCheckRect.size.width += 1;
815 aCheckRect.origin.y = rCurY - aCheckRect.size.height;
816 [pBtn setFrame: aCheckRect];
818 [pCurParent addSubview: [pBtn autorelease]];
821 rCurY = aCheckRect.origin.y - 5;
824 static void addRadio( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset,
825 const rtl::OUString& rText,
826 const rtl::OUString& rProperty, Sequence<rtl::OUString> const & rChoices, sal_Int32 nSelectValue,
827 std::vector<ColumnItem >& rLeftColumn,
828 std::vector<ColumnItem >& rRightColumn,
829 ControllerProperties* pControllerProperties,
830 ControlTarget* pCtrlTarget
834 if( rText.getLength() )
837 NSControl* pTextView = createLabel( rText );
838 NSRect aTextRect = [pTextView frame];
839 aTextRect.origin.x = rCurX + nAttachOffset;
840 [pCurParent addSubview: [pTextView autorelease]];
842 rLeftColumn.push_back( ColumnItem( pTextView ) );
845 aTextRect.origin.y = rCurY - aTextRect.size.height;
846 [pTextView setFrame: aTextRect];
849 rCurY = aTextRect.origin.y - 5;
851 // indent the radio group relative to the text
855 // setup radio matrix
856 NSButtonCell* pProto = [[NSButtonCell alloc] init];
858 NSRect aRadioRect = { { static_cast<CGFloat>(rCurX + nOff), 0 }, { static_cast<CGFloat>(280 - rCurX), static_cast<CGFloat>(5*rChoices.getLength()) } };
859 [pProto setTitle: @"RadioButtonGroup"];
860 [pProto setButtonType: NSRadioButton];
861 NSMatrix* pMatrix = [[NSMatrix alloc] initWithFrame: aRadioRect
862 mode: NSRadioModeMatrix
863 prototype: (NSCell*)pProto
864 numberOfRows: rChoices.getLength()
866 // set individual titles
867 NSArray* pCells = [pMatrix cells];
868 for( sal_Int32 m = 0; m < rChoices.getLength(); m++ )
870 NSCell* pCell = [pCells objectAtIndex: m];
871 linebreakCell( pCell, filterAccelerator( rChoices[m] ) );
872 // connect target and action
873 [pCell setTarget: pCtrlTarget];
874 [pCell setAction: @selector(triggered:)];
875 int nTag = pControllerProperties->addNameAndValueTag( rProperty, m );
876 pControllerProperties->addObservedControl( pCell );
877 [pCell setTag: nTag];
878 // set current selection
879 if( nSelectValue == m )
880 [pMatrix selectCellAtRow: m column: 0];
883 aRadioRect = [pMatrix frame];
885 // move it down, so it comes to the correct position
886 aRadioRect.origin.y = rCurY - aRadioRect.size.height;
887 [pMatrix setFrame: aRadioRect];
888 [pCurParent addSubview: [pMatrix autorelease]];
890 rRightColumn.push_back( ColumnItem( pMatrix ) );
893 rCurY = aRadioRect.origin.y - 5;
898 static void addList( NSView* pCurParent, long& rCurX, long& rCurY, long /*nAttachOffset*/,
899 const rtl::OUString& rText,
900 const rtl::OUString& rProperty, Sequence<rtl::OUString> const & rChoices, sal_Int32 nSelectValue,
901 std::vector<ColumnItem >& rLeftColumn,
902 std::vector<ColumnItem >& rRightColumn,
903 ControllerProperties* pControllerProperties,
904 ControlTarget* pCtrlTarget
907 // don't indent attached lists, looks bad in the existing cases
908 NSControl* pTextView = createLabel( rText );
909 [pCurParent addSubview: [pTextView autorelease]];
910 rLeftColumn.push_back( ColumnItem( pTextView ) );
911 NSRect aTextRect = [pTextView frame];
912 aTextRect.origin.x = rCurX /* + nAttachOffset*/;
914 // don't indent attached lists, looks bad in the existing cases
915 NSRect aBtnRect = { { rCurX /*+ nAttachOffset*/ + aTextRect.size.width, 0 }, { 0, 15 } };
916 NSPopUpButton* pBtn = [[NSPopUpButton alloc] initWithFrame: aBtnRect pullsDown: NO];
919 for( sal_Int32 m = 0; m < rChoices.getLength(); m++ )
921 NSString* pItemText = CreateNSString( rChoices[m] );
922 [pBtn addItemWithTitle: pItemText];
923 NSMenuItem* pItem = [pBtn itemWithTitle: pItemText];
924 int nTag = pControllerProperties->addNameAndValueTag( rProperty, m );
925 [pItem setTag: nTag];
929 [pBtn selectItemAtIndex: nSelectValue];
931 // add the button to observed controls for enabled state changes
932 // also add a tag just for this purpose
933 pControllerProperties->addObservedControl( pBtn );
934 [pBtn setTag: pControllerProperties->addNameTag( rProperty )];
937 [pCurParent addSubview: [pBtn autorelease]];
939 rRightColumn.push_back( ColumnItem( pBtn ) );
941 // connect target and action
942 [pBtn setTarget: pCtrlTarget];
943 [pBtn setAction: @selector(triggered:)];
946 aBtnRect = [pBtn frame];
947 aBtnRect.origin.y = rCurY - aBtnRect.size.height;
948 [pBtn setFrame: aBtnRect];
951 aTextRect.origin.y = aBtnRect.origin.y + (aBtnRect.size.height - aTextRect.size.height)/2;
952 [pTextView setFrame: aTextRect];
955 rCurY = aBtnRect.origin.y - 5;
958 static void addEdit( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset,
959 const rtl::OUString& rCtrlType,
960 const rtl::OUString& rText,
961 const rtl::OUString& rProperty, const PropertyValue* pValue,
962 sal_Int64 nMinValue, sal_Int64 nMaxValue,
963 std::vector<ColumnItem >& rLeftColumn,
964 std::vector<ColumnItem >& rRightColumn,
965 ControllerProperties* pControllerProperties,
966 ControlTarget* pCtrlTarget
970 if( rText.getLength() )
973 NSControl* pTextView = createLabel( rText );
974 [pCurParent addSubview: [pTextView autorelease]];
976 rLeftColumn.push_back( ColumnItem( pTextView ) );
979 NSRect aTextRect = [pTextView frame];
980 aTextRect.origin.x = rCurX + nAttachOffset;
981 aTextRect.origin.y = rCurY - aTextRect.size.height;
982 [pTextView setFrame: aTextRect];
985 rCurY = aTextRect.origin.y - 5;
987 // and set the offset for the real edit field
988 nOff = aTextRect.size.width + 5;
991 NSRect aFieldRect = { { static_cast<CGFloat>(rCurX + nOff + nAttachOffset), 0 }, { 100, 25 } };
992 NSTextField* pFieldView = [[NSTextField alloc] initWithFrame: aFieldRect];
993 [pFieldView setEditable: YES];
994 [pFieldView setSelectable: YES];
995 [pFieldView setDrawsBackground: YES];
996 [pFieldView sizeToFit]; // FIXME: this does nothing
997 [pCurParent addSubview: [pFieldView autorelease]];
999 rRightColumn.push_back( ColumnItem( pFieldView ) );
1001 // add the field to observed controls for enabled state changes
1002 // also add a tag just for this purpose
1003 pControllerProperties->addObservedControl( pFieldView );
1004 int nTag = pControllerProperties->addNameTag( rProperty );
1005 [pFieldView setTag: nTag];
1006 // pControllerProperties->addNamedView( pFieldView, aPropertyName );
1009 aFieldRect.origin.y = rCurY - aFieldRect.size.height;
1010 [pFieldView setFrame: aFieldRect];
1012 if( rCtrlType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Range" ) ) )
1014 // add a stepper control
1015 NSRect aStepFrame = { { aFieldRect.origin.x + aFieldRect.size.width + 5,
1016 aFieldRect.origin.y },
1017 { 15, aFieldRect.size.height } };
1018 NSStepper* pStep = [[NSStepper alloc] initWithFrame: aStepFrame];
1019 [pStep setIncrement: 1];
1020 [pStep setValueWraps: NO];
1021 [pStep setTag: nTag];
1022 [pCurParent addSubview: [pStep autorelease]];
1024 rRightColumn.back().pSubControl = pStep;
1026 pControllerProperties->addObservedControl( pStep );
1027 [pStep setTarget: pCtrlTarget];
1028 [pStep setAction: @selector(triggered:)];
1030 // constrain the text field to decimal numbers
1031 NSNumberFormatter* pFormatter = [[NSNumberFormatter alloc] init];
1032 [pFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4];
1033 [pFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
1034 [pFormatter setAllowsFloats: NO];
1035 [pFormatter setMaximumFractionDigits: 0];
1036 if( nMinValue != nMaxValue )
1038 [pFormatter setMinimum: [[NSNumber numberWithInt: nMinValue] autorelease]];
1039 [pStep setMinValue: nMinValue];
1040 [pFormatter setMaximum: [[NSNumber numberWithInt: nMaxValue] autorelease]];
1041 [pStep setMaxValue: nMaxValue];
1043 [pFieldView setFormatter: pFormatter];
1045 sal_Int64 nSelectVal = 0;
1046 if( pValue && pValue->Value.hasValue() )
1047 pValue->Value >>= nSelectVal;
1049 [pFieldView setIntValue: nSelectVal];
1050 [pStep setIntValue: nSelectVal];
1052 pControllerProperties->addViewPair( pFieldView, pStep );
1053 // connect target and action
1054 [pFieldView setTarget: pCtrlTarget];
1055 [pFieldView setAction: @selector(triggeredNumeric:)];
1056 [pStep setTarget: pCtrlTarget];
1057 [pStep setAction: @selector(triggeredNumeric:)];
1061 // connect target and action
1062 [pFieldView setTarget: pCtrlTarget];
1063 [pFieldView setAction: @selector(triggered:)];
1065 if( pValue && pValue->Value.hasValue() )
1067 rtl::OUString aValue;
1068 pValue->Value >>= aValue;
1069 if( aValue.getLength() )
1071 NSString* pText = CreateNSString( aValue );
1072 [pFieldView setStringValue: pText];
1079 rCurY = aFieldRect.origin.y - 5;
1082 // In 10.5 and later:
1083 // 'setAccessoryView:' is deprecated
1085 // Make deprecation warnings just warnings in a -Werror compilation.
1088 // #pragma GCC diagnostic push
1089 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
1092 @implementation AquaPrintAccessoryView
1093 +(NSObject*)setupPrinterPanel: (NSPrintOperation*)pOp withController: (vcl::PrinterController*)pController withState: (PrintAccessoryViewState*)pState
1095 const Sequence< PropertyValue >& rOptions( pController->getUIOptions() );
1096 if( rOptions.getLength() == 0 )
1099 NSView* pCurParent = 0;
1102 NSRect aViewFrame = { NSZeroPoint, {600, 400 } };
1103 NSRect aTabViewFrame = { { 190, 0 }, {410, 400 } };
1104 NSSize aMaxTabSize = NSZeroSize;
1105 NSView* pAccessoryView = [[NSView alloc] initWithFrame: aViewFrame];
1106 NSTabView* pTabView = [[NSTabView alloc] initWithFrame: aTabViewFrame];
1107 [pAccessoryView addSubview: [pTabView autorelease]];
1109 bool bIgnoreSubgroup = false;
1111 ControllerProperties* pControllerProperties = new ControllerProperties( pController, pOp, pAccessoryView, pTabView, pState );
1112 ControlTarget* pCtrlTarget = [[ControlTarget alloc] initWithControllerMap: pControllerProperties];
1114 std::vector< ColumnItem > aLeftColumn, aRightColumn;
1117 // prepend a "selection" checkbox if the properties have such a selection in PrintContent
1118 bool bAddSelectionCheckBox = false, bSelectionBoxEnabled = false, bSelectionBoxChecked = false;
1119 for( int i = 0; i < rOptions.getLength(); i++ )
1121 Sequence< beans::PropertyValue > aOptProp;
1122 rOptions[i].Value >>= aOptProp;
1124 rtl::OUString aCtrlType;
1125 rtl::OUString aPropertyName;
1126 Sequence< rtl::OUString > aChoices;
1127 Sequence< sal_Bool > aChoicesDisabled;
1128 sal_Int32 aSelectionChecked = 0;
1129 for( int n = 0; n < aOptProp.getLength(); n++ )
1131 const beans::PropertyValue& rEntry( aOptProp[ n ] );
1132 if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ControlType")) )
1134 rEntry.Value >>= aCtrlType;
1136 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Choices")) )
1138 rEntry.Value >>= aChoices;
1140 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ChoicesDisabled")) )
1142 rEntry.Value >>= aChoicesDisabled;
1144 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Property")) )
1147 rEntry.Value >>= aVal;
1148 aPropertyName = aVal.Name;
1149 if( aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) )
1150 aVal.Value >>= aSelectionChecked;
1153 if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) &&
1154 aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) &&
1155 aChoices.getLength() > 2 )
1157 bAddSelectionCheckBox = true;
1158 bSelectionBoxEnabled = aChoicesDisabled.getLength() < 2 || ! aChoicesDisabled[2];
1159 bSelectionBoxChecked = (aSelectionChecked==2);
1164 for( int i = 0; i < rOptions.getLength(); i++ )
1166 Sequence< beans::PropertyValue > aOptProp;
1167 rOptions[i].Value >>= aOptProp;
1169 // extract ui element
1170 bool bEnabled = true;
1171 rtl::OUString aCtrlType;
1172 rtl::OUString aText;
1173 rtl::OUString aPropertyName;
1174 rtl::OUString aGroupHint;
1175 Sequence< rtl::OUString > aChoices;
1176 sal_Int64 nMinValue = 0, nMaxValue = 0;
1177 long nAttachOffset = 0;
1178 sal_Bool bIgnore = sal_False;
1180 for( int n = 0; n < aOptProp.getLength(); n++ )
1182 const beans::PropertyValue& rEntry( aOptProp[ n ] );
1183 if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Text")) )
1185 rEntry.Value >>= aText;
1186 aText = filterAccelerator( aText );
1188 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ControlType")) )
1190 rEntry.Value >>= aCtrlType;
1192 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Choices")) )
1194 rEntry.Value >>= aChoices;
1196 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Property")) )
1199 rEntry.Value >>= aVal;
1200 aPropertyName = aVal.Name;
1202 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Enabled")) )
1204 sal_Bool bValue = sal_True;
1205 rEntry.Value >>= bValue;
1208 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MinValue")) )
1210 rEntry.Value >>= nMinValue;
1212 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MaxValue")) )
1214 rEntry.Value >>= nMaxValue;
1216 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("AttachToDependency")) )
1220 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("InternalUIOnly")) )
1222 rEntry.Value >>= bIgnore;
1224 else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("GroupingHint")) )
1226 rEntry.Value >>= aGroupHint;
1230 if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Group")) ||
1231 aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) ||
1232 aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) ||
1233 aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("List")) ||
1234 aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Edit")) ||
1235 aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Range")) ||
1236 aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Bool")) )
1238 // since our build target is MacOSX 10.4 we can have only one accessory view
1239 // so we have a single accessory view that is tabbed for grouping
1240 if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Group"))
1242 || ( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) && nCurY < -250 && ! bIgnore )
1245 rtl::OUString aGroupTitle( aText );
1246 if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) )
1247 aGroupTitle = pControllerProperties->getMoreString();
1248 // set size of current parent
1250 adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn );
1253 if( ! aText.getLength() )
1255 NSString* pLabel = CreateNSString( aGroupTitle );
1256 NSTabViewItem* pItem = [[NSTabViewItem alloc] initWithIdentifier: pLabel ];
1257 [pItem setLabel: pLabel];
1258 [pTabView addTabViewItem: pItem];
1259 pCurParent = [[NSView alloc] initWithFrame: aTabViewFrame];
1260 [pItem setView: pCurParent];
1268 aLeftColumn.clear();
1269 aRightColumn.clear();
1271 if( bAddSelectionCheckBox )
1273 addBool( pCurParent, nCurX, nCurY, 0,
1274 pControllerProperties->getPrintSelectionString(), bSelectionBoxEnabled,
1275 OUString( "PrintContent" ), bSelectionBoxChecked,
1276 aRightColumn, pControllerProperties, pCtrlTarget );
1277 bAddSelectionCheckBox = false;
1281 if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) && pCurParent )
1283 bIgnoreSubgroup = bIgnore;
1287 addSubgroup( pCurParent, nCurY, aText );
1289 else if( bIgnoreSubgroup || bIgnore )
1293 else if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Bool")) && pCurParent )
1295 sal_Bool bVal = sal_False;
1296 PropertyValue* pVal = pController->getValue( aPropertyName );
1298 pVal->Value >>= bVal;
1299 addBool( pCurParent, nCurX, nCurY, nAttachOffset,
1300 aText, true, aPropertyName, bVal,
1301 aRightColumn, pControllerProperties, pCtrlTarget );
1303 else if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) && pCurParent )
1305 // get currently selected value
1306 sal_Int32 nSelectVal = 0;
1307 PropertyValue* pVal = pController->getValue( aPropertyName );
1308 if( pVal && pVal->Value.hasValue() )
1309 pVal->Value >>= nSelectVal;
1311 addRadio( pCurParent, nCurX, nCurY, nAttachOffset,
1312 aText, aPropertyName, aChoices, nSelectVal,
1313 aLeftColumn, aRightColumn,
1314 pControllerProperties, pCtrlTarget );
1316 else if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("List")) && pCurParent )
1318 PropertyValue* pVal = pController->getValue( aPropertyName );
1319 sal_Int32 aSelectVal = 0;
1320 if( pVal && pVal->Value.hasValue() )
1321 pVal->Value >>= aSelectVal;
1323 addList( pCurParent, nCurX, nCurY, nAttachOffset,
1324 aText, aPropertyName, aChoices, aSelectVal,
1325 aLeftColumn, aRightColumn,
1326 pControllerProperties, pCtrlTarget );
1328 else if( (aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Edit")) || aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Range"))) && pCurParent )
1331 PropertyValue* pVal = pController->getValue( aPropertyName );
1332 addEdit( pCurParent, nCurX, nCurY, nAttachOffset,
1333 aCtrlType, aText, aPropertyName, pVal,
1334 nMinValue, nMaxValue,
1335 aLeftColumn, aRightColumn,
1336 pControllerProperties, pCtrlTarget );
1341 SAL_INFO( "vcl.osx.print", "Unsupported UI option \"" << aCtrlType << "\"");
1345 pControllerProperties->updateEnableState();
1346 adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn );
1348 // leave some space for the preview
1349 if( aMaxTabSize.height < 200 )
1350 aMaxTabSize.height = 200;
1352 // now reposition everything again so it is upper bound
1353 adjustTabViews( pTabView, aMaxTabSize );
1355 // find the minimum needed tab size
1356 NSSize aTabCtrlSize = [pTabView minimumSize];
1357 aTabCtrlSize.height += aMaxTabSize.height + 10;
1358 if( aTabCtrlSize.width < aMaxTabSize.width + 10 )
1359 aTabCtrlSize.width = aMaxTabSize.width + 10;
1360 [pTabView setFrameSize: aTabCtrlSize];
1361 aViewFrame.size.width = aTabCtrlSize.width + aTabViewFrame.origin.x;
1362 aViewFrame.size.height = aTabCtrlSize.height + aTabViewFrame.origin.y;
1363 [pAccessoryView setFrameSize: aViewFrame.size];
1365 pControllerProperties->setupPreview( pCtrlTarget );
1367 // set the accessory view
1368 [pOp setAccessoryView: [pAccessoryView autorelease]];
1370 // set the current selecte tab item
1371 if( pState->nLastPage >= 0 && pState->nLastPage < [pTabView numberOfTabViewItems] )
1372 [pTabView selectTabViewItemAtIndex: pState->nLastPage];
1377 // #pragma GCC diagnostic pop
1381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */