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