1*b1cdbd2cSJim Jagielski/************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski// MARKER(update_precomp.py): autogen include statement, do not remove 25*b1cdbd2cSJim Jagielski#include "precompiled_vcl.hxx" 26*b1cdbd2cSJim Jagielski 27*b1cdbd2cSJim Jagielski#include "tools/resary.hxx" 28*b1cdbd2cSJim Jagielski 29*b1cdbd2cSJim Jagielski#include "vcl/print.hxx" 30*b1cdbd2cSJim Jagielski#include "vcl/image.hxx" 31*b1cdbd2cSJim Jagielski#include "vcl/virdev.hxx" 32*b1cdbd2cSJim Jagielski#include "vcl/svapp.hxx" 33*b1cdbd2cSJim Jagielski#include "vcl/unohelp.hxx" 34*b1cdbd2cSJim Jagielski 35*b1cdbd2cSJim Jagielski#include "aqua/aquaprintview.h" 36*b1cdbd2cSJim Jagielski#include "aqua/salinst.h" 37*b1cdbd2cSJim Jagielski 38*b1cdbd2cSJim Jagielski#include "svdata.hxx" 39*b1cdbd2cSJim Jagielski#include "svids.hrc" 40*b1cdbd2cSJim Jagielski 41*b1cdbd2cSJim Jagielski#include "com/sun/star/i18n/XBreakIterator.hpp" 42*b1cdbd2cSJim Jagielski#include "com/sun/star/i18n/WordType.hpp" 43*b1cdbd2cSJim Jagielski 44*b1cdbd2cSJim Jagielski#include <map> 45*b1cdbd2cSJim Jagielski 46*b1cdbd2cSJim Jagielskiusing namespace vcl; 47*b1cdbd2cSJim Jagielskiusing namespace com::sun::star; 48*b1cdbd2cSJim Jagielskiusing namespace com::sun::star::beans; 49*b1cdbd2cSJim Jagielskiusing namespace com::sun::star::uno; 50*b1cdbd2cSJim Jagielski 51*b1cdbd2cSJim Jagielski/* Note: the accesory view as implemented here is already deprecated in Leopard. Unfortunately 52*b1cdbd2cSJim Jagielski as long as our baseline is Tiger we cannot gain the advantages over multiple accessory views 53*b1cdbd2cSJim Jagielski as well havs having accessory views AND a preview (as long as you are linked vs. 10.4 libraries 54*b1cdbd2cSJim Jagielski the preview insists on not being present. This is unfortunate. 55*b1cdbd2cSJim Jagielski*/ 56*b1cdbd2cSJim Jagielski 57*b1cdbd2cSJim Jagielskiclass ControllerProperties; 58*b1cdbd2cSJim Jagielski 59*b1cdbd2cSJim Jagielski@interface ControlTarget : NSObject 60*b1cdbd2cSJim Jagielski{ 61*b1cdbd2cSJim Jagielski ControllerProperties* mpController; 62*b1cdbd2cSJim Jagielski} 63*b1cdbd2cSJim Jagielski-(id)initWithControllerMap: (ControllerProperties*)pController; 64*b1cdbd2cSJim Jagielski-(void)triggered:(id)pSender; 65*b1cdbd2cSJim Jagielski-(void)triggeredNumeric:(id)pSender; 66*b1cdbd2cSJim Jagielski-(void)triggeredPreview:(id)pSender; 67*b1cdbd2cSJim Jagielski-(void)dealloc; 68*b1cdbd2cSJim Jagielski@end 69*b1cdbd2cSJim Jagielski 70*b1cdbd2cSJim Jagielski 71*b1cdbd2cSJim Jagielskiclass ControllerProperties 72*b1cdbd2cSJim Jagielski{ 73*b1cdbd2cSJim Jagielski vcl::PrinterController* mpController; 74*b1cdbd2cSJim Jagielski std::map< int, rtl::OUString > maTagToPropertyName; 75*b1cdbd2cSJim Jagielski std::map< int, sal_Int32 > maTagToValueInt; 76*b1cdbd2cSJim Jagielski std::map< NSView*, NSView* > maViewPairMap; 77*b1cdbd2cSJim Jagielski std::vector< NSObject* > maViews; 78*b1cdbd2cSJim Jagielski int mnNextTag; 79*b1cdbd2cSJim Jagielski sal_Int32 mnLastPageCount; 80*b1cdbd2cSJim Jagielski PrintAccessoryViewState* mpState; 81*b1cdbd2cSJim Jagielski NSPrintOperation* mpOp; 82*b1cdbd2cSJim Jagielski NSView* mpAccessoryView; 83*b1cdbd2cSJim Jagielski NSTabView* mpTabView; 84*b1cdbd2cSJim Jagielski NSBox* mpPreviewBox; 85*b1cdbd2cSJim Jagielski NSImageView* mpPreview; 86*b1cdbd2cSJim Jagielski NSTextField* mpPageEdit; 87*b1cdbd2cSJim Jagielski NSStepper* mpStepper; 88*b1cdbd2cSJim Jagielski NSTextView* mpPagesLabel; 89*b1cdbd2cSJim Jagielski ResStringArray maLocalizedStrings; 90*b1cdbd2cSJim Jagielski 91*b1cdbd2cSJim Jagielski public: 92*b1cdbd2cSJim Jagielski ControllerProperties( vcl::PrinterController* i_pController, 93*b1cdbd2cSJim Jagielski NSPrintOperation* i_pOp, 94*b1cdbd2cSJim Jagielski NSView* i_pAccessoryView, 95*b1cdbd2cSJim Jagielski NSTabView* i_pTabView, 96*b1cdbd2cSJim Jagielski PrintAccessoryViewState* i_pState ) 97*b1cdbd2cSJim Jagielski : mpController( i_pController ), 98*b1cdbd2cSJim Jagielski mnNextTag( 0 ), 99*b1cdbd2cSJim Jagielski mnLastPageCount( i_pController->getFilteredPageCount() ), 100*b1cdbd2cSJim Jagielski mpState( i_pState ), 101*b1cdbd2cSJim Jagielski mpOp( i_pOp ), 102*b1cdbd2cSJim Jagielski mpAccessoryView( i_pAccessoryView ), 103*b1cdbd2cSJim Jagielski mpTabView( i_pTabView ), 104*b1cdbd2cSJim Jagielski mpPreviewBox( nil ), 105*b1cdbd2cSJim Jagielski mpPreview( nil ), 106*b1cdbd2cSJim Jagielski mpPageEdit( nil ), 107*b1cdbd2cSJim Jagielski mpStepper( nil ), 108*b1cdbd2cSJim Jagielski mpPagesLabel( nil ), 109*b1cdbd2cSJim Jagielski maLocalizedStrings( VclResId( SV_PRINT_NATIVE_STRINGS ) ) 110*b1cdbd2cSJim Jagielski { 111*b1cdbd2cSJim Jagielski mpState->bNeedRestart = false; 112*b1cdbd2cSJim Jagielski DBG_ASSERT( maLocalizedStrings.Count() >= 5, "resources not found !" ); 113*b1cdbd2cSJim Jagielski } 114*b1cdbd2cSJim Jagielski 115*b1cdbd2cSJim Jagielski rtl::OUString getMoreString() 116*b1cdbd2cSJim Jagielski { 117*b1cdbd2cSJim Jagielski return maLocalizedStrings.Count() >= 4 118*b1cdbd2cSJim Jagielski ? rtl::OUString( maLocalizedStrings.GetString( 3 ) ) 119*b1cdbd2cSJim Jagielski : rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "More" ) ); 120*b1cdbd2cSJim Jagielski } 121*b1cdbd2cSJim Jagielski 122*b1cdbd2cSJim Jagielski rtl::OUString getPrintSelectionString() 123*b1cdbd2cSJim Jagielski { 124*b1cdbd2cSJim Jagielski return maLocalizedStrings.Count() >= 5 125*b1cdbd2cSJim Jagielski ? rtl::OUString( maLocalizedStrings.GetString( 4 ) ) 126*b1cdbd2cSJim Jagielski : rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Print selection only" ) ); 127*b1cdbd2cSJim Jagielski } 128*b1cdbd2cSJim Jagielski 129*b1cdbd2cSJim Jagielski void updatePrintJob() 130*b1cdbd2cSJim Jagielski { 131*b1cdbd2cSJim Jagielski // TODO: refresh page count etc from mpController 132*b1cdbd2cSJim Jagielski 133*b1cdbd2cSJim Jagielski // page range may have changed depending on options 134*b1cdbd2cSJim Jagielski sal_Int32 nPages = mpController->getFilteredPageCount(); 135*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1 136*b1cdbd2cSJim Jagielski if( nPages != mnLastPageCount ) 137*b1cdbd2cSJim Jagielski fprintf( stderr, "trouble: number of pages changed from %ld to %ld !\n", mnLastPageCount, nPages ); 138*b1cdbd2cSJim Jagielski #endif 139*b1cdbd2cSJim Jagielski mpState->bNeedRestart = (nPages != mnLastPageCount); 140*b1cdbd2cSJim Jagielski NSTabViewItem* pItem = [mpTabView selectedTabViewItem]; 141*b1cdbd2cSJim Jagielski if( pItem ) 142*b1cdbd2cSJim Jagielski mpState->nLastPage = [mpTabView indexOfTabViewItem: pItem]; 143*b1cdbd2cSJim Jagielski else 144*b1cdbd2cSJim Jagielski mpState->nLastPage = 0; 145*b1cdbd2cSJim Jagielski mnLastPageCount = nPages; 146*b1cdbd2cSJim Jagielski if( mpState->bNeedRestart ) 147*b1cdbd2cSJim Jagielski { 148*b1cdbd2cSJim Jagielski // Warning: bad hack ahead 149*b1cdbd2cSJim Jagielski // Apple does not give us a chance of changing the page count, 150*b1cdbd2cSJim Jagielski // and they don't let us cancel the dialog either 151*b1cdbd2cSJim Jagielski // hack: send a cancel message to the window displaying our views. 152*b1cdbd2cSJim Jagielski // this is ugly. 153*b1cdbd2cSJim Jagielski NSWindow* pNSWindow = [NSApp modalWindow]; 154*b1cdbd2cSJim Jagielski if( pNSWindow ) 155*b1cdbd2cSJim Jagielski [pNSWindow cancelOperation: nil]; 156*b1cdbd2cSJim Jagielski [[mpOp printInfo] setJobDisposition: NSPrintCancelJob]; 157*b1cdbd2cSJim Jagielski } 158*b1cdbd2cSJim Jagielski else 159*b1cdbd2cSJim Jagielski { 160*b1cdbd2cSJim Jagielski sal_Int32 nPage = [mpStepper intValue]; 161*b1cdbd2cSJim Jagielski updatePreviewImage( nPage-1 ); 162*b1cdbd2cSJim Jagielski } 163*b1cdbd2cSJim Jagielski } 164*b1cdbd2cSJim Jagielski 165*b1cdbd2cSJim Jagielski int addNameTag( const rtl::OUString& i_rPropertyName ) 166*b1cdbd2cSJim Jagielski { 167*b1cdbd2cSJim Jagielski int nNewTag = mnNextTag++; 168*b1cdbd2cSJim Jagielski maTagToPropertyName[ nNewTag ] = i_rPropertyName; 169*b1cdbd2cSJim Jagielski return nNewTag; 170*b1cdbd2cSJim Jagielski } 171*b1cdbd2cSJim Jagielski 172*b1cdbd2cSJim Jagielski int addNameAndValueTag( const rtl::OUString& i_rPropertyName, sal_Int32 i_nValue ) 173*b1cdbd2cSJim Jagielski { 174*b1cdbd2cSJim Jagielski int nNewTag = mnNextTag++; 175*b1cdbd2cSJim Jagielski maTagToPropertyName[ nNewTag ] = i_rPropertyName; 176*b1cdbd2cSJim Jagielski maTagToValueInt[ nNewTag ] = i_nValue; 177*b1cdbd2cSJim Jagielski return nNewTag; 178*b1cdbd2cSJim Jagielski } 179*b1cdbd2cSJim Jagielski 180*b1cdbd2cSJim Jagielski void addObservedControl( NSObject* i_pView ) 181*b1cdbd2cSJim Jagielski { 182*b1cdbd2cSJim Jagielski maViews.push_back( i_pView ); 183*b1cdbd2cSJim Jagielski } 184*b1cdbd2cSJim Jagielski 185*b1cdbd2cSJim Jagielski void addViewPair( NSView* i_pLeft, NSView* i_pRight ) 186*b1cdbd2cSJim Jagielski { 187*b1cdbd2cSJim Jagielski maViewPairMap[ i_pLeft ] = i_pRight; 188*b1cdbd2cSJim Jagielski maViewPairMap[ i_pRight ] = i_pLeft; 189*b1cdbd2cSJim Jagielski } 190*b1cdbd2cSJim Jagielski 191*b1cdbd2cSJim Jagielski NSView* getPair( NSView* i_pLeft ) const 192*b1cdbd2cSJim Jagielski { 193*b1cdbd2cSJim Jagielski NSView* pRight = nil; 194*b1cdbd2cSJim Jagielski std::map< NSView*, NSView* >::const_iterator it = maViewPairMap.find( i_pLeft ); 195*b1cdbd2cSJim Jagielski if( it != maViewPairMap.end() ) 196*b1cdbd2cSJim Jagielski pRight = it->second; 197*b1cdbd2cSJim Jagielski return pRight; 198*b1cdbd2cSJim Jagielski } 199*b1cdbd2cSJim Jagielski 200*b1cdbd2cSJim Jagielski void changePropertyWithIntValue( int i_nTag ) 201*b1cdbd2cSJim Jagielski { 202*b1cdbd2cSJim Jagielski std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); 203*b1cdbd2cSJim Jagielski std::map< int, sal_Int32 >::const_iterator value_it = maTagToValueInt.find( i_nTag ); 204*b1cdbd2cSJim Jagielski if( name_it != maTagToPropertyName.end() && value_it != maTagToValueInt.end() ) 205*b1cdbd2cSJim Jagielski { 206*b1cdbd2cSJim Jagielski PropertyValue* pVal = mpController->getValue( name_it->second ); 207*b1cdbd2cSJim Jagielski if( pVal ) 208*b1cdbd2cSJim Jagielski { 209*b1cdbd2cSJim Jagielski pVal->Value <<= value_it->second; 210*b1cdbd2cSJim Jagielski updatePrintJob(); 211*b1cdbd2cSJim Jagielski } 212*b1cdbd2cSJim Jagielski } 213*b1cdbd2cSJim Jagielski } 214*b1cdbd2cSJim Jagielski 215*b1cdbd2cSJim Jagielski void changePropertyWithIntValue( int i_nTag, sal_Int64 i_nValue ) 216*b1cdbd2cSJim Jagielski { 217*b1cdbd2cSJim Jagielski std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); 218*b1cdbd2cSJim Jagielski if( name_it != maTagToPropertyName.end() ) 219*b1cdbd2cSJim Jagielski { 220*b1cdbd2cSJim Jagielski PropertyValue* pVal = mpController->getValue( name_it->second ); 221*b1cdbd2cSJim Jagielski if( pVal ) 222*b1cdbd2cSJim Jagielski { 223*b1cdbd2cSJim Jagielski pVal->Value <<= i_nValue; 224*b1cdbd2cSJim Jagielski updatePrintJob(); 225*b1cdbd2cSJim Jagielski } 226*b1cdbd2cSJim Jagielski } 227*b1cdbd2cSJim Jagielski } 228*b1cdbd2cSJim Jagielski 229*b1cdbd2cSJim Jagielski void changePropertyWithBoolValue( int i_nTag, sal_Bool i_bValue ) 230*b1cdbd2cSJim Jagielski { 231*b1cdbd2cSJim Jagielski std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); 232*b1cdbd2cSJim Jagielski if( name_it != maTagToPropertyName.end() ) 233*b1cdbd2cSJim Jagielski { 234*b1cdbd2cSJim Jagielski PropertyValue* pVal = mpController->getValue( name_it->second ); 235*b1cdbd2cSJim Jagielski if( pVal ) 236*b1cdbd2cSJim Jagielski { 237*b1cdbd2cSJim Jagielski // ugly 238*b1cdbd2cSJim Jagielski if( name_it->second.equalsAscii( "PrintContent" ) ) 239*b1cdbd2cSJim Jagielski pVal->Value <<= i_bValue ? sal_Int32(2) : sal_Int32(0); 240*b1cdbd2cSJim Jagielski else 241*b1cdbd2cSJim Jagielski pVal->Value <<= i_bValue; 242*b1cdbd2cSJim Jagielski updatePrintJob(); 243*b1cdbd2cSJim Jagielski } 244*b1cdbd2cSJim Jagielski } 245*b1cdbd2cSJim Jagielski } 246*b1cdbd2cSJim Jagielski 247*b1cdbd2cSJim Jagielski void changePropertyWithStringValue( int i_nTag, const rtl::OUString& i_rValue ) 248*b1cdbd2cSJim Jagielski { 249*b1cdbd2cSJim Jagielski std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); 250*b1cdbd2cSJim Jagielski if( name_it != maTagToPropertyName.end() ) 251*b1cdbd2cSJim Jagielski { 252*b1cdbd2cSJim Jagielski PropertyValue* pVal = mpController->getValue( name_it->second ); 253*b1cdbd2cSJim Jagielski if( pVal ) 254*b1cdbd2cSJim Jagielski { 255*b1cdbd2cSJim Jagielski pVal->Value <<= i_rValue; 256*b1cdbd2cSJim Jagielski updatePrintJob(); 257*b1cdbd2cSJim Jagielski } 258*b1cdbd2cSJim Jagielski } 259*b1cdbd2cSJim Jagielski } 260*b1cdbd2cSJim Jagielski 261*b1cdbd2cSJim Jagielski void updateEnableState() 262*b1cdbd2cSJim Jagielski { 263*b1cdbd2cSJim Jagielski for( std::vector< NSObject* >::iterator it = maViews.begin(); it != maViews.end(); ++it ) 264*b1cdbd2cSJim Jagielski { 265*b1cdbd2cSJim Jagielski NSObject* pObj = *it; 266*b1cdbd2cSJim Jagielski NSControl* pCtrl = nil; 267*b1cdbd2cSJim Jagielski NSCell* pCell = nil; 268*b1cdbd2cSJim Jagielski if( [pObj isKindOfClass: [NSControl class]] ) 269*b1cdbd2cSJim Jagielski pCtrl = (NSControl*)pObj; 270*b1cdbd2cSJim Jagielski else if( [pObj isKindOfClass: [NSCell class]] ) 271*b1cdbd2cSJim Jagielski pCell = (NSCell*)pObj; 272*b1cdbd2cSJim Jagielski 273*b1cdbd2cSJim Jagielski int nTag = pCtrl ? [pCtrl tag] : 274*b1cdbd2cSJim Jagielski pCell ? [pCell tag] : 275*b1cdbd2cSJim Jagielski -1; 276*b1cdbd2cSJim Jagielski 277*b1cdbd2cSJim Jagielski std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( nTag ); 278*b1cdbd2cSJim Jagielski if( name_it != maTagToPropertyName.end() && ! name_it->second.equalsAscii( "PrintContent" ) ) 279*b1cdbd2cSJim Jagielski { 280*b1cdbd2cSJim Jagielski BOOL bEnabled = mpController->isUIOptionEnabled( name_it->second ) ? YES : NO; 281*b1cdbd2cSJim Jagielski if( pCtrl ) 282*b1cdbd2cSJim Jagielski { 283*b1cdbd2cSJim Jagielski [pCtrl setEnabled: bEnabled]; 284*b1cdbd2cSJim Jagielski NSView* pOther = getPair( pCtrl ); 285*b1cdbd2cSJim Jagielski if( pOther && [pOther isKindOfClass: [NSControl class]] ) 286*b1cdbd2cSJim Jagielski [(NSControl*)pOther setEnabled: bEnabled]; 287*b1cdbd2cSJim Jagielski } 288*b1cdbd2cSJim Jagielski else if( pCell ) 289*b1cdbd2cSJim Jagielski [pCell setEnabled: bEnabled]; 290*b1cdbd2cSJim Jagielski 291*b1cdbd2cSJim Jagielski } 292*b1cdbd2cSJim Jagielski } 293*b1cdbd2cSJim Jagielski } 294*b1cdbd2cSJim Jagielski 295*b1cdbd2cSJim Jagielski void updatePreviewImage( sal_Int32 i_nPage ) 296*b1cdbd2cSJim Jagielski { 297*b1cdbd2cSJim Jagielski sal_Int32 nPages = mpController->getFilteredPageCount(); 298*b1cdbd2cSJim Jagielski NSRect aViewFrame = [mpPreview frame]; 299*b1cdbd2cSJim Jagielski Size aPixelSize( static_cast<long>(aViewFrame.size.width), 300*b1cdbd2cSJim Jagielski static_cast<long>(aViewFrame.size.height) ); 301*b1cdbd2cSJim Jagielski if( i_nPage >= 0 && nPages > i_nPage ) 302*b1cdbd2cSJim Jagielski { 303*b1cdbd2cSJim Jagielski GDIMetaFile aMtf; 304*b1cdbd2cSJim Jagielski PrinterController::PageSize aPageSize( mpController->getFilteredPageFile( i_nPage, aMtf, false ) ); 305*b1cdbd2cSJim Jagielski VirtualDevice aDev; 306*b1cdbd2cSJim Jagielski if( mpController->getPrinter()->GetPrinterOptions().IsConvertToGreyscales() ) 307*b1cdbd2cSJim Jagielski aDev.SetDrawMode( aDev.GetDrawMode() | ( DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL | DRAWMODE_GRAYTEXT | 308*b1cdbd2cSJim Jagielski DRAWMODE_GRAYBITMAP | DRAWMODE_GRAYGRADIENT ) ); 309*b1cdbd2cSJim Jagielski // see salprn.cxx, currently we pretend to be a 720dpi device on printers 310*b1cdbd2cSJim Jagielski aDev.SetReferenceDevice( 720, 720 ); 311*b1cdbd2cSJim Jagielski aDev.EnableOutput( TRUE ); 312*b1cdbd2cSJim Jagielski Size aLogicSize( aDev.PixelToLogic( aPixelSize, MapMode( MAP_100TH_MM ) ) ); 313*b1cdbd2cSJim Jagielski double fScaleX = double(aLogicSize.Width())/double(aPageSize.aSize.Width()); 314*b1cdbd2cSJim Jagielski double fScaleY = double(aLogicSize.Height())/double(aPageSize.aSize.Height()); 315*b1cdbd2cSJim Jagielski double fScale = (fScaleX < fScaleY) ? fScaleX : fScaleY; 316*b1cdbd2cSJim Jagielski // #i104784# if we render the page too small then rounding issues result in 317*b1cdbd2cSJim Jagielski // layout artifacts looking really bad. So scale the page unto a device that is not 318*b1cdbd2cSJim Jagielski // full page size but not too small either. This also results in much better visual 319*b1cdbd2cSJim Jagielski // quality of the preview, e.g. when its height approaches the number of text lines 320*b1cdbd2cSJim Jagielski if( fScale < 0.1 ) 321*b1cdbd2cSJim Jagielski fScale = 0.1; 322*b1cdbd2cSJim Jagielski aMtf.WindStart(); 323*b1cdbd2cSJim Jagielski aMtf.Scale( fScale, fScale ); 324*b1cdbd2cSJim Jagielski aMtf.WindStart(); 325*b1cdbd2cSJim Jagielski aLogicSize.Width() = long(double(aPageSize.aSize.Width()) * fScale); 326*b1cdbd2cSJim Jagielski aLogicSize.Height() = long(double(aPageSize.aSize.Height()) * fScale); 327*b1cdbd2cSJim Jagielski aPixelSize = aDev.LogicToPixel( aLogicSize, MapMode( MAP_100TH_MM ) ); 328*b1cdbd2cSJim Jagielski aDev.SetOutputSizePixel( aPixelSize ); 329*b1cdbd2cSJim Jagielski aMtf.WindStart(); 330*b1cdbd2cSJim Jagielski aDev.SetMapMode( MapMode( MAP_100TH_MM ) ); 331*b1cdbd2cSJim Jagielski aMtf.Play( &aDev, Point( 0, 0 ), aLogicSize ); 332*b1cdbd2cSJim Jagielski aDev.EnableMapMode( FALSE ); 333*b1cdbd2cSJim Jagielski Image aImage( aDev.GetBitmap( Point( 0, 0 ), aPixelSize ) ); 334*b1cdbd2cSJim Jagielski NSImage* pImage = CreateNSImage( aImage ); 335*b1cdbd2cSJim Jagielski [mpPreview setImage: [pImage autorelease]]; 336*b1cdbd2cSJim Jagielski } 337*b1cdbd2cSJim Jagielski else 338*b1cdbd2cSJim Jagielski [mpPreview setImage: nil]; 339*b1cdbd2cSJim Jagielski } 340*b1cdbd2cSJim Jagielski 341*b1cdbd2cSJim Jagielski void setupPreview( ControlTarget* i_pCtrlTarget ) 342*b1cdbd2cSJim Jagielski { 343*b1cdbd2cSJim Jagielski if( maLocalizedStrings.Count() < 3 ) 344*b1cdbd2cSJim Jagielski return; 345*b1cdbd2cSJim Jagielski 346*b1cdbd2cSJim Jagielski // get the preview control 347*b1cdbd2cSJim Jagielski NSRect aPreviewFrame = [mpAccessoryView frame]; 348*b1cdbd2cSJim Jagielski aPreviewFrame.origin.x = 0; 349*b1cdbd2cSJim Jagielski aPreviewFrame.origin.y = 5; 350*b1cdbd2cSJim Jagielski aPreviewFrame.size.width = 190; 351*b1cdbd2cSJim Jagielski aPreviewFrame.size.height -= 7; 352*b1cdbd2cSJim Jagielski 353*b1cdbd2cSJim Jagielski // create a box to put the preview controls in 354*b1cdbd2cSJim Jagielski mpPreviewBox = [[NSBox alloc] initWithFrame: aPreviewFrame]; 355*b1cdbd2cSJim Jagielski [mpPreviewBox setTitle: [CreateNSString( maLocalizedStrings.GetString( 0 ) ) autorelease]]; 356*b1cdbd2cSJim Jagielski [mpAccessoryView addSubview: [mpPreviewBox autorelease]]; 357*b1cdbd2cSJim Jagielski 358*b1cdbd2cSJim Jagielski // now create the image view of the preview 359*b1cdbd2cSJim Jagielski NSSize aMargins = [mpPreviewBox contentViewMargins]; 360*b1cdbd2cSJim Jagielski aPreviewFrame.origin.x = 0; 361*b1cdbd2cSJim Jagielski aPreviewFrame.origin.y = 34; 362*b1cdbd2cSJim Jagielski aPreviewFrame.size.width -= 2*(aMargins.width+1); 363*b1cdbd2cSJim Jagielski aPreviewFrame.size.height -= 61; 364*b1cdbd2cSJim Jagielski mpPreview = [[NSImageView alloc] initWithFrame: aPreviewFrame]; 365*b1cdbd2cSJim Jagielski [mpPreview setImageScaling: NSScaleProportionally]; 366*b1cdbd2cSJim Jagielski [mpPreview setImageAlignment: NSImageAlignCenter]; 367*b1cdbd2cSJim Jagielski [mpPreview setImageFrameStyle: NSImageFrameNone]; 368*b1cdbd2cSJim Jagielski [mpPreviewBox addSubview: [mpPreview autorelease]]; 369*b1cdbd2cSJim Jagielski 370*b1cdbd2cSJim Jagielski // add a label 371*b1cdbd2cSJim Jagielski sal_Int32 nPages = mpController->getFilteredPageCount(); 372*b1cdbd2cSJim Jagielski rtl::OUStringBuffer aBuf( 16 ); 373*b1cdbd2cSJim Jagielski aBuf.appendAscii( "/ " ); 374*b1cdbd2cSJim Jagielski aBuf.append( rtl::OUString::valueOf( nPages ) ); 375*b1cdbd2cSJim Jagielski 376*b1cdbd2cSJim Jagielski NSString* pText = CreateNSString( aBuf.makeStringAndClear() ); 377*b1cdbd2cSJim Jagielski NSRect aTextRect = { { 100, 5 }, { 100, 22 } }; 378*b1cdbd2cSJim Jagielski mpPagesLabel = [[NSTextView alloc] initWithFrame: aTextRect]; 379*b1cdbd2cSJim Jagielski [mpPagesLabel setFont: [NSFont controlContentFontOfSize: 0]]; 380*b1cdbd2cSJim Jagielski [mpPagesLabel setEditable: NO]; 381*b1cdbd2cSJim Jagielski [mpPagesLabel setSelectable: NO]; 382*b1cdbd2cSJim Jagielski [mpPagesLabel setDrawsBackground: NO]; 383*b1cdbd2cSJim Jagielski [mpPagesLabel setString: [pText autorelease]]; 384*b1cdbd2cSJim Jagielski [mpPagesLabel setToolTip: [CreateNSString( maLocalizedStrings.GetString( 2 ) ) autorelease]]; 385*b1cdbd2cSJim Jagielski [mpPreviewBox addSubview: [mpPagesLabel autorelease]]; 386*b1cdbd2cSJim Jagielski 387*b1cdbd2cSJim Jagielski NSRect aFieldRect = { { 45, 5 }, { 35, 25 } }; 388*b1cdbd2cSJim Jagielski mpPageEdit = [[NSTextField alloc] initWithFrame: aFieldRect]; 389*b1cdbd2cSJim Jagielski [mpPageEdit setEditable: YES]; 390*b1cdbd2cSJim Jagielski [mpPageEdit setSelectable: YES]; 391*b1cdbd2cSJim Jagielski [mpPageEdit setDrawsBackground: YES]; 392*b1cdbd2cSJim Jagielski [mpPageEdit setToolTip: [CreateNSString( maLocalizedStrings.GetString( 1 ) ) autorelease]]; 393*b1cdbd2cSJim Jagielski [mpPreviewBox addSubview: [mpPageEdit autorelease]]; 394*b1cdbd2cSJim Jagielski 395*b1cdbd2cSJim Jagielski // add a stepper control 396*b1cdbd2cSJim Jagielski NSRect aStepFrame = { { 85, 5 }, { 15, 25 } }; 397*b1cdbd2cSJim Jagielski mpStepper = [[NSStepper alloc] initWithFrame: aStepFrame]; 398*b1cdbd2cSJim Jagielski [mpStepper setIncrement: 1]; 399*b1cdbd2cSJim Jagielski [mpStepper setValueWraps: NO]; 400*b1cdbd2cSJim Jagielski [mpPreviewBox addSubview: [mpStepper autorelease]]; 401*b1cdbd2cSJim Jagielski 402*b1cdbd2cSJim Jagielski // constrain the text field to decimal numbers 403*b1cdbd2cSJim Jagielski NSNumberFormatter* pFormatter = [[NSNumberFormatter alloc] init]; 404*b1cdbd2cSJim Jagielski [pFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4]; 405*b1cdbd2cSJim Jagielski [pFormatter setMinimum: [[NSNumber numberWithInt: 1] autorelease]]; 406*b1cdbd2cSJim Jagielski [pFormatter setMaximum: [[NSNumber numberWithInt: nPages] autorelease]]; 407*b1cdbd2cSJim Jagielski [pFormatter setNumberStyle: NSNumberFormatterDecimalStyle]; 408*b1cdbd2cSJim Jagielski [pFormatter setAllowsFloats: NO]; 409*b1cdbd2cSJim Jagielski [pFormatter setMaximumFractionDigits: 0]; 410*b1cdbd2cSJim Jagielski [mpPageEdit setFormatter: pFormatter]; 411*b1cdbd2cSJim Jagielski [mpStepper setMinValue: 1]; 412*b1cdbd2cSJim Jagielski [mpStepper setMaxValue: nPages]; 413*b1cdbd2cSJim Jagielski 414*b1cdbd2cSJim Jagielski [mpPageEdit setIntValue: 1]; 415*b1cdbd2cSJim Jagielski [mpStepper setIntValue: 1]; 416*b1cdbd2cSJim Jagielski 417*b1cdbd2cSJim Jagielski // connect target and action 418*b1cdbd2cSJim Jagielski [mpStepper setTarget: i_pCtrlTarget]; 419*b1cdbd2cSJim Jagielski [mpStepper setAction: @selector(triggeredPreview:)]; 420*b1cdbd2cSJim Jagielski [mpPageEdit setTarget: i_pCtrlTarget]; 421*b1cdbd2cSJim Jagielski [mpPageEdit setAction: @selector(triggeredPreview:)]; 422*b1cdbd2cSJim Jagielski 423*b1cdbd2cSJim Jagielski // set first preview image 424*b1cdbd2cSJim Jagielski updatePreviewImage( 0 ); 425*b1cdbd2cSJim Jagielski } 426*b1cdbd2cSJim Jagielski 427*b1cdbd2cSJim Jagielski void changePreview( NSObject* i_pSender ) 428*b1cdbd2cSJim Jagielski { 429*b1cdbd2cSJim Jagielski if( [i_pSender isMemberOfClass: [NSTextField class]] ) 430*b1cdbd2cSJim Jagielski { 431*b1cdbd2cSJim Jagielski NSTextField* pField = (NSTextField*)i_pSender; 432*b1cdbd2cSJim Jagielski if( pField == mpPageEdit ) // sanity check 433*b1cdbd2cSJim Jagielski { 434*b1cdbd2cSJim Jagielski sal_Int32 nPage = [pField intValue]; 435*b1cdbd2cSJim Jagielski [mpStepper setIntValue: nPage]; 436*b1cdbd2cSJim Jagielski updatePreviewImage( nPage-1 ); 437*b1cdbd2cSJim Jagielski } 438*b1cdbd2cSJim Jagielski } 439*b1cdbd2cSJim Jagielski else if( [i_pSender isMemberOfClass: [NSStepper class]] ) 440*b1cdbd2cSJim Jagielski { 441*b1cdbd2cSJim Jagielski NSStepper* pStepper = (NSStepper*)i_pSender; 442*b1cdbd2cSJim Jagielski if( pStepper == mpStepper ) // sanity check 443*b1cdbd2cSJim Jagielski { 444*b1cdbd2cSJim Jagielski sal_Int32 nPage = [pStepper intValue]; 445*b1cdbd2cSJim Jagielski [mpPageEdit setIntValue: nPage]; 446*b1cdbd2cSJim Jagielski updatePreviewImage( nPage-1 ); 447*b1cdbd2cSJim Jagielski } 448*b1cdbd2cSJim Jagielski } 449*b1cdbd2cSJim Jagielski } 450*b1cdbd2cSJim Jagielski}; 451*b1cdbd2cSJim Jagielski 452*b1cdbd2cSJim Jagielskistatic void filterAccelerator( rtl::OUString& io_rText ) 453*b1cdbd2cSJim Jagielski{ 454*b1cdbd2cSJim Jagielski rtl::OUStringBuffer aBuf( io_rText.getLength() ); 455*b1cdbd2cSJim Jagielski for( sal_Int32 nIndex = 0; nIndex != -1; ) 456*b1cdbd2cSJim Jagielski aBuf.append( io_rText.getToken( 0, '~', nIndex ) ); 457*b1cdbd2cSJim Jagielski io_rText = aBuf.makeStringAndClear(); 458*b1cdbd2cSJim Jagielski} 459*b1cdbd2cSJim Jagielski 460*b1cdbd2cSJim Jagielski@implementation ControlTarget 461*b1cdbd2cSJim Jagielski-(id)initWithControllerMap: (ControllerProperties*)pController 462*b1cdbd2cSJim Jagielski{ 463*b1cdbd2cSJim Jagielski if( (self = [super init]) ) 464*b1cdbd2cSJim Jagielski { 465*b1cdbd2cSJim Jagielski mpController = pController; 466*b1cdbd2cSJim Jagielski } 467*b1cdbd2cSJim Jagielski return self; 468*b1cdbd2cSJim Jagielski} 469*b1cdbd2cSJim Jagielski-(void)triggered:(id)pSender 470*b1cdbd2cSJim Jagielski{ 471*b1cdbd2cSJim Jagielski if( [pSender isMemberOfClass: [NSPopUpButton class]] ) 472*b1cdbd2cSJim Jagielski { 473*b1cdbd2cSJim Jagielski NSPopUpButton* pBtn = (NSPopUpButton*)pSender; 474*b1cdbd2cSJim Jagielski NSMenuItem* pSelected = [pBtn selectedItem]; 475*b1cdbd2cSJim Jagielski if( pSelected ) 476*b1cdbd2cSJim Jagielski { 477*b1cdbd2cSJim Jagielski int nTag = [pSelected tag]; 478*b1cdbd2cSJim Jagielski mpController->changePropertyWithIntValue( nTag ); 479*b1cdbd2cSJim Jagielski } 480*b1cdbd2cSJim Jagielski } 481*b1cdbd2cSJim Jagielski else if( [pSender isMemberOfClass: [NSButton class]] ) 482*b1cdbd2cSJim Jagielski { 483*b1cdbd2cSJim Jagielski NSButton* pBtn = (NSButton*)pSender; 484*b1cdbd2cSJim Jagielski int nTag = [pBtn tag]; 485*b1cdbd2cSJim Jagielski mpController->changePropertyWithBoolValue( nTag, [pBtn state] == NSOnState ); 486*b1cdbd2cSJim Jagielski } 487*b1cdbd2cSJim Jagielski else if( [pSender isMemberOfClass: [NSMatrix class]] ) 488*b1cdbd2cSJim Jagielski { 489*b1cdbd2cSJim Jagielski NSObject* pObj = [(NSMatrix*)pSender selectedCell]; 490*b1cdbd2cSJim Jagielski if( [pObj isMemberOfClass: [NSButtonCell class]] ) 491*b1cdbd2cSJim Jagielski { 492*b1cdbd2cSJim Jagielski NSButtonCell* pCell = (NSButtonCell*)pObj; 493*b1cdbd2cSJim Jagielski int nTag = [pCell tag]; 494*b1cdbd2cSJim Jagielski mpController->changePropertyWithIntValue( nTag ); 495*b1cdbd2cSJim Jagielski } 496*b1cdbd2cSJim Jagielski } 497*b1cdbd2cSJim Jagielski else if( [pSender isMemberOfClass: [NSTextField class]] ) 498*b1cdbd2cSJim Jagielski { 499*b1cdbd2cSJim Jagielski NSTextField* pField = (NSTextField*)pSender; 500*b1cdbd2cSJim Jagielski int nTag = [pField tag]; 501*b1cdbd2cSJim Jagielski rtl::OUString aValue = GetOUString( [pSender stringValue] ); 502*b1cdbd2cSJim Jagielski mpController->changePropertyWithStringValue( nTag, aValue ); 503*b1cdbd2cSJim Jagielski } 504*b1cdbd2cSJim Jagielski else 505*b1cdbd2cSJim Jagielski { 506*b1cdbd2cSJim Jagielski DBG_ERROR( "unsupported class" ); 507*b1cdbd2cSJim Jagielski } 508*b1cdbd2cSJim Jagielski mpController->updateEnableState(); 509*b1cdbd2cSJim Jagielski} 510*b1cdbd2cSJim Jagielski-(void)triggeredNumeric:(id)pSender 511*b1cdbd2cSJim Jagielski{ 512*b1cdbd2cSJim Jagielski if( [pSender isMemberOfClass: [NSTextField class]] ) 513*b1cdbd2cSJim Jagielski { 514*b1cdbd2cSJim Jagielski NSTextField* pField = (NSTextField*)pSender; 515*b1cdbd2cSJim Jagielski int nTag = [pField tag]; 516*b1cdbd2cSJim Jagielski sal_Int64 nValue = [pField intValue]; 517*b1cdbd2cSJim Jagielski 518*b1cdbd2cSJim Jagielski NSView* pOther = mpController->getPair( pField ); 519*b1cdbd2cSJim Jagielski if( pOther ) 520*b1cdbd2cSJim Jagielski [(NSControl*)pOther setIntValue: nValue]; 521*b1cdbd2cSJim Jagielski 522*b1cdbd2cSJim Jagielski mpController->changePropertyWithIntValue( nTag, nValue ); 523*b1cdbd2cSJim Jagielski } 524*b1cdbd2cSJim Jagielski else if( [pSender isMemberOfClass: [NSStepper class]] ) 525*b1cdbd2cSJim Jagielski { 526*b1cdbd2cSJim Jagielski NSStepper* pStep = (NSStepper*)pSender; 527*b1cdbd2cSJim Jagielski int nTag = [pStep tag]; 528*b1cdbd2cSJim Jagielski sal_Int64 nValue = [pStep intValue]; 529*b1cdbd2cSJim Jagielski 530*b1cdbd2cSJim Jagielski NSView* pOther = mpController->getPair( pStep ); 531*b1cdbd2cSJim Jagielski if( pOther ) 532*b1cdbd2cSJim Jagielski [(NSControl*)pOther setIntValue: nValue]; 533*b1cdbd2cSJim Jagielski 534*b1cdbd2cSJim Jagielski mpController->changePropertyWithIntValue( nTag, nValue ); 535*b1cdbd2cSJim Jagielski } 536*b1cdbd2cSJim Jagielski else 537*b1cdbd2cSJim Jagielski { 538*b1cdbd2cSJim Jagielski DBG_ERROR( "unsupported class" ); 539*b1cdbd2cSJim Jagielski } 540*b1cdbd2cSJim Jagielski mpController->updateEnableState(); 541*b1cdbd2cSJim Jagielski} 542*b1cdbd2cSJim Jagielski-(void)triggeredPreview:(id)pSender 543*b1cdbd2cSJim Jagielski{ 544*b1cdbd2cSJim Jagielski mpController->changePreview( pSender ); 545*b1cdbd2cSJim Jagielski} 546*b1cdbd2cSJim Jagielski-(void)dealloc 547*b1cdbd2cSJim Jagielski{ 548*b1cdbd2cSJim Jagielski delete mpController; 549*b1cdbd2cSJim Jagielski [super dealloc]; 550*b1cdbd2cSJim Jagielski} 551*b1cdbd2cSJim Jagielski@end 552*b1cdbd2cSJim Jagielski 553*b1cdbd2cSJim Jagielskistruct ColumnItem 554*b1cdbd2cSJim Jagielski{ 555*b1cdbd2cSJim Jagielski NSControl* pControl; 556*b1cdbd2cSJim Jagielski long nOffset; 557*b1cdbd2cSJim Jagielski NSControl* pSubControl; 558*b1cdbd2cSJim Jagielski 559*b1cdbd2cSJim Jagielski ColumnItem( NSControl* i_pControl = nil, long i_nOffset = 0, NSControl* i_pSub = nil ) 560*b1cdbd2cSJim Jagielski : pControl( i_pControl ) 561*b1cdbd2cSJim Jagielski , nOffset( i_nOffset ) 562*b1cdbd2cSJim Jagielski , pSubControl( i_pSub ) 563*b1cdbd2cSJim Jagielski {} 564*b1cdbd2cSJim Jagielski 565*b1cdbd2cSJim Jagielski long getWidth() const 566*b1cdbd2cSJim Jagielski { 567*b1cdbd2cSJim Jagielski long nWidth = 0; 568*b1cdbd2cSJim Jagielski if( pControl ) 569*b1cdbd2cSJim Jagielski { 570*b1cdbd2cSJim Jagielski NSRect aCtrlRect = [pControl frame]; 571*b1cdbd2cSJim Jagielski nWidth = aCtrlRect.size.width; 572*b1cdbd2cSJim Jagielski nWidth += nOffset; 573*b1cdbd2cSJim Jagielski if( pSubControl ) 574*b1cdbd2cSJim Jagielski { 575*b1cdbd2cSJim Jagielski NSRect aSubRect = [pSubControl frame]; 576*b1cdbd2cSJim Jagielski nWidth += aSubRect.size.width; 577*b1cdbd2cSJim Jagielski nWidth += aSubRect.origin.x - (aCtrlRect.origin.x + aCtrlRect.size.width); 578*b1cdbd2cSJim Jagielski } 579*b1cdbd2cSJim Jagielski } 580*b1cdbd2cSJim Jagielski return nWidth; 581*b1cdbd2cSJim Jagielski } 582*b1cdbd2cSJim Jagielski}; 583*b1cdbd2cSJim Jagielski 584*b1cdbd2cSJim Jagielskistatic void adjustViewAndChildren( NSView* pNSView, NSSize& rMaxSize, 585*b1cdbd2cSJim Jagielski std::vector< ColumnItem >& rLeftColumn, 586*b1cdbd2cSJim Jagielski std::vector< ColumnItem >& rRightColumn 587*b1cdbd2cSJim Jagielski ) 588*b1cdbd2cSJim Jagielski{ 589*b1cdbd2cSJim Jagielski // balance columns 590*b1cdbd2cSJim Jagielski 591*b1cdbd2cSJim Jagielski // first get overall column widths 592*b1cdbd2cSJim Jagielski long nLeftWidth = 0; 593*b1cdbd2cSJim Jagielski long nRightWidth = 0; 594*b1cdbd2cSJim Jagielski for( size_t i = 0; i < rLeftColumn.size(); i++ ) 595*b1cdbd2cSJim Jagielski { 596*b1cdbd2cSJim Jagielski long nW = rLeftColumn[i].getWidth(); 597*b1cdbd2cSJim Jagielski if( nW > nLeftWidth ) 598*b1cdbd2cSJim Jagielski nLeftWidth = nW; 599*b1cdbd2cSJim Jagielski } 600*b1cdbd2cSJim Jagielski for( size_t i = 0; i < rRightColumn.size(); i++ ) 601*b1cdbd2cSJim Jagielski { 602*b1cdbd2cSJim Jagielski long nW = rRightColumn[i].getWidth(); 603*b1cdbd2cSJim Jagielski if( nW > nRightWidth ) 604*b1cdbd2cSJim Jagielski nRightWidth = nW; 605*b1cdbd2cSJim Jagielski } 606*b1cdbd2cSJim Jagielski 607*b1cdbd2cSJim Jagielski // right align left column 608*b1cdbd2cSJim Jagielski for( size_t i = 0; i < rLeftColumn.size(); i++ ) 609*b1cdbd2cSJim Jagielski { 610*b1cdbd2cSJim Jagielski if( rLeftColumn[i].pControl ) 611*b1cdbd2cSJim Jagielski { 612*b1cdbd2cSJim Jagielski NSRect aCtrlRect = [rLeftColumn[i].pControl frame]; 613*b1cdbd2cSJim Jagielski long nX = nLeftWidth - aCtrlRect.size.width; 614*b1cdbd2cSJim Jagielski if( rLeftColumn[i].pSubControl ) 615*b1cdbd2cSJim Jagielski { 616*b1cdbd2cSJim Jagielski NSRect aSubRect = [rLeftColumn[i].pSubControl frame]; 617*b1cdbd2cSJim Jagielski nX -= aSubRect.size.width + (aSubRect.origin.x - (aCtrlRect.origin.x + aCtrlRect.size.width)); 618*b1cdbd2cSJim Jagielski aSubRect.origin.x = nLeftWidth - aSubRect.size.width; 619*b1cdbd2cSJim Jagielski [rLeftColumn[i].pSubControl setFrame: aSubRect]; 620*b1cdbd2cSJim Jagielski } 621*b1cdbd2cSJim Jagielski aCtrlRect.origin.x = nX; 622*b1cdbd2cSJim Jagielski [rLeftColumn[i].pControl setFrame: aCtrlRect]; 623*b1cdbd2cSJim Jagielski } 624*b1cdbd2cSJim Jagielski } 625*b1cdbd2cSJim Jagielski 626*b1cdbd2cSJim Jagielski // left align right column 627*b1cdbd2cSJim Jagielski for( size_t i = 0; i < rRightColumn.size(); i++ ) 628*b1cdbd2cSJim Jagielski { 629*b1cdbd2cSJim Jagielski if( rRightColumn[i].pControl ) 630*b1cdbd2cSJim Jagielski { 631*b1cdbd2cSJim Jagielski NSRect aCtrlRect = [rRightColumn[i].pControl frame]; 632*b1cdbd2cSJim Jagielski long nX = nLeftWidth + 3; 633*b1cdbd2cSJim Jagielski if( rRightColumn[i].pSubControl ) 634*b1cdbd2cSJim Jagielski { 635*b1cdbd2cSJim Jagielski NSRect aSubRect = [rRightColumn[i].pSubControl frame]; 636*b1cdbd2cSJim Jagielski aSubRect.origin.x = nX + aSubRect.origin.x - aCtrlRect.origin.x; 637*b1cdbd2cSJim Jagielski [rRightColumn[i].pSubControl setFrame: aSubRect]; 638*b1cdbd2cSJim Jagielski } 639*b1cdbd2cSJim Jagielski aCtrlRect.origin.x = nX; 640*b1cdbd2cSJim Jagielski [rRightColumn[i].pControl setFrame: aCtrlRect]; 641*b1cdbd2cSJim Jagielski } 642*b1cdbd2cSJim Jagielski } 643*b1cdbd2cSJim Jagielski 644*b1cdbd2cSJim Jagielski NSArray* pSubViews = [pNSView subviews]; 645*b1cdbd2cSJim Jagielski unsigned int nViews = [pSubViews count]; 646*b1cdbd2cSJim Jagielski NSRect aUnion = NSZeroRect; 647*b1cdbd2cSJim Jagielski 648*b1cdbd2cSJim Jagielski // get the combined frame of all subviews 649*b1cdbd2cSJim Jagielski for( unsigned int n = 0; n < nViews; n++ ) 650*b1cdbd2cSJim Jagielski { 651*b1cdbd2cSJim Jagielski aUnion = NSUnionRect( aUnion, [[pSubViews objectAtIndex: n] frame] ); 652*b1cdbd2cSJim Jagielski } 653*b1cdbd2cSJim Jagielski 654*b1cdbd2cSJim Jagielski // move everything so it will fit 655*b1cdbd2cSJim Jagielski for( unsigned int n = 0; n < nViews; n++ ) 656*b1cdbd2cSJim Jagielski { 657*b1cdbd2cSJim Jagielski NSView* pCurSubView = [pSubViews objectAtIndex: n]; 658*b1cdbd2cSJim Jagielski NSRect aFrame = [pCurSubView frame]; 659*b1cdbd2cSJim Jagielski aFrame.origin.x -= aUnion.origin.x - 5; 660*b1cdbd2cSJim Jagielski aFrame.origin.y -= aUnion.origin.y - 5; 661*b1cdbd2cSJim Jagielski [pCurSubView setFrame: aFrame]; 662*b1cdbd2cSJim Jagielski } 663*b1cdbd2cSJim Jagielski 664*b1cdbd2cSJim Jagielski // resize the view itself 665*b1cdbd2cSJim Jagielski aUnion.size.height += 10; 666*b1cdbd2cSJim Jagielski aUnion.size.width += 20; 667*b1cdbd2cSJim Jagielski [pNSView setFrameSize: aUnion.size]; 668*b1cdbd2cSJim Jagielski 669*b1cdbd2cSJim Jagielski if( aUnion.size.width > rMaxSize.width ) 670*b1cdbd2cSJim Jagielski rMaxSize.width = aUnion.size.width; 671*b1cdbd2cSJim Jagielski if( aUnion.size.height > rMaxSize.height ) 672*b1cdbd2cSJim Jagielski rMaxSize.height = aUnion.size.height; 673*b1cdbd2cSJim Jagielski} 674*b1cdbd2cSJim Jagielski 675*b1cdbd2cSJim Jagielskistatic void adjustTabViews( NSTabView* pTabView, NSSize aTabSize ) 676*b1cdbd2cSJim Jagielski{ 677*b1cdbd2cSJim Jagielski // loop over all contained tab pages 678*b1cdbd2cSJim Jagielski NSArray* pTabbedViews = [pTabView tabViewItems]; 679*b1cdbd2cSJim Jagielski int nViews = [pTabbedViews count]; 680*b1cdbd2cSJim Jagielski for( int i = 0; i < nViews; i++ ) 681*b1cdbd2cSJim Jagielski { 682*b1cdbd2cSJim Jagielski NSTabViewItem* pItem = (NSTabViewItem*)[pTabbedViews objectAtIndex: i]; 683*b1cdbd2cSJim Jagielski NSView* pNSView = [pItem view]; 684*b1cdbd2cSJim Jagielski if( pNSView ) 685*b1cdbd2cSJim Jagielski { 686*b1cdbd2cSJim Jagielski NSRect aRect = [pNSView frame]; 687*b1cdbd2cSJim Jagielski double nDiff = aTabSize.height - aRect.size.height; 688*b1cdbd2cSJim Jagielski aRect.size = aTabSize; 689*b1cdbd2cSJim Jagielski [pNSView setFrame: aRect]; 690*b1cdbd2cSJim Jagielski 691*b1cdbd2cSJim Jagielski NSArray* pSubViews = [pNSView subviews]; 692*b1cdbd2cSJim Jagielski unsigned int nSubViews = [pSubViews count]; 693*b1cdbd2cSJim Jagielski 694*b1cdbd2cSJim Jagielski // move everything up 695*b1cdbd2cSJim Jagielski for( unsigned int n = 0; n < nSubViews; n++ ) 696*b1cdbd2cSJim Jagielski { 697*b1cdbd2cSJim Jagielski NSView* pCurSubView = [pSubViews objectAtIndex: n]; 698*b1cdbd2cSJim Jagielski NSRect aFrame = [pCurSubView frame]; 699*b1cdbd2cSJim Jagielski aFrame.origin.y += nDiff; 700*b1cdbd2cSJim Jagielski // give separators the correct width 701*b1cdbd2cSJim Jagielski // separators are currently the only NSBoxes we use 702*b1cdbd2cSJim Jagielski if( [pCurSubView isMemberOfClass: [NSBox class]] ) 703*b1cdbd2cSJim Jagielski { 704*b1cdbd2cSJim Jagielski aFrame.size.width = aTabSize.width - aFrame.origin.x - 10; 705*b1cdbd2cSJim Jagielski } 706*b1cdbd2cSJim Jagielski [pCurSubView setFrame: aFrame]; 707*b1cdbd2cSJim Jagielski } 708*b1cdbd2cSJim Jagielski } 709*b1cdbd2cSJim Jagielski } 710*b1cdbd2cSJim Jagielski} 711*b1cdbd2cSJim Jagielski 712*b1cdbd2cSJim Jagielskistatic NSControl* createLabel( const rtl::OUString& i_rText ) 713*b1cdbd2cSJim Jagielski{ 714*b1cdbd2cSJim Jagielski NSString* pText = CreateNSString( i_rText ); 715*b1cdbd2cSJim Jagielski NSRect aTextRect = { NSZeroPoint, {20, 15} }; 716*b1cdbd2cSJim Jagielski NSTextField* pTextView = [[NSTextField alloc] initWithFrame: aTextRect]; 717*b1cdbd2cSJim Jagielski [pTextView setFont: [NSFont controlContentFontOfSize: 0]]; 718*b1cdbd2cSJim Jagielski [pTextView setEditable: NO]; 719*b1cdbd2cSJim Jagielski [pTextView setSelectable: NO]; 720*b1cdbd2cSJim Jagielski [pTextView setDrawsBackground: NO]; 721*b1cdbd2cSJim Jagielski [pTextView setBordered: NO]; 722*b1cdbd2cSJim Jagielski [pTextView setStringValue: pText]; 723*b1cdbd2cSJim Jagielski [pTextView sizeToFit]; 724*b1cdbd2cSJim Jagielski [pText release]; 725*b1cdbd2cSJim Jagielski return pTextView; 726*b1cdbd2cSJim Jagielski} 727*b1cdbd2cSJim Jagielski 728*b1cdbd2cSJim Jagielskistatic sal_Int32 findBreak( const rtl::OUString& i_rText, sal_Int32 i_nPos ) 729*b1cdbd2cSJim Jagielski{ 730*b1cdbd2cSJim Jagielski sal_Int32 nRet = i_rText.getLength(); 731*b1cdbd2cSJim Jagielski Reference< i18n::XBreakIterator > xBI( vcl::unohelper::CreateBreakIterator() ); 732*b1cdbd2cSJim Jagielski if( xBI.is() ) 733*b1cdbd2cSJim Jagielski { 734*b1cdbd2cSJim Jagielski i18n::Boundary aBoundary = xBI->getWordBoundary( i_rText, i_nPos, 735*b1cdbd2cSJim Jagielski Application::GetSettings().GetLocale(), 736*b1cdbd2cSJim Jagielski i18n::WordType::ANYWORD_IGNOREWHITESPACES, 737*b1cdbd2cSJim Jagielski sal_True ); 738*b1cdbd2cSJim Jagielski nRet = aBoundary.endPos; 739*b1cdbd2cSJim Jagielski } 740*b1cdbd2cSJim Jagielski return nRet; 741*b1cdbd2cSJim Jagielski} 742*b1cdbd2cSJim Jagielski 743*b1cdbd2cSJim Jagielskistatic void linebreakCell( NSCell* pBtn, const rtl::OUString& i_rText ) 744*b1cdbd2cSJim Jagielski{ 745*b1cdbd2cSJim Jagielski NSString* pText = CreateNSString( i_rText ); 746*b1cdbd2cSJim Jagielski [pBtn setTitle: pText]; 747*b1cdbd2cSJim Jagielski [pText release]; 748*b1cdbd2cSJim Jagielski NSSize aSize = [pBtn cellSize]; 749*b1cdbd2cSJim Jagielski if( aSize.width > 280 ) 750*b1cdbd2cSJim Jagielski { 751*b1cdbd2cSJim Jagielski // need two lines 752*b1cdbd2cSJim Jagielski sal_Int32 nLen = i_rText.getLength(); 753*b1cdbd2cSJim Jagielski sal_Int32 nIndex = nLen / 2; 754*b1cdbd2cSJim Jagielski nIndex = findBreak( i_rText, nIndex ); 755*b1cdbd2cSJim Jagielski if( nIndex < nLen ) 756*b1cdbd2cSJim Jagielski { 757*b1cdbd2cSJim Jagielski rtl::OUStringBuffer aBuf( i_rText ); 758*b1cdbd2cSJim Jagielski aBuf.setCharAt( nIndex, '\n' ); 759*b1cdbd2cSJim Jagielski pText = CreateNSString( aBuf.makeStringAndClear() ); 760*b1cdbd2cSJim Jagielski [pBtn setTitle: pText]; 761*b1cdbd2cSJim Jagielski [pText release]; 762*b1cdbd2cSJim Jagielski } 763*b1cdbd2cSJim Jagielski } 764*b1cdbd2cSJim Jagielski} 765*b1cdbd2cSJim Jagielski 766*b1cdbd2cSJim Jagielskistatic void addSubgroup( NSView* pCurParent, long& rCurY, const rtl::OUString& rText ) 767*b1cdbd2cSJim Jagielski{ 768*b1cdbd2cSJim Jagielski NSControl* pTextView = createLabel( rText ); 769*b1cdbd2cSJim Jagielski [pCurParent addSubview: [pTextView autorelease]]; 770*b1cdbd2cSJim Jagielski NSRect aTextRect = [pTextView frame]; 771*b1cdbd2cSJim Jagielski // move to nCurY 772*b1cdbd2cSJim Jagielski aTextRect.origin.y = rCurY - aTextRect.size.height; 773*b1cdbd2cSJim Jagielski [pTextView setFrame: aTextRect]; 774*b1cdbd2cSJim Jagielski 775*b1cdbd2cSJim Jagielski NSRect aSepRect = { { aTextRect.size.width + 1, aTextRect.origin.y }, { 100, 6 } }; 776*b1cdbd2cSJim Jagielski NSBox* pBox = [[NSBox alloc] initWithFrame: aSepRect]; 777*b1cdbd2cSJim Jagielski [pBox setBoxType: NSBoxSeparator]; 778*b1cdbd2cSJim Jagielski [pCurParent addSubview: [pBox autorelease]]; 779*b1cdbd2cSJim Jagielski 780*b1cdbd2cSJim Jagielski // update nCurY 781*b1cdbd2cSJim Jagielski rCurY = aTextRect.origin.y - 5; 782*b1cdbd2cSJim Jagielski} 783*b1cdbd2cSJim Jagielski 784*b1cdbd2cSJim Jagielskistatic void addBool( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset, 785*b1cdbd2cSJim Jagielski const rtl::OUString& rText, sal_Bool bEnabled, 786*b1cdbd2cSJim Jagielski const rtl::OUString& rProperty, sal_Bool bValue, 787*b1cdbd2cSJim Jagielski std::vector<ColumnItem >& rRightColumn, 788*b1cdbd2cSJim Jagielski ControllerProperties* pControllerProperties, 789*b1cdbd2cSJim Jagielski ControlTarget* pCtrlTarget 790*b1cdbd2cSJim Jagielski ) 791*b1cdbd2cSJim Jagielski{ 792*b1cdbd2cSJim Jagielski NSRect aCheckRect = NSMakeRect( rCurX + nAttachOffset, 0, 0, 15); 793*b1cdbd2cSJim Jagielski NSButton* pBtn = [[NSButton alloc] initWithFrame: aCheckRect]; 794*b1cdbd2cSJim Jagielski [pBtn setButtonType: NSSwitchButton]; 795*b1cdbd2cSJim Jagielski [pBtn setState: bValue ? NSOnState : NSOffState]; 796*b1cdbd2cSJim Jagielski if( ! bEnabled ) 797*b1cdbd2cSJim Jagielski [pBtn setEnabled: NO]; 798*b1cdbd2cSJim Jagielski linebreakCell( [pBtn cell], rText ); 799*b1cdbd2cSJim Jagielski [pBtn sizeToFit]; 800*b1cdbd2cSJim Jagielski 801*b1cdbd2cSJim Jagielski rRightColumn.push_back( ColumnItem( pBtn ) ); 802*b1cdbd2cSJim Jagielski 803*b1cdbd2cSJim Jagielski // connect target 804*b1cdbd2cSJim Jagielski [pBtn setTarget: pCtrlTarget]; 805*b1cdbd2cSJim Jagielski [pBtn setAction: @selector(triggered:)]; 806*b1cdbd2cSJim Jagielski int nTag = pControllerProperties->addNameTag( rProperty ); 807*b1cdbd2cSJim Jagielski pControllerProperties->addObservedControl( pBtn ); 808*b1cdbd2cSJim Jagielski [pBtn setTag: nTag]; 809*b1cdbd2cSJim Jagielski 810*b1cdbd2cSJim Jagielski aCheckRect = [pBtn frame]; 811*b1cdbd2cSJim Jagielski // #i115837# add a murphy factor; it can apparently occasionally happen 812*b1cdbd2cSJim Jagielski // that sizeToFit does not a perfect job and that the button linebreaks again 813*b1cdbd2cSJim Jagielski // if - and only if - there is already a '\n' contained in the text and the width 814*b1cdbd2cSJim Jagielski // is minimally of 815*b1cdbd2cSJim Jagielski aCheckRect.size.width += 1; 816*b1cdbd2cSJim Jagielski 817*b1cdbd2cSJim Jagielski // move to rCurY 818*b1cdbd2cSJim Jagielski aCheckRect.origin.y = rCurY - aCheckRect.size.height; 819*b1cdbd2cSJim Jagielski [pBtn setFrame: aCheckRect]; 820*b1cdbd2cSJim Jagielski 821*b1cdbd2cSJim Jagielski [pCurParent addSubview: [pBtn autorelease]]; 822*b1cdbd2cSJim Jagielski 823*b1cdbd2cSJim Jagielski // update rCurY 824*b1cdbd2cSJim Jagielski rCurY = aCheckRect.origin.y - 5; 825*b1cdbd2cSJim Jagielski} 826*b1cdbd2cSJim Jagielski 827*b1cdbd2cSJim Jagielskistatic void addRadio( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset, 828*b1cdbd2cSJim Jagielski const rtl::OUString& rText, 829*b1cdbd2cSJim Jagielski const rtl::OUString& rProperty, Sequence< rtl::OUString > rChoices, sal_Int32 nSelectValue, 830*b1cdbd2cSJim Jagielski std::vector<ColumnItem >& rLeftColumn, 831*b1cdbd2cSJim Jagielski std::vector<ColumnItem >& rRightColumn, 832*b1cdbd2cSJim Jagielski ControllerProperties* pControllerProperties, 833*b1cdbd2cSJim Jagielski ControlTarget* pCtrlTarget 834*b1cdbd2cSJim Jagielski ) 835*b1cdbd2cSJim Jagielski{ 836*b1cdbd2cSJim Jagielski sal_Int32 nOff = 0; 837*b1cdbd2cSJim Jagielski if( rText.getLength() ) 838*b1cdbd2cSJim Jagielski { 839*b1cdbd2cSJim Jagielski // add a label 840*b1cdbd2cSJim Jagielski NSControl* pTextView = createLabel( rText ); 841*b1cdbd2cSJim Jagielski NSRect aTextRect = [pTextView frame]; 842*b1cdbd2cSJim Jagielski aTextRect.origin.x = rCurX + nAttachOffset; 843*b1cdbd2cSJim Jagielski [pCurParent addSubview: [pTextView autorelease]]; 844*b1cdbd2cSJim Jagielski 845*b1cdbd2cSJim Jagielski rLeftColumn.push_back( ColumnItem( pTextView ) ); 846*b1cdbd2cSJim Jagielski 847*b1cdbd2cSJim Jagielski // move to nCurY 848*b1cdbd2cSJim Jagielski aTextRect.origin.y = rCurY - aTextRect.size.height; 849*b1cdbd2cSJim Jagielski [pTextView setFrame: aTextRect]; 850*b1cdbd2cSJim Jagielski 851*b1cdbd2cSJim Jagielski // update nCurY 852*b1cdbd2cSJim Jagielski rCurY = aTextRect.origin.y - 5; 853*b1cdbd2cSJim Jagielski 854*b1cdbd2cSJim Jagielski // indent the radio group relative to the text 855*b1cdbd2cSJim Jagielski // nOff = 20; 856*b1cdbd2cSJim Jagielski } 857*b1cdbd2cSJim Jagielski 858*b1cdbd2cSJim Jagielski // setup radio matrix 859*b1cdbd2cSJim Jagielski NSButtonCell* pProto = [[NSButtonCell alloc] init]; 860*b1cdbd2cSJim Jagielski 861*b1cdbd2cSJim Jagielski NSRect aRadioRect = NSMakeRect( rCurX + nOff, 0, 280 - rCurX, 5*rChoices.getLength()); 862*b1cdbd2cSJim Jagielski [pProto setTitle: @"RadioButtonGroup"]; 863*b1cdbd2cSJim Jagielski [pProto setButtonType: NSRadioButton]; 864*b1cdbd2cSJim Jagielski NSMatrix* pMatrix = [[NSMatrix alloc] initWithFrame: aRadioRect 865*b1cdbd2cSJim Jagielski mode: NSRadioModeMatrix 866*b1cdbd2cSJim Jagielski prototype: (NSCell*)pProto 867*b1cdbd2cSJim Jagielski numberOfRows: rChoices.getLength() 868*b1cdbd2cSJim Jagielski numberOfColumns: 1]; 869*b1cdbd2cSJim Jagielski // set individual titles 870*b1cdbd2cSJim Jagielski NSArray* pCells = [pMatrix cells]; 871*b1cdbd2cSJim Jagielski for( sal_Int32 m = 0; m < rChoices.getLength(); m++ ) 872*b1cdbd2cSJim Jagielski { 873*b1cdbd2cSJim Jagielski NSCell* pCell = [pCells objectAtIndex: m]; 874*b1cdbd2cSJim Jagielski filterAccelerator( rChoices[m] ); 875*b1cdbd2cSJim Jagielski linebreakCell( pCell, rChoices[m] ); 876*b1cdbd2cSJim Jagielski // connect target and action 877*b1cdbd2cSJim Jagielski [pCell setTarget: pCtrlTarget]; 878*b1cdbd2cSJim Jagielski [pCell setAction: @selector(triggered:)]; 879*b1cdbd2cSJim Jagielski int nTag = pControllerProperties->addNameAndValueTag( rProperty, m ); 880*b1cdbd2cSJim Jagielski pControllerProperties->addObservedControl( pCell ); 881*b1cdbd2cSJim Jagielski [pCell setTag: nTag]; 882*b1cdbd2cSJim Jagielski // set current selection 883*b1cdbd2cSJim Jagielski if( nSelectValue == m ) 884*b1cdbd2cSJim Jagielski [pMatrix selectCellAtRow: m column: 0]; 885*b1cdbd2cSJim Jagielski } 886*b1cdbd2cSJim Jagielski [pMatrix sizeToFit]; 887*b1cdbd2cSJim Jagielski aRadioRect = [pMatrix frame]; 888*b1cdbd2cSJim Jagielski 889*b1cdbd2cSJim Jagielski // move it down, so it comes to the correct position 890*b1cdbd2cSJim Jagielski aRadioRect.origin.y = rCurY - aRadioRect.size.height; 891*b1cdbd2cSJim Jagielski [pMatrix setFrame: aRadioRect]; 892*b1cdbd2cSJim Jagielski [pCurParent addSubview: [pMatrix autorelease]]; 893*b1cdbd2cSJim Jagielski 894*b1cdbd2cSJim Jagielski rRightColumn.push_back( ColumnItem( pMatrix ) ); 895*b1cdbd2cSJim Jagielski 896*b1cdbd2cSJim Jagielski // update nCurY 897*b1cdbd2cSJim Jagielski rCurY = aRadioRect.origin.y - 5; 898*b1cdbd2cSJim Jagielski 899*b1cdbd2cSJim Jagielski [pProto release]; 900*b1cdbd2cSJim Jagielski} 901*b1cdbd2cSJim Jagielski 902*b1cdbd2cSJim Jagielskistatic void addList( NSView* pCurParent, long& rCurX, long& rCurY, long /*nAttachOffset*/, 903*b1cdbd2cSJim Jagielski const rtl::OUString& rText, 904*b1cdbd2cSJim Jagielski const rtl::OUString& rProperty, const Sequence< rtl::OUString > rChoices, sal_Int32 nSelectValue, 905*b1cdbd2cSJim Jagielski std::vector<ColumnItem >& rLeftColumn, 906*b1cdbd2cSJim Jagielski std::vector<ColumnItem >& rRightColumn, 907*b1cdbd2cSJim Jagielski ControllerProperties* pControllerProperties, 908*b1cdbd2cSJim Jagielski ControlTarget* pCtrlTarget 909*b1cdbd2cSJim Jagielski ) 910*b1cdbd2cSJim Jagielski{ 911*b1cdbd2cSJim Jagielski // don't indent attached lists, looks bad in the existing cases 912*b1cdbd2cSJim Jagielski NSControl* pTextView = createLabel( rText ); 913*b1cdbd2cSJim Jagielski [pCurParent addSubview: [pTextView autorelease]]; 914*b1cdbd2cSJim Jagielski rLeftColumn.push_back( ColumnItem( pTextView ) ); 915*b1cdbd2cSJim Jagielski NSRect aTextRect = [pTextView frame]; 916*b1cdbd2cSJim Jagielski aTextRect.origin.x = rCurX /* + nAttachOffset*/; 917*b1cdbd2cSJim Jagielski 918*b1cdbd2cSJim Jagielski // don't indent attached lists, looks bad in the existing cases 919*b1cdbd2cSJim Jagielski NSRect aBtnRect = NSMakeRect( rCurX /*+ nAttachOffset*/ + aTextRect.size.width, 0, 0, 15); 920*b1cdbd2cSJim Jagielski NSPopUpButton* pBtn = [[NSPopUpButton alloc] initWithFrame: aBtnRect pullsDown: NO]; 921*b1cdbd2cSJim Jagielski 922*b1cdbd2cSJim Jagielski // iterate options 923*b1cdbd2cSJim Jagielski for( sal_Int32 m = 0; m < rChoices.getLength(); m++ ) 924*b1cdbd2cSJim Jagielski { 925*b1cdbd2cSJim Jagielski NSString* pItemText = CreateNSString( rChoices[m] ); 926*b1cdbd2cSJim Jagielski [pBtn addItemWithTitle: pItemText]; 927*b1cdbd2cSJim Jagielski NSMenuItem* pItem = [pBtn itemWithTitle: pItemText]; 928*b1cdbd2cSJim Jagielski int nTag = pControllerProperties->addNameAndValueTag( rProperty, m ); 929*b1cdbd2cSJim Jagielski [pItem setTag: nTag]; 930*b1cdbd2cSJim Jagielski [pItemText release]; 931*b1cdbd2cSJim Jagielski } 932*b1cdbd2cSJim Jagielski 933*b1cdbd2cSJim Jagielski [pBtn selectItemAtIndex: nSelectValue]; 934*b1cdbd2cSJim Jagielski 935*b1cdbd2cSJim Jagielski // add the button to observed controls for enabled state changes 936*b1cdbd2cSJim Jagielski // also add a tag just for this purpose 937*b1cdbd2cSJim Jagielski pControllerProperties->addObservedControl( pBtn ); 938*b1cdbd2cSJim Jagielski [pBtn setTag: pControllerProperties->addNameTag( rProperty )]; 939*b1cdbd2cSJim Jagielski 940*b1cdbd2cSJim Jagielski [pBtn sizeToFit]; 941*b1cdbd2cSJim Jagielski [pCurParent addSubview: [pBtn autorelease]]; 942*b1cdbd2cSJim Jagielski 943*b1cdbd2cSJim Jagielski rRightColumn.push_back( ColumnItem( pBtn ) ); 944*b1cdbd2cSJim Jagielski 945*b1cdbd2cSJim Jagielski // connect target and action 946*b1cdbd2cSJim Jagielski [pBtn setTarget: pCtrlTarget]; 947*b1cdbd2cSJim Jagielski [pBtn setAction: @selector(triggered:)]; 948*b1cdbd2cSJim Jagielski 949*b1cdbd2cSJim Jagielski // move to nCurY 950*b1cdbd2cSJim Jagielski aBtnRect = [pBtn frame]; 951*b1cdbd2cSJim Jagielski aBtnRect.origin.y = rCurY - aBtnRect.size.height; 952*b1cdbd2cSJim Jagielski [pBtn setFrame: aBtnRect]; 953*b1cdbd2cSJim Jagielski 954*b1cdbd2cSJim Jagielski // align label 955*b1cdbd2cSJim Jagielski aTextRect.origin.y = aBtnRect.origin.y + (aBtnRect.size.height - aTextRect.size.height)/2; 956*b1cdbd2cSJim Jagielski [pTextView setFrame: aTextRect]; 957*b1cdbd2cSJim Jagielski 958*b1cdbd2cSJim Jagielski // update rCurY 959*b1cdbd2cSJim Jagielski rCurY = aBtnRect.origin.y - 5; 960*b1cdbd2cSJim Jagielski} 961*b1cdbd2cSJim Jagielski 962*b1cdbd2cSJim Jagielskistatic void addEdit( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset, 963*b1cdbd2cSJim Jagielski const rtl::OUString rCtrlType, 964*b1cdbd2cSJim Jagielski const rtl::OUString& rText, 965*b1cdbd2cSJim Jagielski const rtl::OUString& rProperty, const PropertyValue* pValue, 966*b1cdbd2cSJim Jagielski sal_Int64 nMinValue, sal_Int64 nMaxValue, 967*b1cdbd2cSJim Jagielski std::vector<ColumnItem >& rLeftColumn, 968*b1cdbd2cSJim Jagielski std::vector<ColumnItem >& rRightColumn, 969*b1cdbd2cSJim Jagielski ControllerProperties* pControllerProperties, 970*b1cdbd2cSJim Jagielski ControlTarget* pCtrlTarget 971*b1cdbd2cSJim Jagielski ) 972*b1cdbd2cSJim Jagielski{ 973*b1cdbd2cSJim Jagielski sal_Int32 nOff = 0; 974*b1cdbd2cSJim Jagielski if( rText.getLength() ) 975*b1cdbd2cSJim Jagielski { 976*b1cdbd2cSJim Jagielski // add a label 977*b1cdbd2cSJim Jagielski NSControl* pTextView = createLabel( rText ); 978*b1cdbd2cSJim Jagielski [pCurParent addSubview: [pTextView autorelease]]; 979*b1cdbd2cSJim Jagielski 980*b1cdbd2cSJim Jagielski rLeftColumn.push_back( ColumnItem( pTextView ) ); 981*b1cdbd2cSJim Jagielski 982*b1cdbd2cSJim Jagielski // move to nCurY 983*b1cdbd2cSJim Jagielski NSRect aTextRect = [pTextView frame]; 984*b1cdbd2cSJim Jagielski aTextRect.origin.x = rCurX + nAttachOffset; 985*b1cdbd2cSJim Jagielski aTextRect.origin.y = rCurY - aTextRect.size.height; 986*b1cdbd2cSJim Jagielski [pTextView setFrame: aTextRect]; 987*b1cdbd2cSJim Jagielski 988*b1cdbd2cSJim Jagielski // update nCurY 989*b1cdbd2cSJim Jagielski rCurY = aTextRect.origin.y - 5; 990*b1cdbd2cSJim Jagielski 991*b1cdbd2cSJim Jagielski // and set the offset for the real edit field 992*b1cdbd2cSJim Jagielski nOff = aTextRect.size.width + 5; 993*b1cdbd2cSJim Jagielski } 994*b1cdbd2cSJim Jagielski 995*b1cdbd2cSJim Jagielski NSRect aFieldRect = NSMakeRect( rCurX + nOff + nAttachOffset, 0, 100, 25); 996*b1cdbd2cSJim Jagielski NSTextField* pFieldView = [[NSTextField alloc] initWithFrame: aFieldRect]; 997*b1cdbd2cSJim Jagielski [pFieldView setEditable: YES]; 998*b1cdbd2cSJim Jagielski [pFieldView setSelectable: YES]; 999*b1cdbd2cSJim Jagielski [pFieldView setDrawsBackground: YES]; 1000*b1cdbd2cSJim Jagielski [pFieldView sizeToFit]; // FIXME: this does nothing 1001*b1cdbd2cSJim Jagielski [pCurParent addSubview: [pFieldView autorelease]]; 1002*b1cdbd2cSJim Jagielski 1003*b1cdbd2cSJim Jagielski rRightColumn.push_back( ColumnItem( pFieldView ) ); 1004*b1cdbd2cSJim Jagielski 1005*b1cdbd2cSJim Jagielski // add the field to observed controls for enabled state changes 1006*b1cdbd2cSJim Jagielski // also add a tag just for this purpose 1007*b1cdbd2cSJim Jagielski pControllerProperties->addObservedControl( pFieldView ); 1008*b1cdbd2cSJim Jagielski int nTag = pControllerProperties->addNameTag( rProperty ); 1009*b1cdbd2cSJim Jagielski [pFieldView setTag: nTag]; 1010*b1cdbd2cSJim Jagielski // pControllerProperties->addNamedView( pFieldView, aPropertyName ); 1011*b1cdbd2cSJim Jagielski 1012*b1cdbd2cSJim Jagielski // move to nCurY 1013*b1cdbd2cSJim Jagielski aFieldRect.origin.y = rCurY - aFieldRect.size.height; 1014*b1cdbd2cSJim Jagielski [pFieldView setFrame: aFieldRect]; 1015*b1cdbd2cSJim Jagielski 1016*b1cdbd2cSJim Jagielski if( rCtrlType.equalsAscii( "Range" ) ) 1017*b1cdbd2cSJim Jagielski { 1018*b1cdbd2cSJim Jagielski // add a stepper control 1019*b1cdbd2cSJim Jagielski NSRect aStepFrame = NSMakeRect( 1020*b1cdbd2cSJim Jagielski aFieldRect.origin.x + aFieldRect.size.width + 5, aFieldRect.origin.y, 1021*b1cdbd2cSJim Jagielski 15, aFieldRect.size.height); 1022*b1cdbd2cSJim Jagielski NSStepper* pStep = [[NSStepper alloc] initWithFrame: aStepFrame]; 1023*b1cdbd2cSJim Jagielski [pStep setIncrement: 1]; 1024*b1cdbd2cSJim Jagielski [pStep setValueWraps: NO]; 1025*b1cdbd2cSJim Jagielski [pStep setTag: nTag]; 1026*b1cdbd2cSJim Jagielski [pCurParent addSubview: [pStep autorelease]]; 1027*b1cdbd2cSJim Jagielski 1028*b1cdbd2cSJim Jagielski rRightColumn.back().pSubControl = pStep; 1029*b1cdbd2cSJim Jagielski 1030*b1cdbd2cSJim Jagielski pControllerProperties->addObservedControl( pStep ); 1031*b1cdbd2cSJim Jagielski [pStep setTarget: pCtrlTarget]; 1032*b1cdbd2cSJim Jagielski [pStep setAction: @selector(triggered:)]; 1033*b1cdbd2cSJim Jagielski 1034*b1cdbd2cSJim Jagielski // constrain the text field to decimal numbers 1035*b1cdbd2cSJim Jagielski NSNumberFormatter* pFormatter = [[NSNumberFormatter alloc] init]; 1036*b1cdbd2cSJim Jagielski [pFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4]; 1037*b1cdbd2cSJim Jagielski [pFormatter setNumberStyle: NSNumberFormatterDecimalStyle]; 1038*b1cdbd2cSJim Jagielski [pFormatter setAllowsFloats: NO]; 1039*b1cdbd2cSJim Jagielski [pFormatter setMaximumFractionDigits: 0]; 1040*b1cdbd2cSJim Jagielski if( nMinValue != nMaxValue ) 1041*b1cdbd2cSJim Jagielski { 1042*b1cdbd2cSJim Jagielski [pFormatter setMinimum: [[NSNumber numberWithInt: nMinValue] autorelease]]; 1043*b1cdbd2cSJim Jagielski [pStep setMinValue: nMinValue]; 1044*b1cdbd2cSJim Jagielski [pFormatter setMaximum: [[NSNumber numberWithInt: nMaxValue] autorelease]]; 1045*b1cdbd2cSJim Jagielski [pStep setMaxValue: nMaxValue]; 1046*b1cdbd2cSJim Jagielski } 1047*b1cdbd2cSJim Jagielski [pFieldView setFormatter: pFormatter]; 1048*b1cdbd2cSJim Jagielski 1049*b1cdbd2cSJim Jagielski sal_Int64 nSelectVal = 0; 1050*b1cdbd2cSJim Jagielski if( pValue && pValue->Value.hasValue() ) 1051*b1cdbd2cSJim Jagielski pValue->Value >>= nSelectVal; 1052*b1cdbd2cSJim Jagielski 1053*b1cdbd2cSJim Jagielski [pFieldView setIntValue: nSelectVal]; 1054*b1cdbd2cSJim Jagielski [pStep setIntValue: nSelectVal]; 1055*b1cdbd2cSJim Jagielski 1056*b1cdbd2cSJim Jagielski pControllerProperties->addViewPair( pFieldView, pStep ); 1057*b1cdbd2cSJim Jagielski // connect target and action 1058*b1cdbd2cSJim Jagielski [pFieldView setTarget: pCtrlTarget]; 1059*b1cdbd2cSJim Jagielski [pFieldView setAction: @selector(triggeredNumeric:)]; 1060*b1cdbd2cSJim Jagielski [pStep setTarget: pCtrlTarget]; 1061*b1cdbd2cSJim Jagielski [pStep setAction: @selector(triggeredNumeric:)]; 1062*b1cdbd2cSJim Jagielski } 1063*b1cdbd2cSJim Jagielski else 1064*b1cdbd2cSJim Jagielski { 1065*b1cdbd2cSJim Jagielski // connect target and action 1066*b1cdbd2cSJim Jagielski [pFieldView setTarget: pCtrlTarget]; 1067*b1cdbd2cSJim Jagielski [pFieldView setAction: @selector(triggered:)]; 1068*b1cdbd2cSJim Jagielski 1069*b1cdbd2cSJim Jagielski if( pValue && pValue->Value.hasValue() ) 1070*b1cdbd2cSJim Jagielski { 1071*b1cdbd2cSJim Jagielski rtl::OUString aValue; 1072*b1cdbd2cSJim Jagielski pValue->Value >>= aValue; 1073*b1cdbd2cSJim Jagielski if( aValue.getLength() ) 1074*b1cdbd2cSJim Jagielski { 1075*b1cdbd2cSJim Jagielski NSString* pText = CreateNSString( aValue ); 1076*b1cdbd2cSJim Jagielski [pFieldView setStringValue: pText]; 1077*b1cdbd2cSJim Jagielski [pText release]; 1078*b1cdbd2cSJim Jagielski } 1079*b1cdbd2cSJim Jagielski } 1080*b1cdbd2cSJim Jagielski } 1081*b1cdbd2cSJim Jagielski 1082*b1cdbd2cSJim Jagielski // update nCurY 1083*b1cdbd2cSJim Jagielski rCurY = aFieldRect.origin.y - 5; 1084*b1cdbd2cSJim Jagielski} 1085*b1cdbd2cSJim Jagielski 1086*b1cdbd2cSJim Jagielski@implementation AquaPrintAccessoryView 1087*b1cdbd2cSJim Jagielski+(NSObject*)setupPrinterPanel: (NSPrintOperation*)pOp withController: (vcl::PrinterController*)pController withState: (PrintAccessoryViewState*)pState 1088*b1cdbd2cSJim Jagielski{ 1089*b1cdbd2cSJim Jagielski const Sequence< PropertyValue >& rOptions( pController->getUIOptions() ); 1090*b1cdbd2cSJim Jagielski if( rOptions.getLength() == 0 ) 1091*b1cdbd2cSJim Jagielski return nil; 1092*b1cdbd2cSJim Jagielski 1093*b1cdbd2cSJim Jagielski NSView* pCurParent = 0; 1094*b1cdbd2cSJim Jagielski long nCurY = 0; 1095*b1cdbd2cSJim Jagielski long nCurX = 0; 1096*b1cdbd2cSJim Jagielski NSRect aViewFrame = { NSZeroPoint, {600, 400 } }; 1097*b1cdbd2cSJim Jagielski NSRect aTabViewFrame = { { 190, 0 }, {410, 400 } }; 1098*b1cdbd2cSJim Jagielski NSSize aMaxTabSize = NSZeroSize; 1099*b1cdbd2cSJim Jagielski NSView* pAccessoryView = [[NSView alloc] initWithFrame: aViewFrame]; 1100*b1cdbd2cSJim Jagielski NSTabView* pTabView = [[NSTabView alloc] initWithFrame: aTabViewFrame]; 1101*b1cdbd2cSJim Jagielski [pAccessoryView addSubview: [pTabView autorelease]]; 1102*b1cdbd2cSJim Jagielski 1103*b1cdbd2cSJim Jagielski sal_Bool bIgnoreSubgroup = sal_False; 1104*b1cdbd2cSJim Jagielski 1105*b1cdbd2cSJim Jagielski ControllerProperties* pControllerProperties = new ControllerProperties( pController, pOp, pAccessoryView, pTabView, pState ); 1106*b1cdbd2cSJim Jagielski ControlTarget* pCtrlTarget = [[ControlTarget alloc] initWithControllerMap: pControllerProperties]; 1107*b1cdbd2cSJim Jagielski 1108*b1cdbd2cSJim Jagielski std::vector< ColumnItem > aLeftColumn, aRightColumn; 1109*b1cdbd2cSJim Jagielski 1110*b1cdbd2cSJim Jagielski // ugly: 1111*b1cdbd2cSJim Jagielski // prepend a "selection" checkbox if the properties have such a selection in PrintContent 1112*b1cdbd2cSJim Jagielski bool bAddSelectionCheckBox = false, bSelectionBoxEnabled = false, bSelectionBoxChecked = false; 1113*b1cdbd2cSJim Jagielski for( int i = 0; i < rOptions.getLength(); i++ ) 1114*b1cdbd2cSJim Jagielski { 1115*b1cdbd2cSJim Jagielski Sequence< beans::PropertyValue > aOptProp; 1116*b1cdbd2cSJim Jagielski rOptions[i].Value >>= aOptProp; 1117*b1cdbd2cSJim Jagielski 1118*b1cdbd2cSJim Jagielski rtl::OUString aCtrlType; 1119*b1cdbd2cSJim Jagielski rtl::OUString aPropertyName; 1120*b1cdbd2cSJim Jagielski Sequence< rtl::OUString > aChoices; 1121*b1cdbd2cSJim Jagielski Sequence< sal_Bool > aChoicesDisabled; 1122*b1cdbd2cSJim Jagielski sal_Int32 aSelectionChecked = 0; 1123*b1cdbd2cSJim Jagielski for( int n = 0; n < aOptProp.getLength(); n++ ) 1124*b1cdbd2cSJim Jagielski { 1125*b1cdbd2cSJim Jagielski const beans::PropertyValue& rEntry( aOptProp[ n ] ); 1126*b1cdbd2cSJim Jagielski if( rEntry.Name.equalsAscii( "ControlType" ) ) 1127*b1cdbd2cSJim Jagielski { 1128*b1cdbd2cSJim Jagielski rEntry.Value >>= aCtrlType; 1129*b1cdbd2cSJim Jagielski } 1130*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "Choices" ) ) 1131*b1cdbd2cSJim Jagielski { 1132*b1cdbd2cSJim Jagielski rEntry.Value >>= aChoices; 1133*b1cdbd2cSJim Jagielski } 1134*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "ChoicesDisabled" ) ) 1135*b1cdbd2cSJim Jagielski { 1136*b1cdbd2cSJim Jagielski rEntry.Value >>= aChoicesDisabled; 1137*b1cdbd2cSJim Jagielski } 1138*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "Property" ) ) 1139*b1cdbd2cSJim Jagielski { 1140*b1cdbd2cSJim Jagielski PropertyValue aVal; 1141*b1cdbd2cSJim Jagielski rEntry.Value >>= aVal; 1142*b1cdbd2cSJim Jagielski aPropertyName = aVal.Name; 1143*b1cdbd2cSJim Jagielski if( aPropertyName.equalsAscii( "PrintContent" ) ) 1144*b1cdbd2cSJim Jagielski aVal.Value >>= aSelectionChecked; 1145*b1cdbd2cSJim Jagielski } 1146*b1cdbd2cSJim Jagielski } 1147*b1cdbd2cSJim Jagielski if( aCtrlType.equalsAscii( "Radio" ) && 1148*b1cdbd2cSJim Jagielski aPropertyName.equalsAscii( "PrintContent" ) && 1149*b1cdbd2cSJim Jagielski aChoices.getLength() > 2 ) 1150*b1cdbd2cSJim Jagielski { 1151*b1cdbd2cSJim Jagielski bAddSelectionCheckBox = true; 1152*b1cdbd2cSJim Jagielski bSelectionBoxEnabled = aChoicesDisabled.getLength() < 2 || ! aChoicesDisabled[2]; 1153*b1cdbd2cSJim Jagielski bSelectionBoxChecked = (aSelectionChecked==2); 1154*b1cdbd2cSJim Jagielski break; 1155*b1cdbd2cSJim Jagielski } 1156*b1cdbd2cSJim Jagielski } 1157*b1cdbd2cSJim Jagielski 1158*b1cdbd2cSJim Jagielski for( int i = 0; i < rOptions.getLength(); i++ ) 1159*b1cdbd2cSJim Jagielski { 1160*b1cdbd2cSJim Jagielski Sequence< beans::PropertyValue > aOptProp; 1161*b1cdbd2cSJim Jagielski rOptions[i].Value >>= aOptProp; 1162*b1cdbd2cSJim Jagielski 1163*b1cdbd2cSJim Jagielski // extract ui element 1164*b1cdbd2cSJim Jagielski bool bEnabled = true; 1165*b1cdbd2cSJim Jagielski rtl::OUString aCtrlType; 1166*b1cdbd2cSJim Jagielski rtl::OUString aText; 1167*b1cdbd2cSJim Jagielski rtl::OUString aPropertyName; 1168*b1cdbd2cSJim Jagielski rtl::OUString aGroupHint; 1169*b1cdbd2cSJim Jagielski Sequence< rtl::OUString > aChoices; 1170*b1cdbd2cSJim Jagielski sal_Int64 nMinValue = 0, nMaxValue = 0; 1171*b1cdbd2cSJim Jagielski long nAttachOffset = 0; 1172*b1cdbd2cSJim Jagielski sal_Bool bIgnore = sal_False; 1173*b1cdbd2cSJim Jagielski 1174*b1cdbd2cSJim Jagielski for( int n = 0; n < aOptProp.getLength(); n++ ) 1175*b1cdbd2cSJim Jagielski { 1176*b1cdbd2cSJim Jagielski const beans::PropertyValue& rEntry( aOptProp[ n ] ); 1177*b1cdbd2cSJim Jagielski if( rEntry.Name.equalsAscii( "Text" ) ) 1178*b1cdbd2cSJim Jagielski { 1179*b1cdbd2cSJim Jagielski rEntry.Value >>= aText; 1180*b1cdbd2cSJim Jagielski filterAccelerator( aText ); 1181*b1cdbd2cSJim Jagielski } 1182*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "ControlType" ) ) 1183*b1cdbd2cSJim Jagielski { 1184*b1cdbd2cSJim Jagielski rEntry.Value >>= aCtrlType; 1185*b1cdbd2cSJim Jagielski } 1186*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "Choices" ) ) 1187*b1cdbd2cSJim Jagielski { 1188*b1cdbd2cSJim Jagielski rEntry.Value >>= aChoices; 1189*b1cdbd2cSJim Jagielski } 1190*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "Property" ) ) 1191*b1cdbd2cSJim Jagielski { 1192*b1cdbd2cSJim Jagielski PropertyValue aVal; 1193*b1cdbd2cSJim Jagielski rEntry.Value >>= aVal; 1194*b1cdbd2cSJim Jagielski aPropertyName = aVal.Name; 1195*b1cdbd2cSJim Jagielski } 1196*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "Enabled" ) ) 1197*b1cdbd2cSJim Jagielski { 1198*b1cdbd2cSJim Jagielski sal_Bool bValue = sal_True; 1199*b1cdbd2cSJim Jagielski rEntry.Value >>= bValue; 1200*b1cdbd2cSJim Jagielski bEnabled = bValue; 1201*b1cdbd2cSJim Jagielski } 1202*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "MinValue" ) ) 1203*b1cdbd2cSJim Jagielski { 1204*b1cdbd2cSJim Jagielski rEntry.Value >>= nMinValue; 1205*b1cdbd2cSJim Jagielski } 1206*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "MaxValue" ) ) 1207*b1cdbd2cSJim Jagielski { 1208*b1cdbd2cSJim Jagielski rEntry.Value >>= nMaxValue; 1209*b1cdbd2cSJim Jagielski } 1210*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "AttachToDependency" ) ) 1211*b1cdbd2cSJim Jagielski { 1212*b1cdbd2cSJim Jagielski nAttachOffset = 20; 1213*b1cdbd2cSJim Jagielski } 1214*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "InternalUIOnly" ) ) 1215*b1cdbd2cSJim Jagielski { 1216*b1cdbd2cSJim Jagielski rEntry.Value >>= bIgnore; 1217*b1cdbd2cSJim Jagielski } 1218*b1cdbd2cSJim Jagielski else if( rEntry.Name.equalsAscii( "GroupingHint" ) ) 1219*b1cdbd2cSJim Jagielski { 1220*b1cdbd2cSJim Jagielski rEntry.Value >>= aGroupHint; 1221*b1cdbd2cSJim Jagielski } 1222*b1cdbd2cSJim Jagielski } 1223*b1cdbd2cSJim Jagielski 1224*b1cdbd2cSJim Jagielski if( aCtrlType.equalsAscii( "Group" ) || 1225*b1cdbd2cSJim Jagielski aCtrlType.equalsAscii( "Subgroup" ) || 1226*b1cdbd2cSJim Jagielski aCtrlType.equalsAscii( "Radio" ) || 1227*b1cdbd2cSJim Jagielski aCtrlType.equalsAscii( "List" ) || 1228*b1cdbd2cSJim Jagielski aCtrlType.equalsAscii( "Edit" ) || 1229*b1cdbd2cSJim Jagielski aCtrlType.equalsAscii( "Range" ) || 1230*b1cdbd2cSJim Jagielski aCtrlType.equalsAscii( "Bool" ) ) 1231*b1cdbd2cSJim Jagielski { 1232*b1cdbd2cSJim Jagielski // since our build target is MacOSX 10.4 we can have only one accessory view 1233*b1cdbd2cSJim Jagielski // so we have a single accessory view that is tabbed for grouping 1234*b1cdbd2cSJim Jagielski if( aCtrlType.equalsAscii( "Group" ) 1235*b1cdbd2cSJim Jagielski || ! pCurParent 1236*b1cdbd2cSJim Jagielski || ( aCtrlType.equalsAscii( "Subgroup" ) && nCurY < -250 && ! bIgnore ) 1237*b1cdbd2cSJim Jagielski ) 1238*b1cdbd2cSJim Jagielski { 1239*b1cdbd2cSJim Jagielski rtl::OUString aGroupTitle( aText ); 1240*b1cdbd2cSJim Jagielski if( aCtrlType.equalsAscii( "Subgroup" ) ) 1241*b1cdbd2cSJim Jagielski aGroupTitle = pControllerProperties->getMoreString(); 1242*b1cdbd2cSJim Jagielski // set size of current parent 1243*b1cdbd2cSJim Jagielski if( pCurParent ) 1244*b1cdbd2cSJim Jagielski adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn ); 1245*b1cdbd2cSJim Jagielski 1246*b1cdbd2cSJim Jagielski // new tab item 1247*b1cdbd2cSJim Jagielski if( ! aText.getLength() ) 1248*b1cdbd2cSJim Jagielski aText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OOo" ) ); 1249*b1cdbd2cSJim Jagielski NSString* pLabel = CreateNSString( aGroupTitle ); 1250*b1cdbd2cSJim Jagielski NSTabViewItem* pItem = [[NSTabViewItem alloc] initWithIdentifier: pLabel ]; 1251*b1cdbd2cSJim Jagielski [pItem setLabel: pLabel]; 1252*b1cdbd2cSJim Jagielski [pTabView addTabViewItem: pItem]; 1253*b1cdbd2cSJim Jagielski pCurParent = [[NSView alloc] initWithFrame: aTabViewFrame]; 1254*b1cdbd2cSJim Jagielski [pItem setView: pCurParent]; 1255*b1cdbd2cSJim Jagielski [pLabel release]; 1256*b1cdbd2cSJim Jagielski 1257*b1cdbd2cSJim Jagielski // reset indent 1258*b1cdbd2cSJim Jagielski nCurX = 20; 1259*b1cdbd2cSJim Jagielski // reset Y 1260*b1cdbd2cSJim Jagielski nCurY = 0; 1261*b1cdbd2cSJim Jagielski // clear columns 1262*b1cdbd2cSJim Jagielski aLeftColumn.clear(); 1263*b1cdbd2cSJim Jagielski aRightColumn.clear(); 1264*b1cdbd2cSJim Jagielski 1265*b1cdbd2cSJim Jagielski if( bAddSelectionCheckBox ) 1266*b1cdbd2cSJim Jagielski { 1267*b1cdbd2cSJim Jagielski addBool( pCurParent, nCurX, nCurY, 0, 1268*b1cdbd2cSJim Jagielski pControllerProperties->getPrintSelectionString(), bSelectionBoxEnabled, 1269*b1cdbd2cSJim Jagielski rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) ), bSelectionBoxChecked, 1270*b1cdbd2cSJim Jagielski aRightColumn, pControllerProperties, pCtrlTarget ); 1271*b1cdbd2cSJim Jagielski bAddSelectionCheckBox = false; 1272*b1cdbd2cSJim Jagielski } 1273*b1cdbd2cSJim Jagielski } 1274*b1cdbd2cSJim Jagielski 1275*b1cdbd2cSJim Jagielski if( aCtrlType.equalsAscii( "Subgroup" ) && pCurParent ) 1276*b1cdbd2cSJim Jagielski { 1277*b1cdbd2cSJim Jagielski bIgnoreSubgroup = bIgnore; 1278*b1cdbd2cSJim Jagielski if( bIgnore ) 1279*b1cdbd2cSJim Jagielski continue; 1280*b1cdbd2cSJim Jagielski 1281*b1cdbd2cSJim Jagielski addSubgroup( pCurParent, nCurY, aText ); 1282*b1cdbd2cSJim Jagielski } 1283*b1cdbd2cSJim Jagielski else if( bIgnoreSubgroup || bIgnore ) 1284*b1cdbd2cSJim Jagielski { 1285*b1cdbd2cSJim Jagielski continue; 1286*b1cdbd2cSJim Jagielski } 1287*b1cdbd2cSJim Jagielski else if( aCtrlType.equalsAscii( "Bool" ) && pCurParent ) 1288*b1cdbd2cSJim Jagielski { 1289*b1cdbd2cSJim Jagielski sal_Bool bVal = sal_False; 1290*b1cdbd2cSJim Jagielski PropertyValue* pVal = pController->getValue( aPropertyName ); 1291*b1cdbd2cSJim Jagielski if( pVal ) 1292*b1cdbd2cSJim Jagielski pVal->Value >>= bVal; 1293*b1cdbd2cSJim Jagielski addBool( pCurParent, nCurX, nCurY, nAttachOffset, 1294*b1cdbd2cSJim Jagielski aText, true, aPropertyName, bVal, 1295*b1cdbd2cSJim Jagielski aRightColumn, pControllerProperties, pCtrlTarget ); 1296*b1cdbd2cSJim Jagielski } 1297*b1cdbd2cSJim Jagielski else if( aCtrlType.equalsAscii( "Radio" ) && pCurParent ) 1298*b1cdbd2cSJim Jagielski { 1299*b1cdbd2cSJim Jagielski // get currently selected value 1300*b1cdbd2cSJim Jagielski sal_Int32 nSelectVal = 0; 1301*b1cdbd2cSJim Jagielski PropertyValue* pVal = pController->getValue( aPropertyName ); 1302*b1cdbd2cSJim Jagielski if( pVal && pVal->Value.hasValue() ) 1303*b1cdbd2cSJim Jagielski pVal->Value >>= nSelectVal; 1304*b1cdbd2cSJim Jagielski 1305*b1cdbd2cSJim Jagielski addRadio( pCurParent, nCurX, nCurY, nAttachOffset, 1306*b1cdbd2cSJim Jagielski aText, aPropertyName, aChoices, nSelectVal, 1307*b1cdbd2cSJim Jagielski aLeftColumn, aRightColumn, 1308*b1cdbd2cSJim Jagielski pControllerProperties, pCtrlTarget ); 1309*b1cdbd2cSJim Jagielski } 1310*b1cdbd2cSJim Jagielski else if( aCtrlType.equalsAscii( "List" ) && pCurParent ) 1311*b1cdbd2cSJim Jagielski { 1312*b1cdbd2cSJim Jagielski PropertyValue* pVal = pController->getValue( aPropertyName ); 1313*b1cdbd2cSJim Jagielski sal_Int32 aSelectVal = 0; 1314*b1cdbd2cSJim Jagielski if( pVal && pVal->Value.hasValue() ) 1315*b1cdbd2cSJim Jagielski pVal->Value >>= aSelectVal; 1316*b1cdbd2cSJim Jagielski 1317*b1cdbd2cSJim Jagielski addList( pCurParent, nCurX, nCurY, nAttachOffset, 1318*b1cdbd2cSJim Jagielski aText, aPropertyName, aChoices, aSelectVal, 1319*b1cdbd2cSJim Jagielski aLeftColumn, aRightColumn, 1320*b1cdbd2cSJim Jagielski pControllerProperties, pCtrlTarget ); 1321*b1cdbd2cSJim Jagielski } 1322*b1cdbd2cSJim Jagielski else if( (aCtrlType.equalsAscii( "Edit" ) || aCtrlType.equalsAscii( "Range" )) && pCurParent ) 1323*b1cdbd2cSJim Jagielski { 1324*b1cdbd2cSJim Jagielski // current value 1325*b1cdbd2cSJim Jagielski PropertyValue* pVal = pController->getValue( aPropertyName ); 1326*b1cdbd2cSJim Jagielski addEdit( pCurParent, nCurX, nCurY, nAttachOffset, 1327*b1cdbd2cSJim Jagielski aCtrlType, aText, aPropertyName, pVal, 1328*b1cdbd2cSJim Jagielski nMinValue, nMaxValue, 1329*b1cdbd2cSJim Jagielski aLeftColumn, aRightColumn, 1330*b1cdbd2cSJim Jagielski pControllerProperties, pCtrlTarget ); 1331*b1cdbd2cSJim Jagielski } 1332*b1cdbd2cSJim Jagielski } 1333*b1cdbd2cSJim Jagielski else 1334*b1cdbd2cSJim Jagielski { 1335*b1cdbd2cSJim Jagielski DBG_ERROR( "Unsupported UI option" ); 1336*b1cdbd2cSJim Jagielski } 1337*b1cdbd2cSJim Jagielski } 1338*b1cdbd2cSJim Jagielski 1339*b1cdbd2cSJim Jagielski pControllerProperties->updateEnableState(); 1340*b1cdbd2cSJim Jagielski adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn ); 1341*b1cdbd2cSJim Jagielski 1342*b1cdbd2cSJim Jagielski // leave some space for the preview 1343*b1cdbd2cSJim Jagielski if( aMaxTabSize.height < 200 ) 1344*b1cdbd2cSJim Jagielski aMaxTabSize.height = 200; 1345*b1cdbd2cSJim Jagielski 1346*b1cdbd2cSJim Jagielski // now reposition everything again so it is upper bound 1347*b1cdbd2cSJim Jagielski adjustTabViews( pTabView, aMaxTabSize ); 1348*b1cdbd2cSJim Jagielski 1349*b1cdbd2cSJim Jagielski // find the minimum needed tab size 1350*b1cdbd2cSJim Jagielski NSSize aTabCtrlSize = [pTabView minimumSize]; 1351*b1cdbd2cSJim Jagielski aTabCtrlSize.height += aMaxTabSize.height + 10; 1352*b1cdbd2cSJim Jagielski if( aTabCtrlSize.width < aMaxTabSize.width + 10 ) 1353*b1cdbd2cSJim Jagielski aTabCtrlSize.width = aMaxTabSize.width + 10; 1354*b1cdbd2cSJim Jagielski [pTabView setFrameSize: aTabCtrlSize]; 1355*b1cdbd2cSJim Jagielski aViewFrame.size.width = aTabCtrlSize.width + aTabViewFrame.origin.x; 1356*b1cdbd2cSJim Jagielski aViewFrame.size.height = aTabCtrlSize.height + aTabViewFrame.origin.y; 1357*b1cdbd2cSJim Jagielski [pAccessoryView setFrameSize: aViewFrame.size]; 1358*b1cdbd2cSJim Jagielski 1359*b1cdbd2cSJim Jagielski pControllerProperties->setupPreview( pCtrlTarget ); 1360*b1cdbd2cSJim Jagielski 1361*b1cdbd2cSJim Jagielski // set the accessory view 1362*b1cdbd2cSJim Jagielski [pOp setAccessoryView: [pAccessoryView autorelease]]; 1363*b1cdbd2cSJim Jagielski 1364*b1cdbd2cSJim Jagielski // set the current selecte tab item 1365*b1cdbd2cSJim Jagielski if( pState->nLastPage >= 0 && pState->nLastPage < [pTabView numberOfTabViewItems] ) 1366*b1cdbd2cSJim Jagielski [pTabView selectTabViewItemAtIndex: pState->nLastPage]; 1367*b1cdbd2cSJim Jagielski 1368*b1cdbd2cSJim Jagielski return pCtrlTarget; 1369*b1cdbd2cSJim Jagielski} 1370*b1cdbd2cSJim Jagielski 1371*b1cdbd2cSJim Jagielski@end 1372