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::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
150 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 55,
151 pDrawingArea
->get_text_height() * 40);
152 CustomWidgetController::SetDrawingArea(pDrawingArea
);
155 void PrintDialog::PrintPreviewWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
157 rRenderContext
.Push();
158 if (vcl::Window
* pDefaultDevice
= dynamic_cast<vcl::Window
*>(Application::GetDefaultDevice()))
160 Font
aFont(rRenderContext
.GetSettings().GetStyleSettings().GetLabelFont());
161 pDefaultDevice
->SetPointFont(rRenderContext
, aFont
);
164 rRenderContext
.SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetDialogColor()));
165 rRenderContext
.Erase();
167 auto nTextHeight
= rRenderContext
.GetTextHeight();
168 Size
aSize(GetOutputSizePixel());
169 Point
aOffset((aSize
.Width() - maPreviewSize
.Width() + nTextHeight
) / 2,
170 (aSize
.Height() - maPreviewSize
.Height() + nTextHeight
) / 2);
174 auto nTop
= aOffset
.Y() - nTextHeight
;
176 auto nWidth
= rRenderContext
.GetTextWidth(maHorzText
);
178 auto nStart
= aOffset
.X() + (maPreviewSize
.Width() - nWidth
) / 2;
179 rRenderContext
.DrawText(Point(nStart
, aOffset
.Y() - nTextHeight
), maHorzText
, 0, maHorzText
.getLength());
181 DecorationView
aDecoView(&rRenderContext
);
182 nTop
= aOffset
.Y() - (nTextHeight
/ 2);
183 aDecoView
.DrawSeparator(Point(aOffset
.X(), nTop
), Point(nStart
- 2, nTop
), false);
184 aDecoView
.DrawSeparator(Point(nStart
+ nWidth
+ 2, nTop
), Point(aOffset
.X() + maPreviewSize
.Width(), nTop
), false);
189 rRenderContext
.Push(PushFlags::FONT
);
190 vcl::Font
aFont(rRenderContext
.GetFont());
191 aFont
.SetOrientation(900);
192 rRenderContext
.SetFont(aFont
);
194 auto nLeft
= aOffset
.X() - nTextHeight
;
196 auto nWidth
= rRenderContext
.GetTextWidth(maVertText
);
197 auto nStart
= aOffset
.Y() + (maPreviewSize
.Height() + nWidth
) / 2;
199 rRenderContext
.DrawText(Point(nLeft
, nStart
), maVertText
, 0, maVertText
.getLength());
201 DecorationView
aDecoView(&rRenderContext
);
202 nLeft
= aOffset
.X() - (nTextHeight
/ 2);
203 aDecoView
.DrawSeparator(Point(nLeft
, aOffset
.Y()), Point(nLeft
, nStart
- nWidth
- 2), true);
204 aDecoView
.DrawSeparator(Point(nLeft
, nStart
+ 2), Point(nLeft
, aOffset
.Y() + maPreviewSize
.Height()), true);
206 rRenderContext
.Pop();
209 if (!maReplacementString
.isEmpty())
211 // replacement is active
212 tools::Rectangle
aTextRect(aOffset
+ Point(2, 2), Size(maPreviewSize
.Width() - 4, maPreviewSize
.Height() - 4));
213 rRenderContext
.DrawText(aTextRect
, maReplacementString
,
214 DrawTextFlags::Center
| DrawTextFlags::VCenter
|
215 DrawTextFlags::WordBreak
| DrawTextFlags::MultiLine
);
219 BitmapEx
aPreviewBitmap(maPreviewBitmap
);
221 // This explicit force-to-scale allows us to get the
222 // mentioned best quality here. Unfortunately this is
223 // currently not sure when using just ::DrawBitmap with
224 // a defined size or ::DrawOutDev
225 aPreviewBitmap
.Scale(maPreviewSize
, BmpScaleFlag::BestQuality
);
226 rRenderContext
.DrawBitmapEx(aOffset
, aPreviewBitmap
);
229 tools::Rectangle
aFrameRect(aOffset
+ Point(-1, -1), Size(maPreviewSize
.Width() + 2, maPreviewSize
.Height() + 2));
230 DecorationView
aDecorationView(&rRenderContext
);
231 aDecorationView
.DrawFrame(aFrameRect
, DrawFrameStyle::Group
);
233 rRenderContext
.Pop();
236 bool PrintDialog::PrintPreviewWindow::Command( const CommandEvent
& rEvt
)
238 if( rEvt
.GetCommand() == CommandEventId::Wheel
)
240 const CommandWheelData
* pWheelData
= rEvt
.GetWheelData();
241 if(pWheelData
->GetDelta() > 0)
242 mpDialog
->previewForward();
243 else if (pWheelData
->GetDelta() < 0)
244 mpDialog
->previewBackward();
247 return CustomWidgetController::Command(rEvt
);
250 void PrintDialog::PrintPreviewWindow::setPreview( const GDIMetaFile
& i_rNewPreview
,
251 const Size
& i_rOrigSize
,
252 const OUString
& i_rPaperName
,
253 const OUString
& i_rReplacement
,
259 maMtf
= i_rNewPreview
;
262 maOrigSize
= i_rOrigSize
;
263 maReplacementString
= i_rReplacement
;
264 mbGreyscale
= i_bGreyscale
;
266 // use correct measurements
267 const LocaleDataWrapper
& rLocWrap(Application::GetSettings().GetLocaleDataWrapper());
268 MapUnit eUnit
= MapUnit::MapMM
;
270 if( rLocWrap
.getMeasurementSystemEnum() == MeasurementSystem::US
)
272 eUnit
= MapUnit::Map100thInch
;
275 Size
aLogicPaperSize(OutputDevice::LogicToLogic(i_rOrigSize
, MapMode(MapUnit::Map100thMM
), MapMode(eUnit
)));
276 OUString
aNumText( rLocWrap
.getNum( aLogicPaperSize
.Width(), nDigits
) );
278 aBuf
.append( aNumText
)
280 aBuf
.appendAscii( eUnit
== MapUnit::MapMM
? "mm" : "in" );
281 if( !i_rPaperName
.isEmpty() )
284 aBuf
.append( i_rPaperName
);
287 maHorzText
= aBuf
.makeStringAndClear();
289 aNumText
= rLocWrap
.getNum( aLogicPaperSize
.Height(), nDigits
);
290 aBuf
.append( aNumText
)
292 aBuf
.appendAscii( eUnit
== MapUnit::MapMM
? "mm" : "in" );
293 maVertText
= aBuf
.makeStringAndClear();
295 // We have a new Metafile and evtl. a new page, so we need to reset
296 // the PreviewBitmap to force new creation
297 maPreviewBitmap
= Bitmap();
299 // sets/calculates e.g. maPreviewSize
300 // also triggers preparePreviewBitmap()
306 void PrintDialog::PrintPreviewWindow::preparePreviewBitmap()
308 if(maPreviewSize
.getWidth() < 0 || maPreviewSize
.getHeight() < 0)
310 // not yet fully initialized, no need to prepare anything
314 // define an allowed number of pixels, also see
315 // defaults for primitive renderers and similar. This
316 // might be centralized and made dependent of 32/64bit
317 const sal_uInt32
nMaxSquarePixels(500000);
319 // check how big (squarePixels) the preview is currently (with
320 // max value of MaxSquarePixels)
321 const sal_uInt32
nCurrentSquarePixels(
324 static_cast<sal_uInt32
>(maPreviewBitmap
.GetSizePixel().getWidth())
325 * static_cast<sal_uInt32
>(maPreviewBitmap
.GetSizePixel().getHeight())));
327 // check how big (squarePixels) the preview needs to be (with
328 // max value of MaxSquarePixels)
329 const sal_uInt32
nRequiredSquarePixels(
332 static_cast<sal_uInt32
>(maPreviewSize
.getWidth())
333 * static_cast<sal_uInt32
>(maPreviewSize
.getHeight())));
335 // check if preview is big enough. Use a scaling value in
336 // the comparison to not get bigger at the last possible moment
337 // what may look awkward and pixelated (again). This means
338 // to use a percentage value - if we have at least
339 // that value of required pixels, we are good.
340 static const double fPreventAwkwardFactor(1.35); // 35%
341 if(nCurrentSquarePixels
>= static_cast<sal_uInt32
>(nRequiredSquarePixels
* fPreventAwkwardFactor
))
343 // at this place we also could add a mechanism to let the preview
344 // bitmap 'shrink' again if it is currently 'too big' -> bigger
345 // than required. I think this is not necessary for now.
347 // already sufficient, done.
351 // check if we have enough square pixels e.g for 8x8 pixels
352 if(nRequiredSquarePixels
< 64)
354 // too small preview - let it empty
358 // Calculate nPlannedSquarePixels which is the required size
359 // expanded by a percentage (with max value of MaxSquarePixels)
360 static const double fExtraSpaceFactor(1.65); // 65%
361 const sal_uInt32
nPlannedSquarePixels(
364 static_cast<sal_uInt32
>(maPreviewSize
.getWidth() * fExtraSpaceFactor
)
365 * static_cast<sal_uInt32
>(maPreviewSize
.getHeight() * fExtraSpaceFactor
)));
367 // calculate back new width and height - it might have been
368 // truncated by MaxSquarePixels.
369 // We know that w*h == nPlannedSquarePixels and w/h == ratio
370 const double fRatio(static_cast<double>(maPreviewSize
.getWidth()) / static_cast<double>(maPreviewSize
.getHeight()));
371 const double fNewWidth(sqrt(static_cast<double>(nPlannedSquarePixels
) * fRatio
));
372 const double fNewHeight(sqrt(static_cast<double>(nPlannedSquarePixels
) / fRatio
));
373 const Size
aScaledSize(basegfx::fround(fNewWidth
), basegfx::fround(fNewHeight
));
375 // check if this eventual maximum is already reached
376 // due to having hit the MaxSquarePixels. Due to using
377 // an integer AspectRatio, we cannot make a numeric exact
378 // comparison - we need to compare if we are close
379 const double fScaledSizeSquare(static_cast<double>(aScaledSize
.getWidth() * aScaledSize
.getHeight()));
380 const double fPreviewSizeSquare(static_cast<double>(maPreviewBitmap
.GetSizePixel().getWidth() * maPreviewBitmap
.GetSizePixel().getHeight()));
382 // test as equal up to 0.1% (0.001)
383 if(fPreviewSizeSquare
!= 0.0 && fabs((fScaledSizeSquare
/ fPreviewSizeSquare
) - 1.0) < 0.001)
385 // maximum is reached, avoid bigger scaling
389 // create temporary VDev and render to it
390 ScopedVclPtrInstance
<VirtualDevice
> pPrerenderVDev(*Application::GetDefaultDevice());
391 pPrerenderVDev
->SetOutputSizePixel(aScaledSize
, false);
392 pPrerenderVDev
->SetReferenceDevice( mnDPIX
, mnDPIY
);
393 pPrerenderVDev
->EnableOutput();
394 pPrerenderVDev
->SetBackground( Wallpaper(COL_WHITE
) );
396 GDIMetaFile
aMtf( maMtf
);
398 Size
aVDevSize( pPrerenderVDev
->GetOutputSizePixel() );
399 const Size
aLogicSize( pPrerenderVDev
->PixelToLogic( aVDevSize
, MapMode( MapUnit::Map100thMM
) ) );
400 Size
aOrigSize( maOrigSize
);
401 if( aOrigSize
.Width() < 1 )
402 aOrigSize
.setWidth( aLogicSize
.Width() );
403 if( aOrigSize
.Height() < 1 )
404 aOrigSize
.setHeight( aLogicSize
.Height() );
405 double fScale
= double(aLogicSize
.Width())/double(aOrigSize
.Width());
407 pPrerenderVDev
->Erase();
408 pPrerenderVDev
->Push();
409 pPrerenderVDev
->SetMapMode(MapMode(MapUnit::Map100thMM
));
410 DrawModeFlags nOldDrawMode
= pPrerenderVDev
->GetDrawMode();
412 pPrerenderVDev
->SetDrawMode( pPrerenderVDev
->GetDrawMode() |
413 ( DrawModeFlags::GrayLine
| DrawModeFlags::GrayFill
| DrawModeFlags::GrayText
|
414 DrawModeFlags::GrayBitmap
| DrawModeFlags::GrayGradient
) );
416 aMtf
.Scale( fScale
, fScale
);
419 const AntialiasingFlags
nOriginalAA(pPrerenderVDev
->GetAntialiasing());
420 pPrerenderVDev
->SetAntialiasing(nOriginalAA
| AntialiasingFlags::EnableB2dDraw
);
421 aMtf
.Play( pPrerenderVDev
.get(), Point( 0, 0 ), aLogicSize
);
422 pPrerenderVDev
->SetAntialiasing(nOriginalAA
);
424 pPrerenderVDev
->Pop();
426 pPrerenderVDev
->SetMapMode(MapMode(MapUnit::MapPixel
));
428 maPreviewBitmap
= pPrerenderVDev
->GetBitmapEx(Point(0, 0), aVDevSize
);
430 pPrerenderVDev
->SetDrawMode( nOldDrawMode
);
433 PrintDialog::ShowNupOrderWindow::ShowNupOrderWindow()
434 : mnOrderMode( NupOrderType::LRTB
)
440 void PrintDialog::ShowNupOrderWindow::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
443 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
444 CustomWidgetController::SetDrawingArea(pDrawingArea
);
445 SetOutputSizePixel(aSize
);
448 void PrintDialog::ShowNupOrderWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*i_rRect*/)
450 rRenderContext
.SetMapMode(MapMode(MapUnit::MapPixel
));
451 rRenderContext
.SetTextColor(rRenderContext
.GetSettings().GetStyleSettings().GetFieldTextColor());
452 rRenderContext
.SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetFieldColor()));
453 rRenderContext
.Erase();
455 int nPages
= mnRows
* mnColumns
;
456 Font
aFont(rRenderContext
.GetSettings().GetStyleSettings().GetFieldFont());
457 aFont
.SetFontSize(Size(0, 24));
458 rRenderContext
.SetFont(aFont
);
459 Size
aSampleTextSize(rRenderContext
.GetTextWidth(OUString::number(nPages
+ 1)), rRenderContext
.GetTextHeight());
460 Size
aOutSize(GetOutputSizePixel());
461 Size
aSubSize(aOutSize
.Width() / mnColumns
, aOutSize
.Height() / mnRows
);
462 // calculate font size: shrink the sample text so it fits
463 double fX
= double(aSubSize
.Width()) / double(aSampleTextSize
.Width());
464 double fY
= double(aSubSize
.Height()) / double(aSampleTextSize
.Height());
465 double fScale
= (fX
< fY
) ? fX
: fY
;
466 long nFontHeight
= long(24.0 * fScale
) - 3;
469 aFont
.SetFontSize(Size( 0, nFontHeight
));
470 rRenderContext
.SetFont(aFont
);
471 long nTextHeight
= rRenderContext
.GetTextHeight();
472 for (int i
= 0; i
< nPages
; i
++)
474 OUString
aPageText(OUString::number(i
+ 1));
478 case NupOrderType::LRTB
:
479 nX
= (i
% mnColumns
);
480 nY
= (i
/ mnColumns
);
482 case NupOrderType::TBLR
:
486 case NupOrderType::RLTB
:
487 nX
= mnColumns
- 1 - (i
% mnColumns
);
488 nY
= (i
/ mnColumns
);
490 case NupOrderType::TBRL
:
491 nX
= mnColumns
- 1 - (i
/ mnRows
);
495 Size
aTextSize(rRenderContext
.GetTextWidth(aPageText
), nTextHeight
);
496 int nDeltaX
= (aSubSize
.Width() - aTextSize
.Width()) / 2;
497 int nDeltaY
= (aSubSize
.Height() - aTextSize
.Height()) / 2;
498 rRenderContext
.DrawText(Point(nX
* aSubSize
.Width() + nDeltaX
,
499 nY
* aSubSize
.Height() + nDeltaY
), aPageText
);
501 DecorationView
aDecorationView(&rRenderContext
);
502 aDecorationView
.DrawFrame(tools::Rectangle(Point(0, 0), aOutSize
), DrawFrameStyle::Group
);
505 Size
const & PrintDialog::getJobPageSize()
507 if( maFirstPageSize
.Width() == 0 && maFirstPageSize
.Height() == 0)
509 maFirstPageSize
= maNupPortraitSize
;
511 if( maPController
->getPageCountProtected() > 0 )
513 PrinterController::PageSize aPageSize
= maPController
->getPageFile( 0, aMtf
, true );
514 maFirstPageSize
= aPageSize
.aSize
;
517 return maFirstPageSize
;
520 PrintDialog::PrintDialog(weld::Window
* i_pWindow
, const std::shared_ptr
<PrinterController
>& i_rController
)
521 : GenericDialogController(i_pWindow
, "vcl/ui/printdialog.ui", "PrintDialog")
522 , maPController( i_rController
)
523 , mxTabCtrl(m_xBuilder
->weld_notebook("tabcontrol"))
524 , mxPageLayoutFrame(m_xBuilder
->weld_frame("layoutframe"))
525 , mxPrinters(m_xBuilder
->weld_combo_box("printersbox"))
526 , mxStatusTxt(m_xBuilder
->weld_label("status"))
527 , mxSetupButton(m_xBuilder
->weld_button("setup"))
528 , mxCopyCountField(m_xBuilder
->weld_spin_button("copycount"))
529 , mxCollateBox(m_xBuilder
->weld_check_button("collate"))
530 , mxCollateImage(m_xBuilder
->weld_image("collateimage"))
531 , mxPageRangeEdit(m_xBuilder
->weld_entry("pagerange"))
532 , mxPageRangesRadioButton(m_xBuilder
->weld_radio_button("rbRangePages"))
533 , mxPaperSidesBox(m_xBuilder
->weld_combo_box("sidesbox"))
534 , mxReverseOrderBox(m_xBuilder
->weld_check_button("reverseorder"))
535 , mxOKButton(m_xBuilder
->weld_button("ok"))
536 , mxCancelButton(m_xBuilder
->weld_button("cancel"))
537 , mxHelpButton(m_xBuilder
->weld_button("help"))
538 , mxMoreOptionsBtn(m_xBuilder
->weld_button("moreoptionsbtn"))
539 , mxBackwardBtn(m_xBuilder
->weld_button("backward"))
540 , mxForwardBtn(m_xBuilder
->weld_button("forward"))
541 , mxFirstBtn(m_xBuilder
->weld_button("btnFirst"))
542 , mxLastBtn(m_xBuilder
->weld_button("btnLast"))
543 , mxPreviewBox(m_xBuilder
->weld_check_button("previewbox"))
544 , mxNumPagesText(m_xBuilder
->weld_label("totalnumpages"))
545 , mxPreview(new PrintPreviewWindow(this))
546 , mxPreviewWindow(new weld::CustomWeld(*m_xBuilder
, "preview", *mxPreview
))
547 , mxPageEdit(m_xBuilder
->weld_entry("pageedit-nospin"))
548 , mxPagesBtn(m_xBuilder
->weld_radio_button("pagespersheetbtn"))
549 , mxBrochureBtn(m_xBuilder
->weld_radio_button("brochure"))
550 , mxPagesBoxTitleTxt(m_xBuilder
->weld_label("pagespersheettxt"))
551 , mxNupPagesBox(m_xBuilder
->weld_combo_box("pagespersheetbox"))
552 , mxNupNumPagesTxt(m_xBuilder
->weld_label("pagestxt"))
553 , mxNupColEdt(m_xBuilder
->weld_spin_button("pagecols"))
554 , mxNupTimesTxt(m_xBuilder
->weld_label("by"))
555 , mxNupRowsEdt(m_xBuilder
->weld_spin_button("pagerows"))
556 , mxPageMarginTxt1(m_xBuilder
->weld_label("pagemargintxt1"))
557 , mxPageMarginEdt(m_xBuilder
->weld_metric_spin_button("pagemarginsb", FieldUnit::MM
))
558 , mxPageMarginTxt2(m_xBuilder
->weld_label("pagemargintxt2"))
559 , mxSheetMarginTxt1(m_xBuilder
->weld_label("sheetmargintxt1"))
560 , mxSheetMarginEdt(m_xBuilder
->weld_metric_spin_button("sheetmarginsb", FieldUnit::MM
))
561 , mxSheetMarginTxt2(m_xBuilder
->weld_label("sheetmargintxt2"))
562 , mxPaperSizeBox(m_xBuilder
->weld_combo_box("papersizebox"))
563 , mxOrientationBox(m_xBuilder
->weld_combo_box("pageorientationbox"))
564 , mxNupOrderTxt(m_xBuilder
->weld_label("labelorder"))
565 , mxNupOrderBox(m_xBuilder
->weld_combo_box("orderbox"))
566 , mxNupOrder(new ShowNupOrderWindow
)
567 , mxNupOrderWin(new weld::CustomWeld(*m_xBuilder
, "orderpreview", *mxNupOrder
))
568 , mxBorderCB(m_xBuilder
->weld_check_button("bordercb"))
569 , mxCustom(m_xBuilder
->weld_widget("customcontents"))
570 , maPrintToFileText( VclResId( SV_PRINT_TOFILE_TXT
) )
571 , maDefPrtText( VclResId( SV_PRINT_DEFPRT_TXT
) )
572 , maNoPageStr( VclResId( SV_PRINT_NOPAGES
) )
573 , maNoPreviewStr( VclResId( SV_PRINT_NOPREVIEW
) )
576 , mbCollateAlwaysOff(false)
577 , mbShowLayoutFrame( true )
578 , mbSingleJobs( false )
580 // save printbutton text, gets exchanged occasionally with print to file
581 maPrintText
= mxOKButton
->get_label();
583 maPageStr
= mxNumPagesText
->get_label();
585 Printer::updatePrinters();
587 mxPrinters
->append_text(maPrintToFileText
);
588 // fill printer listbox
589 std::vector
< OUString
> rQueues( Printer::GetPrinterQueues() );
590 std::sort( rQueues
.begin(), rQueues
.end(), lcl_ListBoxCompare
);
591 for( const auto& rQueue
: rQueues
)
593 mxPrinters
->append_text(rQueue
);
595 // select current printer
596 if (mxPrinters
->find_text(maPController
->getPrinter()->GetName()) != -1)
597 mxPrinters
->set_active_text(maPController
->getPrinter()->GetName());
600 // fall back to last printer
601 SettingsConfigItem
* pItem
= SettingsConfigItem::get();
602 OUString
aValue( pItem
->getValue( "PrintDialog",
604 if (mxPrinters
->find_text(aValue
) != -1)
606 mxPrinters
->set_active_text(aValue
);
607 maPController
->setPrinter( VclPtrInstance
<Printer
>( aValue
) );
611 // fall back to default printer
612 mxPrinters
->set_active_text(Printer::GetDefaultPrinterName());
613 maPController
->setPrinter( VclPtrInstance
<Printer
>( Printer::GetDefaultPrinterName() ) );
617 // not printing to file
618 maPController
->resetPrinterOptions( false );
620 // update the text fields for the printer
623 // set paper sizes listbox
626 // setup dependencies
627 checkControlDependencies();
629 // setup paper sides box
630 setupPaperSidesBox();
632 // set initial focus to "Number of copies"
633 mxCopyCountField
->grab_focus();
634 mxCopyCountField
->select_region(0, -1);
636 // setup sizes for N-Up
637 Size
aNupSize( maPController
->getPrinter()->PixelToLogic(
638 maPController
->getPrinter()->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM
) ) );
639 if( maPController
->getPrinter()->GetOrientation() == Orientation::Landscape
)
641 maNupLandscapeSize
= aNupSize
;
642 // coverity[swapped_arguments : FALSE] - this is in the correct order
643 maNupPortraitSize
= Size( aNupSize
.Height(), aNupSize
.Width() );
647 maNupPortraitSize
= aNupSize
;
648 // coverity[swapped_arguments : FALSE] - this is in the correct order
649 maNupLandscapeSize
= Size( aNupSize
.Height(), aNupSize
.Width() );
652 initFromMultiPageSetup( maPController
->getMultipage() );
654 // setup optional UI options set by application
657 // hide layout frame if unwanted
658 mxPageLayoutFrame
->set_visible(mbShowLayoutFrame
);
660 // restore settings from last run
664 mxOKButton
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
665 mxCancelButton
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
666 mxHelpButton
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
667 mxSetupButton
->connect_clicked( LINK( this, PrintDialog
, ClickHdl
) );
668 mxMoreOptionsBtn
->connect_clicked( LINK( this, PrintDialog
, ClickHdl
) );
669 mxBackwardBtn
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
670 mxForwardBtn
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
671 mxFirstBtn
->connect_clicked(LINK(this, PrintDialog
, ClickHdl
));
672 mxLastBtn
->connect_clicked( LINK( this, PrintDialog
, ClickHdl
) );
673 mxPreviewBox
->connect_clicked( LINK( this, PrintDialog
, ClickHdl
) );
674 mxBorderCB
->connect_clicked( LINK( this, PrintDialog
, ClickHdl
) );
677 mxReverseOrderBox
->connect_toggled( LINK( this, PrintDialog
, ToggleHdl
) );
678 mxCollateBox
->connect_toggled( LINK( this, PrintDialog
, ToggleHdl
) );
679 mxPagesBtn
->connect_toggled( LINK( this, PrintDialog
, ToggleHdl
) );
682 mxPrinters
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
683 mxPaperSidesBox
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
684 mxNupPagesBox
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
685 mxOrientationBox
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
686 mxNupOrderBox
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
687 mxPaperSizeBox
->connect_changed( LINK( this, PrintDialog
, SelectHdl
) );
690 mxPageEdit
->connect_activate( LINK( this, PrintDialog
, ActivateHdl
) );
691 mxPageEdit
->connect_focus_out( LINK( this, PrintDialog
, FocusOutHdl
) );
692 mxCopyCountField
->connect_value_changed( LINK( this, PrintDialog
, SpinModifyHdl
) );
693 mxNupColEdt
->connect_value_changed( LINK( this, PrintDialog
, SpinModifyHdl
) );
694 mxNupRowsEdt
->connect_value_changed( LINK( this, PrintDialog
, SpinModifyHdl
) );
695 mxPageMarginEdt
->connect_value_changed( LINK( this, PrintDialog
, MetricSpinModifyHdl
) );
696 mxSheetMarginEdt
->connect_value_changed( LINK( this, PrintDialog
, MetricSpinModifyHdl
) );
698 updateNupFromPages();
702 PrintDialog::~PrintDialog()
706 void PrintDialog::setupPaperSidesBox()
708 DuplexMode eDuplex
= maPController
->getPrinter()->GetDuplexMode();
710 if ( eDuplex
== DuplexMode::Unknown
|| isPrintToFile() )
712 mxPaperSidesBox
->set_active( 0 );
713 mxPaperSidesBox
->set_sensitive( false );
717 mxPaperSidesBox
->set_active( static_cast<sal_Int32
>(eDuplex
) - 1 );
718 mxPaperSidesBox
->set_sensitive( true );
722 void PrintDialog::storeToSettings()
724 SettingsConfigItem
* pItem
= SettingsConfigItem::get();
726 pItem
->setValue( "PrintDialog",
728 isPrintToFile() ? Printer::GetDefaultPrinterName()
729 : mxPrinters
->get_active_text() );
731 pItem
->setValue( "PrintDialog",
733 mxTabCtrl
->get_tab_label_text(mxTabCtrl
->get_current_page_ident()));
735 pItem
->setValue( "PrintDialog",
737 OStringToOUString(m_xDialog
->get_window_state(WindowStateMask::All
), RTL_TEXTENCODING_UTF8
) );
739 pItem
->setValue( "PrintDialog",
741 mxCopyCountField
->get_text() );
743 pItem
->setValue( "PrintDialog",
745 mxCollateBox
->get_active() ? OUString("true") :
748 pItem
->setValue( "PrintDialog",
750 mbSingleJobs
? OUString("true") :
753 pItem
->setValue( "PrintDialog",
755 hasPreview() ? OUString("true") :
761 void PrintDialog::readFromSettings()
763 SettingsConfigItem
* pItem
= SettingsConfigItem::get();
765 // read last selected tab page; if it exists, activate it
766 OUString aValue
= pItem
->getValue( "PrintDialog",
768 sal_uInt16 nCount
= mxTabCtrl
->get_n_pages();
769 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
771 OString sPageId
= mxTabCtrl
->get_page_ident(i
);
772 if (aValue
== mxTabCtrl
->get_tab_label_text(sPageId
))
774 mxTabCtrl
->set_current_page(sPageId
);
779 // persistent window state
780 aValue
= pItem
->getValue( "PrintDialog",
782 if (!aValue
.isEmpty())
783 m_xDialog
->set_window_state(OUStringToOString(aValue
, RTL_TEXTENCODING_UTF8
));
786 aValue
= pItem
->getValue( "PrintDialog",
788 if( aValue
.equalsIgnoreAsciiCase("alwaysoff") )
790 mbCollateAlwaysOff
= true;
791 mxCollateBox
->set_active( false );
792 mxCollateBox
->set_sensitive( false );
796 mbCollateAlwaysOff
= false;
797 aValue
= pItem
->getValue( "PrintDialog",
799 mxCollateBox
->set_active( aValue
.equalsIgnoreAsciiCase("true") );
802 // collate single jobs
803 aValue
= pItem
->getValue( "PrintDialog",
804 "CollateSingleJobs" );
805 if ( aValue
.equalsIgnoreAsciiCase("true") )
808 mbSingleJobs
= false;
811 aValue
= pItem
->getValue( "PrintDialog",
813 if ( aValue
.equalsIgnoreAsciiCase("false") )
814 mxPreviewBox
->set_active( false );
816 mxPreviewBox
->set_active( true );
820 void PrintDialog::setPaperSizes()
822 mxPaperSizeBox
->clear();
824 VclPtr
<Printer
> aPrt( maPController
->getPrinter() );
825 mePaper
= aPrt
->GetPaper();
827 if ( isPrintToFile() )
829 mxPaperSizeBox
->set_sensitive( false );
833 for (int nPaper
= 0; nPaper
< aPrt
->GetPaperInfoCount(); nPaper
++)
835 PaperInfo aInfo
= aPrt
->GetPaperInfo( nPaper
);
837 Paper ePaper
= aInfo
.getPaper();
839 const LocaleDataWrapper
& rLocWrap(Application::GetSettings().GetLocaleDataWrapper());
840 MapUnit eUnit
= MapUnit::MapMM
;
842 if( rLocWrap
.getMeasurementSystemEnum() == MeasurementSystem::US
)
844 eUnit
= MapUnit::Map100thInch
;
847 Size aSize
= aPrt
->GetPaperSize( nPaper
);
848 Size
aLogicPaperSize( OutputDevice::LogicToLogic( aSize
, MapMode( MapUnit::Map100thMM
), MapMode( eUnit
) ) );
850 OUString
aWidth( rLocWrap
.getNum( aLogicPaperSize
.Width(), nDigits
) );
851 OUString
aHeight( rLocWrap
.getNum( aLogicPaperSize
.Height(), nDigits
) );
852 OUString aUnit
= eUnit
== MapUnit::MapMM
? OUString("mm") : OUString("in");
853 OUString aPaperName
= Printer::GetPaperName( ePaper
) + " " + aWidth
+ aUnit
+ " x " + aHeight
+ aUnit
;
855 mxPaperSizeBox
->append_text(aPaperName
);
857 if ( ePaper
== mePaper
)
858 mxPaperSizeBox
->set_active( nPaper
);
861 mxPaperSizeBox
->set_sensitive( true );
865 void PrintDialog::updatePrinterText()
867 const OUString
aDefPrt( Printer::GetDefaultPrinterName() );
868 const QueueInfo
* pInfo
= Printer::GetQueueInfo( mxPrinters
->get_active_text(), true );
871 // FIXME: status text
873 if( aDefPrt
== pInfo
->GetPrinterName() )
874 aStatus
= maDefPrtText
;
875 mxStatusTxt
->set_label( aStatus
);
879 mxStatusTxt
->set_label( OUString() );
883 void PrintDialog::setPreviewText()
885 OUString
aNewText( maPageStr
.replaceFirst( "%n", OUString::number( mnCachedPages
) ) );
886 mxNumPagesText
->set_label( aNewText
);
889 void PrintDialog::preparePreview( bool i_bMayUseCache
)
891 VclPtr
<Printer
> aPrt( maPController
->getPrinter() );
892 Size aCurPageSize
= aPrt
->PixelToLogic( aPrt
->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM
) );
893 // tdf#123076 Get paper size for the preview top label
894 mePaper
= aPrt
->GetPaper();
897 // page range may have changed depending on options
898 sal_Int32 nPages
= maPController
->getFilteredPageCount();
899 mnCachedPages
= nPages
;
905 mxPreview
->setPreview( aMtf
, aCurPageSize
,
906 Printer::GetPaperName( mePaper
),
908 aPrt
->GetDPIX(), aPrt
->GetDPIY(),
909 aPrt
->GetPrinterOptions().IsConvertToGreyscales()
912 mxForwardBtn
->set_sensitive( false );
913 mxBackwardBtn
->set_sensitive( false );
914 mxFirstBtn
->set_sensitive( false );
915 mxLastBtn
->set_sensitive( false );
917 mxPageEdit
->set_sensitive( false );
922 if( mnCurPage
>= nPages
)
923 mnCurPage
= nPages
-1;
928 const MapMode
aMapMode( MapUnit::Map100thMM
);
931 PrinterController::PageSize aPageSize
=
932 maPController
->getFilteredPageFile( mnCurPage
, aMtf
, i_bMayUseCache
);
933 if( ! aPageSize
.bFullPaper
)
935 Point
aOff( aPrt
->PixelToLogic( aPrt
->GetPageOffsetPixel(), aMapMode
) );
936 aMtf
.Move( aOff
.X(), aOff
.Y() );
940 mxPreview
->setPreview( aMtf
, aCurPageSize
,
941 Printer::GetPaperName( mePaper
),
942 nPages
> 0 ? OUString() : maNoPageStr
,
943 aPrt
->GetDPIX(), aPrt
->GetDPIY(),
944 aPrt
->GetPrinterOptions().IsConvertToGreyscales()
947 mxForwardBtn
->set_sensitive( mnCurPage
< nPages
-1 );
948 mxBackwardBtn
->set_sensitive( mnCurPage
!= 0 );
949 mxFirstBtn
->set_sensitive( mnCurPage
!= 0 );
950 mxLastBtn
->set_sensitive( mnCurPage
< nPages
-1 );
951 mxPageEdit
->set_sensitive( nPages
> 1 );
954 void PrintDialog::updateOrientationBox( const bool bAutomatic
)
958 Orientation eOrientation
= maPController
->getPrinter()->GetOrientation();
959 mxOrientationBox
->set_active( static_cast<sal_Int32
>(eOrientation
) + 1 );
961 else if ( hasOrientationChanged() )
963 mxOrientationBox
->set_active( ORIENTATION_AUTOMATIC
);
967 bool PrintDialog::hasOrientationChanged() const
969 const int nOrientation
= mxOrientationBox
->get_active();
970 const Orientation eOrientation
= maPController
->getPrinter()->GetOrientation();
972 return (nOrientation
== ORIENTATION_LANDSCAPE
&& eOrientation
== Orientation::Portrait
)
973 || (nOrientation
== ORIENTATION_PORTRAIT
&& eOrientation
== Orientation::Landscape
);
976 // make sure paper size matches paper orientation
977 void PrintDialog::checkPaperSize( Size
& rPaperSize
)
979 Orientation eOrientation
= maPController
->getPrinter()->GetOrientation();
980 if ( (eOrientation
== Orientation::Portrait
&& rPaperSize
.Width() > rPaperSize
.Height()) ||
981 (eOrientation
== Orientation::Landscape
&& rPaperSize
.Width() < rPaperSize
.Height()) )
983 // coverity[swapped-arguments : FALSE] - this is in the correct order
984 rPaperSize
= Size( rPaperSize
.Height(), rPaperSize
.Width() );
988 // Always use this function to set paper orientation to make sure everything behaves well
989 void PrintDialog::setPaperOrientation( Orientation eOrientation
)
991 VclPtr
<Printer
> aPrt( maPController
->getPrinter() );
992 aPrt
->SetOrientation( eOrientation
);
994 // check if it's necessary to swap width and height of paper
995 if ( maPController
->isPaperSizeFromUser() )
997 Size
& aPaperSize
= maPController
->getPaperSizeFromUser();
998 checkPaperSize( aPaperSize
);
1000 else if ( maPController
->getPapersizeFromSetup() )
1002 Size
& aPaperSize
= maPController
->getPaperSizeSetup();
1003 checkPaperSize( aPaperSize
);
1007 void PrintDialog::checkControlDependencies()
1009 if (mxCopyCountField
->get_value() > 1)
1010 mxCollateBox
->set_sensitive( !mbCollateAlwaysOff
);
1012 mxCollateBox
->set_sensitive( false );
1014 OUString
aImg(mxCollateBox
->get_active() ? OUString(SV_PRINT_COLLATE_BMP
) : OUString(SV_PRINT_NOCOLLATE_BMP
));
1016 mxCollateImage
->set_from_icon_name(aImg
);
1018 // enable setup button only for printers that can be setup
1019 bool bHaveSetup
= maPController
->getPrinter()->HasSupport( PrinterSupport::SetupDialog
);
1020 mxSetupButton
->set_sensitive(bHaveSetup
);
1023 void PrintDialog::checkOptionalControlDependencies()
1025 for( const auto& rEntry
: maControlToPropertyMap
)
1027 bool bShouldbeEnabled
= maPController
->isUIOptionEnabled( rEntry
.second
);
1029 if (bShouldbeEnabled
&& dynamic_cast<weld::RadioButton
*>(rEntry
.first
))
1031 auto r_it
= maControlToNumValMap
.find( rEntry
.first
);
1032 if( r_it
!= maControlToNumValMap
.end() )
1034 bShouldbeEnabled
= maPController
->isUIChoiceEnabled( rEntry
.second
, r_it
->second
);
1038 bool bIsEnabled
= rEntry
.first
->get_sensitive();
1039 // Enable does not do a change check first, so can be less cheap than expected
1040 if (bShouldbeEnabled
!= bIsEnabled
)
1041 rEntry
.first
->set_sensitive( bShouldbeEnabled
);
1045 void PrintDialog::initFromMultiPageSetup( const vcl::PrinterController::MultiPageSetup
& i_rMPS
)
1047 mxNupOrderWin
->show();
1048 mxPagesBtn
->set_active(true);
1049 mxBrochureBtn
->hide();
1051 // setup field units for metric fields
1052 const LocaleDataWrapper
& rLocWrap(Application::GetSettings().GetLocaleDataWrapper());
1053 FieldUnit eUnit
= FieldUnit::MM
;
1054 sal_uInt16 nDigits
= 0;
1055 if( rLocWrap
.getMeasurementSystemEnum() == MeasurementSystem::US
)
1057 eUnit
= FieldUnit::INCH
;
1061 mxPageMarginEdt
->set_unit( eUnit
);
1062 mxSheetMarginEdt
->set_unit( eUnit
);
1065 mxPageMarginEdt
->set_digits( nDigits
);
1066 mxSheetMarginEdt
->set_digits( nDigits
);
1068 mxSheetMarginEdt
->set_value( mxSheetMarginEdt
->normalize( i_rMPS
.nLeftMargin
), FieldUnit::MM_100TH
);
1069 mxPageMarginEdt
->set_value( mxPageMarginEdt
->normalize( i_rMPS
.nHorizontalSpacing
), FieldUnit::MM_100TH
);
1070 mxBorderCB
->set_active( i_rMPS
.bDrawBorder
);
1071 mxNupRowsEdt
->set_value( i_rMPS
.nRows
);
1072 mxNupColEdt
->set_value( i_rMPS
.nColumns
);
1073 mxNupOrderBox
->set_active( static_cast<sal_Int32
>(i_rMPS
.nOrder
) );
1074 if( i_rMPS
.nRows
!= 1 || i_rMPS
.nColumns
!= 1 )
1076 mxNupPagesBox
->set_active( mxNupPagesBox
->get_count()-1 );
1077 showAdvancedControls( true );
1078 mxNupOrder
->setValues( i_rMPS
.nOrder
, i_rMPS
.nColumns
, i_rMPS
.nRows
);
1082 void PrintDialog::updateNup( bool i_bMayUseCache
)
1084 int nRows
= mxNupRowsEdt
->get_value();
1085 int nCols
= mxNupColEdt
->get_value();
1086 long nPageMargin
= mxPageMarginEdt
->denormalize(mxPageMarginEdt
->get_value( FieldUnit::MM_100TH
));
1087 long nSheetMargin
= mxSheetMarginEdt
->denormalize(mxSheetMarginEdt
->get_value( FieldUnit::MM_100TH
));
1089 PrinterController::MultiPageSetup aMPS
;
1091 aMPS
.nColumns
= nCols
;
1095 aMPS
.nBottomMargin
= nSheetMargin
;
1097 aMPS
.nHorizontalSpacing
=
1098 aMPS
.nVerticalSpacing
= nPageMargin
;
1100 aMPS
.bDrawBorder
= mxBorderCB
->get_active();
1102 aMPS
.nOrder
= static_cast<NupOrderType
>(mxNupOrderBox
->get_active());
1104 int nOrientationMode
= mxOrientationBox
->get_active();
1105 if( nOrientationMode
== ORIENTATION_LANDSCAPE
)
1106 aMPS
.aPaperSize
= maNupLandscapeSize
;
1107 else if( nOrientationMode
== ORIENTATION_PORTRAIT
)
1108 aMPS
.aPaperSize
= maNupPortraitSize
;
1109 else // automatic mode
1111 // get size of first real page to see if it is portrait or landscape
1112 // we assume same page sizes for all the pages for this
1113 Size aPageSize
= getJobPageSize();
1115 Size
aMultiSize( aPageSize
.Width() * nCols
, aPageSize
.Height() * nRows
);
1116 if( aMultiSize
.Width() > aMultiSize
.Height() ) // fits better on landscape
1118 aMPS
.aPaperSize
= maNupLandscapeSize
;
1119 setPaperOrientation( Orientation::Landscape
);
1123 aMPS
.aPaperSize
= maNupPortraitSize
;
1124 setPaperOrientation( Orientation::Portrait
);
1128 maPController
->setMultipage( aMPS
);
1130 mxNupOrder
->setValues( aMPS
.nOrder
, nCols
, nRows
);
1132 preparePreview( i_bMayUseCache
);
1135 void PrintDialog::updateNupFromPages( bool i_bMayUseCache
)
1137 int nPages
= mxNupPagesBox
->get_active_id().toInt32();
1138 int nRows
= mxNupRowsEdt
->get_value();
1139 int nCols
= mxNupColEdt
->get_value();
1140 long nPageMargin
= mxPageMarginEdt
->denormalize(mxPageMarginEdt
->get_value( FieldUnit::MM_100TH
));
1141 long nSheetMargin
= mxSheetMarginEdt
->denormalize(mxSheetMarginEdt
->get_value( FieldUnit::MM_100TH
));
1142 bool bCustom
= false;
1150 else if( nPages
== 2 || nPages
== 4 || nPages
== 6 || nPages
== 9 || nPages
== 16 )
1152 Size
aJobPageSize( getJobPageSize() );
1153 bool bPortrait
= aJobPageSize
.Width() < aJobPageSize
.Height();
1167 else if( nPages
== 4 )
1169 else if( nPages
== 6 )
1182 else if( nPages
== 9 )
1184 else if( nPages
== 16 )
1194 // set upper limits for margins based on job page size and rows/columns
1195 Size
aSize( getJobPageSize() );
1197 // maximum sheet distance: 1/2 sheet
1198 long nHorzMax
= aSize
.Width()/2;
1199 long nVertMax
= aSize
.Height()/2;
1200 if( nSheetMargin
> nHorzMax
)
1201 nSheetMargin
= nHorzMax
;
1202 if( nSheetMargin
> nVertMax
)
1203 nSheetMargin
= nVertMax
;
1205 mxSheetMarginEdt
->set_max(
1206 mxSheetMarginEdt
->normalize(
1207 std::min(nHorzMax
, nVertMax
) ), FieldUnit::MM_100TH
);
1209 // maximum page distance
1210 nHorzMax
= (aSize
.Width() - 2*nSheetMargin
);
1212 nHorzMax
/= (nCols
-1);
1213 nVertMax
= (aSize
.Height() - 2*nSheetMargin
);
1215 nHorzMax
/= (nRows
-1);
1217 if( nPageMargin
> nHorzMax
)
1218 nPageMargin
= nHorzMax
;
1219 if( nPageMargin
> nVertMax
)
1220 nPageMargin
= nVertMax
;
1222 mxPageMarginEdt
->set_max(
1223 mxSheetMarginEdt
->normalize(
1224 std::min(nHorzMax
, nVertMax
) ), FieldUnit::MM_100TH
);
1227 mxNupRowsEdt
->set_value( nRows
);
1228 mxNupColEdt
->set_value( nCols
);
1229 mxPageMarginEdt
->set_value( mxPageMarginEdt
->normalize( nPageMargin
), FieldUnit::MM_100TH
);
1230 mxSheetMarginEdt
->set_value( mxSheetMarginEdt
->normalize( nSheetMargin
), FieldUnit::MM_100TH
);
1232 showAdvancedControls( bCustom
);
1233 updateNup( i_bMayUseCache
);
1236 void PrintDialog::enableNupControls( bool bEnable
)
1238 mxNupPagesBox
->set_sensitive( bEnable
);
1239 mxNupNumPagesTxt
->set_sensitive( bEnable
);
1240 mxNupColEdt
->set_sensitive( bEnable
);
1241 mxNupTimesTxt
->set_sensitive( bEnable
);
1242 mxNupRowsEdt
->set_sensitive( bEnable
);
1243 mxPageMarginTxt1
->set_sensitive( bEnable
);
1244 mxPageMarginEdt
->set_sensitive( bEnable
);
1245 mxPageMarginTxt2
->set_sensitive( bEnable
);
1246 mxSheetMarginTxt1
->set_sensitive( bEnable
);
1247 mxSheetMarginEdt
->set_sensitive( bEnable
);
1248 mxSheetMarginTxt2
->set_sensitive( bEnable
);
1249 mxNupOrderTxt
->set_sensitive( bEnable
);
1250 mxNupOrderBox
->set_sensitive( bEnable
);
1251 mxNupOrderWin
->set_sensitive( bEnable
);
1252 mxBorderCB
->set_sensitive( bEnable
);
1255 void PrintDialog::showAdvancedControls( bool i_bShow
)
1257 mxNupNumPagesTxt
->set_visible( i_bShow
);
1258 mxNupColEdt
->set_visible( i_bShow
);
1259 mxNupTimesTxt
->set_visible( i_bShow
);
1260 mxNupRowsEdt
->set_visible( i_bShow
);
1261 mxPageMarginTxt1
->set_visible( i_bShow
);
1262 mxPageMarginEdt
->set_visible( i_bShow
);
1263 mxPageMarginTxt2
->set_visible( i_bShow
);
1264 mxSheetMarginTxt1
->set_visible( i_bShow
);
1265 mxSheetMarginEdt
->set_visible( i_bShow
);
1266 mxSheetMarginTxt2
->set_visible( i_bShow
);
1271 void setHelpId( weld::Widget
* i_pWindow
, const Sequence
< OUString
>& i_rHelpIds
, sal_Int32 i_nIndex
)
1273 if( i_nIndex
>= 0 && i_nIndex
< i_rHelpIds
.getLength() )
1274 i_pWindow
->set_help_id( OUStringToOString( i_rHelpIds
.getConstArray()[i_nIndex
], RTL_TEXTENCODING_UTF8
) );
1277 void setHelpText( weld::Widget
* i_pWindow
, const Sequence
< OUString
>& i_rHelpTexts
, sal_Int32 i_nIndex
)
1279 // without a help text set and the correct smartID,
1280 // help texts will be retrieved from the online help system
1281 if( i_nIndex
>= 0 && i_nIndex
< i_rHelpTexts
.getLength() )
1282 i_pWindow
->set_tooltip_text(i_rHelpTexts
.getConstArray()[i_nIndex
]);
1286 void PrintDialog::setupOptionalUI()
1288 const Sequence
< PropertyValue
>& rOptions( maPController
->getUIOptions() );
1289 for( const auto& rOption
: rOptions
)
1291 if (rOption
.Name
== "OptionsUIFile")
1293 OUString sOptionsUIFile
;
1294 rOption
.Value
>>= sOptionsUIFile
;
1295 mxCustomOptionsUIBuilder
.reset(Application::CreateBuilder(mxCustom
.get(), sOptionsUIFile
));
1296 std::unique_ptr
<weld::Container
> xWindow
= mxCustomOptionsUIBuilder
->weld_container("box");
1301 Sequence
< beans::PropertyValue
> aOptProp
;
1302 rOption
.Value
>>= aOptProp
;
1304 // extract ui element
1308 OUString aPropertyName
;
1309 Sequence
< OUString
> aChoices
;
1310 Sequence
< sal_Bool
> aChoicesDisabled
;
1311 Sequence
< OUString
> aHelpTexts
;
1312 Sequence
< OUString
> aIDs
;
1313 Sequence
< OUString
> aHelpIds
;
1314 sal_Int64 nMinValue
= 0, nMaxValue
= 0;
1315 OUString aGroupingHint
;
1317 for( const beans::PropertyValue
& rEntry
: std::as_const(aOptProp
) )
1319 if ( rEntry
.Name
== "ID" )
1321 rEntry
.Value
>>= aIDs
;
1322 aID
= OUStringToOString(aIDs
[0], RTL_TEXTENCODING_UTF8
);
1324 if ( rEntry
.Name
== "Text" )
1326 rEntry
.Value
>>= aText
;
1328 else if ( rEntry
.Name
== "ControlType" )
1330 rEntry
.Value
>>= aCtrlType
;
1332 else if ( rEntry
.Name
== "Choices" )
1334 rEntry
.Value
>>= aChoices
;
1336 else if ( rEntry
.Name
== "ChoicesDisabled" )
1338 rEntry
.Value
>>= aChoicesDisabled
;
1340 else if ( rEntry
.Name
== "Property" )
1343 rEntry
.Value
>>= aVal
;
1344 aPropertyName
= aVal
.Name
;
1346 else if ( rEntry
.Name
== "Enabled" )
1349 else if ( rEntry
.Name
== "GroupingHint" )
1351 rEntry
.Value
>>= aGroupingHint
;
1353 else if ( rEntry
.Name
== "DependsOnName" )
1356 else if ( rEntry
.Name
== "DependsOnEntry" )
1359 else if ( rEntry
.Name
== "AttachToDependency" )
1362 else if ( rEntry
.Name
== "MinValue" )
1364 rEntry
.Value
>>= nMinValue
;
1366 else if ( rEntry
.Name
== "MaxValue" )
1368 rEntry
.Value
>>= nMaxValue
;
1370 else if ( rEntry
.Name
== "HelpText" )
1372 if( ! (rEntry
.Value
>>= aHelpTexts
) )
1375 if( rEntry
.Value
>>= aHelpText
)
1377 aHelpTexts
.realloc( 1 );
1378 *aHelpTexts
.getArray() = aHelpText
;
1382 else if ( rEntry
.Name
== "HelpId" )
1384 if( ! (rEntry
.Value
>>= aHelpIds
) )
1387 if( rEntry
.Value
>>= aHelpId
)
1389 aHelpIds
.realloc( 1 );
1390 *aHelpIds
.getArray() = aHelpId
;
1394 else if ( rEntry
.Name
== "HintNoLayoutPage" )
1396 bool bHasLayoutFrame
= false;
1397 rEntry
.Value
>>= bHasLayoutFrame
;
1398 mbShowLayoutFrame
= !bHasLayoutFrame
;
1402 if (aCtrlType
== "Group")
1406 weld::Container
* pPage
= mxTabCtrl
->get_page(aID
);
1410 mxTabCtrl
->set_tab_label_text(aID
, aText
);
1413 if (aHelpIds
.hasElements())
1414 pPage
->set_help_id(OUStringToOString(aHelpIds
.getConstArray()[0], RTL_TEXTENCODING_UTF8
));
1417 if (aHelpTexts
.hasElements())
1418 pPage
->set_tooltip_text(aHelpTexts
.getConstArray()[0]);
1422 else if (aCtrlType
== "Subgroup" && !aID
.isEmpty())
1424 std::unique_ptr
<weld::Widget
> xWidget
;
1425 // since 'New Print Dialog Design' fromwhich in calc is not a frame anymore
1426 if (aID
== "fromwhich")
1428 std::unique_ptr
<weld::Label
> xLabel
= m_xBuilder
->weld_label(aID
);
1429 xLabel
->set_label(aText
);
1430 xWidget
= std::move(xLabel
);
1434 std::unique_ptr
<weld::Frame
> xFrame
= m_xBuilder
->weld_frame(aID
);
1435 if (!xFrame
&& mxCustomOptionsUIBuilder
)
1436 xFrame
= mxCustomOptionsUIBuilder
->weld_frame(aID
);
1439 xFrame
->set_label(aText
);
1440 xWidget
= std::move(xFrame
);
1448 setHelpId(xWidget
.get(), aHelpIds
, 0);
1450 setHelpText(xWidget
.get(), aHelpTexts
, 0);
1455 else if( aCtrlType
== "Bool" && aGroupingHint
== "LayoutPage" && aPropertyName
== "PrintProspect" )
1457 mxBrochureBtn
->set_label(aText
);
1458 mxBrochureBtn
->show();
1461 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1463 pVal
->Value
>>= bVal
;
1464 mxBrochureBtn
->set_active( bVal
);
1465 mxBrochureBtn
->set_sensitive( maPController
->isUIOptionEnabled( aPropertyName
) && pVal
!= nullptr );
1466 mxBrochureBtn
->connect_toggled( LINK( this, PrintDialog
, ToggleHdl
) );
1468 maPropertyToWindowMap
[aPropertyName
].emplace_back(mxBrochureBtn
.get());
1469 maControlToPropertyMap
[mxBrochureBtn
.get()] = aPropertyName
;
1472 setHelpId( mxBrochureBtn
.get(), aHelpIds
, 0 );
1474 setHelpText( mxBrochureBtn
.get(), aHelpTexts
, 0 );
1476 else if (aCtrlType
== "Bool")
1479 std::unique_ptr
<weld::CheckButton
> xNewBox
= m_xBuilder
->weld_check_button(aID
);
1480 if (!xNewBox
&& mxCustomOptionsUIBuilder
)
1481 xNewBox
= mxCustomOptionsUIBuilder
->weld_check_button(aID
);
1485 xNewBox
->set_label( aText
);
1489 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1491 pVal
->Value
>>= bVal
;
1492 xNewBox
->set_active( bVal
);
1493 xNewBox
->connect_toggled( LINK( this, PrintDialog
, UIOption_CheckHdl
) );
1495 maExtraControls
.emplace_back(std::move(xNewBox
));
1497 weld::Widget
* pWidget
= maExtraControls
.back().get();
1499 maPropertyToWindowMap
[aPropertyName
].emplace_back(pWidget
);
1500 maControlToPropertyMap
[pWidget
] = aPropertyName
;
1503 setHelpId(pWidget
, aHelpIds
, 0);
1505 setHelpText(pWidget
, aHelpTexts
, 0);
1507 else if (aCtrlType
== "Radio")
1509 sal_Int32 nCurHelpText
= 0;
1512 sal_Int32 nSelectVal
= 0;
1513 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1514 if( pVal
&& pVal
->Value
.hasValue() )
1515 pVal
->Value
>>= nSelectVal
;
1516 for( sal_Int32 m
= 0; m
< aChoices
.getLength(); m
++ )
1518 aID
= OUStringToOString(aIDs
[m
], RTL_TEXTENCODING_UTF8
);
1519 std::unique_ptr
<weld::RadioButton
> xBtn
= m_xBuilder
->weld_radio_button(aID
);
1520 if (!xBtn
&& mxCustomOptionsUIBuilder
)
1521 xBtn
= mxCustomOptionsUIBuilder
->weld_radio_button(aID
);
1525 xBtn
->set_label( aChoices
[m
] );
1526 xBtn
->set_active( m
== nSelectVal
);
1527 xBtn
->connect_toggled( LINK( this, PrintDialog
, UIOption_RadioHdl
) );
1528 if( aChoicesDisabled
.getLength() > m
&& aChoicesDisabled
[m
] )
1529 xBtn
->set_sensitive( false );
1532 maExtraControls
.emplace_back(std::move(xBtn
));
1534 weld::Widget
* pWidget
= maExtraControls
.back().get();
1536 maPropertyToWindowMap
[ aPropertyName
].emplace_back(pWidget
);
1537 maControlToPropertyMap
[pWidget
] = aPropertyName
;
1538 maControlToNumValMap
[pWidget
] = m
;
1541 setHelpId( pWidget
, aHelpIds
, nCurHelpText
);
1543 setHelpText( pWidget
, aHelpTexts
, nCurHelpText
);
1547 else if ( aCtrlType
== "List" )
1549 std::unique_ptr
<weld::ComboBox
> xList
= m_xBuilder
->weld_combo_box(aID
);
1550 if (!xList
&& mxCustomOptionsUIBuilder
)
1551 xList
= mxCustomOptionsUIBuilder
->weld_combo_box(aID
);
1556 for( const auto& rChoice
: std::as_const(aChoices
) )
1557 xList
->append_text(rChoice
);
1559 sal_Int32 nSelectVal
= 0;
1560 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1561 if( pVal
&& pVal
->Value
.hasValue() )
1562 pVal
->Value
>>= nSelectVal
;
1563 xList
->set_active(nSelectVal
);
1564 xList
->connect_changed( LINK( this, PrintDialog
, UIOption_SelectHdl
) );
1567 maExtraControls
.emplace_back(std::move(xList
));
1569 weld::Widget
* pWidget
= maExtraControls
.back().get();
1571 maPropertyToWindowMap
[ aPropertyName
].emplace_back(pWidget
);
1572 maControlToPropertyMap
[pWidget
] = aPropertyName
;
1575 setHelpId( pWidget
, aHelpIds
, 0 );
1577 setHelpText( pWidget
, aHelpTexts
, 0 );
1579 else if ( aCtrlType
== "Range" )
1581 std::unique_ptr
<weld::SpinButton
> xField
= m_xBuilder
->weld_spin_button(aID
);
1582 if (!xField
&& mxCustomOptionsUIBuilder
)
1583 xField
= mxCustomOptionsUIBuilder
->weld_spin_button(aID
);
1587 // set min/max and current value
1588 if(nMinValue
!= nMaxValue
)
1589 xField
->set_range(nMinValue
, nMaxValue
);
1591 sal_Int64 nCurVal
= 0;
1592 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1593 if( pVal
&& pVal
->Value
.hasValue() )
1594 pVal
->Value
>>= nCurVal
;
1595 xField
->set_value( nCurVal
);
1596 xField
->connect_value_changed( LINK( this, PrintDialog
, UIOption_SpinModifyHdl
) );
1599 maExtraControls
.emplace_back(std::move(xField
));
1601 weld::Widget
* pWidget
= maExtraControls
.back().get();
1603 maPropertyToWindowMap
[ aPropertyName
].emplace_back(pWidget
);
1604 maControlToPropertyMap
[pWidget
] = aPropertyName
;
1607 setHelpId( pWidget
, aHelpIds
, 0 );
1609 setHelpText( pWidget
, aHelpTexts
, 0 );
1611 else if (aCtrlType
== "Edit")
1613 std::unique_ptr
<weld::Entry
> xField
= m_xBuilder
->weld_entry(aID
);
1614 if (!xField
&& mxCustomOptionsUIBuilder
)
1615 xField
= mxCustomOptionsUIBuilder
->weld_entry(aID
);
1620 PropertyValue
* pVal
= maPController
->getValue( aPropertyName
);
1621 if( pVal
&& pVal
->Value
.hasValue() )
1622 pVal
->Value
>>= aCurVal
;
1623 xField
->set_text( aCurVal
);
1624 xField
->connect_changed( LINK( this, PrintDialog
, UIOption_EntryModifyHdl
) );
1627 maExtraControls
.emplace_back(std::move(xField
));
1629 weld::Widget
* pWidget
= maExtraControls
.back().get();
1631 maPropertyToWindowMap
[ aPropertyName
].emplace_back(pWidget
);
1632 maControlToPropertyMap
[pWidget
] = aPropertyName
;
1635 setHelpId( pWidget
, aHelpIds
, 0 );
1637 setHelpText( pWidget
, aHelpTexts
, 0 );
1641 SAL_WARN( "vcl", "Unsupported UI option: \"" << aCtrlType
<< '"');
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 (!mxBrochureBtn
->get_visible() && mxPagesBtn
->get_visible())
1649 mxPagesBoxTitleTxt
->set_label(mxPagesBtn
->get_label());
1650 mxPagesBoxTitleTxt
->show();
1653 mxPagesBoxTitleTxt
->set_accessible_relation_label_for(mxNupPagesBox
.get());
1654 mxNupPagesBox
->set_accessible_relation_labeled_by(mxPagesBoxTitleTxt
.get());
1655 mxPagesBtn
->set_accessible_relation_label_for(nullptr);
1658 // update enable states
1659 checkOptionalControlDependencies();
1661 // print range not shown (currently math only) -> hide spacer line and reverse order
1662 if (!mxPageRangeEdit
->get_visible())
1664 mxReverseOrderBox
->hide();
1667 if (!mxCustomOptionsUIBuilder
)
1668 mxTabCtrl
->remove_page(mxTabCtrl
->get_page_ident(1));
1671 void PrintDialog::makeEnabled( weld::Widget
* i_pWindow
)
1673 auto it
= maControlToPropertyMap
.find( i_pWindow
);
1674 if( it
!= maControlToPropertyMap
.end() )
1676 OUString
aDependency( maPController
->makeEnabled( it
->second
) );
1677 if( !aDependency
.isEmpty() )
1678 updateWindowFromProperty( aDependency
);
1682 void PrintDialog::updateWindowFromProperty( const OUString
& i_rProperty
)
1684 beans::PropertyValue
* pValue
= maPController
->getValue( i_rProperty
);
1685 auto it
= maPropertyToWindowMap
.find( i_rProperty
);
1686 if( pValue
&& it
!= maPropertyToWindowMap
.end() )
1688 const auto& rWindows( it
->second
);
1689 if( ! rWindows
.empty() )
1692 sal_Int32 nVal
= -1;
1693 if( pValue
->Value
>>= bVal
)
1695 // we should have a CheckBox for this one
1696 weld::CheckButton
* pBox
= dynamic_cast<weld::CheckButton
*>(rWindows
.front());
1699 pBox
->set_active( bVal
);
1701 else if ( i_rProperty
== "PrintProspect" )
1703 // EVIL special case
1705 mxBrochureBtn
->set_active(true);
1707 mxPagesBtn
->set_active(true);
1711 SAL_WARN( "vcl", "missing a checkbox" );
1714 else if( pValue
->Value
>>= nVal
)
1716 // this could be a ListBox or a RadioButtonGroup
1717 weld::ComboBox
* pList
= dynamic_cast<weld::ComboBox
*>(rWindows
.front());
1720 pList
->set_active( static_cast< sal_uInt16
>(nVal
) );
1722 else if( nVal
>= 0 && nVal
< sal_Int32(rWindows
.size() ) )
1724 weld::RadioButton
* pBtn
= dynamic_cast<weld::RadioButton
*>(rWindows
[nVal
]);
1725 SAL_WARN_IF( !pBtn
, "vcl", "unexpected control for property" );
1727 pBtn
->set_active(true);
1734 bool PrintDialog::isPrintToFile() const
1736 return ( mxPrinters
->get_active() == 0 );
1739 bool PrintDialog::isCollate() const
1741 return mxCopyCountField
->get_value() > 1 && mxCollateBox
->get_active();
1744 bool PrintDialog::hasPreview() const
1746 return mxPreviewBox
->get_active();
1749 PropertyValue
* PrintDialog::getValueForWindow( weld::Widget
* i_pWindow
) const
1751 PropertyValue
* pVal
= nullptr;
1752 auto it
= maControlToPropertyMap
.find( i_pWindow
);
1753 if( it
!= maControlToPropertyMap
.end() )
1755 pVal
= maPController
->getValue( it
->second
);
1756 SAL_WARN_IF( !pVal
, "vcl", "property value not found" );
1760 OSL_FAIL( "changed control not in property map" );
1765 IMPL_LINK(PrintDialog
, ToggleHdl
, weld::ToggleButton
&, rButton
, void)
1770 IMPL_LINK(PrintDialog
, ClickHdl
, weld::Button
&, rButton
, void)
1772 if (&rButton
== mxOKButton
.get() || &rButton
== mxCancelButton
.get())
1775 m_xDialog
->response(&rButton
== mxOKButton
.get() ? RET_OK
: RET_CANCEL
);
1777 else if( &rButton
== mxHelpButton
.get() )
1779 // start help system
1780 Help
* pHelp
= Application::GetHelp();
1783 pHelp
->Start("vcl/ui/printdialog/PrintDialog", mxOKButton
.get());
1786 else if ( &rButton
== mxPreviewBox
.get() )
1788 preparePreview( true );
1790 else if( &rButton
== mxForwardBtn
.get() )
1794 else if( &rButton
== mxBackwardBtn
.get() )
1798 else if( &rButton
== mxFirstBtn
.get() )
1802 else if( &rButton
== mxLastBtn
.get() )
1806 else if( &rButton
== mxBrochureBtn
.get() )
1808 PropertyValue
* pVal
= getValueForWindow( &rButton
);
1811 bool bVal
= mxBrochureBtn
->get_active();
1812 pVal
->Value
<<= bVal
;
1814 checkOptionalControlDependencies();
1816 // update preview and page settings
1817 preparePreview(false);
1819 if( mxBrochureBtn
->get_active() )
1821 mxOrientationBox
->set_sensitive( false );
1822 mxOrientationBox
->set_active( ORIENTATION_LANDSCAPE
);
1823 mxNupPagesBox
->set_active( 0 );
1824 updateNupFromPages();
1825 showAdvancedControls( false );
1826 enableNupControls( false );
1829 else if( &rButton
== mxPagesBtn
.get() )
1831 mxOrientationBox
->set_sensitive( true );
1832 mxOrientationBox
->set_active( ORIENTATION_AUTOMATIC
);
1833 enableNupControls( true );
1834 updateNupFromPages();
1836 else if( &rButton
== mxCollateBox
.get() )
1838 maPController
->setValue( "Collate",
1839 makeAny( isCollate() ) );
1840 checkControlDependencies();
1842 else if( &rButton
== mxReverseOrderBox
.get() )
1844 bool bChecked
= mxReverseOrderBox
->get_active();
1845 maPController
->setReversePrint( bChecked
);
1846 maPController
->setValue( "PrintReverse",
1847 makeAny( bChecked
) );
1848 preparePreview( true );
1850 else if( &rButton
== mxBorderCB
.get() )
1854 else if ( &rButton
== mxMoreOptionsBtn
.get() )
1856 mxMoreOptionsDlg
.reset(new MoreOptionsDialog(this));
1857 mxMoreOptionsDlg
->run();
1861 if( &rButton
== mxSetupButton
.get() )
1863 maPController
->setupPrinter(m_xDialog
.get());
1865 if ( !isPrintToFile() )
1867 VclPtr
<Printer
> aPrt( maPController
->getPrinter() );
1868 mePaper
= aPrt
->GetPaper();
1870 for (int nPaper
= 0; nPaper
< aPrt
->GetPaperInfoCount(); nPaper
++ )
1872 PaperInfo aInfo
= aPrt
->GetPaperInfo( nPaper
);
1873 aInfo
.doSloppyFit();
1874 Paper ePaper
= aInfo
.getPaper();
1876 if ( mePaper
== ePaper
)
1878 mxPaperSizeBox
->set_active( nPaper
);
1884 updateOrientationBox( false );
1885 setupPaperSidesBox();
1887 // tdf#63905 don't use cache: page size may change
1888 preparePreview(false);
1890 checkControlDependencies();
1895 IMPL_LINK( PrintDialog
, SelectHdl
, weld::ComboBox
&, rBox
, void )
1897 if (&rBox
== mxPrinters
.get())
1899 if ( !isPrintToFile() )
1901 OUString
aNewPrinter(rBox
.get_active_text());
1903 maPController
->setPrinter( VclPtrInstance
<Printer
>( aNewPrinter
) );
1904 maPController
->resetPrinterOptions( false );
1906 updateOrientationBox();
1908 // update text fields
1909 mxOKButton
->set_label(maPrintText
);
1910 updatePrinterText();
1912 preparePreview(false);
1914 else // print to file
1916 // use the default printer or FIXME: the last used one?
1917 maPController
->setPrinter( VclPtrInstance
<Printer
>( Printer::GetDefaultPrinterName() ) );
1918 mxOKButton
->set_label(maPrintToFileText
);
1919 maPController
->resetPrinterOptions( true );
1922 updateOrientationBox();
1923 preparePreview( true );
1926 setupPaperSidesBox();
1928 else if ( &rBox
== mxPaperSidesBox
.get() )
1930 DuplexMode eDuplex
= static_cast<DuplexMode
>(mxPaperSidesBox
->get_active() + 1);
1931 maPController
->getPrinter()->SetDuplexMode( eDuplex
);
1933 else if( &rBox
== mxOrientationBox
.get() )
1935 int nOrientation
= mxOrientationBox
->get_active();
1936 if ( nOrientation
!= ORIENTATION_AUTOMATIC
)
1937 setPaperOrientation( static_cast<Orientation
>( nOrientation
- 1 ) );
1941 else if ( &rBox
== mxNupOrderBox
.get() )
1945 else if( &rBox
== mxNupPagesBox
.get() )
1947 if( !mxPagesBtn
->get_active() )
1948 mxPagesBtn
->set_active(true);
1949 updateNupFromPages( false );
1951 else if ( &rBox
== mxPaperSizeBox
.get() )
1953 VclPtr
<Printer
> aPrt( maPController
->getPrinter() );
1954 PaperInfo aInfo
= aPrt
->GetPaperInfo( rBox
.get_active() );
1955 aInfo
.doSloppyFit();
1956 mePaper
= aInfo
.getPaper();
1958 if ( mePaper
== PAPER_USER
)
1959 aPrt
->SetPaperSizeUser( Size( aInfo
.getWidth(), aInfo
.getHeight() ) );
1961 aPrt
->SetPaper( mePaper
);
1963 Size
aPaperSize( aInfo
.getWidth(), aInfo
.getHeight() );
1964 checkPaperSize( aPaperSize
);
1965 maPController
->setPaperSizeFromUser( aPaperSize
);
1967 preparePreview(false);
1971 IMPL_LINK_NOARG(PrintDialog
, MetricSpinModifyHdl
, weld::MetricSpinButton
&, void)
1973 checkControlDependencies();
1974 updateNupFromPages();
1977 IMPL_LINK_NOARG(PrintDialog
, FocusOutHdl
, weld::Widget
&, void)
1979 ActivateHdl(*mxPageEdit
);
1982 IMPL_LINK_NOARG(PrintDialog
, ActivateHdl
, weld::Entry
&, bool)
1984 sal_Int32 nPage
= mxPageEdit
->get_text().toInt32();
1988 mxPageEdit
->set_text("1");
1990 else if (nPage
> mnCachedPages
)
1992 nPage
= mnCachedPages
;
1993 mxPageEdit
->set_text(OUString::number(mnCachedPages
));
1995 int nNewCurPage
= nPage
- 1;
1996 if (nNewCurPage
!= mnCurPage
)
1998 mnCurPage
= nNewCurPage
;
1999 preparePreview(true);
2004 IMPL_LINK( PrintDialog
, SpinModifyHdl
, weld::SpinButton
&, rEdit
, void )
2006 checkControlDependencies();
2007 if (&rEdit
== mxNupRowsEdt
.get() || &rEdit
== mxNupColEdt
.get())
2009 updateNupFromPages();
2011 else if( &rEdit
== mxCopyCountField
.get() )
2013 maPController
->setValue( "CopyCount",
2014 makeAny( sal_Int32(mxCopyCountField
->get_value()) ) );
2015 maPController
->setValue( "Collate",
2016 makeAny( isCollate() ) );
2020 IMPL_LINK( PrintDialog
, UIOption_CheckHdl
, weld::ToggleButton
&, i_rBox
, void )
2022 PropertyValue
* pVal
= getValueForWindow( &i_rBox
);
2025 makeEnabled( &i_rBox
);
2027 bool bVal
= i_rBox
.get_active();
2028 pVal
->Value
<<= bVal
;
2030 checkOptionalControlDependencies();
2032 // update preview and page settings
2033 preparePreview(false);
2037 IMPL_LINK( PrintDialog
, UIOption_RadioHdl
, weld::ToggleButton
&, i_rBtn
, void )
2039 // this handler gets called for all radiobuttons that get unchecked, too
2040 // however we only want one notification for the new value (that is for
2041 // the button that gets checked)
2042 if( i_rBtn
.get_active() )
2044 PropertyValue
* pVal
= getValueForWindow( &i_rBtn
);
2045 auto it
= maControlToNumValMap
.find( &i_rBtn
);
2046 if( pVal
&& it
!= maControlToNumValMap
.end() )
2048 makeEnabled( &i_rBtn
);
2050 sal_Int32 nVal
= it
->second
;
2051 pVal
->Value
<<= nVal
;
2053 // tdf#63905 use paper size set in printer properties
2054 if (pVal
->Name
== "PageOptions")
2055 maPController
->resetPaperToLastConfigured();
2057 updateOrientationBox();
2059 checkOptionalControlDependencies();
2061 // tdf#41205 give focus to the page range edit if the corresponding radio button was selected
2062 if (pVal
->Name
== "PrintContent" && mxPageRangesRadioButton
->get_active())
2063 mxPageRangeEdit
->grab_focus();
2065 // update preview and page settings
2066 preparePreview(false);
2071 IMPL_LINK( PrintDialog
, UIOption_SelectHdl
, weld::ComboBox
&, i_rBox
, void )
2073 PropertyValue
* pVal
= getValueForWindow( &i_rBox
);
2076 makeEnabled( &i_rBox
);
2078 sal_Int32
nVal( i_rBox
.get_active() );
2079 pVal
->Value
<<= nVal
;
2081 //If we are in impress we start in print slides mode and get a
2082 //maFirstPageSize for slides which are usually landscape mode, if we
2083 //change to notes which are usually in portrait mode, and then visit
2084 //n-up print, we will assume notes are in landscape unless we throw
2085 //away maFirstPageSize when we change page content type
2086 if (pVal
->Name
== "PageContentType")
2087 maFirstPageSize
= Size();
2089 checkOptionalControlDependencies();
2091 // update preview and page settings
2092 preparePreview(false);
2096 IMPL_LINK( PrintDialog
, UIOption_SpinModifyHdl
, weld::SpinButton
&, i_rBox
, void )
2098 PropertyValue
* pVal
= getValueForWindow( &i_rBox
);
2101 makeEnabled( &i_rBox
);
2103 sal_Int64 nVal
= i_rBox
.get_value();
2104 pVal
->Value
<<= nVal
;
2106 checkOptionalControlDependencies();
2108 // update preview and page settings
2109 preparePreview(false);
2113 IMPL_LINK( PrintDialog
, UIOption_EntryModifyHdl
, weld::Entry
&, i_rBox
, void )
2115 PropertyValue
* pVal
= getValueForWindow( &i_rBox
);
2118 makeEnabled( &i_rBox
);
2120 OUString
aVal( i_rBox
.get_text() );
2121 pVal
->Value
<<= aVal
;
2123 checkOptionalControlDependencies();
2125 // update preview and page settings
2126 preparePreview(false);
2130 void PrintDialog::previewForward()
2132 sal_Int32 nValue
= mxPageEdit
->get_text().toInt32() + 1;
2133 if (nValue
<= mnCachedPages
)
2135 mxPageEdit
->set_text(OUString::number(nValue
));
2136 ActivateHdl(*mxPageEdit
);
2140 void PrintDialog::previewBackward()
2142 sal_Int32 nValue
= mxPageEdit
->get_text().toInt32() - 1;
2145 mxPageEdit
->set_text(OUString::number(nValue
));
2146 ActivateHdl(*mxPageEdit
);
2150 void PrintDialog::previewFirst()
2152 mxPageEdit
->set_text("1");
2153 ActivateHdl(*mxPageEdit
);
2156 void PrintDialog::previewLast()
2158 mxPageEdit
->set_text(OUString::number(mnCachedPages
));
2159 ActivateHdl(*mxPageEdit
);
2162 // PrintProgressDialog
2163 PrintProgressDialog::PrintProgressDialog(weld::Window
* i_pParent
, int i_nMax
)
2164 : GenericDialogController(i_pParent
, "vcl/ui/printprogressdialog.ui", "PrintProgressDialog")
2168 , mxText(m_xBuilder
->weld_label("label"))
2169 , mxProgress(m_xBuilder
->weld_progress_bar("progressbar"))
2170 , mxButton(m_xBuilder
->weld_button("cancel"))
2175 maStr
= mxText
->get_label();
2177 //just multiply largest value by 10 and take the width of that string as
2178 //the max size we will want
2179 OUString
aNewText( maStr
.replaceFirst( "%p", OUString::number( mnMax
* 10 ) ) );
2180 aNewText
= aNewText
.replaceFirst( "%n", OUString::number( mnMax
* 10 ) );
2181 mxText
->set_label( aNewText
);
2182 mxText
->set_size_request(mxText
->get_preferred_size().Width(), -1);
2184 //Pick a useful max width
2185 mxProgress
->set_size_request(mxProgress
->get_approximate_digit_width() * 25, -1);
2187 mxButton
->connect_clicked( LINK( this, PrintProgressDialog
, ClickHdl
) );
2190 PrintProgressDialog::~PrintProgressDialog()
2194 IMPL_LINK_NOARG(PrintProgressDialog
, ClickHdl
, weld::Button
&, void)
2199 void PrintProgressDialog::setProgress( int i_nCurrent
)
2206 mxProgress
->set_percentage(mnCur
*100/mnMax
);
2208 OUString
aNewText( maStr
.replaceFirst( "%p", OUString::number( mnCur
) ) );
2209 aNewText
= aNewText
.replaceFirst( "%n", OUString::number( mnMax
) );
2210 mxText
->set_label( aNewText
);
2213 void PrintProgressDialog::tick()
2216 setProgress( ++mnCur
);
2219 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */