1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <printdlg.hxx>
22 #include <strings.hrc>
23 #include <bitmaps.hlst>
25 #include <vcl/commandevent.hxx>
26 #include <vcl/lstbox.hxx>
27 #include <vcl/print.hxx>
28 #include <vcl/wall.hxx>
29 #include <vcl/decoview.hxx>
30 #include <vcl/configsettings.hxx>
31 #include <vcl/help.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/settings.hxx>
34 #include <vcl/virdev.hxx>
36 #include <unotools/localedatawrapper.hxx>
38 #include <sal/log.hxx>
39 #include <osl/diagnose.h>
41 #include <com/sun/star/beans/PropertyValue.hpp>
44 using namespace com::sun::star
;
45 using namespace com::sun::star::uno
;
46 using namespace com::sun::star::lang
;
47 using namespace com::sun::star::container
;
48 using namespace com::sun::star::beans
;
52 ORIENTATION_AUTOMATIC
,
58 bool lcl_ListBoxCompare( const OUString
& rStr1
, const OUString
& rStr2
)
60 return ListBox::NaturalSortCompare( rStr1
, rStr2
) < 0;
64 MoreOptionsDialog::MoreOptionsDialog(PrintDialog
* i_pParent
)
65 : GenericDialogController(i_pParent
->getDialog(), "vcl/ui/moreoptionsdialog.ui", "MoreOptionsDialog")
66 , mpParent( i_pParent
)
67 , mxOKButton(m_xBuilder
->weld_button("ok"))
68 , mxCancelButton(m_xBuilder
->weld_button("cancel"))
69 , mxSingleJobsBox(m_xBuilder
->weld_check_button("singlejobs"))
71 mxSingleJobsBox
->set_active( mpParent
->isSingleJobs() );
73 mxOKButton
->connect_clicked( LINK( this, MoreOptionsDialog
, ClickHdl
) );
74 mxCancelButton
->connect_clicked( LINK( this, MoreOptionsDialog
, ClickHdl
) );
77 MoreOptionsDialog::~MoreOptionsDialog()
81 IMPL_LINK (MoreOptionsDialog
, ClickHdl
, weld::Button
&, rButton
, void)
83 if (&rButton
== mxOKButton
.get())
85 mpParent
->mbSingleJobs
= mxSingleJobsBox
->get_active();
86 m_xDialog
->response(RET_OK
);
88 else if (&rButton
== mxCancelButton
.get())
90 m_xDialog
->response(RET_CANCEL
);
94 PrintDialog::PrintPreviewWindow::PrintPreviewWindow(PrintDialog
* pDialog
)
97 , maOrigSize( 10, 10 )
99 , mnDPIX(Application::GetDefaultDevice()->GetDPIX())
100 , mnDPIY(Application::GetDefaultDevice()->GetDPIY())
102 , maReplacementString()
103 , mbGreyscale( false )
107 PrintDialog::PrintPreviewWindow::~PrintPreviewWindow()
111 void PrintDialog::PrintPreviewWindow::Resize()
113 Size
aNewSize(GetOutputSizePixel());
114 long nTextHeight
= GetDrawingArea()->get_text_height();
115 // leave small space for decoration
116 aNewSize
.AdjustWidth( -(nTextHeight
+ 2) );
117 aNewSize
.AdjustHeight( -(nTextHeight
+ 2) );
121 // #i106435# catch corner case of Size(0,0)
122 Size
aOrigSize( maOrigSize
);
123 if( aOrigSize
.Width() < 1 )
124 aOrigSize
.setWidth( aNewSize
.Width() );
125 if( aOrigSize
.Height() < 1 )
126 aOrigSize
.setHeight( aNewSize
.Height() );
127 if( aOrigSize
.Width() > aOrigSize
.Height() )
129 aScaledSize
= Size( aNewSize
.Width(), aNewSize
.Width() * aOrigSize
.Height() / aOrigSize
.Width() );
130 if( aScaledSize
.Height() > aNewSize
.Height() )
131 fScale
= double(aNewSize
.Height())/double(aScaledSize
.Height());
135 aScaledSize
= Size( aNewSize
.Height() * aOrigSize
.Width() / aOrigSize
.Height(), aNewSize
.Height() );
136 if( aScaledSize
.Width() > aNewSize
.Width() )
137 fScale
= double(aNewSize
.Width())/double(aScaledSize
.Width());
139 aScaledSize
.setWidth( long(aScaledSize
.Width()*fScale
) );
140 aScaledSize
.setHeight( long(aScaledSize
.Height()*fScale
) );
142 maPreviewSize
= aScaledSize
;
144 // check and evtl. recreate preview bitmap
145 preparePreviewBitmap();
148 void PrintDialog::PrintPreviewWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
150 rRenderContext
.Push();
151 if (vcl::Window
* pDefaultDevice
= dynamic_cast<vcl::Window
*>(Application::GetDefaultDevice()))
153 Font
aFont(rRenderContext
.GetSettings().GetStyleSettings().GetLabelFont());
154 pDefaultDevice
->SetPointFont(rRenderContext
, aFont
);
157 rRenderContext
.SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetDialogColor()));
158 rRenderContext
.Erase();
160 auto nTextHeight
= rRenderContext
.GetTextHeight();
161 Size
aSize(GetOutputSizePixel());
162 Point
aOffset((aSize
.Width() - maPreviewSize
.Width() + nTextHeight
) / 2,
163 (aSize
.Height() - maPreviewSize
.Height() + nTextHeight
) / 2);
167 auto nTop
= aOffset
.Y() - nTextHeight
;
169 auto nWidth
= rRenderContext
.GetTextWidth(maHorzText
);
171 auto nStart
= aOffset
.X() + (maPreviewSize
.Width() - nWidth
) / 2;
172 rRenderContext
.DrawText(Point(nStart
, aOffset
.Y() - nTextHeight
), maHorzText
, 0, maHorzText
.getLength());
174 DecorationView
aDecoView(&rRenderContext
);
175 nTop
= aOffset
.Y() - (nTextHeight
/ 2);
176 aDecoView
.DrawSeparator(Point(aOffset
.X(), nTop
), Point(nStart
- 2, nTop
), false);
177 aDecoView
.DrawSeparator(Point(nStart
+ nWidth
+ 2, nTop
), Point(aOffset
.X() + maPreviewSize
.Width(), nTop
), false);
182 rRenderContext
.Push(PushFlags::FONT
);
183 vcl::Font
aFont(rRenderContext
.GetFont());
184 aFont
.SetOrientation(900);
185 rRenderContext
.SetFont(aFont
);
187 auto nLeft
= aOffset
.X() - nTextHeight
;
189 auto nWidth
= rRenderContext
.GetTextWidth(maVertText
);
190 auto nStart
= aOffset
.Y() + (maPreviewSize
.Height() + nWidth
) / 2;
192 rRenderContext
.DrawText(Point(nLeft
, nStart
), maVertText
, 0, maVertText
.getLength());
194 DecorationView
aDecoView(&rRenderContext
);
195 nLeft
= aOffset
.X() - (nTextHeight
/ 2);
196 aDecoView
.DrawSeparator(Point(nLeft
, aOffset
.Y()), Point(nLeft
, nStart
- nWidth
- 2), true);
197 aDecoView
.DrawSeparator(Point(nLeft
, nStart
+ 2), Point(nLeft
, aOffset
.Y() + maPreviewSize
.Height()), true);
199 rRenderContext
.Pop();
202 if (!maReplacementString
.isEmpty())
204 // replacement is active
205 tools::Rectangle
aTextRect(aOffset
+ Point(2, 2), Size(maPreviewSize
.Width() - 4, maPreviewSize
.Height() - 4));
206 rRenderContext
.DrawText(aTextRect
, maReplacementString
,
207 DrawTextFlags::Center
| DrawTextFlags::VCenter
|
208 DrawTextFlags::WordBreak
| DrawTextFlags::MultiLine
);
212 BitmapEx
aPreviewBitmap(maPreviewBitmap
);
214 // This explicit force-to-scale allows us to get the
215 // mentioned best quality here. Unfortunately this is
216 // currently not sure when using just ::DrawBitmap with
217 // a defined size or ::DrawOutDev
218 aPreviewBitmap
.Scale(maPreviewSize
, BmpScaleFlag::BestQuality
);
219 rRenderContext
.DrawBitmapEx(aOffset
, aPreviewBitmap
);
222 tools::Rectangle
aFrameRect(aOffset
+ Point(-1, -1), Size(maPreviewSize
.Width() + 2, maPreviewSize
.Height() + 2));
223 DecorationView
aDecorationView(&rRenderContext
);
224 aDecorationView
.DrawFrame(aFrameRect
, DrawFrameStyle::Group
);
226 rRenderContext
.Pop();
229 bool PrintDialog::PrintPreviewWindow::Command( const CommandEvent
& rEvt
)
231 if( rEvt
.GetCommand() == CommandEventId::Wheel
)
233 const CommandWheelData
* pWheelData
= rEvt
.GetWheelData();
234 if(pWheelData
->GetDelta() > 0)
235 mpDialog
->previewForward();
236 else if (pWheelData
->GetDelta() < 0)
237 mpDialog
->previewBackward();
240 return CustomWidgetController::Command(rEvt
);
243 void PrintDialog::PrintPreviewWindow::setPreview( const GDIMetaFile
& i_rNewPreview
,
244 const Size
& i_rOrigSize
,
245 const OUString
& i_rPaperName
,
246 const OUString
& i_rReplacement
,
252 maMtf
= i_rNewPreview
;
255 maOrigSize
= i_rOrigSize
;
256 maReplacementString
= i_rReplacement
;
257 mbGreyscale
= i_bGreyscale
;
259 // use correct measurements
260 const LocaleDataWrapper
& rLocWrap(Application::GetSettings().GetLocaleDataWrapper());
261 MapUnit eUnit
= MapUnit::MapMM
;
263 if( rLocWrap
.getMeasurementSystemEnum() == MeasurementSystem::US
)
265 eUnit
= MapUnit::Map100thInch
;
268 Size
aLogicPaperSize(OutputDevice::LogicToLogic(i_rOrigSize
, MapMode(MapUnit::Map100thMM
), MapMode(eUnit
)));
269 OUString
aNumText( rLocWrap
.getNum( aLogicPaperSize
.Width(), nDigits
) );
271 aBuf
.append( aNumText
)
273 aBuf
.appendAscii( eUnit
== MapUnit::MapMM
? "mm" : "in" );
274 if( !i_rPaperName
.isEmpty() )
277 aBuf
.append( i_rPaperName
);
280 maHorzText
= aBuf
.makeStringAndClear();
282 aNumText
= rLocWrap
.getNum( aLogicPaperSize
.Height(), nDigits
);
283 aBuf
.append( aNumText
)
285 aBuf
.appendAscii( eUnit
== MapUnit::MapMM
? "mm" : "in" );
286 maVertText
= aBuf
.makeStringAndClear();
288 // We have a new Metafile and evtl. a new page, so we need to reset
289 // the PreviewBitmap to force new creation
290 maPreviewBitmap
= Bitmap();
292 // sets/calculates e.g. maPreviewSize
293 // also triggers preparePreviewBitmap()
299 void PrintDialog::PrintPreviewWindow::preparePreviewBitmap()
301 if(maPreviewSize
.getWidth() < 0 || maPreviewSize
.getHeight() < 0)
303 // not yet fully initialized, no need to prepare anything
307 // define an allowed number of pixels, also see
308 // defaults for primitive renderers and similar. This
309 // might be centralized and made dependent of 32/64bit
310 const sal_uInt32
nMaxSquarePixels(500000);
312 // check how big (squarePixels) the preview is currently (with
313 // max value of MaxSquarePixels)
314 const sal_uInt32
nCurrentSquarePixels(
317 static_cast<sal_uInt32
>(maPreviewBitmap
.GetSizePixel().getWidth())
318 * static_cast<sal_uInt32
>(maPreviewBitmap
.GetSizePixel().getHeight())));
320 // check how big (squarePixels) the preview needs to be (with
321 // max value of MaxSquarePixels)
322 const sal_uInt32
nRequiredSquarePixels(
325 static_cast<sal_uInt32
>(maPreviewSize
.getWidth())
326 * static_cast<sal_uInt32
>(maPreviewSize
.getHeight())));
328 // check if preview is big enough. Use a scaling value in
329 // the comparison to not get bigger at the last possible moment
330 // what may look awkward and pixelated (again). This means
331 // to use a percentage value - if we have at least
332 // that value of required pixels, we are good.
333 static const double fPreventAwkwardFactor(1.35); // 35%
334 if(nCurrentSquarePixels
>= static_cast<sal_uInt32
>(nRequiredSquarePixels
* fPreventAwkwardFactor
))
336 // at this place we also could add a mechanism to let the preview
337 // bitmap 'shrink' again if it is currently 'too big' -> bigger
338 // than required. I think this is not necessary for now.
340 // already sufficient, done.
344 // check if we have enough square pixels e.g for 8x8 pixels
345 if(nRequiredSquarePixels
< 64)
347 // too small preview - let it empty
351 // Calculate nPlannedSquarePixels which is the required size
352 // expanded by a percentage (with max value of MaxSquarePixels)
353 static const double fExtraSpaceFactor(1.65); // 65%
354 const sal_uInt32
nPlannedSquarePixels(
357 static_cast<sal_uInt32
>(maPreviewSize
.getWidth() * fExtraSpaceFactor
)
358 * static_cast<sal_uInt32
>(maPreviewSize
.getHeight() * fExtraSpaceFactor
)));
360 // calculate back new width and height - it might have been
361 // truncated by MaxSquarePixels.
362 // We know that w*h == nPlannedSquarePixels and w/h == ratio
363 const double fRatio(static_cast<double>(maPreviewSize
.getWidth()) / static_cast<double>(maPreviewSize
.getHeight()));
364 const double fNewWidth(sqrt(static_cast<double>(nPlannedSquarePixels
) * fRatio
));
365 const double fNewHeight(sqrt(static_cast<double>(nPlannedSquarePixels
) / fRatio
));
366 const Size
aScaledSize(basegfx::fround(fNewWidth
), basegfx::fround(fNewHeight
));
368 // check if this eventual maximum is already reached
369 // due to having hit the MaxSquarePixels. Due to using
370 // an integer AspectRatio, we cannot make a numeric exact
371 // comparison - we need to compare if we are close
372 const double fScaledSizeSquare(static_cast<double>(aScaledSize
.getWidth() * aScaledSize
.getHeight()));
373 const double fPreviewSizeSquare(static_cast<double>(maPreviewBitmap
.GetSizePixel().getWidth() * maPreviewBitmap
.GetSizePixel().getHeight()));
375 // test as equal up to 0.1% (0.001)
376 if(fPreviewSizeSquare
!= 0.0 && fabs((fScaledSizeSquare
/ fPreviewSizeSquare
) - 1.0) < 0.001)
378 // maximum is reached, avoid bigger scaling
382 // create temporary VDev and render to it
383 ScopedVclPtrInstance
<VirtualDevice
> pPrerenderVDev(*Application::GetDefaultDevice());
384 pPrerenderVDev
->SetOutputSizePixel(aScaledSize
, false);
385 pPrerenderVDev
->SetReferenceDevice( mnDPIX
, mnDPIY
);
386 pPrerenderVDev
->EnableOutput();
387 pPrerenderVDev
->SetBackground( Wallpaper(COL_WHITE
) );
389 GDIMetaFile
aMtf( maMtf
);
391 Size
aVDevSize( pPrerenderVDev
->GetOutputSizePixel() );
392 const Size
aLogicSize( pPrerenderVDev
->PixelToLogic( aVDevSize
, MapMode( MapUnit::Map100thMM
) ) );
393 Size
aOrigSize( maOrigSize
);
394 if( aOrigSize
.Width() < 1 )
395 aOrigSize
.setWidth( aLogicSize
.Width() );
396 if( aOrigSize
.Height() < 1 )
397 aOrigSize
.setHeight( aLogicSize
.Height() );
398 double fScale
= double(aLogicSize
.Width())/double(aOrigSize
.Width());
400 pPrerenderVDev
->Erase();
401 pPrerenderVDev
->Push();
402 pPrerenderVDev
->SetMapMode(MapMode(MapUnit::Map100thMM
));
403 DrawModeFlags nOldDrawMode
= pPrerenderVDev
->GetDrawMode();
405 pPrerenderVDev
->SetDrawMode( pPrerenderVDev
->GetDrawMode() |
406 ( DrawModeFlags::GrayLine
| DrawModeFlags::GrayFill
| DrawModeFlags::GrayText
|
407 DrawModeFlags::GrayBitmap
| DrawModeFlags::GrayGradient
) );
409 aMtf
.Scale( fScale
, fScale
);
412 const AntialiasingFlags
nOriginalAA(pPrerenderVDev
->GetAntialiasing());
413 pPrerenderVDev
->SetAntialiasing(nOriginalAA
| AntialiasingFlags::EnableB2dDraw
);
414 aMtf
.Play( pPrerenderVDev
.get(), Point( 0, 0 ), aLogicSize
);
415 pPrerenderVDev
->SetAntialiasing(nOriginalAA
);
417 pPrerenderVDev
->Pop();
419 pPrerenderVDev
->SetMapMode(MapMode(MapUnit::MapPixel
));
421 maPreviewBitmap
= pPrerenderVDev
->GetBitmapEx(Point(0, 0), aVDevSize
);
423 pPrerenderVDev
->SetDrawMode( nOldDrawMode
);
426 PrintDialog::ShowNupOrderWindow::ShowNupOrderWindow()
427 : mnOrderMode( NupOrderType::LRTB
)
433 void PrintDialog::ShowNupOrderWindow::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
436 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
437 CustomWidgetController::SetDrawingArea(pDrawingArea
);
438 SetOutputSizePixel(aSize
);
441 void PrintDialog::ShowNupOrderWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*i_rRect*/)
443 rRenderContext
.SetMapMode(MapMode(MapUnit::MapPixel
));
444 rRenderContext
.SetTextColor(rRenderContext
.GetSettings().GetStyleSettings().GetFieldTextColor());
445 rRenderContext
.SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetFieldColor()));
446 rRenderContext
.Erase();
448 int nPages
= mnRows
* mnColumns
;
449 Font
aFont(rRenderContext
.GetSettings().GetStyleSettings().GetFieldFont());
450 aFont
.SetFontSize(Size(0, 24));
451 rRenderContext
.SetFont(aFont
);
452 Size
aSampleTextSize(rRenderContext
.GetTextWidth(OUString::number(nPages
+ 1)), rRenderContext
.GetTextHeight());
453 Size
aOutSize(GetOutputSizePixel());
454 Size
aSubSize(aOutSize
.Width() / mnColumns
, aOutSize
.Height() / mnRows
);
455 // calculate font size: shrink the sample text so it fits
456 double fX
= double(aSubSize
.Width()) / double(aSampleTextSize
.Width());
457 double fY
= double(aSubSize
.Height()) / double(aSampleTextSize
.Height());
458 double fScale
= (fX
< fY
) ? fX
: fY
;
459 long nFontHeight
= long(24.0 * fScale
) - 3;
462 aFont
.SetFontSize(Size( 0, nFontHeight
));
463 rRenderContext
.SetFont(aFont
);
464 long nTextHeight
= rRenderContext
.GetTextHeight();
465 for (int i
= 0; i
< nPages
; i
++)
467 OUString
aPageText(OUString::number(i
+ 1));
471 case NupOrderType::LRTB
:
472 nX
= (i
% mnColumns
);
473 nY
= (i
/ mnColumns
);
475 case NupOrderType::TBLR
:
479 case NupOrderType::RLTB
:
480 nX
= mnColumns
- 1 - (i
% mnColumns
);
481 nY
= (i
/ mnColumns
);
483 case NupOrderType::TBRL
:
484 nX
= mnColumns
- 1 - (i
/ mnRows
);
488 Size
aTextSize(rRenderContext
.GetTextWidth(aPageText
), nTextHeight
);
489 int nDeltaX
= (aSubSize
.Width() - aTextSize
.Width()) / 2;
490 int nDeltaY
= (aSubSize
.Height() - aTextSize
.Height()) / 2;
491 rRenderContext
.DrawText(Point(nX
* aSubSize
.Width() + nDeltaX
,
492 nY
* aSubSize
.Height() + nDeltaY
), aPageText
);
494 DecorationView
aDecorationView(&rRenderContext
);
495 aDecorationView
.DrawFrame(tools::Rectangle(Point(0, 0), aOutSize
), DrawFrameStyle::Group
);
498 Size
const & PrintDialog::getJobPageSize()
500 if( maFirstPageSize
.Width() == 0 && maFirstPageSize
.Height() == 0)
502 maFirstPageSize
= maNupPortraitSize
;
504 if( maPController
->getPageCountProtected() > 0 )
506 PrinterController::PageSize aPageSize
= maPController
->getPageFile( 0, aMtf
, true );
507 maFirstPageSize
= aPageSize
.aSize
;
510 return maFirstPageSize
;
513 PrintDialog::PrintDialog(weld::Window
* i_pWindow
, const std::shared_ptr
<PrinterController
>& i_rController
)
514 : GenericDialogController(i_pWindow
, "vcl/ui/printdialog.ui", "PrintDialog")
515 , maPController( i_rController
)
516 , mxTabCtrl(m_xBuilder
->weld_notebook("tabcontrol"))
517 , mxPageLayoutFrame(m_xBuilder
->weld_frame("layoutframe"))
518 , mxPrinters(m_xBuilder
->weld_combo_box("printersbox"))
519 , mxStatusTxt(m_xBuilder
->weld_label("status"))
520 , mxSetupButton(m_xBuilder
->weld_button("setup"))
521 , mxCopyCountField(m_xBuilder
->weld_spin_button("copycount"))
522 , mxCollateBox(m_xBuilder
->weld_check_button("collate"))
523 , mxCollateImage(m_xBuilder
->weld_image("collateimage"))
524 , mxPageRangeEdit(m_xBuilder
->weld_entry("pagerange"))
525 , mxPageRangesRadioButton(m_xBuilder
->weld_radio_button("rbRangePages"))
526 , mxPaperSidesBox(m_xBuilder
->weld_combo_box("sidesbox"))
527 , mxReverseOrderBox(m_xBuilder
->weld_check_button("reverseorder"))
528 , mxOKButton(m_xBuilder
->weld_button("ok"))
529 , mxCancelButton(m_xBuilder
->weld_button("cancel"))
530 , mxHelpButton(m_xBuilder
->weld_button("help"))
531 , mxMoreOptionsBtn(m_xBuilder
->weld_button("moreoptionsbtn"))
532 , mxBackwardBtn(m_xBuilder
->weld_button("backward"))
533 , mxForwardBtn(m_xBuilder
->weld_button("forward"))
534 , mxFirstBtn(m_xBuilder
->weld_button("btnFirst"))
535 , mxLastBtn(m_xBuilder
->weld_button("btnLast"))
536 , mxPreviewBox(m_xBuilder
->weld_check_button("previewbox"))
537 , mxNumPagesText(m_xBuilder
->weld_label("totalnumpages"))
538 , mxPreview(new PrintPreviewWindow(this))
539 , mxPreviewWindow(new weld::CustomWeld(*m_xBuilder
, "preview", *mxPreview
))
540 , mxPageEdit(m_xBuilder
->weld_entry("pageedit-nospin"))
541 , mxPagesBtn(m_xBuilder
->weld_radio_button("pagespersheetbtn"))
542 , mxBrochureBtn(m_xBuilder
->weld_radio_button("brochure"))
543 , mxPagesBoxTitleTxt(m_xBuilder
->weld_label("pagespersheettxt"))
544 , mxNupPagesBox(m_xBuilder
->weld_combo_box("pagespersheetbox"))
545 , mxNupNumPagesTxt(m_xBuilder
->weld_label("pagestxt"))
546 , mxNupColEdt(m_xBuilder
->weld_spin_button("pagecols"))
547 , mxNupTimesTxt(m_xBuilder
->weld_label("by"))
548 , mxNupRowsEdt(m_xBuilder
->weld_spin_button("pagerows"))
549 , mxPageMarginTxt1(m_xBuilder
->weld_label("pagemargintxt1"))
550 , mxPageMarginEdt(m_xBuilder
->weld_metric_spin_button("pagemarginsb", FieldUnit::MM
))
551 , mxPageMarginTxt2(m_xBuilder
->weld_label("pagemargintxt2"))
552 , mxSheetMarginTxt1(m_xBuilder
->weld_label("sheetmargintxt1"))
553 , mxSheetMarginEdt(m_xBuilder
->weld_metric_spin_button("sheetmarginsb", FieldUnit::MM
))
554 , mxSheetMarginTxt2(m_xBuilder
->weld_label("sheetmargintxt2"))
555 , mxPaperSizeBox(m_xBuilder
->weld_combo_box("papersizebox"))
556 , mxOrientationBox(m_xBuilder
->weld_combo_box("pageorientationbox"))
557 , mxNupOrderTxt(m_xBuilder
->weld_label("labelorder"))
558 , mxNupOrderBox(m_xBuilder
->weld_combo_box("orderbox"))
559 , mxNupOrder(new ShowNupOrderWindow
)
560 , mxNupOrderWin(new weld::CustomWeld(*m_xBuilder
, "orderpreview", *mxNupOrder
))
561 , mxBorderCB(m_xBuilder
->weld_check_button("bordercb"))
562 , mxCustom(m_xBuilder
->weld_widget("customcontents"))
563 , maPrintToFileText( VclResId( SV_PRINT_TOFILE_TXT
) )
564 , maDefPrtText( VclResId( SV_PRINT_DEFPRT_TXT
) )
565 , maNoPageStr( VclResId( SV_PRINT_NOPAGES
) )
566 , maNoPreviewStr( VclResId( SV_PRINT_NOPREVIEW
) )
569 , mbCollateAlwaysOff(false)
570 , mbShowLayoutFrame( true )
571 , mbSingleJobs( false )
573 // save printbutton text, gets exchanged occasionally with print to file
574 maPrintText
= mxOKButton
->get_label();
576 maPageStr
= mxNumPagesText
->get_label();
578 Printer::updatePrinters();
580 mxPrinters
->append_text(maPrintToFileText
);
581 // fill printer listbox
582 std::vector
< OUString
> rQueues( Printer::GetPrinterQueues() );
583 std::sort( rQueues
.begin(), rQueues
.end(), lcl_ListBoxCompare
);
584 for( const auto& rQueue
: rQueues
)
586 mxPrinters
->append_text(rQueue
);
588 // select current printer
589 if (mxPrinters
->find_text(maPController
->getPrinter()->GetName()) != -1)
590 mxPrinters
->set_active_text(maPController
->getPrinter()->GetName());
593 // fall back to last printer
594 SettingsConfigItem
* pItem
= SettingsConfigItem::get();
595 OUString
aValue( pItem
->getValue( "PrintDialog",
597 if (mxPrinters
->find_text(aValue
) != -1)
599 mxPrinters
->set_active_text(aValue
);
600 maPController
->setPrinter( VclPtrInstance
<Printer
>( aValue
) );
604 // fall back to default printer
605 mxPrinters
->set_active_text(Printer::GetDefaultPrinterName());
606 maPController
->setPrinter( VclPtrInstance
<Printer
>( Printer::GetDefaultPrinterName() ) );
610 // not printing to file
611 maPController
->resetPrinterOptions( false );
613 // update the text fields for the printer
616 // set paper sizes listbox
619 // setup dependencies
620 checkControlDependencies();
622 // setup paper sides box
623 setupPaperSidesBox();
625 // set initial focus to "Number of copies"
626 mxCopyCountField
->grab_focus();
627 mxCopyCountField
->select_region(0, -1);
629 // setup sizes for N-Up
630 Size
aNupSize( maPController
->getPrinter()->PixelToLogic(
631 maPController
->getPrinter()->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM
) ) );
632 if( maPController
->getPrinter()->GetOrientation() == Orientation::Landscape
)
634 maNupLandscapeSize
= aNupSize
;
635 // coverity[swapped_arguments : FALSE] - this is in the correct order
636 maNupPortraitSize
= Size( aNupSize
.Height(), aNupSize
.Width() );
640 maNupPortraitSize
= aNupSize
;
641 // coverity[swapped_arguments : FALSE] - this is in the correct order
642 maNupLandscapeSize
= Size( aNupSize
.Height(), aNupSize
.Width() );
645 initFromMultiPageSetup( maPController
->getMultipage() );
647 // setup optional UI options set by application
650 // hide layout frame if unwanted
651 mxPageLayoutFrame
->set_visible(mbShowLayoutFrame
);
653 // restore settings from last run
657 mxOKButton
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
658 mxCancelButton
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
659 mxHelpButton
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
660 mxSetupButton
->connect_clicked( LINK( this, PrintDialog
, ClickHdl
) );
661 mxMoreOptionsBtn
->connect_clicked( LINK( this, PrintDialog
, ClickHdl
) );
662 mxBackwardBtn
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
663 mxForwardBtn
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
664 mxFirstBtn
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
665 mxLastBtn
->connect_clicked( LINK( this, PrintDialog
, ClickHdl
) );
666 mxPreviewBox
->connect_clicked( LINK( this, PrintDialog
, ClickHdl
) );
667 mxBorderCB
->connect_clicked( LINK( this, PrintDialog
, ClickHdl
) );
670 mxReverseOrderBox
->connect_toggled( LINK( this, PrintDialog
, ToggleHdl
) );
671 mxCollateBox
->connect_toggled( LINK( this, PrintDialog
, ToggleHdl
) );
672 mxPagesBtn
->connect_toggled( LINK( this, PrintDialog
, ToggleHdl
) );
675 mxPrinters
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
676 mxPaperSidesBox
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
677 mxNupPagesBox
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
678 mxOrientationBox
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
679 mxNupOrderBox
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
680 mxPaperSizeBox
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
683 mxPageEdit
->connect_activate( LINK( this, PrintDialog
, ActivateHdl
) );
684 mxPageEdit
->connect_focus_out( LINK( this, PrintDialog
, FocusOutHdl
) );
685 mxCopyCountField
->connect_value_changed( LINK( this, PrintDialog
, SpinModifyHdl
) );
686 mxNupColEdt
->connect_value_changed( LINK( this, PrintDialog
, SpinModifyHdl
) );
687 mxNupRowsEdt
->connect_value_changed( LINK( this, PrintDialog
, SpinModifyHdl
) );
688 mxPageMarginEdt
->connect_value_changed( LINK( this, PrintDialog
, MetricSpinModifyHdl
) );
689 mxSheetMarginEdt
->connect_value_changed( LINK( this, PrintDialog
, MetricSpinModifyHdl
) );
691 updateNupFromPages();
695 PrintDialog::~PrintDialog()
699 void PrintDialog::setupPaperSidesBox()
701 DuplexMode eDuplex
= maPController
->getPrinter()->GetDuplexMode();
703 if ( eDuplex
== DuplexMode::Unknown
|| isPrintToFile() )
705 mxPaperSidesBox
->set_active( 0 );
706 mxPaperSidesBox
->set_sensitive( false );
710 mxPaperSidesBox
->set_active( static_cast<sal_Int32
>(eDuplex
) - 1 );
711 mxPaperSidesBox
->set_sensitive( true );
715 void PrintDialog::storeToSettings()
717 SettingsConfigItem
* pItem
= SettingsConfigItem::get();
719 pItem
->setValue( "PrintDialog",
721 isPrintToFile() ? Printer::GetDefaultPrinterName()
722 : mxPrinters
->get_active_text() );
724 pItem
->setValue( "PrintDialog",
726 mxTabCtrl
->get_tab_label_text(mxTabCtrl
->get_current_page_ident()));
728 pItem
->setValue( "PrintDialog",
730 OStringToOUString(m_xDialog
->get_window_state(WindowStateMask::All
), RTL_TEXTENCODING_UTF8
) );
732 pItem
->setValue( "PrintDialog",
734 mxCopyCountField
->get_text() );
736 pItem
->setValue( "PrintDialog",
738 mxCollateBox
->get_active() ? OUString("true") :
741 pItem
->setValue( "PrintDialog",
743 mbSingleJobs
? OUString("true") :
746 pItem
->setValue( "PrintDialog",
748 hasPreview() ? OUString("true") :
754 void PrintDialog::readFromSettings()
756 SettingsConfigItem
* pItem
= SettingsConfigItem::get();
758 // read last selected tab page; if it exists, activate it
759 OUString aValue
= pItem
->getValue( "PrintDialog",
761 sal_uInt16 nCount
= mxTabCtrl
->get_n_pages();
762 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
764 OString sPageId
= mxTabCtrl
->get_page_ident(i
);
765 if (aValue
== mxTabCtrl
->get_tab_label_text(sPageId
))
767 mxTabCtrl
->set_current_page(sPageId
);
772 // persistent window state
773 aValue
= pItem
->getValue( "PrintDialog",
775 if (!aValue
.isEmpty())
776 m_xDialog
->set_window_state(OUStringToOString(aValue
, RTL_TEXTENCODING_UTF8
));
779 aValue
= pItem
->getValue( "PrintDialog",
781 if( aValue
.equalsIgnoreAsciiCase("alwaysoff") )
783 mbCollateAlwaysOff
= true;
784 mxCollateBox
->set_active( false );
785 mxCollateBox
->set_sensitive( false );
789 mbCollateAlwaysOff
= false;
790 aValue
= pItem
->getValue( "PrintDialog",
792 mxCollateBox
->set_active( aValue
.equalsIgnoreAsciiCase("true") );
795 // collate single jobs
796 aValue
= pItem
->getValue( "PrintDialog",
797 "CollateSingleJobs" );
798 if ( aValue
.equalsIgnoreAsciiCase("true") )
801 mbSingleJobs
= false;
804 aValue
= pItem
->getValue( "PrintDialog",
806 if ( aValue
.equalsIgnoreAsciiCase("false") )
807 mxPreviewBox
->set_active( false );
809 mxPreviewBox
->set_active( true );
813 void PrintDialog::setPaperSizes()
815 mxPaperSizeBox
->clear();
817 VclPtr
<Printer
> aPrt( maPController
->getPrinter() );
818 mePaper
= aPrt
->GetPaper();
820 if ( isPrintToFile() )
822 mxPaperSizeBox
->set_sensitive( false );
826 for (int nPaper
= 0; nPaper
< aPrt
->GetPaperInfoCount(); nPaper
++)
828 PaperInfo aInfo
= aPrt
->GetPaperInfo( nPaper
);
830 Paper ePaper
= aInfo
.getPaper();
832 const LocaleDataWrapper
& rLocWrap(Application::GetSettings().GetLocaleDataWrapper());
833 MapUnit eUnit
= MapUnit::MapMM
;
835 if( rLocWrap
.getMeasurementSystemEnum() == MeasurementSystem::US
)
837 eUnit
= MapUnit::Map100thInch
;
840 Size aSize
= aPrt
->GetPaperSize( nPaper
);
841 Size
aLogicPaperSize( OutputDevice::LogicToLogic( aSize
, MapMode( MapUnit::Map100thMM
), MapMode( eUnit
) ) );
843 OUString
aWidth( rLocWrap
.getNum( aLogicPaperSize
.Width(), nDigits
) );
844 OUString
aHeight( rLocWrap
.getNum( aLogicPaperSize
.Height(), nDigits
) );
845 OUString aUnit
= eUnit
== MapUnit::MapMM
? OUString("mm") : OUString("in");
846 OUString aPaperName
= Printer::GetPaperName( ePaper
) + " " + aWidth
+ aUnit
+ " x " + aHeight
+ aUnit
;
848 mxPaperSizeBox
->append_text(aPaperName
);
850 if ( ePaper
== mePaper
)
851 mxPaperSizeBox
->set_active( nPaper
);
854 mxPaperSizeBox
->set_sensitive( true );
858 void PrintDialog::updatePrinterText()
860 const OUString
aDefPrt( Printer::GetDefaultPrinterName() );
861 const QueueInfo
* pInfo
= Printer::GetQueueInfo( mxPrinters
->get_active_text(), true );
864 // FIXME: status text
866 if( aDefPrt
== pInfo
->GetPrinterName() )
867 aStatus
= maDefPrtText
;
868 mxStatusTxt
->set_label( aStatus
);
872 mxStatusTxt
->set_label( OUString() );
876 void PrintDialog::setPreviewText()
878 OUString
aNewText( maPageStr
.replaceFirst( "%n", OUString::number( mnCachedPages
) ) );
879 mxNumPagesText
->set_label( aNewText
);
882 void PrintDialog::preparePreview( bool i_bMayUseCache
)
884 VclPtr
<Printer
> aPrt( maPController
->getPrinter() );
885 Size aCurPageSize
= aPrt
->PixelToLogic( aPrt
->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM
) );
888 // page range may have changed depending on options
889 sal_Int32 nPages
= maPController
->getFilteredPageCount();
890 mnCachedPages
= nPages
;
896 mxPreview
->setPreview( aMtf
, aCurPageSize
,
897 Printer::GetPaperName( mePaper
),
899 aPrt
->GetDPIX(), aPrt
->GetDPIY(),
900 aPrt
->GetPrinterOptions().IsConvertToGreyscales()
903 mxForwardBtn
->set_sensitive( false );
904 mxBackwardBtn
->set_sensitive( false );
905 mxFirstBtn
->set_sensitive( false );
906 mxLastBtn
->set_sensitive( false );
908 mxPageEdit
->set_sensitive( false );
913 if( mnCurPage
>= nPages
)
914 mnCurPage
= nPages
-1;
919 const MapMode
aMapMode( MapUnit::Map100thMM
);
922 PrinterController::PageSize aPageSize
=
923 maPController
->getFilteredPageFile( mnCurPage
, aMtf
, i_bMayUseCache
);
924 if( ! aPageSize
.bFullPaper
)
926 Point
aOff( aPrt
->PixelToLogic( aPrt
->GetPageOffsetPixel(), aMapMode
) );
927 aMtf
.Move( aOff
.X(), aOff
.Y() );
931 mxPreview
->setPreview( aMtf
, aCurPageSize
,
932 Printer::GetPaperName( mePaper
),
933 nPages
> 0 ? OUString() : maNoPageStr
,
934 aPrt
->GetDPIX(), aPrt
->GetDPIY(),
935 aPrt
->GetPrinterOptions().IsConvertToGreyscales()
938 mxForwardBtn
->set_sensitive( mnCurPage
< nPages
-1 );
939 mxBackwardBtn
->set_sensitive( mnCurPage
!= 0 );
940 mxFirstBtn
->set_sensitive( mnCurPage
!= 0 );
941 mxLastBtn
->set_sensitive( mnCurPage
< nPages
-1 );
942 mxPageEdit
->set_sensitive( nPages
> 1 );
945 void PrintDialog::updateOrientationBox( const bool bAutomatic
)
949 Orientation eOrientation
= maPController
->getPrinter()->GetOrientation();
950 mxOrientationBox
->set_active( static_cast<sal_Int32
>(eOrientation
) + 1 );
952 else if ( hasOrientationChanged() )
954 mxOrientationBox
->set_active( ORIENTATION_AUTOMATIC
);
958 bool PrintDialog::hasOrientationChanged() const
960 const int nOrientation
= mxOrientationBox
->get_active();
961 const Orientation eOrientation
= maPController
->getPrinter()->GetOrientation();
963 return (nOrientation
== ORIENTATION_LANDSCAPE
&& eOrientation
== Orientation::Portrait
)
964 || (nOrientation
== ORIENTATION_PORTRAIT
&& eOrientation
== Orientation::Landscape
);
967 // make sure paper size matches paper orientation
968 void PrintDialog::checkPaperSize( Size
& rPaperSize
)
970 Orientation eOrientation
= maPController
->getPrinter()->GetOrientation();
971 if ( (eOrientation
== Orientation::Portrait
&& rPaperSize
.Width() > rPaperSize
.Height()) ||
972 (eOrientation
== Orientation::Landscape
&& rPaperSize
.Width() < rPaperSize
.Height()) )
974 // coverity[swapped-arguments : FALSE] - this is in the correct order
975 rPaperSize
= Size( rPaperSize
.Height(), rPaperSize
.Width() );
979 // Always use this function to set paper orientation to make sure everything behaves well
980 void PrintDialog::setPaperOrientation( Orientation eOrientation
)
982 VclPtr
<Printer
> aPrt( maPController
->getPrinter() );
983 aPrt
->SetOrientation( eOrientation
);
985 // check if it's necessary to swap width and height of paper
986 if ( maPController
->isPaperSizeFromUser() )
988 Size
& aPaperSize
= maPController
->getPaperSizeFromUser();
989 checkPaperSize( aPaperSize
);
991 else if ( maPController
->getPapersizeFromSetup() )
993 Size
& aPaperSize
= maPController
->getPaperSizeSetup();
994 checkPaperSize( aPaperSize
);
998 void PrintDialog::checkControlDependencies()
1000 if (mxCopyCountField
->get_value() > 1)
1001 mxCollateBox
->set_sensitive( !mbCollateAlwaysOff
);
1003 mxCollateBox
->set_sensitive( false );
1005 OUString
aImg(mxCollateBox
->get_active() ? OUString(SV_PRINT_COLLATE_BMP
) : OUString(SV_PRINT_NOCOLLATE_BMP
));
1007 mxCollateImage
->set_from_icon_name(aImg
);
1009 // enable setup button only for printers that can be setup
1010 bool bHaveSetup
= maPController
->getPrinter()->HasSupport( PrinterSupport::SetupDialog
);
1011 mxSetupButton
->set_sensitive(bHaveSetup
);
1014 void PrintDialog::checkOptionalControlDependencies()
1016 for( const auto& rEntry
: maControlToPropertyMap
)
1018 bool bShouldbeEnabled
= maPController
->isUIOptionEnabled( rEntry
.second
);
1020 if (bShouldbeEnabled
&& dynamic_cast<weld::RadioButton
*>(rEntry
.first
))
1022 auto r_it
= maControlToNumValMap
.find( rEntry
.first
);
1023 if( r_it
!= maControlToNumValMap
.end() )
1025 bShouldbeEnabled
= maPController
->isUIChoiceEnabled( rEntry
.second
, r_it
->second
);
1029 bool bIsEnabled
= rEntry
.first
->get_sensitive();
1030 // Enable does not do a change check first, so can be less cheap than expected
1031 if (bShouldbeEnabled
!= bIsEnabled
)
1032 rEntry
.first
->set_sensitive( bShouldbeEnabled
);
1036 void PrintDialog::initFromMultiPageSetup( const vcl::PrinterController::MultiPageSetup
& i_rMPS
)
1038 mxNupOrderWin
->show();
1039 mxPagesBtn
->set_active(true);
1040 mxBrochureBtn
->hide();
1042 // setup field units for metric fields
1043 const LocaleDataWrapper
& rLocWrap(Application::GetSettings().GetLocaleDataWrapper());
1044 FieldUnit eUnit
= FieldUnit::MM
;
1045 sal_uInt16 nDigits
= 0;
1046 if( rLocWrap
.getMeasurementSystemEnum() == MeasurementSystem::US
)
1048 eUnit
= FieldUnit::INCH
;
1052 mxPageMarginEdt
->set_unit( eUnit
);
1053 mxSheetMarginEdt
->set_unit( eUnit
);
1056 mxPageMarginEdt
->set_digits( nDigits
);
1057 mxSheetMarginEdt
->set_digits( nDigits
);
1059 mxSheetMarginEdt
->set_value( mxSheetMarginEdt
->normalize( i_rMPS
.nLeftMargin
), FieldUnit::MM_100TH
);
1060 mxPageMarginEdt
->set_value( mxPageMarginEdt
->normalize( i_rMPS
.nHorizontalSpacing
), FieldUnit::MM_100TH
);
1061 mxBorderCB
->set_active( i_rMPS
.bDrawBorder
);
1062 mxNupRowsEdt
->set_value( i_rMPS
.nRows
);
1063 mxNupColEdt
->set_value( i_rMPS
.nColumns
);
1064 mxNupOrderBox
->set_active( static_cast<sal_Int32
>(i_rMPS
.nOrder
) );
1065 if( i_rMPS
.nRows
!= 1 || i_rMPS
.nColumns
!= 1 )
1067 mxNupPagesBox
->set_active( mxNupPagesBox
->get_count()-1 );
1068 showAdvancedControls( true );
1069 mxNupOrder
->setValues( i_rMPS
.nOrder
, i_rMPS
.nColumns
, i_rMPS
.nRows
);
1073 void PrintDialog::updateNup( bool i_bMayUseCache
)
1075 int nRows
= mxNupRowsEdt
->get_value();
1076 int nCols
= mxNupColEdt
->get_value();
1077 long nPageMargin
= mxPageMarginEdt
->denormalize(mxPageMarginEdt
->get_value( FieldUnit::MM_100TH
));
1078 long nSheetMargin
= mxSheetMarginEdt
->denormalize(mxSheetMarginEdt
->get_value( FieldUnit::MM_100TH
));
1080 PrinterController::MultiPageSetup aMPS
;
1082 aMPS
.nColumns
= nCols
;
1086 aMPS
.nBottomMargin
= nSheetMargin
;
1088 aMPS
.nHorizontalSpacing
=
1089 aMPS
.nVerticalSpacing
= nPageMargin
;
1091 aMPS
.bDrawBorder
= mxBorderCB
->get_active();
1093 aMPS
.nOrder
= static_cast<NupOrderType
>(mxNupOrderBox
->get_active());
1095 int nOrientationMode
= mxOrientationBox
->get_active();
1096 if( nOrientationMode
== ORIENTATION_LANDSCAPE
)
1097 aMPS
.aPaperSize
= maNupLandscapeSize
;
1098 else if( nOrientationMode
== ORIENTATION_PORTRAIT
)
1099 aMPS
.aPaperSize
= maNupPortraitSize
;
1100 else // automatic mode
1102 // get size of first real page to see if it is portrait or landscape
1103 // we assume same page sizes for all the pages for this
1104 Size aPageSize
= getJobPageSize();
1106 Size
aMultiSize( aPageSize
.Width() * nCols
, aPageSize
.Height() * nRows
);
1107 if( aMultiSize
.Width() > aMultiSize
.Height() ) // fits better on landscape
1109 aMPS
.aPaperSize
= maNupLandscapeSize
;
1110 setPaperOrientation( Orientation::Landscape
);
1114 aMPS
.aPaperSize
= maNupPortraitSize
;
1115 setPaperOrientation( Orientation::Portrait
);
1119 maPController
->setMultipage( aMPS
);
1121 mxNupOrder
->setValues( aMPS
.nOrder
, nCols
, nRows
);
1123 preparePreview( i_bMayUseCache
);
1126 void PrintDialog::updateNupFromPages( bool i_bMayUseCache
)
1128 int nPages
= mxNupPagesBox
->get_active_id().toInt32();
1129 int nRows
= mxNupRowsEdt
->get_value();
1130 int nCols
= mxNupColEdt
->get_value();
1131 long nPageMargin
= mxPageMarginEdt
->denormalize(mxPageMarginEdt
->get_value( FieldUnit::MM_100TH
));
1132 long nSheetMargin
= mxSheetMarginEdt
->denormalize(mxSheetMarginEdt
->get_value( FieldUnit::MM_100TH
));
1133 bool bCustom
= false;
1141 else if( nPages
== 2 || nPages
== 4 || nPages
== 6 || nPages
== 9 || nPages
== 16 )
1143 Size
aJobPageSize( getJobPageSize() );
1144 bool bPortrait
= aJobPageSize
.Width() < aJobPageSize
.Height();
1158 else if( nPages
== 4 )
1160 else if( nPages
== 6 )
1173 else if( nPages
== 9 )
1175 else if( nPages
== 16 )
1185 // set upper limits for margins based on job page size and rows/columns
1186 Size
aSize( getJobPageSize() );
1188 // maximum sheet distance: 1/2 sheet
1189 long nHorzMax
= aSize
.Width()/2;
1190 long nVertMax
= aSize
.Height()/2;
1191 if( nSheetMargin
> nHorzMax
)
1192 nSheetMargin
= nHorzMax
;
1193 if( nSheetMargin
> nVertMax
)
1194 nSheetMargin
= nVertMax
;
1196 mxSheetMarginEdt
->set_max(
1197 mxSheetMarginEdt
->normalize(
1198 std::min(nHorzMax
, nVertMax
) ), FieldUnit::MM_100TH
);
1200 // maximum page distance
1201 nHorzMax
= (aSize
.Width() - 2*nSheetMargin
);
1203 nHorzMax
/= (nCols
-1);
1204 nVertMax
= (aSize
.Height() - 2*nSheetMargin
);
1206 nHorzMax
/= (nRows
-1);
1208 if( nPageMargin
> nHorzMax
)
1209 nPageMargin
= nHorzMax
;
1210 if( nPageMargin
> nVertMax
)
1211 nPageMargin
= nVertMax
;
1213 mxPageMarginEdt
->set_max(
1214 mxSheetMarginEdt
->normalize(
1215 std::min(nHorzMax
, nVertMax
) ), FieldUnit::MM_100TH
);
1218 mxNupRowsEdt
->set_value( nRows
);
1219 mxNupColEdt
->set_value( nCols
);
1220 mxPageMarginEdt
->set_value( mxPageMarginEdt
->normalize( nPageMargin
), FieldUnit::MM_100TH
);
1221 mxSheetMarginEdt
->set_value( mxSheetMarginEdt
->normalize( nSheetMargin
), FieldUnit::MM_100TH
);
1223 showAdvancedControls( bCustom
);
1224 updateNup( i_bMayUseCache
);
1227 void PrintDialog::enableNupControls( bool bEnable
)
1229 mxNupPagesBox
->set_sensitive( bEnable
);
1230 mxNupNumPagesTxt
->set_sensitive( bEnable
);
1231 mxNupColEdt
->set_sensitive( bEnable
);
1232 mxNupTimesTxt
->set_sensitive( bEnable
);
1233 mxNupRowsEdt
->set_sensitive( bEnable
);
1234 mxPageMarginTxt1
->set_sensitive( bEnable
);
1235 mxPageMarginEdt
->set_sensitive( bEnable
);
1236 mxPageMarginTxt2
->set_sensitive( bEnable
);
1237 mxSheetMarginTxt1
->set_sensitive( bEnable
);
1238 mxSheetMarginEdt
->set_sensitive( bEnable
);
1239 mxSheetMarginTxt2
->set_sensitive( bEnable
);
1240 mxNupOrderTxt
->set_sensitive( bEnable
);
1241 mxNupOrderBox
->set_sensitive( bEnable
);
1242 mxNupOrderWin
->set_sensitive( bEnable
);
1243 mxBorderCB
->set_sensitive( bEnable
);
1246 void PrintDialog::showAdvancedControls( bool i_bShow
)
1248 mxNupNumPagesTxt
->set_visible( i_bShow
);
1249 mxNupColEdt
->set_visible( i_bShow
);
1250 mxNupTimesTxt
->set_visible( i_bShow
);
1251 mxNupRowsEdt
->set_visible( i_bShow
);
1252 mxPageMarginTxt1
->set_visible( i_bShow
);
1253 mxPageMarginEdt
->set_visible( i_bShow
);
1254 mxPageMarginTxt2
->set_visible( i_bShow
);
1255 mxSheetMarginTxt1
->set_visible( i_bShow
);
1256 mxSheetMarginEdt
->set_visible( i_bShow
);
1257 mxSheetMarginTxt2
->set_visible( i_bShow
);
1262 void setHelpId( weld::Widget
* i_pWindow
, const Sequence
< OUString
>& i_rHelpIds
, sal_Int32 i_nIndex
)
1264 if( i_nIndex
>= 0 && i_nIndex
< i_rHelpIds
.getLength() )
1265 i_pWindow
->set_help_id( OUStringToOString( i_rHelpIds
.getConstArray()[i_nIndex
], RTL_TEXTENCODING_UTF8
) );
1268 void setHelpText( weld::Widget
* i_pWindow
, const Sequence
< OUString
>& i_rHelpTexts
, sal_Int32 i_nIndex
)
1270 // without a help text set and the correct smartID,
1271 // help texts will be retrieved from the online help system
1272 if( i_nIndex
>= 0 && i_nIndex
< i_rHelpTexts
.getLength() )
1273 i_pWindow
->set_tooltip_text(i_rHelpTexts
.getConstArray()[i_nIndex
]);
1277 void PrintDialog::setupOptionalUI()
1279 const Sequence
< PropertyValue
>& rOptions( maPController
->getUIOptions() );
1280 for( const auto& rOption
: rOptions
)
1282 if (rOption
.Name
== "OptionsUIFile")
1284 OUString sOptionsUIFile
;
1285 rOption
.Value
>>= sOptionsUIFile
;
1286 mxCustomOptionsUIBuilder
.reset(Application::CreateBuilder(mxCustom
.get(), sOptionsUIFile
));
1287 std::unique_ptr
<weld::Container
> xWindow
= mxCustomOptionsUIBuilder
->weld_container("box");
1292 Sequence
< beans::PropertyValue
> aOptProp
;
1293 rOption
.Value
>>= aOptProp
;
1295 // extract ui element
1299 OUString aPropertyName
;
1300 Sequence
< OUString
> aChoices
;
1301 Sequence
< sal_Bool
> aChoicesDisabled
;
1302 Sequence
< OUString
> aHelpTexts
;
1303 Sequence
< OUString
> aIDs
;
1304 Sequence
< OUString
> aHelpIds
;
1305 sal_Int64 nMinValue
= 0, nMaxValue
= 0;
1306 OUString aGroupingHint
;
1308 for( const beans::PropertyValue
& rEntry
: std::as_const(aOptProp
) )
1310 if ( rEntry
.Name
== "ID" )
1312 rEntry
.Value
>>= aIDs
;
1313 aID
= OUStringToOString(aIDs
[0], RTL_TEXTENCODING_UTF8
);
1315 if ( rEntry
.Name
== "Text" )
1317 rEntry
.Value
>>= aText
;
1319 else if ( rEntry
.Name
== "ControlType" )
1321 rEntry
.Value
>>= aCtrlType
;
1323 else if ( rEntry
.Name
== "Choices" )
1325 rEntry
.Value
>>= aChoices
;
1327 else if ( rEntry
.Name
== "ChoicesDisabled" )
1329 rEntry
.Value
>>= aChoicesDisabled
;
1331 else if ( rEntry
.Name
== "Property" )
1334 rEntry
.Value
>>= aVal
;
1335 aPropertyName
= aVal
.Name
;
1337 else if ( rEntry
.Name
== "Enabled" )
1340 else if ( rEntry
.Name
== "GroupingHint" )
1342 rEntry
.Value
>>= aGroupingHint
;
1344 else if ( rEntry
.Name
== "DependsOnName" )
1347 else if ( rEntry
.Name
== "DependsOnEntry" )
1350 else if ( rEntry
.Name
== "AttachToDependency" )
1353 else if ( rEntry
.Name
== "MinValue" )
1355 rEntry
.Value
>>= nMinValue
;
1357 else if ( rEntry
.Name
== "MaxValue" )
1359 rEntry
.Value
>>= nMaxValue
;
1361 else if ( rEntry
.Name
== "HelpText" )
1363 if( ! (rEntry
.Value
>>= aHelpTexts
) )
1366 if( rEntry
.Value
>>= aHelpText
)
1368 aHelpTexts
.realloc( 1 );
1369 *aHelpTexts
.getArray() = aHelpText
;
1373 else if ( rEntry
.Name
== "HelpId" )
1375 if( ! (rEntry
.Value
>>= aHelpIds
) )
1378 if( rEntry
.Value
>>= aHelpId
)
1380 aHelpIds
.realloc( 1 );
1381 *aHelpIds
.getArray() = aHelpId
;
1385 else if ( rEntry
.Name
== "HintNoLayoutPage" )
1387 bool bHasLayoutFrame
= false;
1388 rEntry
.Value
>>= bHasLayoutFrame
;
1389 mbShowLayoutFrame
= !bHasLayoutFrame
;
1393 if (aCtrlType
== "Group")
1397 weld::Container
* pPage
= mxTabCtrl
->get_page(aID
);
1401 mxTabCtrl
->set_tab_label_text(aID
, aText
);
1404 if (aHelpIds
.hasElements())
1405 pPage
->set_help_id(OUStringToOString(aHelpIds
.getConstArray()[0], RTL_TEXTENCODING_UTF8
));
1408 if (aHelpTexts
.hasElements())
1409 pPage
->set_tooltip_text(aHelpTexts
.getConstArray()[0]);
1413 else if (aCtrlType
== "Subgroup" && !aID
.isEmpty())
1415 std::unique_ptr
<weld::Widget
> xWidget
;
1416 // since 'New Print Dialog Design' fromwhich in calc is not a frame anymore
1417 if (aID
== "fromwhich")
1419 std::unique_ptr
<weld::Label
> xLabel
= m_xBuilder
->weld_label(aID
);
1420 xLabel
->set_label(aText
);
1421 xWidget
= std::move(xLabel
);
1425 std::unique_ptr
<weld::Frame
> xFrame
= m_xBuilder
->weld_frame(aID
);
1426 if (!xFrame
&& mxCustomOptionsUIBuilder
)
1427 xFrame
= mxCustomOptionsUIBuilder
->weld_frame(aID
);
1430 xFrame
->set_label(aText
);
1431 xWidget
= std::move(xFrame
);
1439 setHelpId(xWidget
.get(), aHelpIds
, 0);
1441 setHelpText(xWidget
.get(), aHelpTexts
, 0);
1446 else if( aCtrlType
== "Bool" && aGroupingHint
== "LayoutPage" && aPropertyName
== "PrintProspect" )
1448 mxBrochureBtn
->set_label(aText
);
1449 mxBrochureBtn
->show();
1452 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1454 pVal
->Value
>>= bVal
;
1455 mxBrochureBtn
->set_active( bVal
);
1456 mxBrochureBtn
->set_sensitive( maPController
->isUIOptionEnabled( aPropertyName
) && pVal
!= nullptr );
1457 mxBrochureBtn
->connect_toggled( LINK( this, PrintDialog
, ToggleHdl
) );
1459 maPropertyToWindowMap
[aPropertyName
].emplace_back(mxBrochureBtn
.get());
1460 maControlToPropertyMap
[mxBrochureBtn
.get()] = aPropertyName
;
1463 setHelpId( mxBrochureBtn
.get(), aHelpIds
, 0 );
1465 setHelpText( mxBrochureBtn
.get(), aHelpTexts
, 0 );
1467 else if (aCtrlType
== "Bool")
1470 std::unique_ptr
<weld::CheckButton
> xNewBox
= m_xBuilder
->weld_check_button(aID
);
1471 if (!xNewBox
&& mxCustomOptionsUIBuilder
)
1472 xNewBox
= mxCustomOptionsUIBuilder
->weld_check_button(aID
);
1476 xNewBox
->set_label( aText
);
1480 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1482 pVal
->Value
>>= bVal
;
1483 xNewBox
->set_active( bVal
);
1484 xNewBox
->connect_toggled( LINK( this, PrintDialog
, UIOption_CheckHdl
) );
1486 maExtraControls
.emplace_back(std::move(xNewBox
));
1488 weld::Widget
* pWidget
= maExtraControls
.back().get();
1490 maPropertyToWindowMap
[aPropertyName
].emplace_back(pWidget
);
1491 maControlToPropertyMap
[pWidget
] = aPropertyName
;
1494 setHelpId(pWidget
, aHelpIds
, 0);
1496 setHelpText(pWidget
, aHelpTexts
, 0);
1498 else if (aCtrlType
== "Radio")
1500 sal_Int32 nCurHelpText
= 0;
1503 sal_Int32 nSelectVal
= 0;
1504 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1505 if( pVal
&& pVal
->Value
.hasValue() )
1506 pVal
->Value
>>= nSelectVal
;
1507 for( sal_Int32 m
= 0; m
< aChoices
.getLength(); m
++ )
1509 aID
= OUStringToOString(aIDs
[m
], RTL_TEXTENCODING_UTF8
);
1510 std::unique_ptr
<weld::RadioButton
> xBtn
= m_xBuilder
->weld_radio_button(aID
);
1511 if (!xBtn
&& mxCustomOptionsUIBuilder
)
1512 xBtn
= mxCustomOptionsUIBuilder
->weld_radio_button(aID
);
1516 xBtn
->set_label( aChoices
[m
] );
1517 xBtn
->set_active( m
== nSelectVal
);
1518 xBtn
->connect_toggled( LINK( this, PrintDialog
, UIOption_RadioHdl
) );
1519 if( aChoicesDisabled
.getLength() > m
&& aChoicesDisabled
[m
] )
1520 xBtn
->set_sensitive( false );
1523 maExtraControls
.emplace_back(std::move(xBtn
));
1525 weld::Widget
* pWidget
= maExtraControls
.back().get();
1527 maPropertyToWindowMap
[ aPropertyName
].emplace_back(pWidget
);
1528 maControlToPropertyMap
[pWidget
] = aPropertyName
;
1529 maControlToNumValMap
[pWidget
] = m
;
1532 setHelpId( pWidget
, aHelpIds
, nCurHelpText
);
1534 setHelpText( pWidget
, aHelpTexts
, nCurHelpText
);
1538 else if ( aCtrlType
== "List" )
1540 std::unique_ptr
<weld::ComboBox
> xList
= m_xBuilder
->weld_combo_box(aID
);
1541 if (!xList
&& mxCustomOptionsUIBuilder
)
1542 xList
= mxCustomOptionsUIBuilder
->weld_combo_box(aID
);
1547 for( const auto& rChoice
: std::as_const(aChoices
) )
1548 xList
->append_text(rChoice
);
1550 sal_Int32 nSelectVal
= 0;
1551 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1552 if( pVal
&& pVal
->Value
.hasValue() )
1553 pVal
->Value
>>= nSelectVal
;
1554 xList
->set_active(nSelectVal
);
1555 xList
->connect_changed( LINK( this, PrintDialog
, UIOption_SelectHdl
) );
1558 maExtraControls
.emplace_back(std::move(xList
));
1560 weld::Widget
* pWidget
= maExtraControls
.back().get();
1562 maPropertyToWindowMap
[ aPropertyName
].emplace_back(pWidget
);
1563 maControlToPropertyMap
[pWidget
] = aPropertyName
;
1566 setHelpId( pWidget
, aHelpIds
, 0 );
1568 setHelpText( pWidget
, aHelpTexts
, 0 );
1570 else if ( aCtrlType
== "Range" )
1572 std::unique_ptr
<weld::SpinButton
> xField
= m_xBuilder
->weld_spin_button(aID
);
1573 if (!xField
&& mxCustomOptionsUIBuilder
)
1574 xField
= mxCustomOptionsUIBuilder
->weld_spin_button(aID
);
1578 // set min/max and current value
1579 if(nMinValue
!= nMaxValue
)
1580 xField
->set_range(nMinValue
, nMaxValue
);
1582 sal_Int64 nCurVal
= 0;
1583 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1584 if( pVal
&& pVal
->Value
.hasValue() )
1585 pVal
->Value
>>= nCurVal
;
1586 xField
->set_value( nCurVal
);
1587 xField
->connect_value_changed( LINK( this, PrintDialog
, UIOption_SpinModifyHdl
) );
1590 maExtraControls
.emplace_back(std::move(xField
));
1592 weld::Widget
* pWidget
= maExtraControls
.back().get();
1594 maPropertyToWindowMap
[ aPropertyName
].emplace_back(pWidget
);
1595 maControlToPropertyMap
[pWidget
] = aPropertyName
;
1598 setHelpId( pWidget
, aHelpIds
, 0 );
1600 setHelpText( pWidget
, aHelpTexts
, 0 );
1602 else if (aCtrlType
== "Edit")
1604 std::unique_ptr
<weld::Entry
> xField
= m_xBuilder
->weld_entry(aID
);
1605 if (!xField
&& mxCustomOptionsUIBuilder
)
1606 xField
= mxCustomOptionsUIBuilder
->weld_entry(aID
);
1611 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1612 if( pVal
&& pVal
->Value
.hasValue() )
1613 pVal
->Value
>>= aCurVal
;
1614 xField
->set_text( aCurVal
);
1615 xField
->connect_changed( LINK( this, PrintDialog
, UIOption_EntryModifyHdl
) );
1618 maExtraControls
.emplace_back(std::move(xField
));
1620 weld::Widget
* pWidget
= maExtraControls
.back().get();
1622 maPropertyToWindowMap
[ aPropertyName
].emplace_back(pWidget
);
1623 maControlToPropertyMap
[pWidget
] = aPropertyName
;
1626 setHelpId( pWidget
, aHelpIds
, 0 );
1628 setHelpText( pWidget
, aHelpTexts
, 0 );
1632 SAL_WARN( "vcl", "Unsupported UI option: \"" << aCtrlType
<< '"');
1636 // #i106506# if no brochure button, then the singular Pages radio button
1637 // makes no sense, so replace it by a FixedText label
1638 if (!mxBrochureBtn
->get_visible() && mxPagesBtn
->get_visible())
1640 mxPagesBoxTitleTxt
->set_label(mxPagesBtn
->get_label());
1641 mxPagesBoxTitleTxt
->show();
1644 mxPagesBoxTitleTxt
->set_accessible_relation_label_for(mxNupPagesBox
.get());
1645 mxNupPagesBox
->set_accessible_relation_labeled_by(mxPagesBoxTitleTxt
.get());
1646 mxPagesBtn
->set_accessible_relation_label_for(nullptr);
1649 // update enable states
1650 checkOptionalControlDependencies();
1652 // print range not shown (currently math only) -> hide spacer line and reverse order
1653 if (!mxPageRangeEdit
->get_visible())
1655 mxReverseOrderBox
->hide();
1658 if (!mxCustomOptionsUIBuilder
)
1659 mxTabCtrl
->remove_page(mxTabCtrl
->get_page_ident(1));
1662 void PrintDialog::makeEnabled( weld::Widget
* i_pWindow
)
1664 auto it
= maControlToPropertyMap
.find( i_pWindow
);
1665 if( it
!= maControlToPropertyMap
.end() )
1667 OUString
aDependency( maPController
->makeEnabled( it
->second
) );
1668 if( !aDependency
.isEmpty() )
1669 updateWindowFromProperty( aDependency
);
1673 void PrintDialog::updateWindowFromProperty( const OUString
& i_rProperty
)
1675 beans::PropertyValue
* pValue
= maPController
->getValue( i_rProperty
);
1676 auto it
= maPropertyToWindowMap
.find( i_rProperty
);
1677 if( pValue
&& it
!= maPropertyToWindowMap
.end() )
1679 const auto& rWindows( it
->second
);
1680 if( ! rWindows
.empty() )
1683 sal_Int32 nVal
= -1;
1684 if( pValue
->Value
>>= bVal
)
1686 // we should have a CheckBox for this one
1687 weld::CheckButton
* pBox
= dynamic_cast<weld::CheckButton
*>(rWindows
.front());
1690 pBox
->set_active( bVal
);
1692 else if ( i_rProperty
== "PrintProspect" )
1694 // EVIL special case
1696 mxBrochureBtn
->set_active(true);
1698 mxPagesBtn
->set_active(true);
1702 SAL_WARN( "vcl", "missing a checkbox" );
1705 else if( pValue
->Value
>>= nVal
)
1707 // this could be a ListBox or a RadioButtonGroup
1708 weld::ComboBox
* pList
= dynamic_cast<weld::ComboBox
*>(rWindows
.front());
1711 pList
->set_active( static_cast< sal_uInt16
>(nVal
) );
1713 else if( nVal
>= 0 && nVal
< sal_Int32(rWindows
.size() ) )
1715 weld::RadioButton
* pBtn
= dynamic_cast<weld::RadioButton
*>(rWindows
[nVal
]);
1716 SAL_WARN_IF( !pBtn
, "vcl", "unexpected control for property" );
1718 pBtn
->set_active(true);
1725 bool PrintDialog::isPrintToFile() const
1727 return ( mxPrinters
->get_active() == 0 );
1730 bool PrintDialog::isCollate() const
1732 return mxCopyCountField
->get_value() > 1 && mxCollateBox
->get_active();
1735 bool PrintDialog::hasPreview() const
1737 return mxPreviewBox
->get_active();
1740 PropertyValue
* PrintDialog::getValueForWindow( weld::Widget
* i_pWindow
) const
1742 PropertyValue
* pVal
= nullptr;
1743 auto it
= maControlToPropertyMap
.find( i_pWindow
);
1744 if( it
!= maControlToPropertyMap
.end() )
1746 pVal
= maPController
->getValue( it
->second
);
1747 SAL_WARN_IF( !pVal
, "vcl", "property value not found" );
1751 OSL_FAIL( "changed control not in property map" );
1756 IMPL_LINK(PrintDialog
, ToggleHdl
, weld::ToggleButton
&, rButton
, void)
1761 IMPL_LINK(PrintDialog
, ClickHdl
, weld::Button
&, rButton
, void)
1763 if (&rButton
== mxOKButton
.get() || &rButton
== mxCancelButton
.get())
1766 m_xDialog
->response(&rButton
== mxOKButton
.get() ? RET_OK
: RET_CANCEL
);
1768 else if( &rButton
== mxHelpButton
.get() )
1770 // start help system
1771 Help
* pHelp
= Application::GetHelp();
1774 pHelp
->Start("vcl/ui/printdialog", mxOKButton
.get());
1777 else if ( &rButton
== mxPreviewBox
.get() )
1779 preparePreview( true );
1781 else if( &rButton
== mxForwardBtn
.get() )
1785 else if( &rButton
== mxBackwardBtn
.get() )
1789 else if( &rButton
== mxFirstBtn
.get() )
1793 else if( &rButton
== mxLastBtn
.get() )
1797 else if( &rButton
== mxBrochureBtn
.get() )
1799 PropertyValue
* pVal
= getValueForWindow( &rButton
);
1802 bool bVal
= mxBrochureBtn
->get_active();
1803 pVal
->Value
<<= bVal
;
1805 checkOptionalControlDependencies();
1807 // update preview and page settings
1808 preparePreview(false);
1810 if( mxBrochureBtn
->get_active() )
1812 mxOrientationBox
->set_sensitive( false );
1813 mxOrientationBox
->set_active( ORIENTATION_LANDSCAPE
);
1814 mxNupPagesBox
->set_active( 0 );
1815 updateNupFromPages();
1816 showAdvancedControls( false );
1817 enableNupControls( false );
1820 else if( &rButton
== mxPagesBtn
.get() )
1822 mxOrientationBox
->set_sensitive( true );
1823 mxOrientationBox
->set_active( ORIENTATION_AUTOMATIC
);
1824 enableNupControls( true );
1825 updateNupFromPages();
1827 else if( &rButton
== mxCollateBox
.get() )
1829 maPController
->setValue( "Collate",
1830 makeAny( isCollate() ) );
1831 checkControlDependencies();
1833 else if( &rButton
== mxReverseOrderBox
.get() )
1835 bool bChecked
= mxReverseOrderBox
->get_active();
1836 maPController
->setReversePrint( bChecked
);
1837 maPController
->setValue( "PrintReverse",
1838 makeAny( bChecked
) );
1839 preparePreview( true );
1841 else if( &rButton
== mxBorderCB
.get() )
1845 else if ( &rButton
== mxMoreOptionsBtn
.get() )
1847 mxMoreOptionsDlg
.reset(new MoreOptionsDialog(this));
1848 mxMoreOptionsDlg
->run();
1852 if( &rButton
== mxSetupButton
.get() )
1854 maPController
->setupPrinter(m_xDialog
.get());
1856 if ( !isPrintToFile() )
1858 VclPtr
<Printer
> aPrt( maPController
->getPrinter() );
1859 mePaper
= aPrt
->GetPaper();
1861 for (int nPaper
= 0; nPaper
< aPrt
->GetPaperInfoCount(); nPaper
++ )
1863 PaperInfo aInfo
= aPrt
->GetPaperInfo( nPaper
);
1864 aInfo
.doSloppyFit();
1865 Paper ePaper
= aInfo
.getPaper();
1867 if ( mePaper
== ePaper
)
1869 mxPaperSizeBox
->set_active( nPaper
);
1875 updateOrientationBox( false );
1876 setupPaperSidesBox();
1878 // tdf#63905 don't use cache: page size may change
1879 preparePreview(false);
1881 checkControlDependencies();
1886 IMPL_LINK( PrintDialog
, SelectHdl
, weld::ComboBox
&, rBox
, void )
1888 if (&rBox
== mxPrinters
.get())
1890 if ( !isPrintToFile() )
1892 OUString
aNewPrinter(rBox
.get_active_text());
1894 maPController
->setPrinter( VclPtrInstance
<Printer
>( aNewPrinter
) );
1895 maPController
->resetPrinterOptions( false );
1897 updateOrientationBox();
1899 // update text fields
1900 mxOKButton
->set_label(maPrintText
);
1901 updatePrinterText();
1903 preparePreview(false);
1905 else // print to file
1907 // use the default printer or FIXME: the last used one?
1908 maPController
->setPrinter( VclPtrInstance
<Printer
>( Printer::GetDefaultPrinterName() ) );
1909 mxOKButton
->set_label(maPrintToFileText
);
1910 maPController
->resetPrinterOptions( true );
1913 updateOrientationBox();
1914 preparePreview( true );
1917 setupPaperSidesBox();
1919 else if ( &rBox
== mxPaperSidesBox
.get() )
1921 DuplexMode eDuplex
= static_cast<DuplexMode
>(mxPaperSidesBox
->get_active() + 1);
1922 maPController
->getPrinter()->SetDuplexMode( eDuplex
);
1924 else if( &rBox
== mxOrientationBox
.get() )
1926 int nOrientation
= mxOrientationBox
->get_active();
1927 if ( nOrientation
!= ORIENTATION_AUTOMATIC
)
1928 setPaperOrientation( static_cast<Orientation
>( nOrientation
- 1 ) );
1932 else if ( &rBox
== mxNupOrderBox
.get() )
1936 else if( &rBox
== mxNupPagesBox
.get() )
1938 if( !mxPagesBtn
->get_active() )
1939 mxPagesBtn
->set_active(true);
1940 updateNupFromPages( false );
1942 else if ( &rBox
== mxPaperSizeBox
.get() )
1944 VclPtr
<Printer
> aPrt( maPController
->getPrinter() );
1945 PaperInfo aInfo
= aPrt
->GetPaperInfo( rBox
.get_active() );
1946 aInfo
.doSloppyFit();
1947 mePaper
= aInfo
.getPaper();
1949 if ( mePaper
== PAPER_USER
)
1950 aPrt
->SetPaperSizeUser( Size( aInfo
.getWidth(), aInfo
.getHeight() ) );
1952 aPrt
->SetPaper( mePaper
);
1954 Size
aPaperSize( aInfo
.getWidth(), aInfo
.getHeight() );
1955 checkPaperSize( aPaperSize
);
1956 maPController
->setPaperSizeFromUser( aPaperSize
);
1958 preparePreview(false);
1962 IMPL_LINK_NOARG(PrintDialog
, MetricSpinModifyHdl
, weld::MetricSpinButton
&, void)
1964 checkControlDependencies();
1965 updateNupFromPages();
1968 IMPL_LINK_NOARG(PrintDialog
, FocusOutHdl
, weld::Widget
&, void)
1970 ActivateHdl(*mxPageEdit
);
1973 IMPL_LINK_NOARG(PrintDialog
, ActivateHdl
, weld::Entry
&, bool)
1975 sal_Int32 nPage
= mxPageEdit
->get_text().toInt32();
1979 mxPageEdit
->set_text("1");
1981 else if (nPage
> mnCachedPages
)
1983 nPage
= mnCachedPages
;
1984 mxPageEdit
->set_text(OUString::number(mnCachedPages
));
1986 int nNewCurPage
= nPage
- 1;
1987 if (nNewCurPage
!= mnCurPage
)
1989 mnCurPage
= nNewCurPage
;
1990 preparePreview(true);
1995 IMPL_LINK( PrintDialog
, SpinModifyHdl
, weld::SpinButton
&, rEdit
, void )
1997 checkControlDependencies();
1998 if (&rEdit
== mxNupRowsEdt
.get() || &rEdit
== mxNupColEdt
.get())
2000 updateNupFromPages();
2002 else if( &rEdit
== mxCopyCountField
.get() )
2004 maPController
->setValue( "CopyCount",
2005 makeAny( sal_Int32(mxCopyCountField
->get_value()) ) );
2006 maPController
->setValue( "Collate",
2007 makeAny( isCollate() ) );
2011 IMPL_LINK( PrintDialog
, UIOption_CheckHdl
, weld::ToggleButton
&, i_rBox
, void )
2013 PropertyValue
* pVal
= getValueForWindow( &i_rBox
);
2016 makeEnabled( &i_rBox
);
2018 bool bVal
= i_rBox
.get_active();
2019 pVal
->Value
<<= bVal
;
2021 checkOptionalControlDependencies();
2023 // update preview and page settings
2024 preparePreview(false);
2028 IMPL_LINK( PrintDialog
, UIOption_RadioHdl
, weld::ToggleButton
&, i_rBtn
, void )
2030 // this handler gets called for all radiobuttons that get unchecked, too
2031 // however we only want one notification for the new value (that is for
2032 // the button that gets checked)
2033 if( i_rBtn
.get_active() )
2035 PropertyValue
* pVal
= getValueForWindow( &i_rBtn
);
2036 auto it
= maControlToNumValMap
.find( &i_rBtn
);
2037 if( pVal
&& it
!= maControlToNumValMap
.end() )
2039 makeEnabled( &i_rBtn
);
2041 sal_Int32 nVal
= it
->second
;
2042 pVal
->Value
<<= nVal
;
2044 // tdf#63905 use paper size set in printer properties
2045 if (pVal
->Name
== "PageOptions")
2046 maPController
->resetPaperToLastConfigured();
2048 updateOrientationBox();
2050 checkOptionalControlDependencies();
2052 // tdf#41205 give focus to the page range edit if the corresponding radio button was selected
2053 if (pVal
->Name
== "PrintContent" && mxPageRangesRadioButton
->get_active())
2054 mxPageRangeEdit
->grab_focus();
2056 // update preview and page settings
2057 preparePreview(false);
2062 IMPL_LINK( PrintDialog
, UIOption_SelectHdl
, weld::ComboBox
&, i_rBox
, void )
2064 PropertyValue
* pVal
= getValueForWindow( &i_rBox
);
2067 makeEnabled( &i_rBox
);
2069 sal_Int32
nVal( i_rBox
.get_active() );
2070 pVal
->Value
<<= nVal
;
2072 //If we are in impress we start in print slides mode and get a
2073 //maFirstPageSize for slides which are usually landscape mode, if we
2074 //change to notes which are usually in portrait mode, and then visit
2075 //n-up print, we will assume notes are in landscape unless we throw
2076 //away maFirstPageSize when we change page content type
2077 if (pVal
->Name
== "PageContentType")
2078 maFirstPageSize
= Size();
2080 checkOptionalControlDependencies();
2082 // update preview and page settings
2083 preparePreview(false);
2087 IMPL_LINK( PrintDialog
, UIOption_SpinModifyHdl
, weld::SpinButton
&, i_rBox
, void )
2089 PropertyValue
* pVal
= getValueForWindow( &i_rBox
);
2092 makeEnabled( &i_rBox
);
2094 sal_Int64 nVal
= i_rBox
.get_value();
2095 pVal
->Value
<<= nVal
;
2097 checkOptionalControlDependencies();
2099 // update preview and page settings
2100 preparePreview(false);
2104 IMPL_LINK( PrintDialog
, UIOption_EntryModifyHdl
, weld::Entry
&, i_rBox
, void )
2106 PropertyValue
* pVal
= getValueForWindow( &i_rBox
);
2109 makeEnabled( &i_rBox
);
2111 OUString
aVal( i_rBox
.get_text() );
2112 pVal
->Value
<<= aVal
;
2114 checkOptionalControlDependencies();
2116 // update preview and page settings
2117 preparePreview(false);
2121 void PrintDialog::previewForward()
2123 sal_Int32 nValue
= mxPageEdit
->get_text().toInt32() + 1;
2124 if (nValue
<= mnCachedPages
)
2126 mxPageEdit
->set_text(OUString::number(nValue
));
2127 ActivateHdl(*mxPageEdit
);
2131 void PrintDialog::previewBackward()
2133 sal_Int32 nValue
= mxPageEdit
->get_text().toInt32() - 1;
2136 mxPageEdit
->set_text(OUString::number(nValue
));
2137 ActivateHdl(*mxPageEdit
);
2141 void PrintDialog::previewFirst()
2143 mxPageEdit
->set_text("1");
2144 ActivateHdl(*mxPageEdit
);
2147 void PrintDialog::previewLast()
2149 mxPageEdit
->set_text(OUString::number(mnCachedPages
));
2150 ActivateHdl(*mxPageEdit
);
2153 // PrintProgressDialog
2154 PrintProgressDialog::PrintProgressDialog(weld::Window
* i_pParent
, int i_nMax
)
2155 : GenericDialogController(i_pParent
, "vcl/ui/printprogressdialog.ui", "PrintProgressDialog")
2159 , mxText(m_xBuilder
->weld_label("label"))
2160 , mxProgress(m_xBuilder
->weld_progress_bar("progressbar"))
2161 , mxButton(m_xBuilder
->weld_button("cancel"))
2166 maStr
= mxText
->get_label();
2168 //just multiply largest value by 10 and take the width of that string as
2169 //the max size we will want
2170 OUString
aNewText( maStr
.replaceFirst( "%p", OUString::number( mnMax
* 10 ) ) );
2171 aNewText
= aNewText
.replaceFirst( "%n", OUString::number( mnMax
* 10 ) );
2172 mxText
->set_label( aNewText
);
2173 mxText
->set_size_request(mxText
->get_preferred_size().Width(), -1);
2175 //Pick a useful max width
2176 mxProgress
->set_size_request(mxProgress
->get_approximate_digit_width() * 25, -1);
2178 mxButton
->connect_clicked( LINK( this, PrintProgressDialog
, ClickHdl
) );
2181 PrintProgressDialog::~PrintProgressDialog()
2185 IMPL_LINK_NOARG(PrintProgressDialog
, ClickHdl
, weld::Button
&, void)
2190 void PrintProgressDialog::setProgress( int i_nCurrent
)
2197 mxProgress
->set_percentage(mnCur
*100/mnMax
);
2199 OUString
aNewText( maStr
.replaceFirst( "%p", OUString::number( mnCur
) ) );
2200 aNewText
= aNewText
.replaceFirst( "%n", OUString::number( mnMax
) );
2201 mxText
->set_label( aNewText
);
2204 void PrintProgressDialog::tick()
2207 setProgress( ++mnCur
);
2210 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */