xref: /aoo42x/main/vcl/source/window/printdlg.cxx (revision cdf0e10c)
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 }
597 
598 void PrintDialog::NUpTabPage::readFromSettings()
599 {
600 }
601 
602 void PrintDialog::NUpTabPage::storeToSettings()
603 {
604 }
605 
606 PrintDialog::JobTabPage::JobTabPage( Window* i_pParent, const ResId& rResId )
607     : TabPage( i_pParent, rResId )
608     , maPrinterFL( this, VclResId( SV_PRINT_PRINTERS_FL ) )
609     , maPrinters( this, VclResId( SV_PRINT_PRINTERS ) )
610     , maDetailsBtn( this, VclResId( SV_PRINT_DETAILS_BTN ) )
611     , maStatusLabel( this, VclResId( SV_PRINT_STATUS_TXT ) )
612     , maStatusTxt( this, 0 )
613     , maLocationLabel( this, VclResId( SV_PRINT_LOCATION_TXT ) )
614     , maLocationTxt( this, 0 )
615     , maCommentLabel( this, VclResId( SV_PRINT_COMMENT_TXT ) )
616     , maCommentTxt( this, 0 )
617     , maSetupButton( this, VclResId( SV_PRINT_PRT_SETUP ) )
618     , maCopies( this, VclResId( SV_PRINT_COPIES ) )
619     , maCopySpacer( this, WB_VERT )
620     , maCopyCount( this, VclResId( SV_PRINT_COPYCOUNT ) )
621     , maCopyCountField( this, VclResId( SV_PRINT_COPYCOUNT_FIELD ) )
622     , maCollateBox( this, VclResId( SV_PRINT_COLLATE ) )
623     , maCollateImage( this, VclResId( SV_PRINT_COLLATE_IMAGE ) )
624     , maReverseOrderBox( this, VclResId( SV_PRINT_OPT_REVERSE ) )
625     , maCollateImg( VclResId( SV_PRINT_COLLATE_IMG ) )
626     , maCollateHCImg( VclResId( SV_PRINT_COLLATE_HC_IMG ) )
627     , maNoCollateImg( VclResId( SV_PRINT_NOCOLLATE_IMG ) )
628     , maNoCollateHCImg( VclResId( SV_PRINT_NOCOLLATE_HC_IMG ) )
629     , mnCollateUIMode( 0 )
630 {
631     FreeResource();
632 
633     maCopySpacer.Show();
634     maStatusTxt.Show();
635     maCommentTxt.Show();
636     maLocationTxt.Show();
637 
638     setupLayout();
639 }
640 
641 PrintDialog::JobTabPage::~JobTabPage()
642 {
643 }
644 
645 void PrintDialog::JobTabPage::setupLayout()
646 {
647     // HACK: this is not a dropdown box, but the dropdown line count
648     // sets the results of GetOptimalSize in a normal ListBox
649     maPrinters.SetDropDownLineCount( 4 );
650 
651     boost::shared_ptr<vcl::RowOrColumn> xLayout =
652         boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
653 
654     // add printer fixed line
655     xLayout->addWindow( &maPrinterFL );
656     // add print LB
657     xLayout->addWindow( &maPrinters, 3 );
658 
659     // create a row for details button/text and properties button
660     boost::shared_ptr< vcl::RowOrColumn > xDetRow( new vcl::RowOrColumn( xLayout.get(), false ) );
661     xLayout->addChild( xDetRow );
662     xDetRow->addWindow( &maDetailsBtn );
663     xDetRow->addChild( new vcl::Spacer( xDetRow.get(), 2 ) );
664     xDetRow->addWindow( &maSetupButton );
665 
666     // create an indent for details
667     boost::shared_ptr< vcl::Indenter > xIndent( new vcl::Indenter( xLayout.get() ) );
668     xLayout->addChild( xIndent );
669     // remember details controls
670     mxDetails = xIndent;
671     // create a column for the details
672     boost::shared_ptr< vcl::LabelColumn > xLabelCol( new vcl::LabelColumn( xIndent.get() ) );
673     xIndent->setChild( xLabelCol );
674     xLabelCol->addRow( &maStatusLabel, &maStatusTxt );
675     xLabelCol->addRow( &maLocationLabel, &maLocationTxt );
676     xLabelCol->addRow( &maCommentLabel, &maCommentTxt );
677 
678     // add print range and copies columns
679     xLayout->addWindow( &maCopies );
680     boost::shared_ptr< vcl::RowOrColumn > xRangeRow( new vcl::RowOrColumn( xLayout.get(), false ) );
681     xLayout->addChild( xRangeRow );
682 
683     // create print range and add to range row
684     mxPrintRange.reset( new vcl::RowOrColumn( xRangeRow.get() ) );
685     xRangeRow->addChild( mxPrintRange );
686     xRangeRow->addWindow( &maCopySpacer );
687 
688     boost::shared_ptr< vcl::RowOrColumn > xCopyCollateCol( new vcl::RowOrColumn( xRangeRow.get() ) );
689     xRangeRow->addChild( xCopyCollateCol );
690 
691     // add copies row to copy/collate column
692     boost::shared_ptr< vcl::LabeledElement > xCopiesRow( new vcl::LabeledElement( xCopyCollateCol.get(), 2 ) );
693     xCopyCollateCol->addChild( xCopiesRow );
694     xCopiesRow->setLabel( &maCopyCount );
695     xCopiesRow->setElement( &maCopyCountField );
696     boost::shared_ptr< vcl::LabeledElement > xCollateRow( new vcl::LabeledElement( xCopyCollateCol.get(), 2 ) );
697     xCopyCollateCol->addChild( xCollateRow );
698     xCollateRow->setLabel( &maCollateBox );
699     xCollateRow->setElement( &maCollateImage );
700 
701     // maDetailsBtn.SetStyle( maDetailsBtn.GetStyle() | (WB_SMALLSTYLE | WB_BEVELBUTTON) );
702     mxDetails->show( false, false );
703 }
704 
705 void PrintDialog::JobTabPage::readFromSettings()
706 {
707     SettingsConfigItem* pItem = SettingsConfigItem::get();
708     rtl::OUString aValue;
709 
710     #if 0
711     // do not actually make copy count persistent
712     // the assumption is that this would lead to a lot of unwanted copies
713     aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
714                               rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyCount" ) ) );
715     sal_Int32 nVal = aValue.toInt32();
716     maCopyCountField.SetValue( sal_Int64(nVal > 1 ? nVal : 1) );
717     #endif
718 
719     aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
720                               rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CollateBox" ) ) );
721     if( aValue.equalsIgnoreAsciiCaseAscii( "alwaysoff" ) )
722     {
723         mnCollateUIMode = 1;
724         maCollateBox.Check( sal_False );
725         maCollateBox.Enable( sal_False );
726     }
727     else
728     {
729         mnCollateUIMode = 0;
730         aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
731                                   rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ) );
732         maCollateBox.Check( aValue.equalsIgnoreAsciiCaseAscii( "true" ) );
733     }
734     Resize();
735 }
736 
737 void PrintDialog::JobTabPage::storeToSettings()
738 {
739     SettingsConfigItem* pItem = SettingsConfigItem::get();
740     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
741                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyCount" ) ),
742                      maCopyCountField.GetText() );
743     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
744                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ),
745                      rtl::OUString::createFromAscii( maCollateBox.IsChecked() ? "true" : "false" ) );
746 }
747 
748 PrintDialog::OutputOptPage::OutputOptPage( Window* i_pParent, const ResId& i_rResId )
749     : TabPage( i_pParent, i_rResId )
750     , maOptionsLine( this, VclResId( SV_PRINT_OPT_PRINT_FL ) )
751     , maToFileBox( this, VclResId( SV_PRINT_OPT_TOFILE ) )
752     , maCollateSingleJobsBox( this, VclResId( SV_PRINT_OPT_SINGLEJOBS ) )
753 {
754     FreeResource();
755 
756     setupLayout();
757 }
758 
759 PrintDialog::OutputOptPage::~OutputOptPage()
760 {
761 }
762 
763 void PrintDialog::OutputOptPage::setupLayout()
764 {
765     boost::shared_ptr<vcl::RowOrColumn> xLayout =
766         boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
767 
768     xLayout->addWindow( &maOptionsLine );
769     boost::shared_ptr<vcl::Indenter> xIndent( new vcl::Indenter( xLayout.get(), -1 ) );
770     xLayout->addChild( xIndent );
771     boost::shared_ptr<vcl::RowOrColumn> xCol( new vcl::RowOrColumn( xIndent.get() ) );
772     xIndent->setChild( xCol );
773     mxOptGroup = xCol;
774     xCol->addWindow( &maToFileBox );
775     xCol->addWindow( &maCollateSingleJobsBox );
776 }
777 
778 void PrintDialog::OutputOptPage::readFromSettings()
779 {
780     #if 0
781     SettingsConfigItem* pItem = SettingsConfigItem::get();
782     rtl::OUString aValue;
783 
784     aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
785                               rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ToFile" ) ) );
786     maToFileBox.Check( aValue.equalsIgnoreAsciiCaseAscii( "true" ) );
787     #endif
788 }
789 
790 void PrintDialog::OutputOptPage::storeToSettings()
791 {
792     SettingsConfigItem* pItem = SettingsConfigItem::get();
793     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
794                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ToFile" ) ),
795                      rtl::OUString::createFromAscii( maToFileBox.IsChecked() ? "true" : "false" ) );
796 }
797 
798 PrintDialog::PrintDialog( Window* i_pParent, const boost::shared_ptr<PrinterController>& i_rController )
799     : ModalDialog( i_pParent, VclResId( SV_DLG_PRINT ) )
800     , maOKButton( this, VclResId( SV_PRINT_OK ) )
801     , maCancelButton( this, VclResId( SV_PRINT_CANCEL ) )
802     , maHelpButton( this, VclResId( SV_PRINT_HELP ) )
803     , maPreviewWindow( this, VclResId( SV_PRINT_PAGE_PREVIEW ) )
804     , maPageEdit( this, VclResId( SV_PRINT_PAGE_EDIT ) )
805     , maNumPagesText( this, VclResId( SV_PRINT_PAGE_TXT ) )
806     , maBackwardBtn( this, VclResId( SV_PRINT_PAGE_BACKWARD ) )
807     , maForwardBtn( this, VclResId( SV_PRINT_PAGE_FORWARD ) )
808     , maTabCtrl( this, VclResId( SV_PRINT_TABCTRL ) )
809     , maNUpPage( &maTabCtrl, VclResId( SV_PRINT_TAB_NUP ) )
810     , maJobPage( &maTabCtrl, VclResId( SV_PRINT_TAB_JOB ) )
811     , maOptionsPage( &maTabCtrl, VclResId( SV_PRINT_TAB_OPT ) )
812     , maButtonLine( this, VclResId( SV_PRINT_BUTTONLINE ) )
813     , maPController( i_rController )
814     , maNoPageStr( String( VclResId( SV_PRINT_NOPAGES ) ) )
815     , mnCurPage( 0 )
816     , mnCachedPages( 0 )
817     , maPrintToFileText( String( VclResId( SV_PRINT_TOFILE_TXT ) ) )
818     , maDefPrtText( String( VclResId( SV_PRINT_DEFPRT_TXT ) ) )
819     , mbShowLayoutPage( sal_True )
820 {
821     FreeResource();
822 
823     // save printbutton text, gets exchanged occasionally with print to file
824     maPrintText = maOKButton.GetText();
825 
826     // setup preview controls
827     maForwardBtn.SetStyle( maForwardBtn.GetStyle() | WB_BEVELBUTTON );
828     maBackwardBtn.SetStyle( maBackwardBtn.GetStyle() | WB_BEVELBUTTON );
829 
830     // insert the job (general) tab page first
831     maTabCtrl.InsertPage( SV_PRINT_TAB_JOB, maJobPage.GetText() );
832     maTabCtrl.SetTabPage( SV_PRINT_TAB_JOB, &maJobPage );
833 
834     // set symbols on forward and backward button
835     maBackwardBtn.SetSymbol( SYMBOL_PREV );
836     maForwardBtn.SetSymbol( SYMBOL_NEXT );
837     maBackwardBtn.ImplSetSmallSymbol( sal_True );
838     maForwardBtn.ImplSetSmallSymbol( sal_True );
839 
840     maPageStr = maNumPagesText.GetText();
841 
842     // init reverse print
843     maJobPage.maReverseOrderBox.Check( maPController->getReversePrint() );
844 
845     // fill printer listbox
846     const std::vector< rtl::OUString >& rQueues( Printer::GetPrinterQueues() );
847     for( std::vector< rtl::OUString >::const_iterator it = rQueues.begin();
848          it != rQueues.end(); ++it )
849     {
850         maJobPage.maPrinters.InsertEntry( *it );
851     }
852     // select current printer
853     if( maJobPage.maPrinters.GetEntryPos( maPController->getPrinter()->GetName() ) != LISTBOX_ENTRY_NOTFOUND )
854     {
855         maJobPage.maPrinters.SelectEntry( maPController->getPrinter()->GetName() );
856     }
857     else
858     {
859         // fall back to last printer
860         SettingsConfigItem* pItem = SettingsConfigItem::get();
861         String aValue( pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
862                                         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPrinter" ) ) ) );
863         if( maJobPage.maPrinters.GetEntryPos( aValue ) != LISTBOX_ENTRY_NOTFOUND )
864         {
865             maJobPage.maPrinters.SelectEntry( aValue );
866             maPController->setPrinter( boost::shared_ptr<Printer>( new Printer( aValue ) ) );
867         }
868         else
869         {
870             // fall back to default printer
871             maJobPage.maPrinters.SelectEntry( Printer::GetDefaultPrinterName() );
872             maPController->setPrinter( boost::shared_ptr<Printer>( new Printer( Printer::GetDefaultPrinterName() ) ) );
873         }
874     }
875     // not printing to file
876     maPController->resetPrinterOptions( false );
877 
878     // get the first page
879     preparePreview( true, true );
880 
881     // update the text fields for the printer
882     updatePrinterText();
883 
884     // set a select handler
885     maJobPage.maPrinters.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
886 
887     // setup sizes for N-Up
888     Size aNupSize( maPController->getPrinter()->PixelToLogic(
889                          maPController->getPrinter()->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) ) );
890     if( maPController->getPrinter()->GetOrientation() == ORIENTATION_LANDSCAPE )
891     {
892         maNupLandscapeSize = aNupSize;
893         maNupPortraitSize = Size( aNupSize.Height(), aNupSize.Width() );
894     }
895     else
896     {
897         maNupPortraitSize = aNupSize;
898         maNupLandscapeSize = Size( aNupSize.Height(), aNupSize.Width() );
899     }
900     maNUpPage.initFromMultiPageSetup( maPController->getMultipage() );
901 
902 
903     // setup click handler on the various buttons
904     maOKButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
905     #if OSL_DEBUG_LEVEL > 1
906     maCancelButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
907     #endif
908     maHelpButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
909     maForwardBtn.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
910     maBackwardBtn.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
911     maJobPage.maCollateBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
912     maJobPage.maSetupButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
913     maJobPage.maDetailsBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
914     maNUpPage.maBorderCB.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) );
915     maOptionsPage.maToFileBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
916     maJobPage.maReverseOrderBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
917     maOptionsPage.maCollateSingleJobsBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
918     maNUpPage.maPagesBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
919 
920     // setup modify hdl
921     maPageEdit.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
922     maJobPage.maCopyCountField.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
923     maNUpPage.maNupRowsEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
924     maNUpPage.maNupColEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
925     maNUpPage.maPageMarginEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
926     maNUpPage.maSheetMarginEdt.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) );
927 
928     // setup select hdl
929     maNUpPage.maNupPagesBox.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
930     maNUpPage.maNupOrientationBox.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
931     maNUpPage.maNupOrderBox.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) );
932 
933     // setup the layout
934     setupLayout();
935 
936     // setup optional UI options set by application
937     setupOptionalUI();
938 
939     // set change handler for UI options
940     maPController->setOptionChangeHdl( LINK( this, PrintDialog, UIOptionsChanged ) );
941 
942     // set min size pixel to current size
943     Size aOutSize( GetOutputSizePixel() );
944     SetMinOutputSizePixel( aOutSize );
945 
946     // if there is space enough, enlarge the preview so it gets roughly as
947     // high as the tab control
948     if( aOutSize.Width() < 768 )
949     {
950         Size aJobPageSize( getJobPageSize() );
951         Size aTabSize( maTabCtrl.GetSizePixel() );
952         if( aJobPageSize.Width() < 1 )
953             aJobPageSize.Width() = aTabSize.Width();
954         if( aJobPageSize.Height() < 1 )
955             aJobPageSize.Height() = aTabSize.Height();
956         long nOptPreviewWidth = aTabSize.Height() * aJobPageSize.Width() / aJobPageSize.Height();
957         // add space for borders
958         nOptPreviewWidth += 15;
959         if( aOutSize.Width() - aTabSize.Width() < nOptPreviewWidth )
960         {
961             aOutSize.Width() = aTabSize.Width() + nOptPreviewWidth;
962             if( aOutSize.Width() > 768 ) // don't enlarge the dialog too much
963                 aOutSize.Width() = 768;
964             SetOutputSizePixel( aOutSize );
965         }
966     }
967 
968     // append further tab pages
969     if( mbShowLayoutPage )
970     {
971         maTabCtrl.InsertPage( SV_PRINT_TAB_NUP, maNUpPage.GetText() );
972         maTabCtrl.SetTabPage( SV_PRINT_TAB_NUP, &maNUpPage );
973     }
974     maTabCtrl.InsertPage( SV_PRINT_TAB_OPT, maOptionsPage.GetText() );
975     maTabCtrl.SetTabPage( SV_PRINT_TAB_OPT, &maOptionsPage );
976 
977     // restore settings from last run
978     readFromSettings();
979 
980     // setup dependencies
981     checkControlDependencies();
982 
983 }
984 
985 PrintDialog::~PrintDialog()
986 {
987     while( ! maControls.empty() )
988     {
989         delete maControls.front();
990         maControls.pop_front();
991     }
992 }
993 
994 void PrintDialog::setupLayout()
995 {
996     boost::shared_ptr<vcl::RowOrColumn> xLayout =
997         boost::dynamic_pointer_cast<vcl::RowOrColumn>( getLayout() );
998     xLayout->setOuterBorder( 0 );
999 
1000 
1001     boost::shared_ptr< vcl::RowOrColumn > xPreviewAndTab( new vcl::RowOrColumn( xLayout.get(), false ) );
1002     size_t nIndex = xLayout->addChild( xPreviewAndTab, 5 );
1003     xLayout->setBorders( nIndex, -1, -1, -1, 0 );
1004 
1005     // setup column for preview and sub controls
1006     boost::shared_ptr< vcl::RowOrColumn > xPreview( new vcl::RowOrColumn( xPreviewAndTab.get() ) );
1007     xPreviewAndTab->addChild( xPreview, 5 );
1008     xPreview->addWindow( &maPreviewWindow, 5 );
1009     // get a row for the preview controls
1010     mxPreviewCtrls.reset( new vcl::RowOrColumn( xPreview.get(), false ) );
1011     nIndex = xPreview->addChild( mxPreviewCtrls );
1012     boost::shared_ptr< vcl::Spacer > xSpacer( new vcl::Spacer( mxPreviewCtrls.get(), 2 ) );
1013     mxPreviewCtrls->addChild( xSpacer );
1014     mxPreviewCtrls->addWindow( &maPageEdit );
1015     mxPreviewCtrls->addWindow( &maNumPagesText );
1016     xSpacer.reset( new vcl::Spacer( mxPreviewCtrls.get(), 2 ) );
1017     mxPreviewCtrls->addChild( xSpacer );
1018     mxPreviewCtrls->addWindow( &maBackwardBtn );
1019     mxPreviewCtrls->addWindow( &maForwardBtn );
1020     xSpacer.reset( new vcl::Spacer( mxPreviewCtrls.get(), 2 ) );
1021     mxPreviewCtrls->addChild( xSpacer );
1022 
1023     // continue with the tab ctrl
1024     xPreviewAndTab->addWindow( &maTabCtrl );
1025 
1026     // add the button line
1027     xLayout->addWindow( &maButtonLine );
1028 
1029     // add the row for the buttons
1030     boost::shared_ptr< vcl::RowOrColumn > xButtons( new vcl::RowOrColumn( xLayout.get(), false ) );
1031     nIndex = xLayout->addChild( xButtons );
1032     xLayout->setBorders( nIndex, -1, 0, -1, -1 );
1033 
1034     Size aMinSize( maCancelButton.GetSizePixel() );
1035     // insert help button
1036     xButtons->setMinimumSize( xButtons->addWindow( &maHelpButton ), aMinSize );
1037     // insert a spacer, cancel and OK buttons are right aligned
1038     xSpacer.reset( new vcl::Spacer( xButtons.get(), 2 ) );
1039     xButtons->addChild( xSpacer );
1040     xButtons->setMinimumSize( xButtons->addWindow( &maOKButton ), aMinSize );
1041     xButtons->setMinimumSize( xButtons->addWindow( &maCancelButton ), aMinSize );
1042 }
1043 
1044 void PrintDialog::readFromSettings()
1045 {
1046     maJobPage.readFromSettings();
1047     maNUpPage.readFromSettings();
1048     maOptionsPage.readFromSettings();
1049 
1050     // read last selected tab page; if it exists, actiavte it
1051     SettingsConfigItem* pItem = SettingsConfigItem::get();
1052     rtl::OUString aValue = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
1053                                             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPage" ) ) );
1054     sal_uInt16 nCount = maTabCtrl.GetPageCount();
1055     for( sal_uInt16 i = 0; i < nCount; i++ )
1056     {
1057         sal_uInt16 nPageId = maTabCtrl.GetPageId( i );
1058         if( aValue.equals( maTabCtrl.GetPageText( nPageId ) ) )
1059         {
1060             maTabCtrl.SelectTabPage( nPageId );
1061             break;
1062         }
1063     }
1064     maOKButton.SetText( maOptionsPage.maToFileBox.IsChecked() ? maPrintToFileText : maPrintText );
1065 
1066     // persistent window state
1067     rtl::OUString aWinState( pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
1068                                               rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WindowState" ) ) ) );
1069     if( aWinState.getLength() )
1070         SetWindowState( rtl::OUStringToOString( aWinState, RTL_TEXTENCODING_UTF8 ) );
1071 
1072     if( maOptionsPage.maToFileBox.IsChecked() )
1073     {
1074         maPController->resetPrinterOptions( true );
1075         preparePreview( true, true );
1076     }
1077 }
1078 
1079 void PrintDialog::storeToSettings()
1080 {
1081     maJobPage.storeToSettings();
1082     maNUpPage.storeToSettings();
1083     maOptionsPage.storeToSettings();
1084 
1085     // store last selected printer
1086     SettingsConfigItem* pItem = SettingsConfigItem::get();
1087     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
1088                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPrinter" ) ),
1089                      maJobPage.maPrinters.GetSelectEntry() );
1090 
1091     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
1092                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPage" ) ),
1093                      maTabCtrl.GetPageText( maTabCtrl.GetCurPageId() ) );
1094     pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
1095                      rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WindowState" ) ),
1096                      rtl::OStringToOUString( GetWindowState(), RTL_TEXTENCODING_UTF8 )
1097                      );
1098     pItem->Commit();
1099 }
1100 
1101 bool PrintDialog::isPrintToFile()
1102 {
1103     return maOptionsPage.maToFileBox.IsChecked();
1104 }
1105 
1106 int PrintDialog::getCopyCount()
1107 {
1108     return static_cast<int>(maJobPage.maCopyCountField.GetValue());
1109 }
1110 
1111 bool PrintDialog::isCollate()
1112 {
1113     return maJobPage.maCopyCountField.GetValue() > 1 ? maJobPage.maCollateBox.IsChecked() : sal_False;
1114 }
1115 
1116 bool PrintDialog::isSingleJobs()
1117 {
1118     return maOptionsPage.maCollateSingleJobsBox.IsChecked();
1119 }
1120 
1121 void setHelpId( Window* i_pWindow, const Sequence< rtl::OUString >& i_rHelpIds, sal_Int32 i_nIndex )
1122 {
1123     if( i_nIndex >= 0 && i_nIndex < i_rHelpIds.getLength() )
1124         i_pWindow->SetHelpId( rtl::OUStringToOString( i_rHelpIds.getConstArray()[i_nIndex], RTL_TEXTENCODING_UTF8 ) );
1125 }
1126 
1127 static void setHelpText( Window* i_pWindow, const Sequence< rtl::OUString >& i_rHelpTexts, sal_Int32 i_nIndex )
1128 {
1129     // without a help text set and the correct smartID,
1130     // help texts will be retrieved from the online help system
1131     if( i_nIndex >= 0 && i_nIndex < i_rHelpTexts.getLength() )
1132         i_pWindow->SetHelpText( i_rHelpTexts.getConstArray()[i_nIndex] );
1133 }
1134 
1135 void updateMaxSize( const Size& i_rCheckSize, Size& o_rMaxSize )
1136 {
1137     if( i_rCheckSize.Width() > o_rMaxSize.Width() )
1138         o_rMaxSize.Width() = i_rCheckSize.Width();
1139     if( i_rCheckSize.Height() > o_rMaxSize.Height() )
1140         o_rMaxSize.Height() = i_rCheckSize.Height();
1141 }
1142 
1143 void PrintDialog::setupOptionalUI()
1144 {
1145     std::vector< boost::shared_ptr<vcl::RowOrColumn> > aDynamicColumns;
1146     boost::shared_ptr< vcl::RowOrColumn > pCurColumn;
1147 
1148     Window* pCurParent = 0, *pDynamicPageParent = 0;
1149     sal_uInt16 nOptPageId = 9, nCurSubGroup = 0;
1150     bool bOnStaticPage = false;
1151     bool bSubgroupOnStaticPage = false;
1152 
1153     std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> > aPropertyToDependencyRowMap;
1154 
1155     const Sequence< PropertyValue >& rOptions( maPController->getUIOptions() );
1156     for( int i = 0; i < rOptions.getLength(); i++ )
1157     {
1158         Sequence< beans::PropertyValue > aOptProp;
1159         rOptions[i].Value >>= aOptProp;
1160 
1161         // extract ui element
1162         bool bEnabled = true;
1163         rtl::OUString aCtrlType;
1164         rtl::OUString aText;
1165         rtl::OUString aPropertyName;
1166         Sequence< rtl::OUString > aChoices;
1167         Sequence< sal_Bool > aChoicesDisabled;
1168         Sequence< rtl::OUString > aHelpTexts;
1169         Sequence< rtl::OUString > aHelpIds;
1170         sal_Int64 nMinValue = 0, nMaxValue = 0;
1171         sal_Int32 nCurHelpText = 0;
1172         rtl::OUString aGroupingHint;
1173         rtl::OUString aDependsOnName;
1174         sal_Int32 nDependsOnValue = 0;
1175         sal_Bool bUseDependencyRow = sal_False;
1176 
1177         for( int n = 0; n < aOptProp.getLength(); n++ )
1178         {
1179             const beans::PropertyValue& rEntry( aOptProp[ n ] );
1180             if( rEntry.Name.equalsAscii( "Text" ) )
1181             {
1182                 rEntry.Value >>= aText;
1183             }
1184             else if( rEntry.Name.equalsAscii( "ControlType" ) )
1185             {
1186                 rEntry.Value >>= aCtrlType;
1187             }
1188             else if( rEntry.Name.equalsAscii( "Choices" ) )
1189             {
1190                 rEntry.Value >>= aChoices;
1191             }
1192             else if( rEntry.Name.equalsAscii( "ChoicesDisabled" ) )
1193             {
1194                 rEntry.Value >>= aChoicesDisabled;
1195             }
1196             else if( rEntry.Name.equalsAscii( "Property" ) )
1197             {
1198                 PropertyValue aVal;
1199                 rEntry.Value >>= aVal;
1200                 aPropertyName = aVal.Name;
1201             }
1202             else if( rEntry.Name.equalsAscii( "Enabled" ) )
1203             {
1204                 sal_Bool bValue = sal_True;
1205                 rEntry.Value >>= bValue;
1206                 bEnabled = bValue;
1207             }
1208             else if( rEntry.Name.equalsAscii( "GroupingHint" ) )
1209             {
1210                 rEntry.Value >>= aGroupingHint;
1211             }
1212             else if( rEntry.Name.equalsAscii( "DependsOnName" ) )
1213             {
1214                 rEntry.Value >>= aDependsOnName;
1215             }
1216             else if( rEntry.Name.equalsAscii( "DependsOnEntry" ) )
1217             {
1218                 rEntry.Value >>= nDependsOnValue;
1219             }
1220             else if( rEntry.Name.equalsAscii( "AttachToDependency" ) )
1221             {
1222                 rEntry.Value >>= bUseDependencyRow;
1223             }
1224             else if( rEntry.Name.equalsAscii( "MinValue" ) )
1225             {
1226                 rEntry.Value >>= nMinValue;
1227             }
1228             else if( rEntry.Name.equalsAscii( "MaxValue" ) )
1229             {
1230                 rEntry.Value >>= nMaxValue;
1231             }
1232             else if( rEntry.Name.equalsAscii( "HelpText" ) )
1233             {
1234                 if( ! (rEntry.Value >>= aHelpTexts) )
1235                 {
1236                     rtl::OUString aHelpText;
1237                     if( (rEntry.Value >>= aHelpText) )
1238                     {
1239                         aHelpTexts.realloc( 1 );
1240                         *aHelpTexts.getArray() = aHelpText;
1241                     }
1242                 }
1243             }
1244             else if( rEntry.Name.equalsAscii( "HelpId" ) )
1245             {
1246                 if( ! (rEntry.Value >>= aHelpIds ) )
1247                 {
1248                     rtl::OUString aHelpId;
1249                     if( (rEntry.Value >>= aHelpId) )
1250                     {
1251                         aHelpIds.realloc( 1 );
1252                         *aHelpIds.getArray() = aHelpId;
1253                     }
1254                 }
1255             }
1256             else if( rEntry.Name.equalsAscii( "HintNoLayoutPage" ) )
1257             {
1258                 sal_Bool bNoLayoutPage = sal_False;
1259                 rEntry.Value >>= bNoLayoutPage;
1260                 mbShowLayoutPage = ! bNoLayoutPage;
1261             }
1262         }
1263 
1264         // bUseDependencyRow should only be true if a dependency exists
1265         bUseDependencyRow = bUseDependencyRow && (aDependsOnName.getLength() != 0);
1266 
1267         // is it necessary to switch between static and dynamic pages ?
1268         bool bSwitchPage = false;
1269         if( aGroupingHint.getLength() )
1270             bSwitchPage = true;
1271         else if( aCtrlType.equalsAscii( "Subgroup" ) || (bOnStaticPage && ! bSubgroupOnStaticPage )  )
1272             bSwitchPage = true;
1273         if( bSwitchPage )
1274         {
1275             // restore to dynamic
1276             pCurParent = pDynamicPageParent;
1277             if( ! aDynamicColumns.empty() )
1278                 pCurColumn = aDynamicColumns.back();
1279             else
1280                 pCurColumn.reset();
1281             bOnStaticPage = false;
1282             bSubgroupOnStaticPage = false;
1283 
1284             if( aGroupingHint.equalsAscii( "PrintRange" ) )
1285             {
1286                 pCurColumn = maJobPage.mxPrintRange;
1287                 pCurParent = &maJobPage;            // set job page as current parent
1288                 bOnStaticPage = true;
1289             }
1290             else if( aGroupingHint.equalsAscii( "OptionsPage" ) )
1291             {
1292                 pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maOptionsPage.getLayout());
1293                 pCurParent = &maOptionsPage;        // set options page as current parent
1294                 bOnStaticPage = true;
1295             }
1296             else if( aGroupingHint.equalsAscii( "OptionsPageOptGroup" ) )
1297             {
1298                 pCurColumn = maOptionsPage.mxOptGroup;
1299                 pCurParent = &maOptionsPage;        // set options page as current parent
1300                 bOnStaticPage = true;
1301             }
1302             else if( aGroupingHint.equalsAscii( "LayoutPage" ) )
1303             {
1304                 pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maNUpPage.getLayout());
1305                 pCurParent = &maNUpPage;            // set layout page as current parent
1306                 bOnStaticPage = true;
1307             }
1308             else if( aGroupingHint.getLength() )
1309             {
1310                 pCurColumn = boost::dynamic_pointer_cast<vcl::RowOrColumn>(maJobPage.getLayout());
1311                 pCurParent = &maJobPage;            // set job page as current parent
1312                 bOnStaticPage = true;
1313             }
1314         }
1315 
1316         if( aCtrlType.equalsAscii( "Group" ) ||
1317             ( ! pCurParent && ! (bOnStaticPage || aGroupingHint.getLength() ) ) )
1318         {
1319             // add new tab page
1320             TabPage* pNewGroup = new TabPage( &maTabCtrl );
1321             maControls.push_front( pNewGroup );
1322             pDynamicPageParent = pCurParent = pNewGroup;
1323             pNewGroup->SetText( aText );
1324             maTabCtrl.InsertPage( ++nOptPageId, aText );
1325             maTabCtrl.SetTabPage( nOptPageId, pNewGroup );
1326 
1327             // set help id
1328             setHelpId( pNewGroup, aHelpIds, 0 );
1329             // set help text
1330             setHelpText( pNewGroup, aHelpTexts, 0 );
1331 
1332             // reset subgroup counter
1333             nCurSubGroup = 0;
1334 
1335             aDynamicColumns.push_back( boost::dynamic_pointer_cast<vcl::RowOrColumn>(pNewGroup->getLayout()) );
1336             pCurColumn = aDynamicColumns.back();
1337             pCurColumn->setParentWindow( pNewGroup );
1338             bSubgroupOnStaticPage = false;
1339             bOnStaticPage = false;
1340         }
1341         else if( aCtrlType.equalsAscii( "Subgroup" ) && (pCurParent || aGroupingHint.getLength() ) )
1342         {
1343             bSubgroupOnStaticPage = (aGroupingHint.getLength() != 0);
1344             // create group FixedLine
1345             if( ! aGroupingHint.equalsAscii( "PrintRange" ) ||
1346                 ! pCurColumn->countElements() == 0
1347                )
1348             {
1349                 Window* pNewSub = NULL;
1350                 if( aGroupingHint.equalsAscii( "PrintRange" ) )
1351                     pNewSub = new FixedText( pCurParent, WB_VCENTER );
1352                 else
1353                     pNewSub = new FixedLine( pCurParent );
1354                 maControls.push_front( pNewSub );
1355                 pNewSub->SetText( aText );
1356                 pNewSub->Show();
1357 
1358                 // set help id
1359                 setHelpId( pNewSub, aHelpIds, 0 );
1360                 // set help text
1361                 setHelpText( pNewSub, aHelpTexts, 0 );
1362                 // add group to current column
1363                 pCurColumn->addWindow( pNewSub );
1364             }
1365 
1366             // add an indent to the current column
1367             vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn.get(), -1 );
1368             pCurColumn->addChild( pIndent );
1369             // and create a column inside the indent
1370             pCurColumn.reset( new vcl::RowOrColumn( pIndent ) );
1371             pIndent->setChild( pCurColumn );
1372         }
1373         // EVIL
1374         else if( aCtrlType.equalsAscii( "Bool" ) &&
1375                  aGroupingHint.equalsAscii( "LayoutPage" ) &&
1376                  aPropertyName.equalsAscii( "PrintProspect" )
1377                  )
1378         {
1379             maNUpPage.maBrochureBtn.SetText( aText );
1380             maNUpPage.maBrochureBtn.Show();
1381             setHelpText( &maNUpPage.maBrochureBtn, aHelpTexts, 0 );
1382 
1383             sal_Bool bVal = sal_False;
1384             PropertyValue* pVal = maPController->getValue( aPropertyName );
1385             if( pVal )
1386                 pVal->Value >>= bVal;
1387             maNUpPage.maBrochureBtn.Check( bVal );
1388             maNUpPage.maBrochureBtn.Enable( maPController->isUIOptionEnabled( aPropertyName ) && pVal != NULL );
1389             maNUpPage.maBrochureBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) );
1390 
1391             maPropertyToWindowMap[ aPropertyName ].push_back( &maNUpPage.maBrochureBtn );
1392             maControlToPropertyMap[&maNUpPage.maBrochureBtn] = aPropertyName;
1393 
1394             aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, maNUpPage.mxBrochureDep ) );
1395         }
1396         else
1397         {
1398             boost::shared_ptr<vcl::RowOrColumn> pSaveCurColumn( pCurColumn );
1399 
1400             if( bUseDependencyRow )
1401             {
1402                 // find the correct dependency row (if any)
1403                 std::pair< std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >::iterator,
1404                            std::multimap< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >::iterator > aDepRange;
1405                 aDepRange = aPropertyToDependencyRowMap.equal_range( aDependsOnName );
1406                 if( aDepRange.first != aDepRange.second )
1407                 {
1408                     while( nDependsOnValue && aDepRange.first != aDepRange.second )
1409                     {
1410                         nDependsOnValue--;
1411                         ++aDepRange.first;
1412                     }
1413                     if( aDepRange.first != aPropertyToDependencyRowMap.end() )
1414                     {
1415                         pCurColumn = aDepRange.first->second;
1416                         maReverseDependencySet.insert( aPropertyName );
1417                     }
1418                 }
1419             }
1420             if( aCtrlType.equalsAscii( "Bool" ) && pCurParent )
1421             {
1422                 // add a check box
1423                 CheckBox* pNewBox = new CheckBox( pCurParent );
1424                 maControls.push_front( pNewBox );
1425                 pNewBox->SetText( aText );
1426                 pNewBox->Show();
1427 
1428                 sal_Bool bVal = sal_False;
1429                 PropertyValue* pVal = maPController->getValue( aPropertyName );
1430                 if( pVal )
1431                     pVal->Value >>= bVal;
1432                 pNewBox->Check( bVal );
1433                 pNewBox->SetToggleHdl( LINK( this, PrintDialog, UIOption_CheckHdl ) );
1434 
1435                 maPropertyToWindowMap[ aPropertyName ].push_back( pNewBox );
1436                 maControlToPropertyMap[pNewBox] = aPropertyName;
1437 
1438                 // set help id
1439                 setHelpId( pNewBox, aHelpIds, 0 );
1440                 // set help text
1441                 setHelpText( pNewBox, aHelpTexts, 0 );
1442 
1443                 boost::shared_ptr<vcl::RowOrColumn> pDependencyRow( new vcl::RowOrColumn( pCurColumn.get(), false ) );
1444                 pCurColumn->addChild( pDependencyRow );
1445                 aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pDependencyRow ) );
1446 
1447                 // add checkbox to current column
1448                 pDependencyRow->addWindow( pNewBox );
1449             }
1450             else if( aCtrlType.equalsAscii( "Radio" ) && pCurParent )
1451             {
1452                 boost::shared_ptr<vcl::RowOrColumn> pRadioColumn( pCurColumn );
1453                 if( aText.getLength() )
1454                 {
1455                     // add a FixedText:
1456                     FixedText* pHeading = new FixedText( pCurParent );
1457                     maControls.push_front( pHeading );
1458                     pHeading->SetText( aText );
1459                     pHeading->Show();
1460 
1461                     // set help id
1462                     setHelpId( pHeading, aHelpIds, nCurHelpText );
1463                     // set help text
1464                     setHelpText( pHeading, aHelpTexts, nCurHelpText );
1465                     nCurHelpText++;
1466                     // add fixed text to current column
1467                     pCurColumn->addWindow( pHeading );
1468                     // add an indent to the current column
1469                     vcl::Indenter* pIndent = new vcl::Indenter( pCurColumn.get(), 15 );
1470                     pCurColumn->addChild( pIndent );
1471                     // and create a column inside the indent
1472                     pRadioColumn.reset( new vcl::RowOrColumn( pIndent ) );
1473                     pIndent->setChild( pRadioColumn );
1474                 }
1475                 // iterate options
1476                 sal_Int32 nSelectVal = 0;
1477                 PropertyValue* pVal = maPController->getValue( aPropertyName );
1478                 if( pVal && pVal->Value.hasValue() )
1479                     pVal->Value >>= nSelectVal;
1480                 for( sal_Int32 m = 0; m < aChoices.getLength(); m++ )
1481                 {
1482                     boost::shared_ptr<vcl::LabeledElement> pLabel( new vcl::LabeledElement( pRadioColumn.get(), 1 ) );
1483                     pRadioColumn->addChild( pLabel );
1484                     boost::shared_ptr<vcl::RowOrColumn> pDependencyRow( new vcl::RowOrColumn( pLabel.get(), false ) );
1485                     pLabel->setElement( pDependencyRow );
1486                     aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pDependencyRow ) );
1487 
1488                     RadioButton* pBtn = new RadioButton( pCurParent, m == 0 ? WB_GROUP : 0 );
1489                     maControls.push_front( pBtn );
1490                     pBtn->SetText( aChoices[m] );
1491                     pBtn->Check( m == nSelectVal );
1492                     pBtn->SetToggleHdl( LINK( this, PrintDialog, UIOption_RadioHdl ) );
1493                     if( aChoicesDisabled.getLength() > m && aChoicesDisabled[m] == sal_True )
1494                         pBtn->Enable( sal_False );
1495                     pBtn->Show();
1496                     maPropertyToWindowMap[ aPropertyName ].push_back( pBtn );
1497                     maControlToPropertyMap[pBtn] = aPropertyName;
1498                     maControlToNumValMap[pBtn] = m;
1499 
1500                     // set help id
1501                     setHelpId( pBtn, aHelpIds, nCurHelpText );
1502                     // set help text
1503                     setHelpText( pBtn, aHelpTexts, nCurHelpText );
1504                     nCurHelpText++;
1505                     // add the radio button to the column
1506                     pLabel->setLabel( pBtn );
1507                 }
1508             }
1509             else if( ( aCtrlType.equalsAscii( "List" )   ||
1510                        aCtrlType.equalsAscii( "Range" )  ||
1511                        aCtrlType.equalsAscii( "Edit" )
1512                      ) && pCurParent )
1513             {
1514                 // create a row in the current column
1515                 boost::shared_ptr<vcl::RowOrColumn> pFieldColumn( new vcl::RowOrColumn( pCurColumn.get(), false ) );
1516                 pCurColumn->addChild( pFieldColumn );
1517                 aPropertyToDependencyRowMap.insert( std::pair< rtl::OUString, boost::shared_ptr<vcl::RowOrColumn> >( aPropertyName, pFieldColumn ) );
1518 
1519                 vcl::LabeledElement* pLabel = NULL;
1520                 if( aText.getLength() )
1521                 {
1522                     // add a FixedText:
1523                     FixedText* pHeading = new FixedText( pCurParent, WB_VCENTER );
1524                     maControls.push_front( pHeading );
1525                     pHeading->SetText( aText );
1526                     pHeading->Show();
1527 
1528                     // add to row
1529                     pLabel = new vcl::LabeledElement( pFieldColumn.get(), 2 );
1530                     pFieldColumn->addChild( pLabel );
1531                     pLabel->setLabel( pHeading );
1532                 }
1533 
1534                 if( aCtrlType.equalsAscii( "List" ) )
1535                 {
1536                     ListBox* pList = new ListBox( pCurParent, WB_DROPDOWN | WB_BORDER );
1537                     maControls.push_front( pList );
1538 
1539                     // iterate options
1540                     for( sal_Int32 m = 0; m < aChoices.getLength(); m++ )
1541                     {
1542                         pList->InsertEntry( aChoices[m] );
1543                     }
1544                     sal_Int32 nSelectVal = 0;
1545                     PropertyValue* pVal = maPController->getValue( aPropertyName );
1546                     if( pVal && pVal->Value.hasValue() )
1547                         pVal->Value >>= nSelectVal;
1548                     pList->SelectEntryPos( static_cast<sal_uInt16>(nSelectVal) );
1549                     pList->SetSelectHdl( LINK( this, PrintDialog, UIOption_SelectHdl ) );
1550                     pList->SetDropDownLineCount( static_cast<sal_uInt16>(aChoices.getLength()) );
1551                     pList->Show();
1552 
1553                     // set help id
1554                     setHelpId( pList, aHelpIds, 0 );
1555                     // set help text
1556                     setHelpText( pList, aHelpTexts, 0 );
1557 
1558                     maPropertyToWindowMap[ aPropertyName ].push_back( pList );
1559                     maControlToPropertyMap[pList] = aPropertyName;
1560 
1561                     // finish the pair
1562                     if( pLabel )
1563                         pLabel->setElement( pList );
1564                     else
1565                         pFieldColumn->addWindow( pList );
1566                 }
1567                 else if( aCtrlType.equalsAscii( "Range" ) )
1568                 {
1569                     NumericField* pField = new NumericField( pCurParent, WB_BORDER | WB_SPIN );
1570                     maControls.push_front( pField );
1571 
1572                     // set min/max and current value
1573                     if( nMinValue != nMaxValue )
1574                     {
1575                         pField->SetMin( nMinValue );
1576                         pField->SetMax( nMaxValue );
1577                     }
1578                     sal_Int64 nCurVal = 0;
1579                     PropertyValue* pVal = maPController->getValue( aPropertyName );
1580                     if( pVal && pVal->Value.hasValue() )
1581                         pVal->Value >>= nCurVal;
1582                     pField->SetValue( nCurVal );
1583                     pField->SetModifyHdl( LINK( this, PrintDialog, UIOption_ModifyHdl ) );
1584                     pField->Show();
1585 
1586                     // set help id
1587                     setHelpId( pField, aHelpIds, 0 );
1588                     // set help text
1589                     setHelpText( pField, aHelpTexts, 0 );
1590 
1591                     maPropertyToWindowMap[ aPropertyName ].push_back( pField );
1592                     maControlToPropertyMap[pField] = aPropertyName;
1593 
1594                     // add to row
1595                     if( pLabel )
1596                         pLabel->setElement( pField );
1597                     else
1598                         pFieldColumn->addWindow( pField );
1599                 }
1600                 else if( aCtrlType.equalsAscii( "Edit" ) )
1601                 {
1602                     Edit* pField = new Edit( pCurParent, WB_BORDER );
1603                     maControls.push_front( pField );
1604 
1605                     rtl::OUString aCurVal;
1606                     PropertyValue* pVal = maPController->getValue( aPropertyName );
1607                     if( pVal && pVal->Value.hasValue() )
1608                         pVal->Value >>= aCurVal;
1609                     pField->SetText( aCurVal );
1610                     pField->SetModifyHdl( LINK( this, PrintDialog, UIOption_ModifyHdl ) );
1611                     pField->Show();
1612 
1613                     // set help id
1614                     setHelpId( pField, aHelpIds, 0 );
1615                     // set help text
1616                     setHelpText( pField, aHelpTexts, 0 );
1617 
1618                     maPropertyToWindowMap[ aPropertyName ].push_back( pField );
1619                     maControlToPropertyMap[pField] = aPropertyName;
1620 
1621                     // add to row
1622                     if( pLabel )
1623                         pLabel->setElement( pField );
1624                     else
1625                         pFieldColumn->addWindow( pField, 2 );
1626                 }
1627             }
1628             else
1629             {
1630                 DBG_ERROR( "Unsupported UI option" );
1631             }
1632 
1633             pCurColumn = pSaveCurColumn;
1634         }
1635     }
1636 
1637     // #i106506# if no brochure button, then the singular Pages radio button
1638     // makes no sense, so replace it by a FixedText label
1639     if( ! maNUpPage.maBrochureBtn.IsVisible() )
1640     {
1641         if( maNUpPage.mxPagesBtnLabel.get() )
1642         {
1643             maNUpPage.maPagesBoxTitleTxt.SetText( maNUpPage.maPagesBtn.GetText() );
1644             maNUpPage.maPagesBoxTitleTxt.Show( sal_True );
1645             maNUpPage.mxPagesBtnLabel->setLabel( &maNUpPage.maPagesBoxTitleTxt );
1646             maNUpPage.maPagesBtn.Show( sal_False );
1647         }
1648     }
1649 
1650     // update enable states
1651     checkOptionalControlDependencies();
1652 
1653     // print range empty (currently math only) -> hide print range and spacer line
1654     if( maJobPage.mxPrintRange->countElements() == 0 )
1655     {
1656         maJobPage.mxPrintRange->show( false, false );
1657         maJobPage.maCopySpacer.Show( sal_False );
1658         maJobPage.maReverseOrderBox.Show( sal_False );
1659     }
1660     else
1661     {
1662         // add an indent to the current column
1663         vcl::Indenter* pIndent = new vcl::Indenter( maJobPage.mxPrintRange.get(), -1 );
1664         maJobPage.mxPrintRange->addChild( pIndent );
1665         // and create a column inside the indent
1666         pIndent->setWindow( &maJobPage.maReverseOrderBox );
1667         maJobPage.maReverseOrderBox.Show( sal_True );
1668     }
1669 
1670 #ifdef WNT
1671     // FIXME: the GetNativeControlRegion call on Windows has some issues
1672     // (which skew the results of GetOptimalSize())
1673     // however fixing this thoroughly needs to take interaction with paint into
1674     // account, making the right fix less simple. Fix this the right way
1675     // at some point. For now simply add some space at the lowest element
1676     size_t nIndex = maJobPage.getLayout()->countElements();
1677     if( nIndex > 0 ) // sanity check
1678         maJobPage.getLayout()->setBorders( nIndex-1, 0, 0, 0, -1 );
1679 #endif
1680 
1681     // create auto mnemomnics now so they can be calculated in layout
1682     ImplWindowAutoMnemonic( &maJobPage );
1683     ImplWindowAutoMnemonic( &maNUpPage );
1684     ImplWindowAutoMnemonic( &maOptionsPage );
1685     ImplWindowAutoMnemonic( this );
1686 
1687     // calculate job page
1688     Size aMaxSize = maJobPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED );
1689     // and layout page
1690     updateMaxSize( maNUpPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
1691     // and options page
1692     updateMaxSize( maOptionsPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ), aMaxSize );
1693 
1694     for( std::vector< boost::shared_ptr<vcl::RowOrColumn> >::iterator it = aDynamicColumns.begin();
1695          it != aDynamicColumns.end(); ++it )
1696     {
1697         Size aPageSize( (*it)->getOptimalSize( WINDOWSIZE_PREFERRED ) );
1698         updateMaxSize( aPageSize, aMaxSize );
1699     }
1700 
1701     // resize dialog if necessary
1702     Size aTabSize = maTabCtrl.GetTabPageSizePixel();
1703     maTabCtrl.SetMinimumSizePixel( maTabCtrl.GetSizePixel() );
1704     if( aMaxSize.Height() > aTabSize.Height() || aMaxSize.Width() > aTabSize.Width() )
1705     {
1706         Size aCurSize( GetOutputSizePixel() );
1707         if( aMaxSize.Height() > aTabSize.Height() )
1708 		{
1709             aCurSize.Height() += aMaxSize.Height() - aTabSize.Height();
1710 			aTabSize.Height() = aMaxSize.Height();
1711 		}
1712         if( aMaxSize.Width() > aTabSize.Width() )
1713         {
1714             aCurSize.Width() += aMaxSize.Width() - aTabSize.Width();
1715             // and the tab ctrl needs more space, too
1716             aTabSize.Width() = aMaxSize.Width();
1717         }
1718         maTabCtrl.SetTabPageSizePixel( aTabSize );
1719         maTabCtrl.SetMinimumSizePixel( maTabCtrl.GetSizePixel() );
1720     }
1721 
1722     Size aSz = getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED );
1723     SetOutputSizePixel( aSz );
1724 }
1725 
1726 void PrintDialog::DataChanged( const DataChangedEvent& i_rDCEvt )
1727 {
1728     // react on settings changed
1729     if( i_rDCEvt.GetType() == DATACHANGED_SETTINGS )
1730         checkControlDependencies();
1731     ModalDialog::DataChanged( i_rDCEvt );
1732 }
1733 
1734 void PrintDialog::checkControlDependencies()
1735 {
1736     if( maJobPage.maCopyCountField.GetValue() > 1 )
1737         maJobPage.maCollateBox.Enable( maJobPage.mnCollateUIMode == 0 );
1738     else
1739         maJobPage.maCollateBox.Enable( sal_False );
1740 
1741     Image aImg( maJobPage.maCollateBox.IsChecked() ? maJobPage.maCollateImg : maJobPage.maNoCollateImg );
1742     Image aHCImg( maJobPage.maCollateBox.IsChecked() ? maJobPage.maCollateHCImg : maJobPage.maNoCollateHCImg );
1743     bool bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
1744 
1745     Size aImgSize( aImg.GetSizePixel() );
1746     Size aHCImgSize( aHCImg.GetSizePixel() );
1747 
1748     if( aHCImgSize.Width() > aImgSize.Width() )
1749         aImgSize.Width() = aHCImgSize.Width();
1750     if( aHCImgSize.Height() > aImgSize.Height() )
1751         aImgSize.Height() = aHCImgSize.Height();
1752 
1753     // adjust size of image
1754     maJobPage.maCollateImage.SetSizePixel( aImgSize );
1755     maJobPage.maCollateImage.SetImage( bHC ? aHCImg : aImg );
1756     maJobPage.maCollateImage.SetModeImage( aHCImg, BMP_COLOR_HIGHCONTRAST );
1757     maJobPage.getLayout()->resize();
1758 
1759     // enable setup button only for printers that can be setup
1760     bool bHaveSetup = maPController->getPrinter()->HasSupport( SUPPORT_SETUPDIALOG );
1761     maJobPage.maSetupButton.Enable( bHaveSetup );
1762     if( bHaveSetup )
1763     {
1764         if( ! maJobPage.maSetupButton.IsVisible() )
1765         {
1766             Point aPrinterPos( maJobPage.maPrinters.GetPosPixel() );
1767             Point aSetupPos( maJobPage.maSetupButton.GetPosPixel() );
1768             Size aPrinterSize( maJobPage.maPrinters.GetSizePixel() );
1769             aPrinterSize.Width() = aSetupPos.X() - aPrinterPos.X() - LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ).Width();
1770             maJobPage.maPrinters.SetSizePixel( aPrinterSize );
1771             maJobPage.maSetupButton.Show();
1772             getLayout()->resize();
1773         }
1774     }
1775     else
1776     {
1777         if( maJobPage.maSetupButton.IsVisible() )
1778         {
1779             Point aPrinterPos( maJobPage.maPrinters.GetPosPixel() );
1780             Point aSetupPos( maJobPage.maSetupButton.GetPosPixel() );
1781             Size aPrinterSize( maJobPage.maPrinters.GetSizePixel() );
1782             Size aSetupSize( maJobPage.maSetupButton.GetSizePixel() );
1783             aPrinterSize.Width() = aSetupPos.X() + aSetupSize.Width() - aPrinterPos.X();
1784             maJobPage.maPrinters.SetSizePixel( aPrinterSize );
1785             maJobPage.maSetupButton.Hide();
1786             getLayout()->resize();
1787         }
1788     }
1789 }
1790 
1791 void PrintDialog::checkOptionalControlDependencies()
1792 {
1793     for( std::map< Window*, rtl::OUString >::iterator it = maControlToPropertyMap.begin();
1794          it != maControlToPropertyMap.end(); ++it )
1795     {
1796         bool bShouldbeEnabled = maPController->isUIOptionEnabled( it->second );
1797         if( ! bShouldbeEnabled )
1798         {
1799             // enable controls that are directly attached to a dependency anyway
1800             // if the normally disabled controls get modified, change the dependency
1801             // so the control would be enabled
1802             // example: in print range "Print All" is selected, "Page Range" is then of course
1803             // not selected and the Edit for the Page Range would be disabled
1804             // as a convenience we should enable the Edit anyway and automatically select
1805             // "Page Range" instead of "Print All" if the Edit gets modified
1806             if( maReverseDependencySet.find( it->second ) != maReverseDependencySet.end() )
1807             {
1808                 rtl::OUString aDep( maPController->getDependency( it->second ) );
1809                 // if the dependency is at least enabled, then enable this control anyway
1810                 if( aDep.getLength() && maPController->isUIOptionEnabled( aDep ) )
1811                     bShouldbeEnabled = true;
1812             }
1813         }
1814 
1815         if( bShouldbeEnabled && dynamic_cast<RadioButton*>(it->first) )
1816         {
1817             std::map< Window*, sal_Int32 >::const_iterator r_it = maControlToNumValMap.find( it->first );
1818             if( r_it != maControlToNumValMap.end() )
1819             {
1820                 bShouldbeEnabled = maPController->isUIChoiceEnabled( it->second, r_it->second );
1821             }
1822         }
1823 
1824 
1825         bool bIsEnabled = it->first->IsEnabled();
1826         // Enable does not do a change check first, so can be less cheap than expected
1827         if( bShouldbeEnabled != bIsEnabled )
1828             it->first->Enable( bShouldbeEnabled );
1829     }
1830 }
1831 
1832 static rtl::OUString searchAndReplace( const rtl::OUString& i_rOrig, const char* i_pRepl, sal_Int32 i_nReplLen, const rtl::OUString& i_rRepl )
1833 {
1834     sal_Int32 nPos = i_rOrig.indexOfAsciiL( i_pRepl, i_nReplLen );
1835     if( nPos != -1 )
1836     {
1837         rtl::OUStringBuffer aBuf( i_rOrig.getLength() );
1838         aBuf.append( i_rOrig.getStr(), nPos );
1839         aBuf.append( i_rRepl );
1840         if( nPos + i_nReplLen < i_rOrig.getLength() )
1841             aBuf.append( i_rOrig.getStr() + nPos + i_nReplLen );
1842         return aBuf.makeStringAndClear();
1843     }
1844     return i_rOrig;
1845 }
1846 
1847 void PrintDialog::updatePrinterText()
1848 {
1849     String aDefPrt( Printer::GetDefaultPrinterName() );
1850     const QueueInfo* pInfo = Printer::GetQueueInfo( maJobPage.maPrinters.GetSelectEntry(), true );
1851     if( pInfo )
1852     {
1853         maJobPage.maLocationTxt.SetText( pInfo->GetLocation() );
1854         maJobPage.maCommentTxt.SetText( pInfo->GetComment() );
1855         // FIXME: status text
1856         rtl::OUString aStatus;
1857         if( aDefPrt == pInfo->GetPrinterName() )
1858             aStatus = maDefPrtText;
1859         maJobPage.maStatusTxt.SetText( aStatus );
1860     }
1861     else
1862     {
1863         maJobPage.maLocationTxt.SetText( String() );
1864         maJobPage.maCommentTxt.SetText( String() );
1865         maJobPage.maStatusTxt.SetText( String() );
1866     }
1867 }
1868 
1869 void PrintDialog::setPreviewText( sal_Int32 )
1870 {
1871     rtl::OUString aNewText( searchAndReplace( maPageStr, "%n", 2, rtl::OUString::valueOf( mnCachedPages )  ) );
1872     maNumPagesText.SetText( aNewText );
1873 
1874     // if layout is already established the refresh layout of
1875     // preview controls since text length may have changes
1876     if( mxPreviewCtrls.get() )
1877         mxPreviewCtrls->setManagedArea( mxPreviewCtrls->getManagedArea() );
1878 }
1879 
1880 void PrintDialog::preparePreview( bool i_bNewPage, bool i_bMayUseCache )
1881 {
1882     // page range may have changed depending on options
1883     sal_Int32 nPages = maPController->getFilteredPageCount();
1884     mnCachedPages = nPages;
1885 
1886     if( mnCurPage >= nPages )
1887         mnCurPage = nPages-1;
1888     if( mnCurPage < 0 )
1889         mnCurPage = 0;
1890 
1891     setPreviewText( mnCurPage );
1892 
1893     maPageEdit.SetMin( 1 );
1894     maPageEdit.SetMax( nPages );
1895 
1896     if( i_bNewPage )
1897     {
1898         const MapMode aMapMode( MAP_100TH_MM );
1899         GDIMetaFile aMtf;
1900         boost::shared_ptr<Printer> aPrt( maPController->getPrinter() );
1901         if( nPages > 0 )
1902         {
1903             PrinterController::PageSize aPageSize =
1904                 maPController->getFilteredPageFile( mnCurPage, aMtf, i_bMayUseCache );
1905             if( ! aPageSize.bFullPaper )
1906             {
1907                 Point aOff( aPrt->PixelToLogic( aPrt->GetPageOffsetPixel(), aMapMode ) );
1908                 aMtf.Move( aOff.X(), aOff.Y() );
1909             }
1910         }
1911 
1912         Size aCurPageSize = aPrt->PixelToLogic( aPrt->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) );
1913         maPreviewWindow.setPreview( aMtf, aCurPageSize,
1914                                     aPrt->GetPaperName( false ),
1915                                     nPages > 0 ? rtl::OUString() : maNoPageStr,
1916                                     aPrt->ImplGetDPIX(), aPrt->ImplGetDPIY(),
1917                                     aPrt->GetPrinterOptions().IsConvertToGreyscales()
1918                                    );
1919 
1920         maForwardBtn.Enable( mnCurPage < nPages-1 );
1921         maBackwardBtn.Enable( mnCurPage != 0 );
1922         maPageEdit.Enable( nPages > 1 );
1923     }
1924 }
1925 
1926 Size PrintDialog::getJobPageSize()
1927 {
1928     if( maFirstPageSize.Width() == 0 && maFirstPageSize.Height() == 0)
1929     {
1930         maFirstPageSize = maNupPortraitSize;
1931         GDIMetaFile aMtf;
1932         if( maPController->getPageCountProtected() > 0 )
1933         {
1934             PrinterController::PageSize aPageSize = maPController->getPageFile( 0, aMtf, true );
1935             maFirstPageSize = aPageSize.aSize;
1936         }
1937     }
1938     return maFirstPageSize;
1939 }
1940 
1941 void PrintDialog::updateNupFromPages()
1942 {
1943     long nPages = long(maNUpPage.maNupPagesBox.GetEntryData(maNUpPage.maNupPagesBox.GetSelectEntryPos()));
1944     int nRows   = int(maNUpPage.maNupRowsEdt.GetValue());
1945     int nCols   = int(maNUpPage.maNupColEdt.GetValue());
1946     long nPageMargin  = long(maNUpPage.maPageMarginEdt.Denormalize(maNUpPage.maPageMarginEdt.GetValue( FUNIT_100TH_MM )));
1947     long nSheetMargin = long(maNUpPage.maSheetMarginEdt.Denormalize(maNUpPage.maSheetMarginEdt.GetValue( FUNIT_100TH_MM )));
1948     bool bCustom = false;
1949 
1950     if( nPages == 1 )
1951     {
1952         nRows = nCols = 1;
1953         nSheetMargin = 0;
1954         nPageMargin = 0;
1955     }
1956     else if( nPages == 2 || nPages == 4 || nPages == 6 || nPages == 9 || nPages == 16 )
1957     {
1958         Size aJobPageSize( getJobPageSize() );
1959         bool bPortrait = aJobPageSize.Width() < aJobPageSize.Height();
1960         if( nPages == 2 )
1961         {
1962             if( bPortrait )
1963                 nRows = 1, nCols = 2;
1964             else
1965                 nRows = 2, nCols = 1;
1966         }
1967         else if( nPages == 4 )
1968             nRows = nCols = 2;
1969         else if( nPages == 6 )
1970         {
1971             if( bPortrait )
1972                 nRows = 2, nCols = 3;
1973             else
1974                 nRows = 3, nCols = 2;
1975         }
1976         else if( nPages == 9 )
1977             nRows = nCols = 3;
1978         else if( nPages == 16 )
1979             nRows = nCols = 4;
1980         nPageMargin = 0;
1981         nSheetMargin = 0;
1982     }
1983     else
1984         bCustom = true;
1985 
1986     if( nPages > 1 )
1987     {
1988         // set upper limits for margins based on job page size and rows/columns
1989         Size aSize( getJobPageSize() );
1990 
1991         // maximum sheet distance: 1/2 sheet
1992         long nHorzMax = aSize.Width()/2;
1993         long nVertMax = aSize.Height()/2;
1994         if( nSheetMargin > nHorzMax )
1995             nSheetMargin = nHorzMax;
1996         if( nSheetMargin > nVertMax )
1997             nSheetMargin = nVertMax;
1998 
1999         maNUpPage.maSheetMarginEdt.SetMax(
2000                   maNUpPage.maSheetMarginEdt.Normalize(
2001                            nHorzMax > nVertMax ? nVertMax : nHorzMax ), FUNIT_100TH_MM );
2002 
2003         // maximum page distance
2004         nHorzMax = (aSize.Width() - 2*nSheetMargin);
2005         if( nCols > 1 )
2006             nHorzMax /= (nCols-1);
2007         nVertMax = (aSize.Height() - 2*nSheetMargin);
2008         if( nRows > 1 )
2009             nHorzMax /= (nRows-1);
2010 
2011         if( nPageMargin > nHorzMax )
2012             nPageMargin = nHorzMax;
2013         if( nPageMargin > nVertMax )
2014             nPageMargin = nVertMax;
2015 
2016         maNUpPage.maPageMarginEdt.SetMax(
2017                  maNUpPage.maSheetMarginEdt.Normalize(
2018                            nHorzMax > nVertMax ? nVertMax : nHorzMax ), FUNIT_100TH_MM );
2019     }
2020 
2021     maNUpPage.maNupRowsEdt.SetValue( nRows );
2022     maNUpPage.maNupColEdt.SetValue( nCols );
2023     maNUpPage.maPageMarginEdt.SetValue( maNUpPage.maPageMarginEdt.Normalize( nPageMargin ), FUNIT_100TH_MM );
2024     maNUpPage.maSheetMarginEdt.SetValue( maNUpPage.maSheetMarginEdt.Normalize( nSheetMargin ), FUNIT_100TH_MM );
2025 
2026     maNUpPage.showAdvancedControls( bCustom );
2027     if( bCustom )
2028     {
2029         // see if we have to enlarge the dialog to make the tab page fit
2030         Size aCurSize( maNUpPage.getLayout()->getOptimalSize( WINDOWSIZE_PREFERRED ) );
2031         Size aTabSize( maTabCtrl.GetTabPageSizePixel() );
2032         if( aTabSize.Height() < aCurSize.Height() )
2033         {
2034             Size aDlgSize( GetSizePixel() );
2035             aDlgSize.Height() += aCurSize.Height() - aTabSize.Height();
2036             SetSizePixel( aDlgSize );
2037         }
2038     }
2039 
2040     updateNup();
2041 }
2042 
2043 void PrintDialog::updateNup()
2044 {
2045     int nRows         = int(maNUpPage.maNupRowsEdt.GetValue());
2046     int nCols         = int(maNUpPage.maNupColEdt.GetValue());
2047     long nPageMargin  = long(maNUpPage.maPageMarginEdt.Denormalize(maNUpPage.maPageMarginEdt.GetValue( FUNIT_100TH_MM )));
2048     long nSheetMargin = long(maNUpPage.maSheetMarginEdt.Denormalize(maNUpPage.maSheetMarginEdt.GetValue( FUNIT_100TH_MM )));
2049 
2050     PrinterController::MultiPageSetup aMPS;
2051     aMPS.nRows         = nRows;
2052     aMPS.nColumns      = nCols;
2053     aMPS.nRepeat       = 1;
2054     aMPS.nLeftMargin   =
2055     aMPS.nTopMargin    =
2056     aMPS.nRightMargin  =
2057     aMPS.nBottomMargin = nSheetMargin;
2058 
2059     aMPS.nHorizontalSpacing =
2060     aMPS.nVerticalSpacing   = nPageMargin;
2061 
2062     aMPS.bDrawBorder        = maNUpPage.maBorderCB.IsChecked();
2063 
2064     int nOrderMode = int(sal_IntPtr(maNUpPage.maNupOrderBox.GetEntryData(
2065                            maNUpPage.maNupOrderBox.GetSelectEntryPos() )));
2066     if( nOrderMode == SV_PRINT_PRT_NUP_ORDER_LRTB )
2067         aMPS.nOrder = PrinterController::LRTB;
2068     else if( nOrderMode == SV_PRINT_PRT_NUP_ORDER_TBLR )
2069         aMPS.nOrder = PrinterController::TBLR;
2070     else if( nOrderMode == SV_PRINT_PRT_NUP_ORDER_RLTB )
2071         aMPS.nOrder = PrinterController::RLTB;
2072     else if( nOrderMode == SV_PRINT_PRT_NUP_ORDER_TBRL )
2073         aMPS.nOrder = PrinterController::TBRL;
2074 
2075     int nOrientationMode = int(sal_IntPtr(maNUpPage.maNupOrientationBox.GetEntryData(
2076                                  maNUpPage.maNupOrientationBox.GetSelectEntryPos() )));
2077     if( nOrientationMode == SV_PRINT_PRT_NUP_ORIENTATION_LANDSCAPE )
2078         aMPS.aPaperSize = maNupLandscapeSize;
2079     else if( nOrientationMode == SV_PRINT_PRT_NUP_ORIENTATION_PORTRAIT )
2080         aMPS.aPaperSize = maNupPortraitSize;
2081     else // automatic mode
2082     {
2083         // get size of first real page to see if it is portrait or landscape
2084         // we assume same page sizes for all the pages for this
2085         Size aPageSize = getJobPageSize();
2086 
2087         Size aMultiSize( aPageSize.Width() * nCols, aPageSize.Height() * nRows );
2088         if( aMultiSize.Width() > aMultiSize.Height() ) // fits better on landscape
2089             aMPS.aPaperSize = maNupLandscapeSize;
2090         else
2091             aMPS.aPaperSize = maNupPortraitSize;
2092     }
2093 
2094     maPController->setMultipage( aMPS );
2095 
2096     maNUpPage.maNupOrderWin.setValues( nOrderMode, nCols, nRows );
2097 
2098     preparePreview( true, true );
2099 }
2100 
2101 IMPL_LINK( PrintDialog, SelectHdl, ListBox*, pBox )
2102 {
2103     if(  pBox == &maJobPage.maPrinters )
2104     {
2105         String aNewPrinter( pBox->GetSelectEntry() );
2106         // set new printer
2107         maPController->setPrinter( boost::shared_ptr<Printer>( new Printer( aNewPrinter ) ) );
2108         maPController->resetPrinterOptions( maOptionsPage.maToFileBox.IsChecked() );
2109         // update text fields
2110         updatePrinterText();
2111         preparePreview( true, false );
2112     }
2113     else if( pBox == &maNUpPage.maNupOrientationBox || pBox == &maNUpPage.maNupOrderBox )
2114     {
2115         updateNup();
2116     }
2117     else if( pBox == &maNUpPage.maNupPagesBox )
2118     {
2119         if( !maNUpPage.maPagesBtn.IsChecked() )
2120             maNUpPage.maPagesBtn.Check();
2121         updateNupFromPages();
2122     }
2123 
2124     return 0;
2125 }
2126 
2127 IMPL_LINK( PrintDialog, ClickHdl, Button*, pButton )
2128 {
2129     if( pButton == &maOKButton || pButton == &maCancelButton )
2130     {
2131         storeToSettings();
2132         EndDialog( pButton == &maOKButton );
2133     }
2134     else if( pButton == &maHelpButton )
2135     {
2136         // start help system
2137         Help* pHelp = Application::GetHelp();
2138         if( pHelp )
2139         {
2140             pHelp->Start( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:OK" ) ), &maOKButton );
2141         }
2142     }
2143     else if( pButton == &maForwardBtn )
2144     {
2145         previewForward();
2146     }
2147     else if( pButton == &maBackwardBtn )
2148     {
2149         previewBackward();
2150     }
2151     else if( pButton == &maOptionsPage.maToFileBox )
2152     {
2153         maOKButton.SetText( maOptionsPage.maToFileBox.IsChecked() ? maPrintToFileText : maPrintText );
2154         maPController->resetPrinterOptions( maOptionsPage.maToFileBox.IsChecked() );
2155         getLayout()->resize();
2156         preparePreview( true, true );
2157     }
2158     else if( pButton == &maNUpPage.maBrochureBtn )
2159     {
2160         PropertyValue* pVal = getValueForWindow( pButton );
2161         if( pVal )
2162         {
2163             sal_Bool bVal = maNUpPage.maBrochureBtn.IsChecked();
2164             pVal->Value <<= bVal;
2165 
2166             checkOptionalControlDependencies();
2167 
2168             // update preview and page settings
2169             preparePreview();
2170         }
2171         if( maNUpPage.maBrochureBtn.IsChecked() )
2172         {
2173             maNUpPage.maNupPagesBox.SelectEntryPos( 0 );
2174             updateNupFromPages();
2175             maNUpPage.showAdvancedControls( false );
2176             maNUpPage.enableNupControls( false );
2177         }
2178     }
2179     else if( pButton == &maNUpPage.maPagesBtn )
2180     {
2181         maNUpPage.enableNupControls( true );
2182         updateNupFromPages();
2183     }
2184     else if( pButton == &maJobPage.maDetailsBtn )
2185     {
2186         bool bShow = maJobPage.maDetailsBtn.IsChecked();
2187         maJobPage.mxDetails->show( bShow );
2188         if( bShow )
2189         {
2190             maDetailsCollapsedSize = GetOutputSizePixel();
2191             // enlarge dialog if necessary
2192             Size aMinSize( maJobPage.getLayout()->getOptimalSize( WINDOWSIZE_MINIMUM ) );
2193             Size aCurSize( maJobPage.GetSizePixel() );
2194             if( aCurSize.Height() < aMinSize.Height() )
2195             {
2196                 Size aDlgSize( GetOutputSizePixel() );
2197                 aDlgSize.Height() += aMinSize.Height() - aCurSize.Height();
2198                 SetOutputSizePixel( aDlgSize );
2199             }
2200             maDetailsExpandedSize = GetOutputSizePixel();
2201         }
2202         else if( maDetailsCollapsedSize.Width() > 0   &&
2203                  maDetailsCollapsedSize.Height() > 0 )
2204         {
2205             // if the user did not resize the dialog
2206             // make it smaller again on collapsing the details
2207             Size aDlgSize( GetOutputSizePixel() );
2208             if( aDlgSize == maDetailsExpandedSize &&
2209                 aDlgSize.Height() > maDetailsCollapsedSize.Height() )
2210             {
2211                 SetOutputSizePixel( maDetailsCollapsedSize );
2212             }
2213         }
2214     }
2215     else if( pButton == &maJobPage.maCollateBox )
2216     {
2217         maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ),
2218                                  makeAny( sal_Bool(isCollate()) ) );
2219         checkControlDependencies();
2220     }
2221     else if( pButton == &maJobPage.maReverseOrderBox )
2222     {
2223         sal_Bool bChecked = maJobPage.maReverseOrderBox.IsChecked();
2224         maPController->setReversePrint( bChecked );
2225         maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintReverse" ) ),
2226                                  makeAny( bChecked ) );
2227         preparePreview( true, true );
2228     }
2229     else if( pButton == &maNUpPage.maBorderCB )
2230     {
2231         updateNup();
2232     }
2233     else
2234     {
2235         if( pButton == &maJobPage.maSetupButton )
2236         {
2237             maPController->setupPrinter( this );
2238             preparePreview( true, true );
2239         }
2240         checkControlDependencies();
2241     }
2242     return 0;
2243 }
2244 
2245 IMPL_LINK( PrintDialog, ModifyHdl, Edit*, pEdit )
2246 {
2247     checkControlDependencies();
2248     if( pEdit == &maNUpPage.maNupRowsEdt || pEdit == &maNUpPage.maNupColEdt ||
2249         pEdit == &maNUpPage.maSheetMarginEdt || pEdit == &maNUpPage.maPageMarginEdt
2250        )
2251     {
2252         updateNupFromPages();
2253     }
2254     else if( pEdit == &maPageEdit )
2255     {
2256         mnCurPage = sal_Int32( maPageEdit.GetValue() - 1 );
2257         preparePreview( true, true );
2258     }
2259     else if( pEdit == &maJobPage.maCopyCountField )
2260     {
2261         maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyCount" ) ),
2262                                makeAny( sal_Int32(maJobPage.maCopyCountField.GetValue()) ) );
2263         maPController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ),
2264                                makeAny( sal_Bool(isCollate()) ) );
2265     }
2266     return 0;
2267 }
2268 
2269 IMPL_LINK( PrintDialog, UIOptionsChanged, void*, EMPTYARG )
2270 {
2271     checkOptionalControlDependencies();
2272     return 0;
2273 }
2274 
2275 PropertyValue* PrintDialog::getValueForWindow( Window* i_pWindow ) const
2276 {
2277     PropertyValue* pVal = NULL;
2278     std::map< Window*, rtl::OUString >::const_iterator it = maControlToPropertyMap.find( i_pWindow );
2279     if( it != maControlToPropertyMap.end() )
2280     {
2281         pVal = maPController->getValue( it->second );
2282         DBG_ASSERT( pVal, "property value not found" );
2283     }
2284     else
2285     {
2286         DBG_ERROR( "changed control not in property map" );
2287     }
2288     return pVal;
2289 }
2290 
2291 void PrintDialog::updateWindowFromProperty( const rtl::OUString& i_rProperty )
2292 {
2293     beans::PropertyValue* pValue = maPController->getValue( i_rProperty );
2294     std::map< rtl::OUString, std::vector< Window* > >::const_iterator it = maPropertyToWindowMap.find( i_rProperty );
2295     if( pValue && it != maPropertyToWindowMap.end() )
2296     {
2297         const std::vector< Window* >& rWindows( it->second );
2298         if( ! rWindows.empty() )
2299         {
2300             sal_Bool bVal = sal_False;
2301             sal_Int32 nVal = -1;
2302             if( pValue->Value >>= bVal )
2303             {
2304                 // we should have a CheckBox for this one
2305                 CheckBox* pBox = dynamic_cast< CheckBox* >( rWindows.front() );
2306                 if( pBox )
2307                 {
2308                     pBox->Check( bVal );
2309                 }
2310                 else if( i_rProperty.equalsAscii( "PrintProspect" ) )
2311                 {
2312                     // EVIL special case
2313                     if( bVal )
2314                         maNUpPage.maBrochureBtn.Check();
2315                     else
2316                         maNUpPage.maPagesBtn.Check();
2317                 }
2318                 else
2319                 {
2320                     DBG_ASSERT( 0, "missing a checkbox" );
2321                 }
2322             }
2323             else if( pValue->Value >>= nVal )
2324             {
2325                 // this could be a ListBox or a RadioButtonGroup
2326                 ListBox* pList = dynamic_cast< ListBox* >( rWindows.front() );
2327                 if( pList )
2328                 {
2329                     pList->SelectEntryPos( static_cast< sal_uInt16 >(nVal) );
2330                 }
2331                 else if( nVal >= 0 && nVal < sal_Int32(rWindows.size() ) )
2332                 {
2333                     RadioButton* pBtn = dynamic_cast< RadioButton* >( rWindows[nVal] );
2334                     DBG_ASSERT( pBtn, "unexpected control for property" );
2335                     if( pBtn )
2336                         pBtn->Check();
2337                 }
2338             }
2339         }
2340     }
2341 }
2342 
2343 void PrintDialog::makeEnabled( Window* i_pWindow )
2344 {
2345     std::map< Window*, rtl::OUString >::const_iterator it = maControlToPropertyMap.find( i_pWindow );
2346     if( it != maControlToPropertyMap.end() )
2347     {
2348         rtl::OUString aDependency( maPController->makeEnabled( it->second ) );
2349         if( aDependency.getLength() )
2350             updateWindowFromProperty( aDependency );
2351     }
2352 }
2353 
2354 IMPL_LINK( PrintDialog, UIOption_CheckHdl, CheckBox*, i_pBox )
2355 {
2356     PropertyValue* pVal = getValueForWindow( i_pBox );
2357     if( pVal )
2358     {
2359         makeEnabled( i_pBox );
2360 
2361         sal_Bool bVal = i_pBox->IsChecked();
2362         pVal->Value <<= bVal;
2363 
2364         checkOptionalControlDependencies();
2365 
2366         // update preview and page settings
2367         preparePreview();
2368     }
2369     return 0;
2370 }
2371 
2372 IMPL_LINK( PrintDialog, UIOption_RadioHdl, RadioButton*, i_pBtn )
2373 {
2374     // this handler gets called for all radiobuttons that get unchecked, too
2375     // however we only want one notificaction for the new value (that is for
2376     // the button that gets checked)
2377     if( i_pBtn->IsChecked() )
2378     {
2379         PropertyValue* pVal = getValueForWindow( i_pBtn );
2380         std::map< Window*, sal_Int32 >::const_iterator it = maControlToNumValMap.find( i_pBtn );
2381         if( pVal && it != maControlToNumValMap.end() )
2382         {
2383             makeEnabled( i_pBtn );
2384 
2385             sal_Int32 nVal = it->second;
2386             pVal->Value <<= nVal;
2387 
2388             checkOptionalControlDependencies();
2389 
2390             // update preview and page settings
2391             preparePreview();
2392         }
2393     }
2394     return 0;
2395 }
2396 
2397 IMPL_LINK( PrintDialog, UIOption_SelectHdl, ListBox*, i_pBox )
2398 {
2399     PropertyValue* pVal = getValueForWindow( i_pBox );
2400     if( pVal )
2401     {
2402         makeEnabled( i_pBox );
2403 
2404         sal_Int32 nVal( i_pBox->GetSelectEntryPos() );
2405         pVal->Value <<= nVal;
2406 
2407         checkOptionalControlDependencies();
2408 
2409         // update preview and page settings
2410         preparePreview();
2411     }
2412     return 0;
2413 }
2414 
2415 IMPL_LINK( PrintDialog, UIOption_ModifyHdl, Edit*, i_pBox )
2416 {
2417     PropertyValue* pVal = getValueForWindow( i_pBox );
2418     if( pVal )
2419     {
2420         makeEnabled( i_pBox );
2421 
2422         NumericField* pNum = dynamic_cast<NumericField*>(i_pBox);
2423         MetricField* pMetric = dynamic_cast<MetricField*>(i_pBox);
2424         if( pNum )
2425         {
2426             sal_Int64 nVal = pNum->GetValue();
2427             pVal->Value <<= nVal;
2428         }
2429         else if( pMetric )
2430         {
2431             sal_Int64 nVal = pMetric->GetValue();
2432             pVal->Value <<= nVal;
2433         }
2434         else
2435         {
2436             rtl::OUString aVal( i_pBox->GetText() );
2437             pVal->Value <<= aVal;
2438         }
2439 
2440         checkOptionalControlDependencies();
2441 
2442         // update preview and page settings
2443         preparePreview();
2444     }
2445     return 0;
2446 }
2447 
2448 void PrintDialog::Command( const CommandEvent& rEvt )
2449 {
2450     if( rEvt.GetCommand() == COMMAND_WHEEL )
2451     {
2452         const CommandWheelData* pWheelData = rEvt.GetWheelData();
2453         if( pWheelData->GetDelta() > 0 )
2454             previewForward();
2455         else if( pWheelData->GetDelta() < 0 )
2456             previewBackward();
2457         /*
2458         else
2459             huh ?
2460         */
2461     }
2462 }
2463 
2464 void PrintDialog::Resize()
2465 {
2466     // maLayout.setManagedArea( Rectangle( Point( 0, 0 ), GetSizePixel() ) );
2467     // and do the preview; however the metafile does not need to be gotten anew
2468     preparePreview( false );
2469 
2470     // do an invalidate for the benefit of the grouping elements
2471     Invalidate();
2472 }
2473 
2474 void PrintDialog::previewForward()
2475 {
2476     maPageEdit.Up();
2477 }
2478 
2479 void PrintDialog::previewBackward()
2480 {
2481     maPageEdit.Down();
2482 }
2483 
2484 // -----------------------------------------------------------------------------
2485 //
2486 // PrintProgressDialog
2487 //
2488 // -----------------------------------------------------------------------------
2489 
2490 PrintProgressDialog::PrintProgressDialog( Window* i_pParent, int i_nMax ) :
2491     ModelessDialog( i_pParent, VclResId( SV_DLG_PRINT_PROGRESS ) ),
2492     maText( this, VclResId( SV_PRINT_PROGRESS_TEXT ) ),
2493     maButton( this, VclResId( SV_PRINT_PROGRESS_CANCEL ) ),
2494     mbCanceled( false ),
2495     mnCur( 0 ),
2496     mnMax( i_nMax ),
2497     mnProgressHeight( 15 ),
2498     mbNativeProgress( false )
2499 {
2500     FreeResource();
2501 
2502     if( mnMax < 1 )
2503         mnMax = 1;
2504 
2505     maStr = maText.GetText();
2506 
2507     maButton.SetClickHdl( LINK( this, PrintProgressDialog, ClickHdl ) );
2508 
2509 }
2510 
2511 PrintProgressDialog::~PrintProgressDialog()
2512 {
2513 }
2514 
2515 IMPL_LINK( PrintProgressDialog, ClickHdl, Button*, pButton )
2516 {
2517     if( pButton == &maButton )
2518         mbCanceled = true;
2519 
2520     return 0;
2521 }
2522 
2523 void PrintProgressDialog::implCalcProgressRect()
2524 {
2525     if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
2526     {
2527         ImplControlValue aValue;
2528         Rectangle aControlRegion( Point(), Size( 100, mnProgressHeight ) );
2529         Rectangle aNativeControlRegion, aNativeContentRegion;
2530         if( GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion,
2531                                     CTRL_STATE_ENABLED, aValue, rtl::OUString(),
2532                                     aNativeControlRegion, aNativeContentRegion ) )
2533         {
2534             mnProgressHeight = aNativeControlRegion.GetHeight();
2535         }
2536         mbNativeProgress = true;
2537     }
2538     maProgressRect = Rectangle( Point( 10, maText.GetPosPixel().Y() + maText.GetSizePixel().Height() + 8 ),
2539                                 Size( GetSizePixel().Width() - 20, mnProgressHeight ) );
2540 }
2541 
2542 void PrintProgressDialog::setProgress( int i_nCurrent, int i_nMax )
2543 {
2544     if( maProgressRect.IsEmpty() )
2545         implCalcProgressRect();
2546 
2547     mnCur = i_nCurrent;
2548     if( i_nMax != -1 )
2549         mnMax = i_nMax;
2550 
2551     if( mnMax < 1 )
2552         mnMax = 1;
2553 
2554     rtl::OUString aNewText( searchAndReplace( maStr, "%p", 2, rtl::OUString::valueOf( mnCur ) ) );
2555     aNewText = searchAndReplace( aNewText, "%n", 2, rtl::OUString::valueOf( mnMax ) );
2556     maText.SetText( aNewText );
2557 
2558     // update progress
2559     Invalidate( maProgressRect, INVALIDATE_UPDATE );
2560 }
2561 
2562 void PrintProgressDialog::tick()
2563 {
2564     if( mnCur < mnMax )
2565         setProgress( ++mnCur );
2566 }
2567 
2568 void PrintProgressDialog::reset()
2569 {
2570     mbCanceled = false;
2571     setProgress( 0 );
2572 }
2573 
2574 void PrintProgressDialog::Paint( const Rectangle& )
2575 {
2576     if( maProgressRect.IsEmpty() )
2577         implCalcProgressRect();
2578 
2579     Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
2580 	const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2581 	Color aPrgsColor = rStyleSettings.GetHighlightColor();
2582 	if ( aPrgsColor == rStyleSettings.GetFaceColor() )
2583 		aPrgsColor = rStyleSettings.GetDarkShadowColor();
2584 	SetLineColor();
2585 	SetFillColor( aPrgsColor );
2586 
2587     const long nOffset = 3;
2588     const long nWidth = 3*mnProgressHeight/2;
2589     const long nFullWidth = nWidth + nOffset;
2590     const long nMaxCount = maProgressRect.GetWidth() / nFullWidth;
2591     DrawProgress( this, maProgressRect.TopLeft(),
2592                         nOffset,
2593                         nWidth,
2594                         mnProgressHeight,
2595                         static_cast<sal_uInt16>(0),
2596                         static_cast<sal_uInt16>(10000*mnCur/mnMax),
2597                         static_cast<sal_uInt16>(10000/nMaxCount),
2598                         maProgressRect
2599                         );
2600     Pop();
2601 
2602     if( ! mbNativeProgress )
2603     {
2604         DecorationView aDecoView( this );
2605         Rectangle aFrameRect( maProgressRect );
2606         aFrameRect.Left() -= nOffset;
2607         aFrameRect.Right() += nOffset;
2608         aFrameRect.Top() -= nOffset;
2609         aFrameRect.Bottom() += nOffset;
2610         aDecoView.DrawFrame( aFrameRect );
2611     }
2612 }
2613 
2614