xref: /aoo41x/main/vcl/source/window/printdlg.cxx (revision 0dccdc5d)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_vcl.hxx"
29 
30 #include "printdlg.hxx"
31 #include "svdata.hxx"
32 #include "svids.hrc"
33 #include "jobset.h"
34 
35 #include "vcl/print.hxx"
36 #include "vcl/dialog.hxx"
37 #include "vcl/button.hxx"
38 #include "vcl/wall.hxx"
39 #include "vcl/status.hxx"
40 #include "vcl/decoview.hxx"
41 #include "vcl/arrange.hxx"
42 #include "vcl/configsettings.hxx"
43 #include "vcl/help.hxx"
44 #include "vcl/decoview.hxx"
45 #include "vcl/svapp.hxx"
46 #include "vcl/unohelp.hxx"
47 
48 #include "unotools/localedatawrapper.hxx"
49 
50 #include "rtl/strbuf.hxx"
51 
52 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
53 #include "com/sun/star/container/XNameAccess.hpp"
54 #include "com/sun/star/beans/PropertyValue.hpp"
55 #include "com/sun/star/awt/Size.hpp"
56 
57 using namespace vcl;
58 using namespace com::sun::star;
59 using namespace com::sun::star::uno;
60 using namespace com::sun::star::lang;
61 using namespace com::sun::star::container;
62 using namespace com::sun::star::beans;
63 
64 PrintDialog::PrintPreviewWindow::PrintPreviewWindow( Window* i_pParent, const ResId& i_rId )
65     : Window( i_pParent, i_rId )
66     , maOrigSize( 10, 10 )
67     , maPageVDev( *this )
68     , maToolTipString( String( VclResId( SV_PRINT_PRINTPREVIEW_TXT ) ) )
69     , mbGreyscale( false )
70     , maHorzDim( this, WB_HORZ | WB_CENTER  )
71     , maVertDim( this, WB_VERT | WB_VCENTER )
72 {
73     SetPaintTransparent( sal_True );
74     SetBackground();
75     if( useHCColorReplacement() )
76         maPageVDev.SetBackground( GetSettings().GetStyleSettings().GetWindowColor() );
77     else
78         maPageVDev.SetBackground( Color( COL_WHITE ) );
79     maHorzDim.Show();
80     maVertDim.Show();
81 
82     maHorzDim.SetText( String( RTL_CONSTASCII_USTRINGPARAM( "2.0in" ) ) );
83     maVertDim.SetText( String( RTL_CONSTASCII_USTRINGPARAM( "2.0in" ) ) );
84 }
85 
86 PrintDialog::PrintPreviewWindow::~PrintPreviewWindow()
87 {
88 }
89 
90 bool PrintDialog::PrintPreviewWindow::useHCColorReplacement() const
91 {
92     bool bRet = false;
93     if( GetSettings().GetStyleSettings().GetHighContrastMode() )
94     {
95         try
96         {
97             // get service provider
98             Reference< XMultiServiceFactory > xSMgr( unohelper::GetMultiServiceFactory() );
99             // create configuration hierachical access name
100             if( xSMgr.is() )
101             {
102                 try
103                 {
104                     Reference< XMultiServiceFactory > xConfigProvider(
105                         Reference< XMultiServiceFactory >(
106                             xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
107                                             "com.sun.star.configuration.ConfigurationProvider" ))),
108                             UNO_QUERY )
109                         );
110                     if( xConfigProvider.is() )
111                     {
112                         Sequence< Any > aArgs(1);
113                         PropertyValue aVal;
114                         aVal.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
115                         aVal.Value <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Accessibility" ) );
116                         aArgs.getArray()[0] <<= aVal;
117                         Reference< XNameAccess > xConfigAccess(
118                             Reference< XNameAccess >(
119                                 xConfigProvider->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
120                                                     "com.sun.star.configuration.ConfigurationAccess" )),
121                                                                                 aArgs ),
122                                 UNO_QUERY )
123                             );
124                         if( xConfigAccess.is() )
125                         {
126                             try
127                             {
128                                 sal_Bool bValue = sal_False;
129                                 Any aAny = xConfigAccess->getByName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsForPagePreviews" ) ) );
130                                 if( aAny >>= bValue )
131                                     bRet = bool(bValue);
132                             }
133                             catch( NoSuchElementException& )
134                             {
135                             }
136                             catch( WrappedTargetException& )
137                             {
138                             }
139                         }
140                     }
141                 }
142                 catch( Exception& )
143                 {
144                 }
145             }
146         }
147         catch( WrappedTargetException& )
148         {
149         }
150     }
151     return bRet;
152 }
153 
154 void PrintDialog::PrintPreviewWindow::DataChanged( const DataChangedEvent& i_rDCEvt )
155 {
156     // react on settings changed
157     if( i_rDCEvt.GetType() == DATACHANGED_SETTINGS )
158     {
159         if( useHCColorReplacement() )
160             maPageVDev.SetBackground( GetSettings().GetStyleSettings().GetWindowColor() );
161         else
162             maPageVDev.SetBackground( Color( COL_WHITE ) );
163     }
164     Window::DataChanged( i_rDCEvt );
165 }
166 
167 void PrintDialog::PrintPreviewWindow::Resize()
168 {
169     Size aNewSize( GetSizePixel() );
170     long nTextHeight = maHorzDim.GetTextHeight();
171     // leave small space for decoration
172     aNewSize.Width() -= nTextHeight + 2;
173     aNewSize.Height() -= nTextHeight + 2;
174     Size aScaledSize;
175     double fScale = 1.0;
176 
177     // #i106435# catch corner case of Size(0,0)
178     Size aOrigSize( maOrigSize );
179     if( aOrigSize.Width() < 1 )
180         aOrigSize.Width() = aNewSize.Width();
181     if( aOrigSize.Height() < 1 )
182         aOrigSize.Height() = aNewSize.Height();
183     if( aOrigSize.Width() > aOrigSize.Height() )
184     {
185         aScaledSize = Size( aNewSize.Width(), aNewSize.Width() * aOrigSize.Height() / aOrigSize.Width() );
186         if( aScaledSize.Height() > aNewSize.Height() )
187             fScale = double(aNewSize.Height())/double(aScaledSize.Height());
188     }
189     else
190     {
191         aScaledSize = Size( aNewSize.Height() * aOrigSize.Width() / aOrigSize.Height(), aNewSize.Height() );
192         if( aScaledSize.Width() > aNewSize.Width() )
193             fScale = double(aNewSize.Width())/double(aScaledSize.Width());
194     }
195     aScaledSize.Width() = long(aScaledSize.Width()*fScale);
196     aScaledSize.Height() = long(aScaledSize.Height()*fScale);
197 
198     maPreviewSize = aScaledSize;
199 
200     // #i104784# if we render the page too small then rounding issues result in
201     // layout artifacts looking really bad. So scale the page unto a device that is not
202     // full page size but not too small either. This also results in much better visual
203     // quality of the preview, e.g. when its height approaches the number of text lines
204     // find a good scaling factor
205     Size aPreviewMMSize( maPageVDev.PixelToLogic( aScaledSize, MapMode( MAP_100TH_MM ) ) );
206     double fZoom = double(maOrigSize.Height())/double(aPreviewMMSize.Height());
207     while( fZoom > 10 )
208     {
209         aScaledSize.Width() *= 2;
210         aScaledSize.Height() *= 2;
211         fZoom /= 2.0;
212     }
213 
214     maPageVDev.SetOutputSizePixel( aScaledSize, sal_False );
215 
216     // position dimension lines
217     Point aRef( nTextHeight + (aNewSize.Width() - maPreviewSize.Width())/2,
218                 nTextHeight + (aNewSize.Height() - maPreviewSize.Height())/2 );
219     maHorzDim.SetPosSizePixel( Point( aRef.X(), aRef.Y() - nTextHeight ),
220                                Size( maPreviewSize.Width(), nTextHeight ) );
221     maVertDim.SetPosSizePixel( Point( aRef.X() - nTextHeight, aRef.Y() ),
222                                Size( nTextHeight, maPreviewSize.Height() ) );
223 
224 }
225 
226 void PrintDialog::PrintPreviewWindow::Paint( const Rectangle& )
227 {
228     long nTextHeight = maHorzDim.GetTextHeight();
229     Size aSize( GetSizePixel() );
230     aSize.Width()  -= nTextHeight;
231     aSize.Height() -= nTextHeight;
232     if( maReplacementString.getLength() != 0 )
233     {
234         // replacement is active
235         Push();
236         Rectangle aTextRect( Point( nTextHeight, nTextHeight ), aSize );
237         DecorationView aVw( this );
238         aVw.DrawFrame( aTextRect, FRAME_DRAW_GROUP );
239         aTextRect.Left()   += 2;
240         aTextRect.Top()    += 2;
241         aTextRect.Right()  -= 2;
242         aTextRect.Bottom() -= 2;
243         Font aFont( GetSettings().GetStyleSettings().GetLabelFont() );
244         SetZoomedPointFont( aFont );
245         DrawText( aTextRect, maReplacementString,
246                   TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE
247                  );
248         Pop();
249     }
250     else
251     {
252         GDIMetaFile aMtf( maMtf );
253 
254         Point aOffset( (aSize.Width() - maPreviewSize.Width()) / 2 + nTextHeight,
255                        (aSize.Height() - maPreviewSize.Height()) / 2 + nTextHeight );
256 
257         Size aVDevSize( maPageVDev.GetOutputSizePixel() );
258         const Size aLogicSize( maPageVDev.PixelToLogic( aVDevSize, MapMode( MAP_100TH_MM ) ) );
259         Size aOrigSize( maOrigSize );
260         if( aOrigSize.Width() < 1 )
261             aOrigSize.Width() = aLogicSize.Width();
262         if( aOrigSize.Height() < 1 )
263             aOrigSize.Height() = aLogicSize.Height();
264         double fScale = double(aLogicSize.Width())/double(aOrigSize.Width());
265 
266 
267         maPageVDev.Erase();
268         maPageVDev.Push();
269         maPageVDev.SetMapMode( MAP_100TH_MM );
270         sal_uLong nOldDrawMode = maPageVDev.GetDrawMode();
271         if( mbGreyscale )
272             maPageVDev.SetDrawMode( maPageVDev.GetDrawMode() |
273                                     ( DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL | DRAWMODE_GRAYTEXT |
274                                       DRAWMODE_GRAYBITMAP | DRAWMODE_GRAYGRADIENT ) );
275         aMtf.WindStart();
276         aMtf.Scale( fScale, fScale );
277         aMtf.WindStart();
278         aMtf.Play( &maPageVDev, Point( 0, 0 ), aLogicSize );
279         maPageVDev.Pop();
280 
281         SetMapMode( MAP_PIXEL );
282         maPageVDev.SetMapMode( MAP_PIXEL );
283         DrawOutDev( aOffset, maPreviewSize, Point( 0, 0 ), aVDevSize, maPageVDev );
284         maPageVDev.SetDrawMode( nOldDrawMode );
285 
286         DecorationView aVw( this );
287         Rectangle aFrame( aOffset + Point( -1, -1 ), Size( maPreviewSize.Width() + 2, maPreviewSize.Height() + 2 ) );
288         aVw.DrawFrame( aFrame, FRAME_DRAW_GROUP );
289     }
290 }
291 
292 void PrintDialog::PrintPreviewWindow::Command( const CommandEvent& rEvt )
293 {
294     if( rEvt.GetCommand() == COMMAND_WHEEL )
295     {
296         const CommandWheelData* pWheelData = rEvt.GetWheelData();
297         PrintDialog* pDlg = dynamic_cast<PrintDialog*>(GetParent());
298         if( pDlg )
299         {
300             if( pWheelData->GetDelta() > 0 )
301                 pDlg->previewForward();
302             else if( pWheelData->GetDelta() < 0 )
303                 pDlg->previewBackward();
304             /*
305             else
306                 huh ?
307             */
308         }
309     }
310 }
311 
312 void PrintDialog::PrintPreviewWindow::setPreview( const GDIMetaFile& i_rNewPreview,
313                                                   const Size& i_rOrigSize,
314                                                   const rtl::OUString& i_rPaperName,
315                                                   const rtl::OUString& i_rReplacement,
316                                                   sal_Int32 i_nDPIX,
317                                                   sal_Int32 i_nDPIY,
318                                                   bool i_bGreyscale
319                                                  )
320 {
321     rtl::OUStringBuffer aBuf( 256 );
322     aBuf.append( maToolTipString );
323     SetQuickHelpText( aBuf.makeStringAndClear() );
324     maMtf = i_rNewPreview;
325     if( useHCColorReplacement() )
326     {
327         maMtf.ReplaceColors( Color( COL_BLACK ), Color( COL_WHITE ), 30 );
328     }
329 
330     maOrigSize = i_rOrigSize;
331     maReplacementString = i_rReplacement;
332     mbGreyscale = i_bGreyscale;
333     maPageVDev.SetReferenceDevice( i_nDPIX, i_nDPIY );
334     maPageVDev.EnableOutput( sal_True );
335 
336     // use correct measurements
337     const LocaleDataWrapper& rLocWrap( GetSettings().GetLocaleDataWrapper() );
338     MapUnit eUnit = MAP_MM;
339     int nDigits = 0;
340     if( rLocWrap.getMeasurementSystemEnum() == MEASURE_US )
341     {
342         eUnit = MAP_100TH_INCH;
343         nDigits = 2;
344     }
345     Size aLogicPaperSize( LogicToLogic( i_rOrigSize, MapMode( MAP_100TH_MM ), MapMode( eUnit ) ) );
346     String aNumText( rLocWrap.getNum( aLogicPaperSize.Width(), nDigits ) );
347     aBuf.append( aNumText );
348     aBuf.appendAscii( eUnit == MAP_MM ? "mm" : "in" );
349     if( i_rPaperName.getLength() )
350     {
351         aBuf.appendAscii( " (" );
352         aBuf.append( i_rPaperName );
353         aBuf.append( sal_Unicode(')') );
354     }
355     maHorzDim.SetText( aBuf.makeStringAndClear() );
356 
357     aNumText = rLocWrap.getNum( aLogicPaperSize.Height(), nDigits );
358     aBuf.append( aNumText );
359     aBuf.appendAscii( eUnit == MAP_MM ? "mm" : "in" );
360     maVertDim.SetText( aBuf.makeStringAndClear() );
361 
362     Resize();
363     Invalidate();
364 }
365 
366 PrintDialog::ShowNupOrderWindow::ShowNupOrderWindow( Window* i_pParent )
367     : Window( i_pParent, WB_NOBORDER )
368     , mnOrderMode( 0 )
369     , mnRows( 1 )
370     , mnColumns( 1 )
371 {
372     ImplInitSettings();
373 }
374 
375 PrintDialog::ShowNupOrderWindow::~ShowNupOrderWindow()
376 {
377 }
378 
379 void PrintDialog::ShowNupOrderWindow::ImplInitSettings()
380 {
381     SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
382 }
383 
384 void PrintDialog::ShowNupOrderWindow::Paint( const Rectangle& i_rRect )
385 {
386     Window::Paint( i_rRect );
387     SetMapMode( MAP_PIXEL );
388     SetTextColor( GetSettings().GetStyleSettings().GetFieldTextColor() );
389 
390     int nPages = mnRows * mnColumns;
391     Font aFont( GetSettings().GetStyleSettings().GetFieldFont() );
392     aFont.SetSize( Size( 0, 24 ) );
393     SetFont( aFont );
394     Size aSampleTextSize( GetTextWidth( rtl::OUString::valueOf( sal_Int32(nPages+1) ) ), GetTextHeight() );
395 
396     Size aOutSize( GetOutputSizePixel() );
397     Size aSubSize( aOutSize.Width() / mnColumns, aOutSize.Height() / mnRows );
398     // calculate font size: shrink the sample text so it fits
399     double fX = double(aSubSize.Width())/double(aSampleTextSize.Width());
400     double fY = double(aSubSize.Height())/double(aSampleTextSize.Height());
401     double fScale = (fX < fY) ? fX : fY;
402     long nFontHeight = long(24.0*fScale) - 3;
403     if( nFontHeight < 5 )
404         nFontHeight = 5;
405     aFont.SetSize( Size( 0, nFontHeight ) );
406     SetFont( aFont );
407     long nTextHeight = GetTextHeight();
408     for( int i = 0; i < nPages; i++ )
409     {
410         rtl::OUString aPageText( rtl::OUString::valueOf( sal_Int32(i+1) ) );
411         int nX = 0, nY = 0;
412         switch( mnOrderMode )
413         {
414         case SV_PRINT_PRT_NUP_ORDER_LRTB:
415             nX = (i % mnColumns); nY = (i / mnColumns);
416             break;
417         case SV_PRINT_PRT_NUP_ORDER_TBLR:
418             nX = (i / mnRows); nY = (i % mnRows);
419             break;
420         case SV_PRINT_PRT_NUP_ORDER_RLTB:
421             nX = mnColumns - 1 - (i % mnColumns); nY = (i / mnColumns);
422             break;
423         case SV_PRINT_PRT_NUP_ORDER_TBRL:
424             nX = mnColumns - 1 - (i / mnRows); nY = (i % mnRows);
425             break;
426         }
427         Size aTextSize( GetTextWidth( aPageText ), nTextHeight );
428         int nDeltaX = (aSubSize.Width() - aTextSize.Width()) / 2;
429         int nDeltaY = (aSubSize.Height() - aTextSize.Height()) / 2;
430         DrawText( Point( nX * aSubSize.Width() + nDeltaX,
431                          nY * aSubSize.Height() + nDeltaY ),
432                   aPageText );
433     }
434     DecorationView aVw( this );
435     aVw.DrawFrame( Rectangle( Point( 0, 0), aOutSize ), FRAME_DRAW_GROUP );
436 }
437 
438 PrintDialog::NUpTabPage::NUpTabPage( Window* i_pParent, const ResId& rResId )
439     : TabPage( i_pParent, rResId )
440     , maNupLine( this, VclResId( SV_PRINT_PRT_NUP_LAYOUT_FL ) )
441     , maPagesBtn( this, VclResId( SV_PRINT_PRT_NUP_PAGES_BTN ) )
442     , maBrochureBtn( this, VclResId( SV_PRINT_PRT_NUP_BROCHURE_BTN ) )
443     , maPagesBoxTitleTxt( this, 0 )
444     , maNupPagesBox( this, VclResId( SV_PRINT_PRT_NUP_PAGES_BOX ) )
445     , maNupNumPagesTxt( this, VclResId( SV_PRINT_PRT_NUP_NUM_PAGES_TXT ) )
446     , maNupColEdt( this, VclResId( SV_PRINT_PRT_NUP_COLS_EDT ) )
447     , maNupTimesTxt( this, VclResId( SV_PRINT_PRT_NUP_TIMES_TXT ) )
448     , maNupRowsEdt( this, VclResId( SV_PRINT_PRT_NUP_ROWS_EDT ) )
449     , maPageMarginTxt1( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_PAGES_1_TXT ) )
450     , maPageMarginEdt( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_PAGES_EDT ) )
451     , maPageMarginTxt2( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_PAGES_2_TXT ) )
452     , maSheetMarginTxt1( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_SHEET_1_TXT ) )
453     , maSheetMarginEdt( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_SHEET_EDT ) )
454     , maSheetMarginTxt2( this, VclResId( SV_PRINT_PRT_NUP_MARGINS_SHEET_2_TXT ) )
455     , maNupOrientationTxt( this, VclResId( SV_PRINT_PRT_NUP_ORIENTATION_TXT ) )
456     , maNupOrientationBox( this, VclResId( SV_PRINT_PRT_NUP_ORIENTATION_BOX ) )
457     , maNupOrderTxt( this, VclResId( SV_PRINT_PRT_NUP_ORDER_TXT ) )
458     , maNupOrderBox( this, VclResId( SV_PRINT_PRT_NUP_ORDER_BOX ) )
459     , maNupOrderWin( this )
460     , maBorderCB( this, VclResId( SV_PRINT_PRT_NUP_BORDER_CB ) )
461 {
462     FreeResource();
463 
464     maNupOrderWin.Show();
465     maPagesBtn.Check( sal_True );
466     maBrochureBtn.Show( sal_False );
467 
468     // setup field units for metric fields
469     const LocaleDataWrapper& rLocWrap( maPageMarginEdt.GetLocaleDataWrapper() );
470     FieldUnit eUnit = FUNIT_MM;
471     sal_uInt16 nDigits = 0;
472     if( rLocWrap.getMeasurementSystemEnum() == MEASURE_US )
473     {
474         eUnit = FUNIT_INCH;
475         nDigits = 2;
476     }
477     // set units
478     maPageMarginEdt.SetUnit( eUnit );
479     maSheetMarginEdt.SetUnit( eUnit );
480 
481     // set precision
482     maPageMarginEdt.SetDecimalDigits( nDigits );
483     maSheetMarginEdt.SetDecimalDigits( nDigits );
484 
485     setupLayout();
486 }
487 
488 PrintDialog::NUpTabPage::~NUpTabPage()
489 {
490 }
491 
492 void PrintDialog::NUpTabPage::enableNupControls( bool bEnable )
493 {
494     maNupPagesBox.Enable( sal_True );
495     maNupNumPagesTxt.Enable( bEnable );
496     maNupColEdt.Enable( bEnable );
497     maNupTimesTxt.Enable( bEnable );
498     maNupRowsEdt.Enable( bEnable );
499     maPageMarginTxt1.Enable( bEnable );
500     maPageMarginEdt.Enable( bEnable );
501     maPageMarginTxt2.Enable( bEnable );
502     maSheetMarginTxt1.Enable( bEnable );
503     maSheetMarginEdt.Enable( bEnable );
504     maSheetMarginTxt2.Enable( bEnable );
505     maNupOrientationTxt.Enable( bEnable );
506     maNupOrientationBox.Enable( bEnable );
507     maNupOrderTxt.Enable( bEnable );
508     maNupOrderBox.Enable( bEnable );
509     maNupOrderWin.Enable( bEnable );
510     maBorderCB.Enable( bEnable );
511 }
512 
513 void PrintDialog::NUpTabPage::showAdvancedControls( bool i_bShow )
514 {
515     maNupNumPagesTxt.Show( i_bShow );
516     maNupColEdt.Show( i_bShow );
517     maNupTimesTxt.Show( i_bShow );
518     maNupRowsEdt.Show( i_bShow );
519     maPageMarginTxt1.Show( i_bShow );
520     maPageMarginEdt.Show( i_bShow );
521     maPageMarginTxt2.Show( i_bShow );
522     maSheetMarginTxt1.Show( i_bShow );
523     maSheetMarginEdt.Show( i_bShow );
524     maSheetMarginTxt2.Show( i_bShow );
525     maNupOrientationTxt.Show( i_bShow );
526     maNupOrientationBox.Show( i_bShow );
527     getLayout()->resize();
528 }
529 
530 void PrintDialog::NUpTabPage::setupLayout()
531 {
532     boost::shared_ptr<vcl::RowOrColumn> xLayout =
533         boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
534     Size aBorder( LogicToPixel( Size( 6, 6 ), MapMode( MAP_APPFONT ) ) );
535     /*  According to OOo style guide, the horizontal indentation of child
536         elements to their parent element should always be 6 map units. */
537     long nIndent = aBorder.Width();
538 
539     xLayout->addWindow( &maNupLine );
540     boost::shared_ptr< vcl::RowOrColumn > xRow( new vcl::RowOrColumn( xLayout.get(), false ) );
541     xLayout->addChild( xRow );
542     boost::shared_ptr< vcl::Indenter > xIndent( new vcl::Indenter( xRow.get() ) );
543     xRow->addChild( xIndent );
544 
545     boost::shared_ptr< vcl::RowOrColumn > xShowNupCol( new vcl::RowOrColumn( xRow.get() ) );
546     xRow->addChild( xShowNupCol, -1 );
547     xShowNupCol->setMinimumSize( xShowNupCol->addWindow( &maNupOrderWin ), Size( 70, 70 ) );
548     boost::shared_ptr< vcl::Spacer > xSpacer( new vcl::Spacer( xShowNupCol.get() ) );
549     xShowNupCol->addChild( xSpacer );
550 
551     boost::shared_ptr< vcl::LabelColumn > xMainCol( new vcl::LabelColumn( xIndent.get() ) );
552     xIndent->setChild( xMainCol );
553 
554     size_t nPagesIndex = xMainCol->addRow( &maPagesBtn, &maNupPagesBox );
555     mxPagesBtnLabel = boost::dynamic_pointer_cast<vcl::LabeledElement>( xMainCol->getChild( nPagesIndex ) );
556 
557     xRow.reset( new vcl::RowOrColumn( xMainCol.get(), false ) );
558     xMainCol->addRow( &maNupNumPagesTxt, xRow, nIndent );
559     xRow->addWindow( &maNupColEdt );
560     xRow->addWindow( &maNupTimesTxt );
561     xRow->addWindow( &maNupRowsEdt );
562 
563     boost::shared_ptr< vcl::LabeledElement > xLab( new vcl::LabeledElement( xMainCol.get(), 2 ) );
564     xLab->setLabel( &maPageMarginEdt );
565     xLab->setElement( &maPageMarginTxt2 );
566     xMainCol->addRow( &maPageMarginTxt1, xLab, nIndent );
567 
568     xLab.reset( new vcl::LabeledElement( xMainCol.get(), 2 ) );
569     xLab->setLabel( &maSheetMarginEdt );
570     xLab->setElement( &maSheetMarginTxt2 );
571     xMainCol->addRow( &maSheetMarginTxt1, xLab, nIndent );
572 
573     xMainCol->addRow( &maNupOrientationTxt, &maNupOrientationBox, nIndent );
574     xMainCol->addRow( &maNupOrderTxt, &maNupOrderBox, nIndent );
575     xMainCol->setBorders( xMainCol->addWindow( &maBorderCB ), nIndent, 0, 0, 0 );
576 
577     xSpacer.reset( new vcl::Spacer( xMainCol.get(), 0, Size( 10, WindowArranger::getDefaultBorder() ) ) );
578     xMainCol->addChild( xSpacer );
579 
580     xRow.reset( new vcl::RowOrColumn( xMainCol.get(), false ) );
581     xMainCol->addRow( &maBrochureBtn, xRow );
582     // remember brochure row for dependencies
583     mxBrochureDep = xRow;
584 
585     // initially advanced controls are not shown, rows=columns=1
586     showAdvancedControls( false );
587 }
588 
589 void PrintDialog::NUpTabPage::initFromMultiPageSetup( const vcl::PrinterController::MultiPageSetup& i_rMPS )
590 {
591     maSheetMarginEdt.SetValue( maSheetMarginEdt.Normalize( i_rMPS.nLeftMargin ), FUNIT_100TH_MM );
592     maPageMarginEdt.SetValue( maPageMarginEdt.Normalize( i_rMPS.nHorizontalSpacing ), FUNIT_100TH_MM );
593     maBorderCB.Check( i_rMPS.bDrawBorder );
594     maNupRowsEdt.SetValue( i_rMPS.nRows );
595     maNupColEdt.SetValue( i_rMPS.nColumns );
596     maBorderCB.Check( i_rMPS.bDrawBorder );
597     for( sal_uInt16 i = 0; i < maNupOrderBox.GetEntryCount(); i++ )
598     {
599         if( int(sal_IntPtr(maNupOrderBox.GetEntryData( i ))) == i_rMPS.nOrder )
600             maNupOrderBox.SelectEntryPos( i );
601     }
602     if( i_rMPS.nRows != 1 || i_rMPS.nColumns != 1 )
603     {
604         maNupPagesBox.SelectEntryPos( maNupPagesBox.GetEntryCount()-1 );
605         showAdvancedControls( true );
606         maNupOrderWin.setValues( i_rMPS.nOrder, i_rMPS.nColumns, i_rMPS.nRows );
607     }
608 }
609 
610 void PrintDialog::NUpTabPage::readFromSettings()
611 {
612 }
613 
614 void PrintDialog::NUpTabPage::storeToSettings()
615 {
616 }
617 
618 PrintDialog::JobTabPage::JobTabPage( Window* i_pParent, const ResId& rResId )
619     : TabPage( i_pParent, rResId )
620     , maPrinterFL( this, VclResId( SV_PRINT_PRINTERS_FL ) )
621     , maPrinters( this, VclResId( SV_PRINT_PRINTERS ) )
622     , maDetailsBtn( this, VclResId( SV_PRINT_DETAILS_BTN ) )
623     , maStatusLabel( this, VclResId( SV_PRINT_STATUS_TXT ) )
624     , maStatusTxt( this, 0 )
625     , maLocationLabel( this, VclResId( SV_PRINT_LOCATION_TXT ) )
626     , maLocationTxt( this, 0 )
627     , maCommentLabel( this, VclResId( SV_PRINT_COMMENT_TXT ) )
628     , maCommentTxt( this, 0 )
629     , maSetupButton( this, VclResId( SV_PRINT_PRT_SETUP ) )
630     , maCopies( this, VclResId( SV_PRINT_COPIES ) )
631     , maCopySpacer( this, WB_VERT )
632     , maCopyCount( this, VclResId( SV_PRINT_COPYCOUNT ) )
633     , maCopyCountField( this, VclResId( SV_PRINT_COPYCOUNT_FIELD ) )
634     , maCollateBox( this, VclResId( SV_PRINT_COLLATE ) )
635     , maCollateImage( this, VclResId( SV_PRINT_COLLATE_IMAGE ) )
636     , maReverseOrderBox( this, VclResId( SV_PRINT_OPT_REVERSE ) )
637     , maCollateImg( VclResId( SV_PRINT_COLLATE_IMG ) )
638     , maCollateHCImg( VclResId( SV_PRINT_COLLATE_HC_IMG ) )
639     , maNoCollateImg( VclResId( SV_PRINT_NOCOLLATE_IMG ) )
640     , maNoCollateHCImg( VclResId( SV_PRINT_NOCOLLATE_HC_IMG ) )
641     , mnCollateUIMode( 0 )
642 {
643     FreeResource();
644 
645     maCopySpacer.Show();
646     maStatusTxt.Show();
647     maCommentTxt.Show();
648     maLocationTxt.Show();
649 
650     setupLayout();
651 }
652 
653 PrintDialog::JobTabPage::~JobTabPage()
654 {
655 }
656 
657 void PrintDialog::JobTabPage::setupLayout()
658 {
659     // HACK: this is not a dropdown box, but the dropdown line count
660     // sets the results of GetOptimalSize in a normal ListBox
661     maPrinters.SetDropDownLineCount( 4 );
662 
663     boost::shared_ptr<vcl::RowOrColumn> xLayout =
664         boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
665 
666     // add printer fixed line
667     xLayout->addWindow( &maPrinterFL );
668     // add print LB
669     xLayout->addWindow( &maPrinters, 3 );
670 
671     // create a row for details button/text and properties button
672     boost::shared_ptr< vcl::RowOrColumn > xDetRow( new vcl::RowOrColumn( xLayout.get(), false ) );
673     xLayout->addChild( xDetRow );
674     xDetRow->addWindow( &maDetailsBtn );
675     xDetRow->addChild( new vcl::Spacer( xDetRow.get(), 2 ) );
676     xDetRow->addWindow( &maSetupButton );
677 
678     // create an indent for details
679     boost::shared_ptr< vcl::Indenter > xIndent( new vcl::Indenter( xLayout.get() ) );
680     xLayout->addChild( xIndent );
681     // remember details controls
682     mxDetails = xIndent;
683     // create a column for the details
684     boost::shared_ptr< vcl::LabelColumn > xLabelCol( new vcl::LabelColumn( xIndent.get() ) );
685     xIndent->setChild( xLabelCol );
686     xLabelCol->addRow( &maStatusLabel, &maStatusTxt );
687     xLabelCol->addRow( &maLocationLabel, &maLocationTxt );
688     xLabelCol->addRow( &maCommentLabel, &maCommentTxt );
689 
690     // add print range and copies columns
691     xLayout->addWindow( &maCopies );
692     boost::shared_ptr< vcl::RowOrColumn > xRangeRow( new vcl::RowOrColumn( xLayout.get(), false ) );
693     xLayout->addChild( xRangeRow );
694 
695     // create print range and add to range row
696     mxPrintRange.reset( new vcl::RowOrColumn( xRangeRow.get() ) );
697     xRangeRow->addChild( mxPrintRange );
698     xRangeRow->addWindow( &maCopySpacer );
699 
700     boost::shared_ptr< vcl::RowOrColumn > xCopyCollateCol( new vcl::RowOrColumn( xRangeRow.get() ) );
701     xRangeRow->addChild( xCopyCollateCol );
702 
703     // add copies row to copy/collate column
704     boost::shared_ptr< vcl::LabeledElement > xCopiesRow( new vcl::LabeledElement( xCopyCollateCol.get(), 2 ) );
705     xCopyCollateCol->addChild( xCopiesRow );
706     xCopiesRow->setLabel( &maCopyCount );
707     xCopiesRow->setElement( &maCopyCountField );
708     boost::shared_ptr< vcl::LabeledElement > xCollateRow( new vcl::LabeledElement( xCopyCollateCol.get(), 2 ) );
709     xCopyCollateCol->addChild( xCollateRow );
710     xCollateRow->setLabel( &maCollateBox );
711     xCollateRow->setElement( &maCollateImage );
712 
713     // maDetailsBtn.SetStyle( maDetailsBtn.GetStyle() | (WB_SMALLSTYLE | WB_BEVELBUTTON) );
714     mxDetails->show( false, false );
715 }
716 
717 void PrintDialog::JobTabPage::readFromSettings()
718 {
719     SettingsConfigItem* pItem = SettingsConfigItem::get();
720     rtl::OUString aValue;
721 
722     #if 0
723     // do not actually make copy count persistent
724     // the assumption is that this would lead to a lot of unwanted copies
725     aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
726                               rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyCount" ) ) );
727     sal_Int32 nVal = aValue.toInt32();
728     maCopyCountField.SetValue( sal_Int64(nVal > 1 ? nVal : 1) );
729     #endif
730 
731     aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
732                               rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CollateBox" ) ) );
733     if( aValue.equalsIgnoreAsciiCaseAscii( "alwaysoff" ) )
734     {
735         mnCollateUIMode = 1;
736         maCollateBox.Check( sal_False );
737         maCollateBox.Enable( sal_False );
738     }
739     else
740     {
741         mnCollateUIMode = 0;
742         aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
743                                   rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ) );
744         maCollateBox.Check( aValue.equalsIgnoreAsciiCaseAscii( "true" ) );
745     }
746     Resize();
747 }
748 
749 void PrintDialog::JobTabPage::storeToSettings()
750 {
751     SettingsConfigItem* pItem = SettingsConfigItem::get();
752     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
753                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyCount" ) ),
754                      maCopyCountField.GetText() );
755     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
756                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ),
757                      rtl::OUString::createFromAscii( maCollateBox.IsChecked() ? "true" : "false" ) );
758 }
759 
760 PrintDialog::OutputOptPage::OutputOptPage( Window* i_pParent, const ResId& i_rResId )
761     : TabPage( i_pParent, i_rResId )
762     , maOptionsLine( this, VclResId( SV_PRINT_OPT_PRINT_FL ) )
763     , maToFileBox( this, VclResId( SV_PRINT_OPT_TOFILE ) )
764     , maCollateSingleJobsBox( this, VclResId( SV_PRINT_OPT_SINGLEJOBS ) )
765 {
766     FreeResource();
767 
768     setupLayout();
769 }
770 
771 PrintDialog::OutputOptPage::~OutputOptPage()
772 {
773 }
774 
775 void PrintDialog::OutputOptPage::setupLayout()
776 {
777     boost::shared_ptr<vcl::RowOrColumn> xLayout =
778         boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
779 
780     xLayout->addWindow( &maOptionsLine );
781     boost::shared_ptr<vcl::Indenter> xIndent( new vcl::Indenter( xLayout.get(), -1 ) );
782     xLayout->addChild( xIndent );
783     boost::shared_ptr<vcl::RowOrColumn> xCol( new vcl::RowOrColumn( xIndent.get() ) );
784     xIndent->setChild( xCol );
785     mxOptGroup = xCol;
786     xCol->addWindow( &maToFileBox );
787     xCol->addWindow( &maCollateSingleJobsBox );
788 }
789 
790 void PrintDialog::OutputOptPage::readFromSettings()
791 {
792     #if 0
793     SettingsConfigItem* pItem = SettingsConfigItem::get();
794     rtl::OUString aValue;
795 
796     aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
797                               rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ToFile" ) ) );
798     maToFileBox.Check( aValue.equalsIgnoreAsciiCaseAscii( "true" ) );
799     #endif
800 }
801 
802 void PrintDialog::OutputOptPage::storeToSettings()
803 {
804     SettingsConfigItem* pItem = SettingsConfigItem::get();
805     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
806                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ToFile" ) ),
807                      rtl::OUString::createFromAscii( maToFileBox.IsChecked() ? "true" : "false" ) );
808 }
809 
810 PrintDialog::PrintDialog( Window* i_pParent, const boost::shared_ptr<PrinterController>& i_rController )
811     : ModalDialog( i_pParent, VclResId( SV_DLG_PRINT ) )
812     , maOKButton( this, VclResId( SV_PRINT_OK ) )
813     , maCancelButton( this, VclResId( SV_PRINT_CANCEL ) )
814     , maHelpButton( this, VclResId( SV_PRINT_HELP ) )
815     , maPreviewWindow( this, VclResId( SV_PRINT_PAGE_PREVIEW ) )
816     , maPageEdit( this, VclResId( SV_PRINT_PAGE_EDIT ) )
817     , maNumPagesText( this, VclResId( SV_PRINT_PAGE_TXT ) )
818     , maBackwardBtn( this, VclResId( SV_PRINT_PAGE_BACKWARD ) )
819     , maForwardBtn( this, VclResId( SV_PRINT_PAGE_FORWARD ) )
820     , maTabCtrl( this, VclResId( SV_PRINT_TABCTRL ) )
821     , maNUpPage( &maTabCtrl, VclResId( SV_PRINT_TAB_NUP ) )
822     , maJobPage( &maTabCtrl, VclResId( SV_PRINT_TAB_JOB ) )
823     , maOptionsPage( &maTabCtrl, VclResId( SV_PRINT_TAB_OPT ) )
824     , maButtonLine( this, VclResId( SV_PRINT_BUTTONLINE ) )
825     , maPController( i_rController )
826     , maNoPageStr( String( VclResId( SV_PRINT_NOPAGES ) ) )
827     , mnCurPage( 0 )
828     , mnCachedPages( 0 )
829     , maPrintToFileText( String( VclResId( SV_PRINT_TOFILE_TXT ) ) )
830     , maDefPrtText( String( VclResId( SV_PRINT_DEFPRT_TXT ) ) )
831     , mbShowLayoutPage( sal_True )
832 {
833     FreeResource();
834 
835     // save printbutton text, gets exchanged occasionally with print to file
836     maPrintText = maOKButton.GetText();
837 
838     // setup preview controls
839     maForwardBtn.SetStyle( maForwardBtn.GetStyle() | WB_BEVELBUTTON );
840     maBackwardBtn.SetStyle( maBackwardBtn.GetStyle() | WB_BEVELBUTTON );
841 
842     // insert the job (general) tab page first
843     maTabCtrl.InsertPage( SV_PRINT_TAB_JOB, maJobPage.GetText() );
844     maTabCtrl.SetTabPage( SV_PRINT_TAB_JOB, &maJobPage );
845 
846     // set symbols on forward and backward button
847     maBackwardBtn.SetSymbol( SYMBOL_PREV );
848     maForwardBtn.SetSymbol( SYMBOL_NEXT );
849     maBackwardBtn.ImplSetSmallSymbol( sal_True );
850     maForwardBtn.ImplSetSmallSymbol( sal_True );
851 
852     maPageStr = maNumPagesText.GetText();
853 
854     // init reverse print
855     maJobPage.maReverseOrderBox.Check( maPController->getReversePrint() );
856 
857     // fill printer listbox
858     const std::vector< rtl::OUString >& rQueues( Printer::GetPrinterQueues() );
859     for( std::vector< rtl::OUString >::const_iterator it = rQueues.begin();
860          it != rQueues.end(); ++it )
861     {
862         maJobPage.maPrinters.InsertEntry( *it );
863     }
864     // select current printer
865     if( maJobPage.maPrinters.GetEntryPos( maPController->getPrinter()->GetName() ) != LISTBOX_ENTRY_NOTFOUND )
866     {
867         maJobPage.maPrinters.SelectEntry( maPController->getPrinter()->GetName() );
868     }
869     else
870     {
871         // fall back to last printer
872         SettingsConfigItem* pItem = SettingsConfigItem::get();
873         String aValue( pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
874                                         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPrinter" ) ) ) );
875         if( maJobPage.maPrinters.GetEntryPos( aValue ) != LISTBOX_ENTRY_NOTFOUND )
876         {
877             maJobPage.maPrinters.SelectEntry( aValue );
878             maPController->setPrinter( boost::shared_ptr<Printer>( new Printer( aValue ) ) );
879         }
880         else
881         {
882             // fall back to default printer
883             maJobPage.maPrinters.SelectEntry( Printer::GetDefaultPrinterName() );
884             maPController->setPrinter( boost::shared_ptr<Printer>( new Printer( Printer::GetDefaultPrinterName() ) ) );
885         }
886     }
887     // not printing to file
888     maPController->resetPrinterOptions( false );
889 
890     // get the first page
891     preparePreview( true, true );
892 
893     // update the text fields for the printer
894     updatePrinterText();
895 
896     // set a select handler
897     maJobPage.maPrinters.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
898 
899     // setup sizes for N-Up
900     Size aNupSize( maPController->getPrinter()->PixelToLogic(
901                          maPController->getPrinter()->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) ) );
902     if( maPController->getPrinter()->GetOrientation() == ORIENTATION_LANDSCAPE )
903     {
904         maNupLandscapeSize = aNupSize;
905         maNupPortraitSize = Size( aNupSize.Height(), aNupSize.Width() );
906     }
907     else
908     {
909         maNupPortraitSize = aNupSize;
910         maNupLandscapeSize = Size( aNupSize.Height(), aNupSize.Width() );
911     }
912     maNUpPage.initFromMultiPageSetup( maPController->getMultipage() );
913 
914 
915     // setup click handler on the various buttons
916     maOKButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
917     #if OSL_DEBUG_LEVEL > 1
918     maCancelButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
919     #endif
920     maHelpButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
921     maForwardBtn.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
922     maBackwardBtn.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
923     maJobPage.maCollateBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
924     maJobPage.maSetupButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
925     maJobPage.maDetailsBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
926     maNUpPage.maBorderCB.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
927     maOptionsPage.maToFileBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
928     maJobPage.maReverseOrderBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
929     maOptionsPage.maCollateSingleJobsBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
930     maNUpPage.maPagesBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
931 
932     // setup modify hdl
933     maPageEdit.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
934     maJobPage.maCopyCountField.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
935     maNUpPage.maNupRowsEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
936     maNUpPage.maNupColEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
937     maNUpPage.maPageMarginEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
938     maNUpPage.maSheetMarginEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
939 
940     // setup select hdl
941     maNUpPage.maNupPagesBox.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
942     maNUpPage.maNupOrientationBox.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
943     maNUpPage.maNupOrderBox.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
944 
945     // setup the layout
946     setupLayout();
947 
948     // setup optional UI options set by application
949     setupOptionalUI();
950 
951     // set change handler for UI options
952     maPController->setOptionChangeHdl( LINK( this, PrintDialog, UIOptionsChanged ) );
953 
954     // set min size pixel to current size
955     Size aOutSize( GetOutputSizePixel() );
956     SetMinOutputSizePixel( aOutSize );
957 
958     // if there is space enough, enlarge the preview so it gets roughly as
959     // high as the tab control
960     if( aOutSize.Width() < 768 )
961     {
962         Size aJobPageSize( getJobPageSize() );
963         Size aTabSize( maTabCtrl.GetSizePixel() );
964         if( aJobPageSize.Width() < 1 )
965             aJobPageSize.Width() = aTabSize.Width();
966         if( aJobPageSize.Height() < 1 )
967             aJobPageSize.Height() = aTabSize.Height();
968         long nOptPreviewWidth = aTabSize.Height() * aJobPageSize.Width() / aJobPageSize.Height();
969         // add space for borders
970         nOptPreviewWidth += 15;
971         if( aOutSize.Width() - aTabSize.Width() < nOptPreviewWidth )
972         {
973             aOutSize.Width() = aTabSize.Width() + nOptPreviewWidth;
974             if( aOutSize.Width() > 768 ) // don't enlarge the dialog too much
975                 aOutSize.Width() = 768;
976             SetOutputSizePixel( aOutSize );
977         }
978     }
979 
980     // append further tab pages
981     if( mbShowLayoutPage )
982     {
983         maTabCtrl.InsertPage( SV_PRINT_TAB_NUP, maNUpPage.GetText() );
984         maTabCtrl.SetTabPage( SV_PRINT_TAB_NUP, &maNUpPage );
985     }
986     maTabCtrl.InsertPage( SV_PRINT_TAB_OPT, maOptionsPage.GetText() );
987     maTabCtrl.SetTabPage( SV_PRINT_TAB_OPT, &maOptionsPage );
988 
989     // restore settings from last run
990     readFromSettings();
991 
992     // setup dependencies
993     checkControlDependencies();
994 
995 }
996 
997 PrintDialog::~PrintDialog()
998 {
999     while( ! maControls.empty() )
1000     {
1001         delete maControls.front();
1002         maControls.pop_front();
1003     }
1004 }
1005 
1006 void PrintDialog::setupLayout()
1007 {
1008     boost::shared_ptr<vcl::RowOrColumn> xLayout =
1009         boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
1010     xLayout->setOuterBorder( 0 );
1011 
1012 
1013     boost::shared_ptr< vcl::RowOrColumn > xPreviewAndTab( new vcl::RowOrColumn( xLayout.get(), false ) );
1014     size_t nIndex = xLayout->addChild( xPreviewAndTab, 5 );
1015     xLayout->setBorders( nIndex, -1, -1, -1, 0 );
1016 
1017     // setup column for preview and sub controls
1018     boost::shared_ptr< vcl::RowOrColumn > xPreview( new vcl::RowOrColumn( xPreviewAndTab.get() ) );
1019     xPreviewAndTab->addChild( xPreview, 5 );
1020     xPreview->addWindow( &maPreviewWindow, 5 );
1021     // get a row for the preview controls
1022     mxPreviewCtrls.reset( new vcl::RowOrColumn( xPreview.get(), false ) );
1023     nIndex = xPreview->addChild( mxPreviewCtrls );
1024     boost::shared_ptr< vcl::Spacer > xSpacer( new vcl::Spacer( mxPreviewCtrls.get(), 2 ) );
1025     mxPreviewCtrls->addChild( xSpacer );
1026     mxPreviewCtrls->addWindow( &maPageEdit );
1027     mxPreviewCtrls->addWindow( &maNumPagesText );
1028     xSpacer.reset( new vcl::Spacer( mxPreviewCtrls.get(), 2 ) );
1029     mxPreviewCtrls->addChild( xSpacer );
1030     mxPreviewCtrls->addWindow( &maBackwardBtn );
1031     mxPreviewCtrls->addWindow( &maForwardBtn );
1032     xSpacer.reset( new vcl::Spacer( mxPreviewCtrls.get(), 2 ) );
1033     mxPreviewCtrls->addChild( xSpacer );
1034 
1035     // continue with the tab ctrl
1036     xPreviewAndTab->addWindow( &maTabCtrl );
1037 
1038     // add the button line
1039     xLayout->addWindow( &maButtonLine );
1040 
1041     // add the row for the buttons
1042     boost::shared_ptr< vcl::RowOrColumn > xButtons( new vcl::RowOrColumn( xLayout.get(), false ) );
1043     nIndex = xLayout->addChild( xButtons );
1044     xLayout->setBorders( nIndex, -1, 0, -1, -1 );
1045 
1046     Size aMinSize( maCancelButton.GetSizePixel() );
1047     // insert help button
1048     xButtons->setMinimumSize( xButtons->addWindow( &maHelpButton ), aMinSize );
1049     // insert a spacer, cancel and OK buttons are right aligned
1050     xSpacer.reset( new vcl::Spacer( xButtons.get(), 2 ) );
1051     xButtons->addChild( xSpacer );
1052     xButtons->setMinimumSize( xButtons->addWindow( &maOKButton ), aMinSize );
1053     xButtons->setMinimumSize( xButtons->addWindow( &maCancelButton ), aMinSize );
1054 }
1055 
1056 void PrintDialog::readFromSettings()
1057 {
1058     maJobPage.readFromSettings();
1059     maNUpPage.readFromSettings();
1060     maOptionsPage.readFromSettings();
1061 
1062     // read last selected tab page; if it exists, actiavte it
1063     SettingsConfigItem* pItem = SettingsConfigItem::get();
1064     rtl::OUString aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
1065                                             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPage" ) ) );
1066     sal_uInt16 nCount = maTabCtrl.GetPageCount();
1067     for( sal_uInt16 i = 0; i < nCount; i++ )
1068     {
1069         sal_uInt16 nPageId = maTabCtrl.GetPageId( i );
1070         if( aValue.equals( maTabCtrl.GetPageText( nPageId ) ) )
1071         {
1072             maTabCtrl.SelectTabPage( nPageId );
1073             break;
1074         }
1075     }
1076     maOKButton.SetText( maOptionsPage.maToFileBox.IsChecked() ? maPrintToFileText : maPrintText );
1077 
1078     // persistent window state
1079     rtl::OUString aWinState( pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
1080                                               rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WindowState" ) ) ) );
1081     if( aWinState.getLength() )
1082         SetWindowState( rtl::OUStringToOString( aWinState, RTL_TEXTENCODING_UTF8 ) );
1083 
1084     if( maOptionsPage.maToFileBox.IsChecked() )
1085     {
1086         maPController->resetPrinterOptions( true );
1087         preparePreview( true, true );
1088     }
1089 }
1090 
1091 void PrintDialog::storeToSettings()
1092 {
1093     maJobPage.storeToSettings();
1094     maNUpPage.storeToSettings();
1095     maOptionsPage.storeToSettings();
1096 
1097     // store last selected printer
1098     SettingsConfigItem* pItem = SettingsConfigItem::get();
1099     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
1100                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPrinter" ) ),
1101                      maJobPage.maPrinters.GetSelectEntry() );
1102 
1103     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
1104                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPage" ) ),
1105                      maTabCtrl.GetPageText( maTabCtrl.GetCurPageId() ) );
1106     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
1107                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WindowState" ) ),
1108                      rtl::OStringToOUString( GetWindowState(), RTL_TEXTENCODING_UTF8 )
1109                      );
1110     pItem->Commit();
1111 }
1112 
1113 bool PrintDialog::isPrintToFile()
1114 {
1115     return maOptionsPage.maToFileBox.IsChecked();
1116 }
1117 
1118 int PrintDialog::getCopyCount()
1119 {
1120     return static_cast<int>(maJobPage.maCopyCountField.GetValue());
1121 }
1122 
1123 bool PrintDialog::isCollate()
1124 {
1125     return maJobPage.maCopyCountField.GetValue() > 1 ? maJobPage.maCollateBox.IsChecked() : sal_False;
1126 }
1127 
1128 bool PrintDialog::isSingleJobs()
1129 {
1130     return maOptionsPage.maCollateSingleJobsBox.IsChecked();
1131 }
1132 
1133 void setHelpId( Window* i_pWindow, const Sequence< rtl::OUString >& i_rHelpIds, sal_Int32 i_nIndex )
1134 {
1135     if( i_nIndex >= 0 && i_nIndex < i_rHelpIds.getLength() )
1136         i_pWindow->SetHelpId( rtl::OUStringToOString( i_rHelpIds.getConstArray()[i_nIndex], RTL_TEXTENCODING_UTF8 ) );
1137 }
1138 
1139 static void setHelpText( Window* i_pWindow, const Sequence< rtl::OUString >& i_rHelpTexts, sal_Int32 i_nIndex )
1140 {
1141     // without a help text set and the correct smartID,
1142     // help texts will be retrieved from the online help system
1143     if( i_nIndex >= 0 && i_nIndex < i_rHelpTexts.getLength() )
1144         i_pWindow->SetHelpText( i_rHelpTexts.getConstArray()[i_nIndex] );
1145 }
1146 
1147 void updateMaxSize( const Size& i_rCheckSize, Size& o_rMaxSize )
1148 {
1149     if( i_rCheckSize.Width() > o_rMaxSize.Width() )
1150         o_rMaxSize.Width() = i_rCheckSize.Width();
1151     if( i_rCheckSize.Height() > o_rMaxSize.Height() )
1152         o_rMaxSize.Height() = i_rCheckSize.Height();
1153 }
1154 
1155 void PrintDialog::setupOptionalUI()
1156 {
1157     std::vector< boost::shared_ptr<vcl::RowOrColumn> > aDynamicColumns;
1158     boost::shared_ptr< vcl::RowOrColumn > pCurColumn;
1159 
1160     Window* pCurParent = 0, *pDynamicPageParent = 0;
1161     sal_uInt16 nOptPageId = 9, nCurSubGroup = 0;
1162     bool bOnStaticPage = false;
1163     bool bSubgroupOnStaticPage = false;
1164 
1165     std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> > aPropertyToDependencyRowMap;
1166 
1167     const Sequence< PropertyValue >& rOptions( maPController->getUIOptions() );
1168     for( int i = 0; i < rOptions.getLength(); i++ )
1169     {
1170         Sequence< beans::PropertyValue > aOptProp;
1171         rOptions[i].Value >>= aOptProp;
1172 
1173         // extract ui element
1174         bool bEnabled = true;
1175         rtl::OUString aCtrlType;
1176         rtl::OUString aText;
1177         rtl::OUString aPropertyName;
1178         Sequence< rtl::OUString > aChoices;
1179         Sequence< sal_Bool > aChoicesDisabled;
1180         Sequence< rtl::OUString > aHelpTexts;
1181         Sequence< rtl::OUString > aHelpIds;
1182         sal_Int64 nMinValue = 0, nMaxValue = 0;
1183         sal_Int32 nCurHelpText = 0;
1184         rtl::OUString aGroupingHint;
1185         rtl::OUString aDependsOnName;
1186         sal_Int32 nDependsOnValue = 0;
1187         sal_Bool bUseDependencyRow = sal_False;
1188 
1189         for( int n = 0; n < aOptProp.getLength(); n++ )
1190         {
1191             const beans::PropertyValue& rEntry( aOptProp[ n ] );
1192             if( rEntry.Name.equalsAscii( "Text" ) )
1193             {
1194                 rEntry.Value >>= aText;
1195             }
1196             else if( rEntry.Name.equalsAscii( "ControlType" ) )
1197             {
1198                 rEntry.Value >>= aCtrlType;
1199             }
1200             else if( rEntry.Name.equalsAscii( "Choices" ) )
1201             {
1202                 rEntry.Value >>= aChoices;
1203             }
1204             else if( rEntry.Name.equalsAscii( "ChoicesDisabled" ) )
1205             {
1206                 rEntry.Value >>= aChoicesDisabled;
1207             }
1208             else if( rEntry.Name.equalsAscii( "Property" ) )
1209             {
1210                 PropertyValue aVal;
1211                 rEntry.Value >>= aVal;
1212                 aPropertyName = aVal.Name;
1213             }
1214             else if( rEntry.Name.equalsAscii( "Enabled" ) )
1215             {
1216                 sal_Bool bValue = sal_True;
1217                 rEntry.Value >>= bValue;
1218                 bEnabled = bValue;
1219             }
1220             else if( rEntry.Name.equalsAscii( "GroupingHint" ) )
1221             {
1222                 rEntry.Value >>= aGroupingHint;
1223             }
1224             else if( rEntry.Name.equalsAscii( "DependsOnName" ) )
1225             {
1226                 rEntry.Value >>= aDependsOnName;
1227             }
1228             else if( rEntry.Name.equalsAscii( "DependsOnEntry" ) )
1229             {
1230                 rEntry.Value >>= nDependsOnValue;
1231             }
1232             else if( rEntry.Name.equalsAscii( "AttachToDependency" ) )
1233             {
1234                 rEntry.Value >>= bUseDependencyRow;
1235             }
1236             else if( rEntry.Name.equalsAscii( "MinValue" ) )
1237             {
1238                 rEntry.Value >>= nMinValue;
1239             }
1240             else if( rEntry.Name.equalsAscii( "MaxValue" ) )
1241             {
1242                 rEntry.Value >>= nMaxValue;
1243             }
1244             else if( rEntry.Name.equalsAscii( "HelpText" ) )
1245             {
1246                 if( ! (rEntry.Value >>= aHelpTexts) )
1247                 {
1248                     rtl::OUString aHelpText;
1249                     if( (rEntry.Value >>= aHelpText) )
1250                     {
1251                         aHelpTexts.realloc( 1 );
1252                         *aHelpTexts.getArray() = aHelpText;
1253                     }
1254                 }
1255             }
1256             else if( rEntry.Name.equalsAscii( "HelpId" ) )
1257             {
1258                 if( ! (rEntry.Value >>= aHelpIds ) )
1259                 {
1260                     rtl::OUString aHelpId;
1261                     if( (rEntry.Value >>= aHelpId) )
1262                     {
1263                         aHelpIds.realloc( 1 );
1264                         *aHelpIds.getArray() = aHelpId;
1265                     }
1266                 }
1267             }
1268             else if( rEntry.Name.equalsAscii( "HintNoLayoutPage" ) )
1269             {
1270                 sal_Bool bNoLayoutPage = sal_False;
1271                 rEntry.Value >>= bNoLayoutPage;
1272                 mbShowLayoutPage = ! bNoLayoutPage;
1273             }
1274         }
1275 
1276         // bUseDependencyRow should only be true if a dependency exists
1277         bUseDependencyRow = bUseDependencyRow && (aDependsOnName.getLength() != 0);
1278 
1279         // is it necessary to switch between static and dynamic pages ?
1280         bool bSwitchPage = false;
1281         if( aGroupingHint.getLength() )
1282             bSwitchPage = true;
1283         else if( aCtrlType.equalsAscii( "Subgroup" ) || (bOnStaticPage && ! bSubgroupOnStaticPage )  )
1284             bSwitchPage = true;
1285         if( bSwitchPage )
1286         {
1287             // restore to dynamic
1288             pCurParent = pDynamicPageParent;
1289             if( ! aDynamicColumns.empty() )
1290                 pCurColumn = aDynamicColumns.back();
1291             else
1292                 pCurColumn.reset();
1293             bOnStaticPage = false;
1294             bSubgroupOnStaticPage = false;
1295 
1296             if( aGroupingHint.equalsAscii( "PrintRange" ) )
1297             {
1298                 pCurColumn = maJobPage.mxPrintRange;
1299                 pCurParent = &maJobPage;            // set job page as current parent
1300                 bOnStaticPage = true;
1301             }
1302             else if( aGroupingHint.equalsAscii( "OptionsPage" ) )
1303             {
1304                 pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maOptionsPage.getLayout());
1305                 pCurParent = &maOptionsPage;        // set options page as current parent
1306                 bOnStaticPage = true;
1307             }
1308             else if( aGroupingHint.equalsAscii( "OptionsPageOptGroup" ) )
1309             {
1310                 pCurColumn = maOptionsPage.mxOptGroup;
1311                 pCurParent = &maOptionsPage;        // set options page as current parent
1312                 bOnStaticPage = true;
1313             }
1314             else if( aGroupingHint.equalsAscii( "LayoutPage" ) )
1315             {
1316                 pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maNUpPage.getLayout());
1317                 pCurParent = &maNUpPage;            // set layout page as current parent
1318                 bOnStaticPage = true;
1319             }
1320             else if( aGroupingHint.getLength() )
1321             {
1322                 pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maJobPage.getLayout());
1323                 pCurParent = &maJobPage;            // set job page as current parent
1324                 bOnStaticPage = true;
1325             }
1326         }
1327 
1328         if( aCtrlType.equalsAscii( "Group" ) ||
1329             ( ! pCurParent && ! (bOnStaticPage || aGroupingHint.getLength() ) ) )
1330         {
1331             // add new tab page
1332             TabPage* pNewGroup = new TabPage( &maTabCtrl );
1333             maControls.push_front( pNewGroup );
1334             pDynamicPageParent = pCurParent = pNewGroup;
1335             pNewGroup->SetText( aText );
1336             maTabCtrl.InsertPage( ++nOptPageId, aText );
1337             maTabCtrl.SetTabPage( nOptPageId, pNewGroup );
1338 
1339             // set help id
1340             setHelpId( pNewGroup, aHelpIds, 0 );
1341             // set help text
1342             setHelpText( pNewGroup, aHelpTexts, 0 );
1343 
1344             // reset subgroup counter
1345             nCurSubGroup = 0;
1346 
1347             aDynamicColumns.push_back( boost::dynamic_pointer_cast<vcl::RowOrColumn>(pNewGroup->getLayout()) );
1348             pCurColumn = aDynamicColumns.back();
1349             pCurColumn->setParentWindow( pNewGroup );
1350             bSubgroupOnStaticPage = false;
1351             bOnStaticPage = false;
1352         }
1353         else if( aCtrlType.equalsAscii( "Subgroup" ) && (pCurParent || aGroupingHint.getLength() ) )
1354         {
1355             bSubgroupOnStaticPage = (aGroupingHint.getLength() != 0);
1356             // create group FixedLine
1357             if( ! aGroupingHint.equalsAscii( "PrintRange" ) ||
1358                 ! pCurColumn->countElements() == 0
1359                )
1360             {
1361                 Window* pNewSub = NULL;
1362                 if( aGroupingHint.equalsAscii( "PrintRange" ) )
1363                     pNewSub = new FixedText( pCurParent, WB_VCENTER );
1364                 else
1365                     pNewSub = new FixedLine( pCurParent );
1366                 maControls.push_front( pNewSub );
1367                 pNewSub->SetText( aText );
1368                 pNewSub->Show();
1369 
1370                 // set help id
1371                 setHelpId( pNewSub, aHelpIds, 0 );
1372                 // set help text
1373                 setHelpText( pNewSub, aHelpTexts, 0 );
1374                 // add group to current column
1375                 pCurColumn->addWindow( pNewSub );
1376             }
1377 
1378             // add an indent to the current column
1379             vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn.get(), -1 );
1380             pCurColumn->addChild( pIndent );
1381             // and create a column inside the indent
1382             pCurColumn.reset( new vcl::RowOrColumn( pIndent ) );
1383             pIndent->setChild( pCurColumn );
1384         }
1385         // EVIL
1386         else if( aCtrlType.equalsAscii( "Bool" ) &&
1387                  aGroupingHint.equalsAscii( "LayoutPage" ) &&
1388                  aPropertyName.equalsAscii( "PrintProspect" )
1389                  )
1390         {
1391             maNUpPage.maBrochureBtn.SetText( aText );
1392             maNUpPage.maBrochureBtn.Show();
1393             setHelpText( &maNUpPage.maBrochureBtn, aHelpTexts, 0 );
1394 
1395             sal_Bool bVal = sal_False;
1396             PropertyValue* pVal = maPController->getValue( aPropertyName );
1397             if( pVal )
1398                 pVal->Value >>= bVal;
1399             maNUpPage.maBrochureBtn.Check( bVal );
1400             maNUpPage.maBrochureBtn.Enable( maPController->isUIOptionEnabled( aPropertyName ) && pVal != NULL );
1401             maNUpPage.maBrochureBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
1402 
1403             maPropertyToWindowMap[ aPropertyName ].push_back( &maNUpPage.maBrochureBtn );
1404             maControlToPropertyMap[&maNUpPage.maBrochureBtn] = aPropertyName;
1405 
1406             aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, maNUpPage.mxBrochureDep ) );
1407         }
1408         else
1409         {
1410             boost::shared_ptr<vcl::RowOrColumn> pSaveCurColumn( pCurColumn );
1411 
1412             if( bUseDependencyRow )
1413             {
1414                 // find the correct dependency row (if any)
1415                 std::pair< std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >::iterator,
1416                            std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >::iterator > aDepRange;
1417                 aDepRange = aPropertyToDependencyRowMap.equal_range( aDependsOnName );
1418                 if( aDepRange.first != aDepRange.second )
1419                 {
1420                     while( nDependsOnValue && aDepRange.first != aDepRange.second )
1421                     {
1422                         nDependsOnValue--;
1423                         ++aDepRange.first;
1424                     }
1425                     if( aDepRange.first != aPropertyToDependencyRowMap.end() )
1426                     {
1427                         pCurColumn = aDepRange.first->second;
1428                         maReverseDependencySet.insert( aPropertyName );
1429                     }
1430                 }
1431             }
1432             if( aCtrlType.equalsAscii( "Bool" ) && pCurParent )
1433             {
1434                 // add a check box
1435                 CheckBox* pNewBox = new CheckBox( pCurParent );
1436                 maControls.push_front( pNewBox );
1437                 pNewBox->SetText( aText );
1438                 pNewBox->Show();
1439 
1440                 sal_Bool bVal = sal_False;
1441                 PropertyValue* pVal = maPController->getValue( aPropertyName );
1442                 if( pVal )
1443                     pVal->Value >>= bVal;
1444                 pNewBox->Check( bVal );
1445                 pNewBox->SetToggleHdl( LINK( this, PrintDialog, UIOption_CheckHdl ) );
1446 
1447                 maPropertyToWindowMap[ aPropertyName ].push_back( pNewBox );
1448                 maControlToPropertyMap[pNewBox] = aPropertyName;
1449 
1450                 // set help id
1451                 setHelpId( pNewBox, aHelpIds, 0 );
1452                 // set help text
1453                 setHelpText( pNewBox, aHelpTexts, 0 );
1454 
1455                 boost::shared_ptr<vcl::RowOrColumn> pDependencyRow( new vcl::RowOrColumn( pCurColumn.get(), false ) );
1456                 pCurColumn->addChild( pDependencyRow );
1457                 aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pDependencyRow ) );
1458 
1459                 // add checkbox to current column
1460                 pDependencyRow->addWindow( pNewBox );
1461             }
1462             else if( aCtrlType.equalsAscii( "Radio" ) && pCurParent )
1463             {
1464                 boost::shared_ptr<vcl::RowOrColumn> pRadioColumn( pCurColumn );
1465                 if( aText.getLength() )
1466                 {
1467                     // add a FixedText:
1468                     FixedText* pHeading = new FixedText( pCurParent );
1469                     maControls.push_front( pHeading );
1470                     pHeading->SetText( aText );
1471                     pHeading->Show();
1472 
1473                     // set help id
1474                     setHelpId( pHeading, aHelpIds, nCurHelpText );
1475                     // set help text
1476                     setHelpText( pHeading, aHelpTexts, nCurHelpText );
1477                     nCurHelpText++;
1478                     // add fixed text to current column
1479                     pCurColumn->addWindow( pHeading );
1480                     // add an indent to the current column
1481                     vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn.get(), 15 );
1482                     pCurColumn->addChild( pIndent );
1483                     // and create a column inside the indent
1484                     pRadioColumn.reset( new vcl::RowOrColumn( pIndent ) );
1485                     pIndent->setChild( pRadioColumn );
1486                 }
1487                 // iterate options
1488                 sal_Int32 nSelectVal = 0;
1489                 PropertyValue* pVal = maPController->getValue( aPropertyName );
1490                 if( pVal && pVal->Value.hasValue() )
1491                     pVal->Value >>= nSelectVal;
1492                 for( sal_Int32 m = 0; m < aChoices.getLength(); m++ )
1493                 {
1494                     boost::shared_ptr<vcl::LabeledElement> pLabel( new vcl::LabeledElement( pRadioColumn.get(), 1 ) );
1495                     pRadioColumn->addChild( pLabel );
1496                     boost::shared_ptr<vcl::RowOrColumn> pDependencyRow( new vcl::RowOrColumn( pLabel.get(), false ) );
1497                     pLabel->setElement( pDependencyRow );
1498                     aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pDependencyRow ) );
1499 
1500                     RadioButton* pBtn = new RadioButton( pCurParent, m == 0 ? WB_GROUP : 0 );
1501                     maControls.push_front( pBtn );
1502                     pBtn->SetText( aChoices[m] );
1503                     pBtn->Check( m == nSelectVal );
1504                     pBtn->SetToggleHdl( LINK( this, PrintDialog, UIOption_RadioHdl ) );
1505                     if( aChoicesDisabled.getLength() > m && aChoicesDisabled[m] == sal_True )
1506                         pBtn->Enable( sal_False );
1507                     pBtn->Show();
1508                     maPropertyToWindowMap[ aPropertyName ].push_back( pBtn );
1509                     maControlToPropertyMap[pBtn] = aPropertyName;
1510                     maControlToNumValMap[pBtn] = m;
1511 
1512                     // set help id
1513                     setHelpId( pBtn, aHelpIds, nCurHelpText );
1514                     // set help text
1515                     setHelpText( pBtn, aHelpTexts, nCurHelpText );
1516                     nCurHelpText++;
1517                     // add the radio button to the column
1518                     pLabel->setLabel( pBtn );
1519                 }
1520             }
1521             else if( ( aCtrlType.equalsAscii( "List" )   ||
1522                        aCtrlType.equalsAscii( "Range" )  ||
1523                        aCtrlType.equalsAscii( "Edit" )
1524                      ) && pCurParent )
1525             {
1526                 // create a row in the current column
1527                 boost::shared_ptr<vcl::RowOrColumn> pFieldColumn( new vcl::RowOrColumn( pCurColumn.get(), false ) );
1528                 pCurColumn->addChild( pFieldColumn );
1529                 aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pFieldColumn ) );
1530 
1531                 vcl::LabeledElement* pLabel = NULL;
1532                 if( aText.getLength() )
1533                 {
1534                     // add a FixedText:
1535                     FixedText* pHeading = new FixedText( pCurParent, WB_VCENTER );
1536                     maControls.push_front( pHeading );
1537                     pHeading->SetText( aText );
1538                     pHeading->Show();
1539 
1540                     // add to row
1541                     pLabel = new vcl::LabeledElement( pFieldColumn.get(), 2 );
1542                     pFieldColumn->addChild( pLabel );
1543                     pLabel->setLabel( pHeading );
1544                 }
1545 
1546                 if( aCtrlType.equalsAscii( "List" ) )
1547                 {
1548                     ListBox* pList = new ListBox( pCurParent, WB_DROPDOWN | WB_BORDER );
1549                     maControls.push_front( pList );
1550 
1551                     // iterate options
1552                     for( sal_Int32 m = 0; m < aChoices.getLength(); m++ )
1553                     {
1554                         pList->InsertEntry( aChoices[m] );
1555                     }
1556                     sal_Int32 nSelectVal = 0;
1557                     PropertyValue* pVal = maPController->getValue( aPropertyName );
1558                     if( pVal && pVal->Value.hasValue() )
1559                         pVal->Value >>= nSelectVal;
1560                     pList->SelectEntryPos( static_cast<sal_uInt16>(nSelectVal) );
1561                     pList->SetSelectHdl( LINK( this, PrintDialog, UIOption_SelectHdl ) );
1562                     pList->SetDropDownLineCount( static_cast<sal_uInt16>(aChoices.getLength()) );
1563                     pList->Show();
1564 
1565                     // set help id
1566                     setHelpId( pList, aHelpIds, 0 );
1567                     // set help text
1568                     setHelpText( pList, aHelpTexts, 0 );
1569 
1570                     maPropertyToWindowMap[ aPropertyName ].push_back( pList );
1571                     maControlToPropertyMap[pList] = aPropertyName;
1572 
1573                     // finish the pair
1574                     if( pLabel )
1575                         pLabel->setElement( pList );
1576                     else
1577                         pFieldColumn->addWindow( pList );
1578                 }
1579                 else if( aCtrlType.equalsAscii( "Range" ) )
1580                 {
1581                     NumericField* pField = new NumericField( pCurParent, WB_BORDER | WB_SPIN );
1582                     maControls.push_front( pField );
1583 
1584                     // set min/max and current value
1585                     if( nMinValue != nMaxValue )
1586                     {
1587                         pField->SetMin( nMinValue );
1588                         pField->SetMax( nMaxValue );
1589                     }
1590                     sal_Int64 nCurVal = 0;
1591                     PropertyValue* pVal = maPController->getValue( aPropertyName );
1592                     if( pVal && pVal->Value.hasValue() )
1593                         pVal->Value >>= nCurVal;
1594                     pField->SetValue( nCurVal );
1595                     pField->SetModifyHdl( LINK( this, PrintDialog, UIOption_ModifyHdl ) );
1596                     pField->Show();
1597 
1598                     // set help id
1599                     setHelpId( pField, aHelpIds, 0 );
1600                     // set help text
1601                     setHelpText( pField, aHelpTexts, 0 );
1602 
1603                     maPropertyToWindowMap[ aPropertyName ].push_back( pField );
1604                     maControlToPropertyMap[pField] = aPropertyName;
1605 
1606                     // add to row
1607                     if( pLabel )
1608                         pLabel->setElement( pField );
1609                     else
1610                         pFieldColumn->addWindow( pField );
1611                 }
1612                 else if( aCtrlType.equalsAscii( "Edit" ) )
1613                 {
1614                     Edit* pField = new Edit( pCurParent, WB_BORDER );
1615                     maControls.push_front( pField );
1616 
1617                     rtl::OUString aCurVal;
1618                     PropertyValue* pVal = maPController->getValue( aPropertyName );
1619                     if( pVal && pVal->Value.hasValue() )
1620                         pVal->Value >>= aCurVal;
1621                     pField->SetText( aCurVal );
1622                     pField->SetModifyHdl( LINK( this, PrintDialog, UIOption_ModifyHdl ) );
1623                     pField->Show();
1624 
1625                     // set help id
1626                     setHelpId( pField, aHelpIds, 0 );
1627                     // set help text
1628                     setHelpText( pField, aHelpTexts, 0 );
1629 
1630                     maPropertyToWindowMap[ aPropertyName ].push_back( pField );
1631                     maControlToPropertyMap[pField] = aPropertyName;
1632 
1633                     // add to row
1634                     if( pLabel )
1635                         pLabel->setElement( pField );
1636                     else
1637                         pFieldColumn->addWindow( pField, 2 );
1638                 }
1639             }
1640             else
1641             {
1642                 DBG_ERROR( "Unsupported UI option" );
1643             }
1644 
1645             pCurColumn = pSaveCurColumn;
1646         }
1647     }
1648 
1649     // #i106506# if no brochure button, then the singular Pages radio button
1650     // makes no sense, so replace it by a FixedText label
1651     if( ! maNUpPage.maBrochureBtn.IsVisible() )
1652     {
1653         if( maNUpPage.mxPagesBtnLabel.get() )
1654         {
1655             maNUpPage.maPagesBoxTitleTxt.SetText( maNUpPage.maPagesBtn.GetText() );
1656             maNUpPage.maPagesBoxTitleTxt.Show( sal_True );
1657             maNUpPage.mxPagesBtnLabel->setLabel( &maNUpPage.maPagesBoxTitleTxt );
1658             maNUpPage.maPagesBtn.Show( sal_False );
1659         }
1660     }
1661 
1662     // update enable states
1663     checkOptionalControlDependencies();
1664 
1665     // print range empty (currently math only) -> hide print range and spacer line
1666     if( maJobPage.mxPrintRange->countElements() == 0 )
1667     {
1668         maJobPage.mxPrintRange->show( false, false );
1669         maJobPage.maCopySpacer.Show( sal_False );
1670         maJobPage.maReverseOrderBox.Show( sal_False );
1671     }
1672     else
1673     {
1674         // add an indent to the current column
1675         vcl::Indenter* pIndent = new vcl::Indenter( maJobPage.mxPrintRange.get(), -1 );
1676         maJobPage.mxPrintRange->addChild( pIndent );
1677         // and create a column inside the indent
1678         pIndent->setWindow( &maJobPage.maReverseOrderBox );
1679         maJobPage.maReverseOrderBox.Show( sal_True );
1680     }
1681 
1682 #ifdef WNT
1683     // FIXME: the GetNativeControlRegion call on Windows has some issues
1684     // (which skew the results of GetOptimalSize())
1685     // however fixing this thoroughly needs to take interaction with paint into
1686     // account, making the right fix less simple. Fix this the right way
1687     // at some point. For now simply add some space at the lowest element
1688     size_t nIndex = maJobPage.getLayout()->countElements();
1689     if( nIndex > 0 ) // sanity check
1690         maJobPage.getLayout()->setBorders( nIndex-1, 0, 0, 0, -1 );
1691 #endif
1692 
1693     // create auto mnemomnics now so they can be calculated in layout
1694     ImplWindowAutoMnemonic( &maJobPage );
1695     ImplWindowAutoMnemonic( &maNUpPage );
1696     ImplWindowAutoMnemonic( &maOptionsPage );
1697     ImplWindowAutoMnemonic( this );
1698 
1699     // calculate job page
1700     Size aMaxSize = maJobPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED );
1701     // and layout page
1702     updateMaxSize( maNUpPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
1703     // and options page
1704     updateMaxSize( maOptionsPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
1705 
1706     for( std::vector< boost::shared_ptr<vcl::RowOrColumn> >::iterator it = aDynamicColumns.begin();
1707          it != aDynamicColumns.end(); ++it )
1708     {
1709         Size aPageSize( (*it)->getOptimalSize( WINDOWSIZE_PREFERRED ) );
1710         updateMaxSize( aPageSize, aMaxSize );
1711     }
1712 
1713     // resize dialog if necessary
1714     Size aTabSize = maTabCtrl.GetTabPageSizePixel();
1715     maTabCtrl.SetMinimumSizePixel( maTabCtrl.GetSizePixel() );
1716     if( aMaxSize.Height() > aTabSize.Height() || aMaxSize.Width() > aTabSize.Width() )
1717     {
1718         Size aCurSize( GetOutputSizePixel() );
1719         if( aMaxSize.Height() > aTabSize.Height() )
1720 		{
1721             aCurSize.Height() += aMaxSize.Height() - aTabSize.Height();
1722 			aTabSize.Height() = aMaxSize.Height();
1723 		}
1724         if( aMaxSize.Width() > aTabSize.Width() )
1725         {
1726             aCurSize.Width() += aMaxSize.Width() - aTabSize.Width();
1727             // and the tab ctrl needs more space, too
1728             aTabSize.Width() = aMaxSize.Width();
1729         }
1730         maTabCtrl.SetTabPageSizePixel( aTabSize );
1731         maTabCtrl.SetMinimumSizePixel( maTabCtrl.GetSizePixel() );
1732     }
1733 
1734     Size aSz = getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED );
1735     SetOutputSizePixel( aSz );
1736 }
1737 
1738 void PrintDialog::DataChanged( const DataChangedEvent& i_rDCEvt )
1739 {
1740     // react on settings changed
1741     if( i_rDCEvt.GetType() == DATACHANGED_SETTINGS )
1742         checkControlDependencies();
1743     ModalDialog::DataChanged( i_rDCEvt );
1744 }
1745 
1746 void PrintDialog::checkControlDependencies()
1747 {
1748     if( maJobPage.maCopyCountField.GetValue() > 1 )
1749         maJobPage.maCollateBox.Enable( maJobPage.mnCollateUIMode == 0 );
1750     else
1751         maJobPage.maCollateBox.Enable( sal_False );
1752 
1753     Image aImg( maJobPage.maCollateBox.IsChecked() ? maJobPage.maCollateImg : maJobPage.maNoCollateImg );
1754     Image aHCImg( maJobPage.maCollateBox.IsChecked() ? maJobPage.maCollateHCImg : maJobPage.maNoCollateHCImg );
1755     bool bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
1756 
1757     Size aImgSize( aImg.GetSizePixel() );
1758     Size aHCImgSize( aHCImg.GetSizePixel() );
1759 
1760     if( aHCImgSize.Width() > aImgSize.Width() )
1761         aImgSize.Width() = aHCImgSize.Width();
1762     if( aHCImgSize.Height() > aImgSize.Height() )
1763         aImgSize.Height() = aHCImgSize.Height();
1764 
1765     // adjust size of image
1766     maJobPage.maCollateImage.SetSizePixel( aImgSize );
1767     maJobPage.maCollateImage.SetImage( bHC ? aHCImg : aImg );
1768     maJobPage.maCollateImage.SetModeImage( aHCImg, BMP_COLOR_HIGHCONTRAST );
1769     maJobPage.getLayout()->resize();
1770 
1771     // enable setup button only for printers that can be setup
1772     bool bHaveSetup = maPController->getPrinter()->HasSupport( SUPPORT_SETUPDIALOG );
1773     maJobPage.maSetupButton.Enable( bHaveSetup );
1774     if( bHaveSetup )
1775     {
1776         if( ! maJobPage.maSetupButton.IsVisible() )
1777         {
1778             Point aPrinterPos( maJobPage.maPrinters.GetPosPixel() );
1779             Point aSetupPos( maJobPage.maSetupButton.GetPosPixel() );
1780             Size aPrinterSize( maJobPage.maPrinters.GetSizePixel() );
1781             aPrinterSize.Width() = aSetupPos.X() - aPrinterPos.X() - LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ).Width();
1782             maJobPage.maPrinters.SetSizePixel( aPrinterSize );
1783             maJobPage.maSetupButton.Show();
1784             getLayout()->resize();
1785         }
1786     }
1787     else
1788     {
1789         if( maJobPage.maSetupButton.IsVisible() )
1790         {
1791             Point aPrinterPos( maJobPage.maPrinters.GetPosPixel() );
1792             Point aSetupPos( maJobPage.maSetupButton.GetPosPixel() );
1793             Size aPrinterSize( maJobPage.maPrinters.GetSizePixel() );
1794             Size aSetupSize( maJobPage.maSetupButton.GetSizePixel() );
1795             aPrinterSize.Width() = aSetupPos.X() + aSetupSize.Width() - aPrinterPos.X();
1796             maJobPage.maPrinters.SetSizePixel( aPrinterSize );
1797             maJobPage.maSetupButton.Hide();
1798             getLayout()->resize();
1799         }
1800     }
1801 }
1802 
1803 void PrintDialog::checkOptionalControlDependencies()
1804 {
1805     for( std::map< Window*, rtl::OUString >::iterator it = maControlToPropertyMap.begin();
1806          it != maControlToPropertyMap.end(); ++it )
1807     {
1808         bool bShouldbeEnabled = maPController->isUIOptionEnabled( it->second );
1809         if( ! bShouldbeEnabled )
1810         {
1811             // enable controls that are directly attached to a dependency anyway
1812             // if the normally disabled controls get modified, change the dependency
1813             // so the control would be enabled
1814             // example: in print range "Print All" is selected, "Page Range" is then of course
1815             // not selected and the Edit for the Page Range would be disabled
1816             // as a convenience we should enable the Edit anyway and automatically select
1817             // "Page Range" instead of "Print All" if the Edit gets modified
1818             if( maReverseDependencySet.find( it->second ) != maReverseDependencySet.end() )
1819             {
1820                 rtl::OUString aDep( maPController->getDependency( it->second ) );
1821                 // if the dependency is at least enabled, then enable this control anyway
1822                 if( aDep.getLength() && maPController->isUIOptionEnabled( aDep ) )
1823                     bShouldbeEnabled = true;
1824             }
1825         }
1826 
1827         if( bShouldbeEnabled && dynamic_cast<RadioButton*>(it->first) )
1828         {
1829             std::map< Window*, sal_Int32 >::const_iterator r_it = maControlToNumValMap.find( it->first );
1830             if( r_it != maControlToNumValMap.end() )
1831             {
1832                 bShouldbeEnabled = maPController->isUIChoiceEnabled( it->second, r_it->second );
1833             }
1834         }
1835 
1836 
1837         bool bIsEnabled = it->first->IsEnabled();
1838         // Enable does not do a change check first, so can be less cheap than expected
1839         if( bShouldbeEnabled != bIsEnabled )
1840             it->first->Enable( bShouldbeEnabled );
1841     }
1842 }
1843 
1844 static rtl::OUString searchAndReplace( const rtl::OUString& i_rOrig, const char* i_pRepl, sal_Int32 i_nReplLen, const rtl::OUString& i_rRepl )
1845 {
1846     sal_Int32 nPos = i_rOrig.indexOfAsciiL( i_pRepl, i_nReplLen );
1847     if( nPos != -1 )
1848     {
1849         rtl::OUStringBuffer aBuf( i_rOrig.getLength() );
1850         aBuf.append( i_rOrig.getStr(), nPos );
1851         aBuf.append( i_rRepl );
1852         if( nPos + i_nReplLen < i_rOrig.getLength() )
1853             aBuf.append( i_rOrig.getStr() + nPos + i_nReplLen );
1854         return aBuf.makeStringAndClear();
1855     }
1856     return i_rOrig;
1857 }
1858 
1859 void PrintDialog::updatePrinterText()
1860 {
1861     String aDefPrt( Printer::GetDefaultPrinterName() );
1862     const QueueInfo* pInfo = Printer::GetQueueInfo( maJobPage.maPrinters.GetSelectEntry(), true );
1863     if( pInfo )
1864     {
1865         maJobPage.maLocationTxt.SetText( pInfo->GetLocation() );
1866         maJobPage.maCommentTxt.SetText( pInfo->GetComment() );
1867         // FIXME: status text
1868         rtl::OUString aStatus;
1869         if( aDefPrt == pInfo->GetPrinterName() )
1870             aStatus = maDefPrtText;
1871         maJobPage.maStatusTxt.SetText( aStatus );
1872     }
1873     else
1874     {
1875         maJobPage.maLocationTxt.SetText( String() );
1876         maJobPage.maCommentTxt.SetText( String() );
1877         maJobPage.maStatusTxt.SetText( String() );
1878     }
1879 }
1880 
1881 void PrintDialog::setPreviewText( sal_Int32 )
1882 {
1883     rtl::OUString aNewText( searchAndReplace( maPageStr, "%n", 2, rtl::OUString::valueOf( mnCachedPages )  ) );
1884     maNumPagesText.SetText( aNewText );
1885 
1886     // if layout is already established the refresh layout of
1887     // preview controls since text length may have changes
1888     if( mxPreviewCtrls.get() )
1889         mxPreviewCtrls->setManagedArea( mxPreviewCtrls->getManagedArea() );
1890 }
1891 
1892 void PrintDialog::preparePreview( bool i_bNewPage, bool i_bMayUseCache )
1893 {
1894     // page range may have changed depending on options
1895     sal_Int32 nPages = maPController->getFilteredPageCount();
1896     mnCachedPages = nPages;
1897 
1898     if( mnCurPage >= nPages )
1899         mnCurPage = nPages-1;
1900     if( mnCurPage < 0 )
1901         mnCurPage = 0;
1902 
1903     setPreviewText( mnCurPage );
1904 
1905     maPageEdit.SetMin( 1 );
1906     maPageEdit.SetMax( nPages );
1907 
1908     if( i_bNewPage )
1909     {
1910         const MapMode aMapMode( MAP_100TH_MM );
1911         GDIMetaFile aMtf;
1912         boost::shared_ptr<Printer> aPrt( maPController->getPrinter() );
1913         if( nPages > 0 )
1914         {
1915             PrinterController::PageSize aPageSize =
1916                 maPController->getFilteredPageFile( mnCurPage, aMtf, i_bMayUseCache );
1917             if( ! aPageSize.bFullPaper )
1918             {
1919                 Point aOff( aPrt->PixelToLogic( aPrt->GetPageOffsetPixel(), aMapMode ) );
1920                 aMtf.Move( aOff.X(), aOff.Y() );
1921             }
1922         }
1923 
1924         Size aCurPageSize = aPrt->PixelToLogic( aPrt->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) );
1925         maPreviewWindow.setPreview( aMtf, aCurPageSize,
1926                                     aPrt->GetPaperName( false ),
1927                                     nPages > 0 ? rtl::OUString() : maNoPageStr,
1928                                     aPrt->ImplGetDPIX(), aPrt->ImplGetDPIY(),
1929                                     aPrt->GetPrinterOptions().IsConvertToGreyscales()
1930                                    );
1931 
1932         maForwardBtn.Enable( mnCurPage < nPages-1 );
1933         maBackwardBtn.Enable( mnCurPage != 0 );
1934         maPageEdit.Enable( nPages > 1 );
1935     }
1936 }
1937 
1938 Size PrintDialog::getJobPageSize()
1939 {
1940     if( maFirstPageSize.Width() == 0 && maFirstPageSize.Height() == 0)
1941     {
1942         maFirstPageSize = maNupPortraitSize;
1943         GDIMetaFile aMtf;
1944         if( maPController->getPageCountProtected() > 0 )
1945         {
1946             PrinterController::PageSize aPageSize = maPController->getPageFile( 0, aMtf, true );
1947             maFirstPageSize = aPageSize.aSize;
1948         }
1949     }
1950     return maFirstPageSize;
1951 }
1952 
1953 void PrintDialog::updateNupFromPages()
1954 {
1955     long nPages = long(maNUpPage.maNupPagesBox.GetEntryData(maNUpPage.maNupPagesBox.GetSelectEntryPos()));
1956     int nRows   = int(maNUpPage.maNupRowsEdt.GetValue());
1957     int nCols   = int(maNUpPage.maNupColEdt.GetValue());
1958     long nPageMargin  = long(maNUpPage.maPageMarginEdt.Denormalize(maNUpPage.maPageMarginEdt.GetValue( FUNIT_100TH_MM )));
1959     long nSheetMargin = long(maNUpPage.maSheetMarginEdt.Denormalize(maNUpPage.maSheetMarginEdt.GetValue( FUNIT_100TH_MM )));
1960     bool bCustom = false;
1961 
1962     if( nPages == 1 )
1963     {
1964         nRows = nCols = 1;
1965         nSheetMargin = 0;
1966         nPageMargin = 0;
1967     }
1968     else if( nPages == 2 || nPages == 4 || nPages == 6 || nPages == 9 || nPages == 16 )
1969     {
1970         Size aJobPageSize( getJobPageSize() );
1971         bool bPortrait = aJobPageSize.Width() < aJobPageSize.Height();
1972         if( nPages == 2 )
1973         {
1974             if( bPortrait )
1975                 nRows = 1, nCols = 2;
1976             else
1977                 nRows = 2, nCols = 1;
1978         }
1979         else if( nPages == 4 )
1980             nRows = nCols = 2;
1981         else if( nPages == 6 )
1982         {
1983             if( bPortrait )
1984                 nRows = 2, nCols = 3;
1985             else
1986                 nRows = 3, nCols = 2;
1987         }
1988         else if( nPages == 9 )
1989             nRows = nCols = 3;
1990         else if( nPages == 16 )
1991             nRows = nCols = 4;
1992         nPageMargin = 0;
1993         nSheetMargin = 0;
1994     }
1995     else
1996         bCustom = true;
1997 
1998     if( nPages > 1 )
1999     {
2000         // set upper limits for margins based on job page size and rows/columns
2001         Size aSize( getJobPageSize() );
2002 
2003         // maximum sheet distance: 1/2 sheet
2004         long nHorzMax = aSize.Width()/2;
2005         long nVertMax = aSize.Height()/2;
2006         if( nSheetMargin > nHorzMax )
2007             nSheetMargin = nHorzMax;
2008         if( nSheetMargin > nVertMax )
2009             nSheetMargin = nVertMax;
2010 
2011         maNUpPage.maSheetMarginEdt.SetMax(
2012                   maNUpPage.maSheetMarginEdt.Normalize(
2013                            nHorzMax > nVertMax ? nVertMax : nHorzMax ), FUNIT_100TH_MM );
2014 
2015         // maximum page distance
2016         nHorzMax = (aSize.Width() - 2*nSheetMargin);
2017         if( nCols > 1 )
2018             nHorzMax /= (nCols-1);
2019         nVertMax = (aSize.Height() - 2*nSheetMargin);
2020         if( nRows > 1 )
2021             nHorzMax /= (nRows-1);
2022 
2023         if( nPageMargin > nHorzMax )
2024             nPageMargin = nHorzMax;
2025         if( nPageMargin > nVertMax )
2026             nPageMargin = nVertMax;
2027 
2028         maNUpPage.maPageMarginEdt.SetMax(
2029                  maNUpPage.maSheetMarginEdt.Normalize(
2030                            nHorzMax > nVertMax ? nVertMax : nHorzMax ), FUNIT_100TH_MM );
2031     }
2032 
2033     maNUpPage.maNupRowsEdt.SetValue( nRows );
2034     maNUpPage.maNupColEdt.SetValue( nCols );
2035     maNUpPage.maPageMarginEdt.SetValue( maNUpPage.maPageMarginEdt.Normalize( nPageMargin ), FUNIT_100TH_MM );
2036     maNUpPage.maSheetMarginEdt.SetValue( maNUpPage.maSheetMarginEdt.Normalize( nSheetMargin ), FUNIT_100TH_MM );
2037 
2038     maNUpPage.showAdvancedControls( bCustom );
2039     if( bCustom )
2040     {
2041         // see if we have to enlarge the dialog to make the tab page fit
2042         Size aCurSize( maNUpPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ) );
2043         Size aTabSize( maTabCtrl.GetTabPageSizePixel() );
2044         if( aTabSize.Height() < aCurSize.Height() )
2045         {
2046             Size aDlgSize( GetSizePixel() );
2047             aDlgSize.Height() += aCurSize.Height() - aTabSize.Height();
2048             SetSizePixel( aDlgSize );
2049         }
2050     }
2051 
2052     updateNup();
2053 }
2054 
2055 void PrintDialog::updateNup()
2056 {
2057     int nRows         = int(maNUpPage.maNupRowsEdt.GetValue());
2058     int nCols         = int(maNUpPage.maNupColEdt.GetValue());
2059     long nPageMargin  = long(maNUpPage.maPageMarginEdt.Denormalize(maNUpPage.maPageMarginEdt.GetValue( FUNIT_100TH_MM )));
2060     long nSheetMargin = long(maNUpPage.maSheetMarginEdt.Denormalize(maNUpPage.maSheetMarginEdt.GetValue( FUNIT_100TH_MM )));
2061 
2062     PrinterController::MultiPageSetup aMPS;
2063     aMPS.nRows         = nRows;
2064     aMPS.nColumns      = nCols;
2065     aMPS.nRepeat       = 1;
2066     aMPS.nLeftMargin   =
2067     aMPS.nTopMargin    =
2068     aMPS.nRightMargin  =
2069     aMPS.nBottomMargin = nSheetMargin;
2070 
2071     aMPS.nHorizontalSpacing =
2072     aMPS.nVerticalSpacing   = nPageMargin;
2073 
2074     aMPS.bDrawBorder        = maNUpPage.maBorderCB.IsChecked();
2075 
2076     int nOrderMode = int(sal_IntPtr(maNUpPage.maNupOrderBox.GetEntryData(
2077                            maNUpPage.maNupOrderBox.GetSelectEntryPos() )));
2078     if( nOrderMode == SV_PRINT_PRT_NUP_ORDER_LRTB )
2079         aMPS.nOrder = PrinterController::LRTB;
2080     else if( nOrderMode == SV_PRINT_PRT_NUP_ORDER_TBLR )
2081         aMPS.nOrder = PrinterController::TBLR;
2082     else if( nOrderMode == SV_PRINT_PRT_NUP_ORDER_RLTB )
2083         aMPS.nOrder = PrinterController::RLTB;
2084     else if( nOrderMode == SV_PRINT_PRT_NUP_ORDER_TBRL )
2085         aMPS.nOrder = PrinterController::TBRL;
2086 
2087     int nOrientationMode = int(sal_IntPtr(maNUpPage.maNupOrientationBox.GetEntryData(
2088                                  maNUpPage.maNupOrientationBox.GetSelectEntryPos() )));
2089     if( nOrientationMode == SV_PRINT_PRT_NUP_ORIENTATION_LANDSCAPE )
2090         aMPS.aPaperSize = maNupLandscapeSize;
2091     else if( nOrientationMode == SV_PRINT_PRT_NUP_ORIENTATION_PORTRAIT )
2092         aMPS.aPaperSize = maNupPortraitSize;
2093     else // automatic mode
2094     {
2095         // get size of first real page to see if it is portrait or landscape
2096         // we assume same page sizes for all the pages for this
2097         Size aPageSize = getJobPageSize();
2098 
2099         Size aMultiSize( aPageSize.Width() * nCols, aPageSize.Height() * nRows );
2100         if( aMultiSize.Width() > aMultiSize.Height() ) // fits better on landscape
2101             aMPS.aPaperSize = maNupLandscapeSize;
2102         else
2103             aMPS.aPaperSize = maNupPortraitSize;
2104     }
2105 
2106     maPController->setMultipage( aMPS );
2107 
2108     maNUpPage.maNupOrderWin.setValues( nOrderMode, nCols, nRows );
2109 
2110     preparePreview( true, true );
2111 }
2112 
2113 IMPL_LINK( PrintDialog, SelectHdl, ListBox*, pBox )
2114 {
2115     if(  pBox == &maJobPage.maPrinters )
2116     {
2117         String aNewPrinter( pBox->GetSelectEntry() );
2118         // set new printer
2119         maPController->setPrinter( boost::shared_ptr<Printer>( new Printer( aNewPrinter ) ) );
2120         maPController->resetPrinterOptions( maOptionsPage.maToFileBox.IsChecked() );
2121         // update text fields
2122         updatePrinterText();
2123         preparePreview( true, false );
2124     }
2125     else if( pBox == &maNUpPage.maNupOrientationBox || pBox == &maNUpPage.maNupOrderBox )
2126     {
2127         updateNup();
2128     }
2129     else if( pBox == &maNUpPage.maNupPagesBox )
2130     {
2131         if( !maNUpPage.maPagesBtn.IsChecked() )
2132             maNUpPage.maPagesBtn.Check();
2133         updateNupFromPages();
2134     }
2135 
2136     return 0;
2137 }
2138 
2139 IMPL_LINK( PrintDialog, ClickHdl, Button*, pButton )
2140 {
2141     if( pButton == &maOKButton || pButton == &maCancelButton )
2142     {
2143         storeToSettings();
2144         EndDialog( pButton == &maOKButton );
2145     }
2146     else if( pButton == &maHelpButton )
2147     {
2148         // start help system
2149         Help* pHelp = Application::GetHelp();
2150         if( pHelp )
2151         {
2152             pHelp->Start( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:OK" ) ), &maOKButton );
2153         }
2154     }
2155     else if( pButton == &maForwardBtn )
2156     {
2157         previewForward();
2158     }
2159     else if( pButton == &maBackwardBtn )
2160     {
2161         previewBackward();
2162     }
2163     else if( pButton == &maOptionsPage.maToFileBox )
2164     {
2165         maOKButton.SetText( maOptionsPage.maToFileBox.IsChecked() ? maPrintToFileText : maPrintText );
2166         maPController->resetPrinterOptions( maOptionsPage.maToFileBox.IsChecked() );
2167         getLayout()->resize();
2168         preparePreview( true, true );
2169     }
2170     else if( pButton == &maNUpPage.maBrochureBtn )
2171     {
2172         PropertyValue* pVal = getValueForWindow( pButton );
2173         if( pVal )
2174         {
2175             sal_Bool bVal = maNUpPage.maBrochureBtn.IsChecked();
2176             pVal->Value <<= bVal;
2177 
2178             checkOptionalControlDependencies();
2179 
2180             // update preview and page settings
2181             preparePreview();
2182         }
2183         if( maNUpPage.maBrochureBtn.IsChecked() )
2184         {
2185             maNUpPage.maNupPagesBox.SelectEntryPos( 0 );
2186             updateNupFromPages();
2187             maNUpPage.showAdvancedControls( false );
2188             maNUpPage.enableNupControls( false );
2189         }
2190     }
2191     else if( pButton == &maNUpPage.maPagesBtn )
2192     {
2193         maNUpPage.enableNupControls( true );
2194         updateNupFromPages();
2195     }
2196     else if( pButton == &maJobPage.maDetailsBtn )
2197     {
2198         bool bShow = maJobPage.maDetailsBtn.IsChecked();
2199         maJobPage.mxDetails->show( bShow );
2200         if( bShow )
2201         {
2202             maDetailsCollapsedSize = GetOutputSizePixel();
2203             // enlarge dialog if necessary
2204             Size aMinSize( maJobPage.getLayout()->getOptimalSize( WINDOWSIZE_MINIMUM ) );
2205             Size aCurSize( maJobPage.GetSizePixel() );
2206             if( aCurSize.Height() < aMinSize.Height() )
2207             {
2208                 Size aDlgSize( GetOutputSizePixel() );
2209                 aDlgSize.Height() += aMinSize.Height() - aCurSize.Height();
2210                 SetOutputSizePixel( aDlgSize );
2211             }
2212             maDetailsExpandedSize = GetOutputSizePixel();
2213         }
2214         else if( maDetailsCollapsedSize.Width() > 0   &&
2215                  maDetailsCollapsedSize.Height() > 0 )
2216         {
2217             // if the user did not resize the dialog
2218             // make it smaller again on collapsing the details
2219             Size aDlgSize( GetOutputSizePixel() );
2220             if( aDlgSize == maDetailsExpandedSize &&
2221                 aDlgSize.Height() > maDetailsCollapsedSize.Height() )
2222             {
2223                 SetOutputSizePixel( maDetailsCollapsedSize );
2224             }
2225         }
2226     }
2227     else if( pButton == &maJobPage.maCollateBox )
2228     {
2229         maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ),
2230                                  makeAny( sal_Bool(isCollate()) ) );
2231         checkControlDependencies();
2232     }
2233     else if( pButton == &maJobPage.maReverseOrderBox )
2234     {
2235         sal_Bool bChecked = maJobPage.maReverseOrderBox.IsChecked();
2236         maPController->setReversePrint( bChecked );
2237         maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintReverse" ) ),
2238                                  makeAny( bChecked ) );
2239         preparePreview( true, true );
2240     }
2241     else if( pButton == &maNUpPage.maBorderCB )
2242     {
2243         updateNup();
2244     }
2245     else
2246     {
2247         if( pButton == &maJobPage.maSetupButton )
2248         {
2249             maPController->setupPrinter( this );
2250             preparePreview( true, true );
2251         }
2252         checkControlDependencies();
2253     }
2254     return 0;
2255 }
2256 
2257 IMPL_LINK( PrintDialog, ModifyHdl, Edit*, pEdit )
2258 {
2259     checkControlDependencies();
2260     if( pEdit == &maNUpPage.maNupRowsEdt || pEdit == &maNUpPage.maNupColEdt ||
2261         pEdit == &maNUpPage.maSheetMarginEdt || pEdit == &maNUpPage.maPageMarginEdt
2262        )
2263     {
2264         updateNupFromPages();
2265     }
2266     else if( pEdit == &maPageEdit )
2267     {
2268         mnCurPage = sal_Int32( maPageEdit.GetValue() - 1 );
2269         preparePreview( true, true );
2270     }
2271     else if( pEdit == &maJobPage.maCopyCountField )
2272     {
2273         maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyCount" ) ),
2274                                makeAny( sal_Int32(maJobPage.maCopyCountField.GetValue()) ) );
2275         maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ),
2276                                makeAny( sal_Bool(isCollate()) ) );
2277     }
2278     return 0;
2279 }
2280 
2281 IMPL_LINK( PrintDialog, UIOptionsChanged, void*, EMPTYARG )
2282 {
2283     checkOptionalControlDependencies();
2284     return 0;
2285 }
2286 
2287 PropertyValue* PrintDialog::getValueForWindow( Window* i_pWindow ) const
2288 {
2289     PropertyValue* pVal = NULL;
2290     std::map< Window*, rtl::OUString >::const_iterator it = maControlToPropertyMap.find( i_pWindow );
2291     if( it != maControlToPropertyMap.end() )
2292     {
2293         pVal = maPController->getValue( it->second );
2294         DBG_ASSERT( pVal, "property value not found" );
2295     }
2296     else
2297     {
2298         DBG_ERROR( "changed control not in property map" );
2299     }
2300     return pVal;
2301 }
2302 
2303 void PrintDialog::updateWindowFromProperty( const rtl::OUString& i_rProperty )
2304 {
2305     beans::PropertyValue* pValue = maPController->getValue( i_rProperty );
2306     std::map< rtl::OUString, std::vector< Window* > >::const_iterator it = maPropertyToWindowMap.find( i_rProperty );
2307     if( pValue && it != maPropertyToWindowMap.end() )
2308     {
2309         const std::vector< Window* >& rWindows( it->second );
2310         if( ! rWindows.empty() )
2311         {
2312             sal_Bool bVal = sal_False;
2313             sal_Int32 nVal = -1;
2314             if( pValue->Value >>= bVal )
2315             {
2316                 // we should have a CheckBox for this one
2317                 CheckBox* pBox = dynamic_cast< CheckBox* >( rWindows.front() );
2318                 if( pBox )
2319                 {
2320                     pBox->Check( bVal );
2321                 }
2322                 else if( i_rProperty.equalsAscii( "PrintProspect" ) )
2323                 {
2324                     // EVIL special case
2325                     if( bVal )
2326                         maNUpPage.maBrochureBtn.Check();
2327                     else
2328                         maNUpPage.maPagesBtn.Check();
2329                 }
2330                 else
2331                 {
2332                     DBG_ASSERT( 0, "missing a checkbox" );
2333                 }
2334             }
2335             else if( pValue->Value >>= nVal )
2336             {
2337                 // this could be a ListBox or a RadioButtonGroup
2338                 ListBox* pList = dynamic_cast< ListBox* >( rWindows.front() );
2339                 if( pList )
2340                 {
2341                     pList->SelectEntryPos( static_cast< sal_uInt16 >(nVal) );
2342                 }
2343                 else if( nVal >= 0 && nVal < sal_Int32(rWindows.size() ) )
2344                 {
2345                     RadioButton* pBtn = dynamic_cast< RadioButton* >( rWindows[nVal] );
2346                     DBG_ASSERT( pBtn, "unexpected control for property" );
2347                     if( pBtn )
2348                         pBtn->Check();
2349                 }
2350             }
2351         }
2352     }
2353 }
2354 
2355 void PrintDialog::makeEnabled( Window* i_pWindow )
2356 {
2357     std::map< Window*, rtl::OUString >::const_iterator it = maControlToPropertyMap.find( i_pWindow );
2358     if( it != maControlToPropertyMap.end() )
2359     {
2360         rtl::OUString aDependency( maPController->makeEnabled( it->second ) );
2361         if( aDependency.getLength() )
2362             updateWindowFromProperty( aDependency );
2363     }
2364 }
2365 
2366 IMPL_LINK( PrintDialog, UIOption_CheckHdl, CheckBox*, i_pBox )
2367 {
2368     PropertyValue* pVal = getValueForWindow( i_pBox );
2369     if( pVal )
2370     {
2371         makeEnabled( i_pBox );
2372 
2373         sal_Bool bVal = i_pBox->IsChecked();
2374         pVal->Value <<= bVal;
2375 
2376         checkOptionalControlDependencies();
2377 
2378         // update preview and page settings
2379         preparePreview();
2380     }
2381     return 0;
2382 }
2383 
2384 IMPL_LINK( PrintDialog, UIOption_RadioHdl, RadioButton*, i_pBtn )
2385 {
2386     // this handler gets called for all radiobuttons that get unchecked, too
2387     // however we only want one notificaction for the new value (that is for
2388     // the button that gets checked)
2389     if( i_pBtn->IsChecked() )
2390     {
2391         PropertyValue* pVal = getValueForWindow( i_pBtn );
2392         std::map< Window*, sal_Int32 >::const_iterator it = maControlToNumValMap.find( i_pBtn );
2393         if( pVal && it != maControlToNumValMap.end() )
2394         {
2395             makeEnabled( i_pBtn );
2396 
2397             sal_Int32 nVal = it->second;
2398             pVal->Value <<= nVal;
2399 
2400             checkOptionalControlDependencies();
2401 
2402             // update preview and page settings
2403             preparePreview();
2404         }
2405     }
2406     return 0;
2407 }
2408 
2409 IMPL_LINK( PrintDialog, UIOption_SelectHdl, ListBox*, i_pBox )
2410 {
2411     PropertyValue* pVal = getValueForWindow( i_pBox );
2412     if( pVal )
2413     {
2414         makeEnabled( i_pBox );
2415 
2416         sal_Int32 nVal( i_pBox->GetSelectEntryPos() );
2417         pVal->Value <<= nVal;
2418 
2419         checkOptionalControlDependencies();
2420 
2421         // update preview and page settings
2422         preparePreview();
2423     }
2424     return 0;
2425 }
2426 
2427 IMPL_LINK( PrintDialog, UIOption_ModifyHdl, Edit*, i_pBox )
2428 {
2429     PropertyValue* pVal = getValueForWindow( i_pBox );
2430     if( pVal )
2431     {
2432         makeEnabled( i_pBox );
2433 
2434         NumericField* pNum = dynamic_cast<NumericField*>(i_pBox);
2435         MetricField* pMetric = dynamic_cast<MetricField*>(i_pBox);
2436         if( pNum )
2437         {
2438             sal_Int64 nVal = pNum->GetValue();
2439             pVal->Value <<= nVal;
2440         }
2441         else if( pMetric )
2442         {
2443             sal_Int64 nVal = pMetric->GetValue();
2444             pVal->Value <<= nVal;
2445         }
2446         else
2447         {
2448             rtl::OUString aVal( i_pBox->GetText() );
2449             pVal->Value <<= aVal;
2450         }
2451 
2452         checkOptionalControlDependencies();
2453 
2454         // update preview and page settings
2455         preparePreview();
2456     }
2457     return 0;
2458 }
2459 
2460 void PrintDialog::Command( const CommandEvent& rEvt )
2461 {
2462     if( rEvt.GetCommand() == COMMAND_WHEEL )
2463     {
2464         const CommandWheelData* pWheelData = rEvt.GetWheelData();
2465         if( pWheelData->GetDelta() > 0 )
2466             previewForward();
2467         else if( pWheelData->GetDelta() < 0 )
2468             previewBackward();
2469         /*
2470         else
2471             huh ?
2472         */
2473     }
2474 }
2475 
2476 void PrintDialog::Resize()
2477 {
2478     // maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
2479     // and do the preview; however the metafile does not need to be gotten anew
2480     preparePreview( false );
2481 
2482     // do an invalidate for the benefit of the grouping elements
2483     Invalidate();
2484 }
2485 
2486 void PrintDialog::previewForward()
2487 {
2488     maPageEdit.Up();
2489 }
2490 
2491 void PrintDialog::previewBackward()
2492 {
2493     maPageEdit.Down();
2494 }
2495 
2496 // -----------------------------------------------------------------------------
2497 //
2498 // PrintProgressDialog
2499 //
2500 // -----------------------------------------------------------------------------
2501 
2502 PrintProgressDialog::PrintProgressDialog( Window* i_pParent, int i_nMax ) :
2503     ModelessDialog( i_pParent, VclResId( SV_DLG_PRINT_PROGRESS ) ),
2504     maText( this, VclResId( SV_PRINT_PROGRESS_TEXT ) ),
2505     maButton( this, VclResId( SV_PRINT_PROGRESS_CANCEL ) ),
2506     mbCanceled( false ),
2507     mnCur( 0 ),
2508     mnMax( i_nMax ),
2509     mnProgressHeight( 15 ),
2510     mbNativeProgress( false )
2511 {
2512     FreeResource();
2513 
2514     if( mnMax < 1 )
2515         mnMax = 1;
2516 
2517     maStr = maText.GetText();
2518 
2519     maButton.SetClickHdl( LINK( this, PrintProgressDialog, ClickHdl ) );
2520 
2521 }
2522 
2523 PrintProgressDialog::~PrintProgressDialog()
2524 {
2525 }
2526 
2527 IMPL_LINK( PrintProgressDialog, ClickHdl, Button*, pButton )
2528 {
2529     if( pButton == &maButton )
2530         mbCanceled = true;
2531 
2532     return 0;
2533 }
2534 
2535 void PrintProgressDialog::implCalcProgressRect()
2536 {
2537     if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
2538     {
2539         ImplControlValue aValue;
2540         Rectangle aControlRegion( Point(), Size( 100, mnProgressHeight ) );
2541         Rectangle aNativeControlRegion, aNativeContentRegion;
2542         if( GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion,
2543                                     CTRL_STATE_ENABLED, aValue, rtl::OUString(),
2544                                     aNativeControlRegion, aNativeContentRegion ) )
2545         {
2546             mnProgressHeight = aNativeControlRegion.GetHeight();
2547         }
2548         mbNativeProgress = true;
2549     }
2550     maProgressRect = Rectangle( Point( 10, maText.GetPosPixel().Y() + maText.GetSizePixel().Height() + 8 ),
2551                                 Size( GetSizePixel().Width() - 20, mnProgressHeight ) );
2552 }
2553 
2554 void PrintProgressDialog::setProgress( int i_nCurrent, int i_nMax )
2555 {
2556     if( maProgressRect.IsEmpty() )
2557         implCalcProgressRect();
2558 
2559     mnCur = i_nCurrent;
2560     if( i_nMax != -1 )
2561         mnMax = i_nMax;
2562 
2563     if( mnMax < 1 )
2564         mnMax = 1;
2565 
2566     rtl::OUString aNewText( searchAndReplace( maStr, "%p", 2, rtl::OUString::valueOf( mnCur ) ) );
2567     aNewText = searchAndReplace( aNewText, "%n", 2, rtl::OUString::valueOf( mnMax ) );
2568     maText.SetText( aNewText );
2569 
2570     // update progress
2571     Invalidate( maProgressRect, INVALIDATE_UPDATE );
2572 }
2573 
2574 void PrintProgressDialog::tick()
2575 {
2576     if( mnCur < mnMax )
2577         setProgress( ++mnCur );
2578 }
2579 
2580 void PrintProgressDialog::reset()
2581 {
2582     mbCanceled = false;
2583     setProgress( 0 );
2584 }
2585 
2586 void PrintProgressDialog::Paint( const Rectangle& )
2587 {
2588     if( maProgressRect.IsEmpty() )
2589         implCalcProgressRect();
2590 
2591     Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
2592 	const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2593 	Color aPrgsColor = rStyleSettings.GetHighlightColor();
2594 	if ( aPrgsColor == rStyleSettings.GetFaceColor() )
2595 		aPrgsColor = rStyleSettings.GetDarkShadowColor();
2596 	SetLineColor();
2597 	SetFillColor( aPrgsColor );
2598 
2599     const long nOffset = 3;
2600     const long nWidth = 3*mnProgressHeight/2;
2601     const long nFullWidth = nWidth + nOffset;
2602     const long nMaxCount = maProgressRect.GetWidth() / nFullWidth;
2603     DrawProgress( this, maProgressRect.TopLeft(),
2604                         nOffset,
2605                         nWidth,
2606                         mnProgressHeight,
2607                         static_cast<sal_uInt16>(0),
2608                         static_cast<sal_uInt16>(10000*mnCur/mnMax),
2609                         static_cast<sal_uInt16>(10000/nMaxCount),
2610                         maProgressRect
2611                         );
2612     Pop();
2613 
2614     if( ! mbNativeProgress )
2615     {
2616         DecorationView aDecoView( this );
2617         Rectangle aFrameRect( maProgressRect );
2618         aFrameRect.Left() -= nOffset;
2619         aFrameRect.Right() += nOffset;
2620         aFrameRect.Top() -= nOffset;
2621         aFrameRect.Bottom() += nOffset;
2622         aDecoView.DrawFrame( aFrameRect );
2623     }
2624 }
2625 
2626