office-gobmx/vcl/aqua/source/gdi/aquaprintaccessoryview.mm
Stephan Bergmann fa545023ad Introduce HAVE_GCC_PRAGMA_DIAGNOSTIC_{MODIFY,SCOPE}
...replacing hard-coded GCC version checks.  Those checks that guard

  #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"

appear relevant only for GCC itself, not Clang (which used to fail the old
guards because it typically announces itself with a rather low
__GNUC__/__GNUC_MINOR__ version), see 6e67c03dc0
"Enable -Wnon-virtual-dtor for GCC 4.6"

Change-Id: I6bfa4d5caa6192e7a203ce829682bf6bb8d61a1b
2013-03-25 08:52:54 +01:00

1397 lines
52 KiB
Text

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice 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 "tools/resary.hxx"
#include "vcl/print.hxx"
#include "vcl/image.hxx"
#include "vcl/virdev.hxx"
#include "vcl/svapp.hxx"
#include "vcl/unohelp.hxx"
#include "aqua/aquaprintview.h"
#include "aqua/salinst.h"
#include "quartz/utils.h"
#include "svdata.hxx"
#include "svids.hrc"
#include "com/sun/star/i18n/XBreakIterator.hpp"
#include "com/sun/star/i18n/WordType.hpp"
#include <map>
using namespace vcl;
using namespace com::sun::star;
using namespace com::sun::star::beans;
using namespace com::sun::star::uno;
/* Note: the accesory view as implemented here is already deprecated in Leopard. Unfortunately
as long as our baseline is Tiger we cannot gain the advantages over multiple accessory views
as well havs having accessory views AND a preview (as long as you are linked vs. 10.4 libraries
the preview insists on not being present. This is unfortunate.
*/
class ControllerProperties;
@interface ControlTarget : NSObject
{
ControllerProperties* mpController;
}
-(id)initWithControllerMap: (ControllerProperties*)pController;
-(void)triggered:(id)pSender;
-(void)triggeredNumeric:(id)pSender;
-(void)triggeredPreview:(id)pSender;
-(void)dealloc;
@end
class ControllerProperties
{
vcl::PrinterController* mpController;
std::map< int, rtl::OUString > maTagToPropertyName;
std::map< int, sal_Int32 > maTagToValueInt;
std::map< NSView*, NSView* > maViewPairMap;
std::vector< NSObject* > maViews;
int mnNextTag;
sal_Int32 mnLastPageCount;
PrintAccessoryViewState* mpState;
NSPrintOperation* mpOp;
NSView* mpAccessoryView;
NSTabView* mpTabView;
NSBox* mpPreviewBox;
NSImageView* mpPreview;
NSTextField* mpPageEdit;
NSStepper* mpStepper;
NSTextView* mpPagesLabel;
ResStringArray maLocalizedStrings;
public:
ControllerProperties( vcl::PrinterController* i_pController,
NSPrintOperation* i_pOp,
NSView* i_pAccessoryView,
NSTabView* i_pTabView,
PrintAccessoryViewState* i_pState )
: mpController( i_pController ),
mnNextTag( 0 ),
mnLastPageCount( i_pController->getFilteredPageCount() ),
mpState( i_pState ),
mpOp( i_pOp ),
mpAccessoryView( i_pAccessoryView ),
mpTabView( i_pTabView ),
mpPreviewBox( nil ),
mpPreview( nil ),
mpPageEdit( nil ),
mpStepper( nil ),
mpPagesLabel( nil ),
maLocalizedStrings( VclResId( SV_PRINT_NATIVE_STRINGS ) )
{
mpState->bNeedRestart = false;
DBG_ASSERT( maLocalizedStrings.Count() >= 5, "resources not found !" );
}
rtl::OUString getMoreString()
{
return maLocalizedStrings.Count() >= 4
? rtl::OUString( maLocalizedStrings.GetString( 3 ) )
: rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "More" ) );
}
rtl::OUString getPrintSelectionString()
{
return maLocalizedStrings.Count() >= 5
? rtl::OUString( maLocalizedStrings.GetString( 4 ) )
: rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Print selection only" ) );
}
void updatePrintJob()
{
// TODO: refresh page count etc from mpController
// page range may have changed depending on options
sal_Int32 nPages = mpController->getFilteredPageCount();
#if OSL_DEBUG_LEVEL > 1
if( nPages != mnLastPageCount )
fprintf( stderr, "trouble: number of pages changed from %ld to %ld !\n", mnLastPageCount, nPages );
#endif
mpState->bNeedRestart = (nPages != mnLastPageCount);
NSTabViewItem* pItem = [mpTabView selectedTabViewItem];
if( pItem )
mpState->nLastPage = [mpTabView indexOfTabViewItem: pItem];
else
mpState->nLastPage = 0;
mnLastPageCount = nPages;
if( mpState->bNeedRestart )
{
#if 0
// Warning: bad hack ahead
// Apple does not give us a chance of changing the page count,
// and they don't let us cancel the dialog either
// hack: send a cancel message to the window displaying our views.
// this is ugly.
for( std::vector< NSObject* >::iterator it = maViews.begin(); it != maViews.end(); ++it )
{
if( [*it isKindOfClass: [NSView class]] )
{
NSView* pView = (NSView*)*it;
NSWindow* pWindow = [pView window];
if( pWindow )
{
[pWindow cancelOperation: nil];
break;
}
}
}
#else
NSWindow* pWindow = [NSApp modalWindow];
if( pWindow )
[pWindow cancelOperation: nil];
#endif
[[mpOp printInfo] setJobDisposition: NSPrintCancelJob];
}
else
{
sal_Int32 nPage = [mpStepper intValue];
updatePreviewImage( nPage-1 );
}
}
int addNameTag( const rtl::OUString& i_rPropertyName )
{
int nNewTag = mnNextTag++;
maTagToPropertyName[ nNewTag ] = i_rPropertyName;
return nNewTag;
}
int addNameAndValueTag( const rtl::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, rtl::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() )
{
PropertyValue* pVal = mpController->getValue( name_it->second );
if( pVal )
{
pVal->Value <<= value_it->second;
updatePrintJob();
}
}
}
void changePropertyWithIntValue( int i_nTag, sal_Int64 i_nValue )
{
std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag );
if( name_it != maTagToPropertyName.end() )
{
PropertyValue* pVal = mpController->getValue( name_it->second );
if( pVal )
{
pVal->Value <<= i_nValue;
updatePrintJob();
}
}
}
void changePropertyWithBoolValue( int i_nTag, sal_Bool i_bValue )
{
std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag );
if( name_it != maTagToPropertyName.end() )
{
PropertyValue* pVal = mpController->getValue( name_it->second );
if( pVal )
{
// ugly
if( name_it->second.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) )
pVal->Value <<= i_bValue ? sal_Int32(2) : sal_Int32(0);
else
pVal->Value <<= i_bValue;
updatePrintJob();
}
}
}
void changePropertyWithStringValue( int i_nTag, const rtl::OUString& i_rValue )
{
std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag );
if( name_it != maTagToPropertyName.end() )
{
PropertyValue* pVal = mpController->getValue( name_it->second );
if( pVal )
{
pVal->Value <<= i_rValue;
updatePrintJob();
}
}
}
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 = (NSControl*)pObj;
else if( [pObj isKindOfClass: [NSCell class]] )
pCell = (NSCell*)pObj;
int nTag = pCtrl ? [pCtrl tag] :
pCell ? [pCell tag] :
-1;
std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( nTag );
if( name_it != maTagToPropertyName.end() && ! name_it->second.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) )
{
BOOL bEnabled = mpController->isUIOptionEnabled( name_it->second ) ? YES : NO;
if( pCtrl )
{
[pCtrl setEnabled: bEnabled];
NSView* pOther = getPair( pCtrl );
if( pOther && [pOther isKindOfClass: [NSControl class]] )
[(NSControl*)pOther setEnabled: bEnabled];
}
else if( pCell )
[pCell setEnabled: bEnabled];
}
}
}
void updatePreviewImage( sal_Int32 i_nPage )
{
sal_Int32 nPages = mpController->getFilteredPageCount();
NSRect aViewFrame = [mpPreview frame];
Size aPixelSize( static_cast<long>(aViewFrame.size.width),
static_cast<long>(aViewFrame.size.height) );
if( i_nPage >= 0 && nPages > i_nPage )
{
GDIMetaFile aMtf;
PrinterController::PageSize aPageSize( mpController->getFilteredPageFile( i_nPage, aMtf, false ) );
VirtualDevice aDev;
if( mpController->getPrinter()->GetPrinterOptions().IsConvertToGreyscales() )
aDev.SetDrawMode( aDev.GetDrawMode() | ( DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL | DRAWMODE_GRAYTEXT |
DRAWMODE_GRAYBITMAP | DRAWMODE_GRAYGRADIENT ) );
// see salprn.cxx, currently we pretend to be a 720dpi device on printers
aDev.SetReferenceDevice( 720, 720 );
aDev.EnableOutput( TRUE );
Size aLogicSize( aDev.PixelToLogic( aPixelSize, MapMode( MAP_100TH_MM ) ) );
double fScaleX = double(aLogicSize.Width())/double(aPageSize.aSize.Width());
double fScaleY = double(aLogicSize.Height())/double(aPageSize.aSize.Height());
double fScale = (fScaleX < fScaleY) ? fScaleX : fScaleY;
// #i104784# if we render the page too small then rounding issues result in
// layout artifacts looking really bad. So scale the page unto a device that is not
// full page size but not too small either. This also results in much better visual
// quality of the preview, e.g. when its height approaches the number of text lines
if( fScale < 0.1 )
fScale = 0.1;
aMtf.WindStart();
aMtf.Scale( fScale, fScale );
aMtf.WindStart();
aLogicSize.Width() = long(double(aPageSize.aSize.Width()) * fScale);
aLogicSize.Height() = long(double(aPageSize.aSize.Height()) * fScale);
aPixelSize = aDev.LogicToPixel( aLogicSize, MapMode( MAP_100TH_MM ) );
aDev.SetOutputSizePixel( aPixelSize );
aMtf.WindStart();
aDev.SetMapMode( MapMode( MAP_100TH_MM ) );
aMtf.Play( &aDev, Point( 0, 0 ), aLogicSize );
aDev.EnableMapMode( FALSE );
Image aImage( aDev.GetBitmap( Point( 0, 0 ), aPixelSize ) );
NSImage* pImage = CreateNSImage( aImage );
[mpPreview setImage: [pImage autorelease]];
}
else
[mpPreview setImage: nil];
}
void setupPreview( ControlTarget* i_pCtrlTarget )
{
if( maLocalizedStrings.Count() < 3 )
return;
// get the preview control
NSRect aPreviewFrame = [mpAccessoryView frame];
aPreviewFrame.origin.x = 0;
aPreviewFrame.origin.y = 5;
aPreviewFrame.size.width = 190;
aPreviewFrame.size.height -= 7;
// create a box to put the preview controls in
mpPreviewBox = [[NSBox alloc] initWithFrame: aPreviewFrame];
[mpPreviewBox setTitle: [CreateNSString( maLocalizedStrings.GetString( 0 ) ) autorelease]];
[mpAccessoryView addSubview: [mpPreviewBox autorelease]];
// now create the image view of the preview
NSSize aMargins = [mpPreviewBox contentViewMargins];
aPreviewFrame.origin.x = 0;
aPreviewFrame.origin.y = 34;
aPreviewFrame.size.width -= 2*(aMargins.width+1);
aPreviewFrame.size.height -= 61;
mpPreview = [[NSImageView alloc] initWithFrame: aPreviewFrame];
[mpPreview setImageScaling: NSScaleProportionally];
[mpPreview setImageAlignment: NSImageAlignCenter];
[mpPreview setImageFrameStyle: NSImageFrameNone];
[mpPreviewBox addSubview: [mpPreview autorelease]];
// add a label
sal_Int32 nPages = mpController->getFilteredPageCount();
rtl::OUStringBuffer aBuf( 16 );
aBuf.appendAscii( "/ " );
aBuf.append( rtl::OUString::valueOf( nPages ) );
NSString* pText = CreateNSString( aBuf.makeStringAndClear() );
NSRect aTextRect = { { 100, 5 }, { 100, 22 } };
mpPagesLabel = [[NSTextView alloc] initWithFrame: aTextRect];
[mpPagesLabel setFont: [NSFont controlContentFontOfSize: 0]];
[mpPagesLabel setEditable: NO];
[mpPagesLabel setSelectable: NO];
[mpPagesLabel setDrawsBackground: NO];
[mpPagesLabel setString: [pText autorelease]];
[mpPagesLabel setToolTip: [CreateNSString( maLocalizedStrings.GetString( 2 ) ) autorelease]];
[mpPreviewBox addSubview: [mpPagesLabel autorelease]];
NSRect aFieldRect = { { 45, 5 }, { 35, 25 } };
mpPageEdit = [[NSTextField alloc] initWithFrame: aFieldRect];
[mpPageEdit setEditable: YES];
[mpPageEdit setSelectable: YES];
[mpPageEdit setDrawsBackground: YES];
[mpPageEdit setToolTip: [CreateNSString( maLocalizedStrings.GetString( 1 ) ) autorelease]];
[mpPreviewBox addSubview: [mpPageEdit autorelease]];
// add a stepper control
NSRect aStepFrame = { { 85, 5 }, { 15, 25 } };
mpStepper = [[NSStepper alloc] initWithFrame: aStepFrame];
[mpStepper setIncrement: 1];
[mpStepper setValueWraps: NO];
[mpPreviewBox addSubview: [mpStepper autorelease]];
// constrain the text field to decimal numbers
NSNumberFormatter* pFormatter = [[NSNumberFormatter alloc] init];
[pFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4];
[pFormatter setMinimum: [[NSNumber numberWithInt: 1] autorelease]];
[pFormatter setMaximum: [[NSNumber numberWithInt: nPages] autorelease]];
[pFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
[pFormatter setAllowsFloats: NO];
[pFormatter setMaximumFractionDigits: 0];
[mpPageEdit setFormatter: pFormatter];
[mpStepper setMinValue: 1];
[mpStepper setMaxValue: nPages];
[mpPageEdit setIntValue: 1];
[mpStepper setIntValue: 1];
// connect target and action
[mpStepper setTarget: i_pCtrlTarget];
[mpStepper setAction: @selector(triggeredPreview:)];
[mpPageEdit setTarget: i_pCtrlTarget];
[mpPageEdit setAction: @selector(triggeredPreview:)];
// set first preview image
updatePreviewImage( 0 );
}
void changePreview( NSObject* i_pSender )
{
if( [i_pSender isMemberOfClass: [NSTextField class]] )
{
NSTextField* pField = (NSTextField*)i_pSender;
if( pField == mpPageEdit ) // sanity check
{
sal_Int32 nPage = [pField intValue];
[mpStepper setIntValue: nPage];
updatePreviewImage( nPage-1 );
}
}
else if( [i_pSender isMemberOfClass: [NSStepper class]] )
{
NSStepper* pStepper = (NSStepper*)i_pSender;
if( pStepper == mpStepper ) // sanity check
{
sal_Int32 nPage = [pStepper intValue];
[mpPageEdit setIntValue: nPage];
updatePreviewImage( nPage-1 );
}
}
}
};
static void filterAccelerator( rtl::OUString& io_rText )
{
rtl::OUStringBuffer aBuf( io_rText.getLength() );
for( sal_Int32 nIndex = 0; nIndex != -1; )
aBuf.append( io_rText.getToken( 0, '~', nIndex ) );
io_rText = 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 = (NSPopUpButton*)pSender;
NSMenuItem* pSelected = [pBtn selectedItem];
if( pSelected )
{
int nTag = [pSelected tag];
mpController->changePropertyWithIntValue( nTag );
}
}
else if( [pSender isMemberOfClass: [NSButton class]] )
{
NSButton* pBtn = (NSButton*)pSender;
int nTag = [pBtn tag];
mpController->changePropertyWithBoolValue( nTag, [pBtn state] == NSOnState );
}
else if( [pSender isMemberOfClass: [NSMatrix class]] )
{
NSObject* pObj = [(NSMatrix*)pSender selectedCell];
if( [pObj isMemberOfClass: [NSButtonCell class]] )
{
NSButtonCell* pCell = (NSButtonCell*)pObj;
int nTag = [pCell tag];
mpController->changePropertyWithIntValue( nTag );
}
}
else if( [pSender isMemberOfClass: [NSTextField class]] )
{
NSTextField* pField = (NSTextField*)pSender;
int nTag = [pField tag];
rtl::OUString aValue = GetOUString( [pSender stringValue] );
mpController->changePropertyWithStringValue( nTag, aValue );
}
else
{
SAL_INFO( "vcl.aqua.print", "Unsupported class" << ([pSender class] ? [NSStringFromClass([pSender class]) UTF8String] : "nil"));
}
mpController->updateEnableState();
}
-(void)triggeredNumeric:(id)pSender
{
if( [pSender isMemberOfClass: [NSTextField class]] )
{
NSTextField* pField = (NSTextField*)pSender;
int nTag = [pField tag];
sal_Int64 nValue = [pField intValue];
NSView* pOther = mpController->getPair( pField );
if( pOther )
[(NSControl*)pOther setIntValue: nValue];
mpController->changePropertyWithIntValue( nTag, nValue );
}
else if( [pSender isMemberOfClass: [NSStepper class]] )
{
NSStepper* pStep = (NSStepper*)pSender;
int nTag = [pStep tag];
sal_Int64 nValue = [pStep intValue];
NSView* pOther = mpController->getPair( pStep );
if( pOther )
[(NSControl*)pOther setIntValue: nValue];
mpController->changePropertyWithIntValue( nTag, nValue );
}
else
{
SAL_INFO( "vcl.aqua.print", "Unsupported class" << ([pSender class] ? [NSStringFromClass([pSender class]) UTF8String] : "nil"));
}
mpController->updateEnableState();
}
-(void)triggeredPreview:(id)pSender
{
mpController->changePreview( pSender );
}
-(void)dealloc
{
delete mpController;
[super dealloc];
}
@end
struct ColumnItem
{
NSControl* pControl;
long nOffset;
NSControl* pSubControl;
ColumnItem( NSControl* i_pControl = nil, long i_nOffset = 0, NSControl* i_pSub = nil )
: pControl( i_pControl )
, nOffset( i_nOffset )
, pSubControl( i_pSub )
{}
long getWidth() const
{
long 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* pView, NSSize& rMaxSize,
std::vector< ColumnItem >& rLeftColumn,
std::vector< ColumnItem >& rRightColumn
)
{
// balance columns
// first get overall column widths
long nLeftWidth = 0;
long nRightWidth = 0;
for( size_t i = 0; i < rLeftColumn.size(); i++ )
{
long nW = rLeftColumn[i].getWidth();
if( nW > nLeftWidth )
nLeftWidth = nW;
}
for( size_t i = 0; i < rRightColumn.size(); i++ )
{
long 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];
long 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];
long 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 = [pView subviews];
unsigned int nViews = [pSubViews count];
NSRect aUnion = { { 0, 0 }, { 0, 0 } };
// 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;
[pView 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 = (NSTabViewItem*)[pTabbedViews objectAtIndex: i];
NSView* pView = [pItem view];
if( pView )
{
NSRect aRect = [pView frame];
double nDiff = aTabSize.height - aRect.size.height;
aRect.size = aTabSize;
[pView setFrame: aRect];
NSArray* pSubViews = [pView 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 rtl::OUString& i_rText )
{
NSString* pText = CreateNSString( i_rText );
NSRect aTextRect = { { 0, 0 }, {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 rtl::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,
sal_True );
nRet = aBoundary.endPos;
}
return nRet;
}
static void linebreakCell( NSCell* pBtn, const rtl::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 )
{
rtl::OUStringBuffer aBuf( i_rText );
aBuf[nIndex] = '\n';
pText = CreateNSString( aBuf.makeStringAndClear() );
[pBtn setTitle: pText];
[pText release];
}
}
}
static void addSubgroup( NSView* pCurParent, long& rCurY, const rtl::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, long& rCurX, long& rCurY, long nAttachOffset,
const rtl::OUString& rText, sal_Bool bEnabled,
const rtl::OUString& rProperty, sal_Bool bValue,
std::vector<ColumnItem >& rRightColumn,
ControllerProperties* pControllerProperties,
ControlTarget* pCtrlTarget
)
{
NSRect aCheckRect = { { static_cast<CGFloat>(rCurX + nAttachOffset), 0 }, { 0, 15 } };
NSButton* pBtn = [[NSButton alloc] initWithFrame: aCheckRect];
[pBtn setButtonType: NSSwitchButton];
[pBtn setState: bValue ? NSOnState : NSOffState];
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, long& rCurX, long& rCurY, long nAttachOffset,
const rtl::OUString& rText,
const rtl::OUString& rProperty, Sequence< rtl::OUString > rChoices, sal_Int32 nSelectValue,
std::vector<ColumnItem >& rLeftColumn,
std::vector<ColumnItem >& rRightColumn,
ControllerProperties* pControllerProperties,
ControlTarget* pCtrlTarget
)
{
sal_Int32 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 = { { static_cast<CGFloat>(rCurX + nOff), 0 }, { static_cast<CGFloat>(280 - rCurX), static_cast<CGFloat>(5*rChoices.getLength()) } };
[pProto setTitle: @"RadioButtonGroup"];
[pProto setButtonType: NSRadioButton];
NSMatrix* pMatrix = [[NSMatrix alloc] initWithFrame: aRadioRect
mode: NSRadioModeMatrix
prototype: (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];
filterAccelerator( rChoices[m] );
linebreakCell( pCell, 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, long& rCurX, long& rCurY, long /*nAttachOffset*/,
const rtl::OUString& rText,
const rtl::OUString& rProperty, const Sequence< rtl::OUString > 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, long& rCurX, long& rCurY, long nAttachOffset,
const rtl::OUString rCtrlType,
const rtl::OUString& rText,
const rtl::OUString& rProperty, const PropertyValue* pValue,
sal_Int64 nMinValue, sal_Int64 nMaxValue,
std::vector<ColumnItem >& rLeftColumn,
std::vector<ColumnItem >& rRightColumn,
ControllerProperties* pControllerProperties,
ControlTarget* pCtrlTarget
)
{
sal_Int32 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 = { { static_cast<CGFloat>(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.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "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] autorelease]];
[pStep setMinValue: nMinValue];
[pFormatter setMaximum: [[NSNumber numberWithInt: nMaxValue] autorelease]];
[pStep setMaxValue: nMaxValue];
}
[pFieldView setFormatter: pFormatter];
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() )
{
rtl::OUString aValue;
pValue->Value >>= aValue;
if( aValue.getLength() )
{
NSString* pText = CreateNSString( aValue );
[pFieldView setStringValue: pText];
[pText release];
}
}
}
// update nCurY
rCurY = aFieldRect.origin.y - 5;
}
// In 10.5 and later:
// 'setAccessoryView:' is deprecated
// Make deprecation warnings just warnings in a -Werror compilation.
#if HAVE_GCC_PRAGMA_DIAGNOSTIC_MODIFY
// #pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wdeprecated-declarations"
#endif
@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;
NSView* pCurParent = 0;
long nCurY = 0;
long nCurX = 0;
NSRect aViewFrame = { { 0, 0 }, {600, 400 } };
NSRect aTabViewFrame = { { 190, 0 }, {410, 400 } };
NSSize aMaxTabSize = { 0, 0 };
NSView* pAccessoryView = [[NSView alloc] initWithFrame: aViewFrame];
NSTabView* pTabView = [[NSTabView alloc] initWithFrame: aTabViewFrame];
[pAccessoryView addSubview: [pTabView autorelease]];
sal_Bool bIgnoreSubgroup = sal_False;
ControllerProperties* pControllerProperties = new ControllerProperties( pController, pOp, pAccessoryView, pTabView, pState );
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( int i = 0; i < rOptions.getLength(); i++ )
{
Sequence< beans::PropertyValue > aOptProp;
rOptions[i].Value >>= aOptProp;
rtl::OUString aCtrlType;
rtl::OUString aPropertyName;
Sequence< rtl::OUString > aChoices;
Sequence< sal_Bool > aChoicesDisabled;
sal_Int32 aSelectionChecked = 0;
for( int n = 0; n < aOptProp.getLength(); n++ )
{
const beans::PropertyValue& rEntry( aOptProp[ n ] );
if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ControlType")) )
{
rEntry.Value >>= aCtrlType;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Choices")) )
{
rEntry.Value >>= aChoices;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ChoicesDisabled")) )
{
rEntry.Value >>= aChoicesDisabled;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Property")) )
{
PropertyValue aVal;
rEntry.Value >>= aVal;
aPropertyName = aVal.Name;
if( aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) )
aVal.Value >>= aSelectionChecked;
}
}
if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) &&
aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) &&
aChoices.getLength() > 2 )
{
bAddSelectionCheckBox = true;
bSelectionBoxEnabled = aChoicesDisabled.getLength() < 2 || ! aChoicesDisabled[2];
bSelectionBoxChecked = (aSelectionChecked==2);
break;
}
}
for( int i = 0; i < rOptions.getLength(); i++ )
{
Sequence< beans::PropertyValue > aOptProp;
rOptions[i].Value >>= aOptProp;
// extract ui element
bool bEnabled = true;
rtl::OUString aCtrlType;
rtl::OUString aText;
rtl::OUString aPropertyName;
rtl::OUString aGroupHint;
Sequence< rtl::OUString > aChoices;
sal_Int64 nMinValue = 0, nMaxValue = 0;
long nAttachOffset = 0;
sal_Bool bIgnore = sal_False;
for( int n = 0; n < aOptProp.getLength(); n++ )
{
const beans::PropertyValue& rEntry( aOptProp[ n ] );
if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Text")) )
{
rEntry.Value >>= aText;
filterAccelerator( aText );
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ControlType")) )
{
rEntry.Value >>= aCtrlType;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Choices")) )
{
rEntry.Value >>= aChoices;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Property")) )
{
PropertyValue aVal;
rEntry.Value >>= aVal;
aPropertyName = aVal.Name;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Enabled")) )
{
sal_Bool bValue = sal_True;
rEntry.Value >>= bValue;
bEnabled = bValue;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MinValue")) )
{
rEntry.Value >>= nMinValue;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MaxValue")) )
{
rEntry.Value >>= nMaxValue;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("AttachToDependency")) )
{
nAttachOffset = 20;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("InternalUIOnly")) )
{
rEntry.Value >>= bIgnore;
}
else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("GroupingHint")) )
{
rEntry.Value >>= aGroupHint;
}
}
if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Group")) ||
aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) ||
aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) ||
aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("List")) ||
aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Edit")) ||
aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Range")) ||
aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Bool")) )
{
// since our build target is MacOSX 10.4 we can have only one accessory view
// so we have a single accessory view that is tabbed for grouping
if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Group"))
|| ! pCurParent
|| ( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) && nCurY < -250 && ! bIgnore )
)
{
rtl::OUString aGroupTitle( aText );
if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) )
aGroupTitle = pControllerProperties->getMoreString();
// set size of current parent
if( pCurParent )
adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn );
// new tab item
if( ! aText.getLength() )
aText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OOo" ) );
NSString* pLabel = CreateNSString( aGroupTitle );
NSTabViewItem* pItem = [[NSTabViewItem alloc] initWithIdentifier: pLabel ];
[pItem setLabel: pLabel];
[pTabView addTabViewItem: pItem];
pCurParent = [[NSView alloc] initWithFrame: aTabViewFrame];
[pItem setView: pCurParent];
[pLabel release];
// reset indent
nCurX = 20;
// reset Y
nCurY = 0;
// clear columns
aLeftColumn.clear();
aRightColumn.clear();
if( bAddSelectionCheckBox )
{
addBool( pCurParent, nCurX, nCurY, 0,
pControllerProperties->getPrintSelectionString(), bSelectionBoxEnabled,
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) ), bSelectionBoxChecked,
aRightColumn, pControllerProperties, pCtrlTarget );
bAddSelectionCheckBox = false;
}
}
if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) && pCurParent )
{
bIgnoreSubgroup = bIgnore;
if( bIgnore )
continue;
addSubgroup( pCurParent, nCurY, aText );
}
else if( bIgnoreSubgroup || bIgnore )
{
continue;
}
else if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Bool")) && pCurParent )
{
sal_Bool bVal = sal_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.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("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.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("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.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Edit")) || aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("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.aqua.print", "Unsupported UI option \"" << aCtrlType << "\"");
}
}
pControllerProperties->updateEnableState();
adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn );
// leave some space for the preview
if( aMaxTabSize.height < 200 )
aMaxTabSize.height = 200;
// 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];
pControllerProperties->setupPreview( pCtrlTarget );
// set the accessory view
[pOp setAccessoryView: [pAccessoryView autorelease]];
// set the current selecte tab item
if( pState->nLastPage >= 0 && pState->nLastPage < [pTabView numberOfTabViewItems] )
[pTabView selectTabViewItemAtIndex: pState->nLastPage];
return pCtrlTarget;
}
// #pragma GCC diagnostic pop
@end
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */