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