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 <vcl/layout.hxx>
21 #include <vcl/print.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/metaact.hxx>
24 #include <vcl/configsettings.hxx>
25 #include <vcl/unohelp.hxx>
26 #include <tools/urlobj.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <comphelper/sequence.hxx>
29 #include <sal/types.h>
31 #include "printdlg.hxx"
33 #include "salinst.hxx"
37 #include <com/sun/star/container/XNameAccess.hpp>
38 #include <com/sun/star/ui/dialogs/FilePicker.hpp>
39 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
40 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
41 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
42 #include <com/sun/star/view/DuplexMode.hpp>
43 #include <com/sun/star/lang/IllegalArgumentException.hpp>
44 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
45 #include <com/sun/star/awt/Size.hpp>
47 #include <unordered_map>
48 #include <unordered_set>
57 PrinterController::PageSize aSize
;
60 std::vector
< CacheEntry
> maPages
;
61 std::vector
< sal_Int32
> maPageNumbers
;
62 std::vector
< sal_Int32
> maCacheRanking
;
64 static const sal_Int32 nCacheSize
= 6;
66 void updateRanking( sal_Int32 nLastHit
)
68 if( maCacheRanking
[0] != nLastHit
)
70 for( sal_Int32 i
= nCacheSize
-1; i
> 0; i
-- )
71 maCacheRanking
[i
] = maCacheRanking
[i
-1];
72 maCacheRanking
[0] = nLastHit
;
78 : maPages( nCacheSize
)
79 , maPageNumbers( nCacheSize
, -1 )
80 , maCacheRanking( nCacheSize
)
82 for( sal_Int32 i
= 0; i
< nCacheSize
; i
++ )
83 maCacheRanking
[i
] = nCacheSize
- i
- 1;
86 // caution: does not ensure uniqueness
87 void insert( sal_Int32 i_nPageNo
, const GDIMetaFile
& i_rPage
, const PrinterController::PageSize
& i_rSize
)
89 sal_Int32 nReplacePage
= maCacheRanking
.back();
90 maPages
[ nReplacePage
].aPage
= i_rPage
;
91 maPages
[ nReplacePage
].aSize
= i_rSize
;
92 maPageNumbers
[ nReplacePage
] = i_nPageNo
;
93 // cache insertion means in our case, the page was just queried
94 // so update the ranking
95 updateRanking( nReplacePage
);
98 // caution: bad algorithm; should there ever be reason to increase the cache size beyond 6
99 // this needs to be urgently rewritten. However do NOT increase the cache size lightly,
100 // whole pages can be rather memory intensive
101 bool get( sal_Int32 i_nPageNo
, GDIMetaFile
& o_rPageFile
, PrinterController::PageSize
& o_rSize
)
103 for( sal_Int32 i
= 0; i
< nCacheSize
; ++i
)
105 if( maPageNumbers
[i
] == i_nPageNo
)
108 o_rPageFile
= maPages
[i
].aPage
;
109 o_rSize
= maPages
[i
].aSize
;
118 for( sal_Int32 i
= 0; i
< nCacheSize
; ++i
)
120 maPageNumbers
[i
] = -1;
121 maPages
[i
].aPage
.Clear();
122 maCacheRanking
[i
] = nCacheSize
- i
- 1;
127 class vcl::ImplPrinterControllerData
130 struct ControlDependency
132 OUString maDependsOnName
;
133 sal_Int32 mnDependsOnEntry
;
135 ControlDependency() : mnDependsOnEntry( -1 ) {}
138 typedef std::unordered_map
< OUString
, size_t, OUStringHash
> PropertyToIndexMap
;
139 typedef std::unordered_map
< OUString
, ControlDependency
, OUStringHash
> ControlDependencyMap
;
140 typedef std::unordered_map
< OUString
, css::uno::Sequence
< sal_Bool
>, OUStringHash
> ChoiceDisableMap
;
142 VclPtr
< Printer
> mxPrinter
;
143 css::uno::Sequence
< css::beans::PropertyValue
> maUIOptions
;
144 std::vector
< css::beans::PropertyValue
> maUIProperties
;
145 std::vector
< bool > maUIPropertyEnabled
;
146 PropertyToIndexMap maPropertyToIndex
;
147 ControlDependencyMap maControlDependencies
;
148 ChoiceDisableMap maChoiceDisableMap
;
151 bool mbReversePageOrder
;
152 bool mbPapersizeFromSetup
;
153 bool mbPrinterModified
;
154 css::view::PrintableState meJobState
;
156 vcl::PrinterController::MultiPageSetup maMultiPage
;
158 VclPtr
<vcl::PrintProgressDialog
> mpProgress
;
160 ImplPageCache maPageCache
;
162 // set by user through printer properties subdialog of printer settings dialog
163 Size maDefaultPageSize
;
164 // set by user through printer properties subdialog of printer settings dialog
165 sal_Int32 mnDefaultPaperBin
;
166 // Set by user through printer properties subdialog of print dialog.
167 // Overrides application-set tray for a page.
168 sal_Int32 mnFixedPaperBin
;
170 // N.B. Apparently we have three levels of paper tray settings
171 // (latter overrides former):
173 // 2. tray set for a concrete page by an application, e.g., writer
174 // allows setting a printer tray (for the default printer) for a
175 // page style. This setting can be overridden by user by selecting
176 // "Use only paper tray from printer preferences" on the Options
177 // page in the print dialog, in which case the default tray is
178 // used for all pages.
179 // 3. tray set in printer properties the printer dialog
180 // I'm not quite sure why 1. and 3. are distinct, but the commit
181 // history suggests this is intentional...
183 ImplPrinterControllerData() :
186 mbReversePageOrder( false ),
187 mbPapersizeFromSetup( false ),
188 mbPrinterModified( false ),
189 meJobState( css::view::PrintableState_JOB_STARTED
),
190 mpProgress( nullptr ),
191 mnDefaultPaperBin( -1 ),
192 mnFixedPaperBin( -1 )
194 ~ImplPrinterControllerData() { mpProgress
.disposeAndClear(); }
196 const Size
& getRealPaperSize( const Size
& i_rPageSize
, bool bNoNUP
) const
198 if( mbPapersizeFromSetup
)
199 return maDefaultPageSize
;
200 if( maMultiPage
.nRows
* maMultiPage
.nColumns
> 1 && ! bNoNUP
)
201 return maMultiPage
.aPaperSize
;
204 bool isFixedPageSize() const
205 { return mbPapersizeFromSetup
; }
206 PrinterController::PageSize
modifyJobSetup( const css::uno::Sequence
< css::beans::PropertyValue
>& i_rProps
);
207 void resetPaperToLastConfigured();
210 PrinterController::PrinterController( const VclPtr
<Printer
>& i_xPrinter
)
211 : mpImplData( new ImplPrinterControllerData
)
213 mpImplData
->mxPrinter
= i_xPrinter
;
216 static OUString
queryFile( Printer
* pPrinter
)
220 css::uno::Reference
< css::uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
221 css::uno::Reference
< css::ui::dialogs::XFilePicker3
> xFilePicker
= css::ui::dialogs::FilePicker::createWithMode(xContext
, css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION
);
226 // add PostScript and PDF
227 bool bPS
= true, bPDF
= true;
230 if( pPrinter
->GetCapabilities( PrinterCapType::PDF
) )
236 xFilePicker
->appendFilter( "PostScript", "*.ps" );
238 xFilePicker
->appendFilter( "Portable Document Format", "*.pdf" );
241 xFilePicker
->appendFilter( "*.PRN", "*.prn" );
243 // add arbitrary files
244 xFilePicker
->appendFilter(VclResId(SV_STDTEXT_ALLFILETYPES
), "*.*");
246 catch (const css::lang::IllegalArgumentException
&)
248 SAL_WARN( "vcl.gdi", "caught IllegalArgumentException when registering filter" );
251 if( xFilePicker
->execute() == css::ui::dialogs::ExecutableDialogResults::OK
)
253 css::uno::Sequence
< OUString
> aPathSeq( xFilePicker
->getSelectedFiles() );
254 INetURLObject
aObj( aPathSeq
[0] );
255 aResult
= aObj
.PathToFileName();
262 std::shared_ptr
<PrinterController
> mxController
;
263 JobSetup maInitSetup
;
265 PrintJobAsync(const std::shared_ptr
<PrinterController
>& i_xController
,
266 const JobSetup
& i_rInitSetup
)
267 : mxController( i_xController
), maInitSetup( i_rInitSetup
)
270 DECL_LINK( ExecJob
, void*, void );
273 IMPL_LINK_NOARG(PrintJobAsync
, ExecJob
, void*, void)
275 Printer::ImplPrintJob(mxController
, maInitSetup
);
277 // clean up, do not access members after this
281 void Printer::PrintJob(const std::shared_ptr
<PrinterController
>& i_xController
,
282 const JobSetup
& i_rInitSetup
)
284 bool bSynchronous
= false;
285 css::beans::PropertyValue
* pVal
= i_xController
->getValue( OUString( "Wait" ) );
287 pVal
->Value
>>= bSynchronous
;
290 ImplPrintJob(i_xController
, i_rInitSetup
);
293 PrintJobAsync
* pAsync
= new PrintJobAsync(i_xController
, i_rInitSetup
);
294 Application::PostUserEvent( LINK( pAsync
, PrintJobAsync
, ExecJob
) );
298 bool Printer::PreparePrintJob(std::shared_ptr
<PrinterController
> xController
,
299 const JobSetup
& i_rInitSetup
)
301 // check if there is a default printer; if not, show an error box (if appropriate)
302 if( GetDefaultPrinterName().isEmpty() )
304 if (xController
->isShowDialogs())
306 ScopedVclPtrInstance
<MessageDialog
> aBox(
307 nullptr, "ErrorNoPrinterDialog",
308 "vcl/ui/errornoprinterdialog.ui");
311 xController
->setValue( "IsDirect",
312 css::uno::makeAny( false ) );
317 // #i114306# changed behavior back from persistence
318 // if no specific printer is already set, create the default printer
319 if (!xController
->getPrinter())
321 OUString
aPrinterName( i_rInitSetup
.GetPrinterName() );
322 VclPtrInstance
<Printer
> xPrinter( aPrinterName
);
323 xPrinter
->SetJobSetup(i_rInitSetup
);
324 xController
->setPrinter(xPrinter
);
327 // reset last page property
328 xController
->setLastPage(false);
330 // update "PageRange" property inferring from other properties:
331 // case 1: "Pages" set from UNO API ->
332 // setup "Print Selection" and insert "PageRange" attribute
333 // case 2: "All pages" is selected
334 // update "Page range" attribute to have a sensible default,
335 // but leave "All" as selected
337 // "Pages" attribute from API is now equivalent to "PageRange"
338 // AND "PrintContent" = 1 except calc where it is "PrintRange" = 1
339 // Argh ! That sure needs cleaning up
340 css::beans::PropertyValue
* pContentVal
= xController
->getValue(OUString("PrintRange"));
342 pContentVal
= xController
->getValue(OUString("PrintContent"));
344 // case 1: UNO API has set "Pages"
345 css::beans::PropertyValue
* pPagesVal
= xController
->getValue(OUString("Pages"));
349 pPagesVal
->Value
>>= aPagesVal
;
350 if( !aPagesVal
.isEmpty() )
352 // "Pages" attribute from API is now equivalent to "PageRange"
353 // AND "PrintContent" = 1 except calc where it is "PrintRange" = 1
354 // Argh ! That sure needs cleaning up
357 pContentVal
->Value
<<= sal_Int32( 1 );
358 xController
->setValue("PageRange", pPagesVal
->Value
);
362 // case 2: is "All" selected ?
363 else if( pContentVal
)
365 sal_Int32 nContent
= -1;
366 if( pContentVal
->Value
>>= nContent
)
370 // do not overwrite PageRange if it is already set
371 css::beans::PropertyValue
* pRangeVal
= xController
->getValue(OUString("PageRange"));
374 pRangeVal
->Value
>>= aRange
;
375 if( aRange
.isEmpty() )
377 sal_Int32 nPages
= xController
->getPageCount();
380 OUStringBuffer
aBuf( 32 );
385 aBuf
.append( nPages
);
387 xController
->setValue("PageRange", css::uno::makeAny(aBuf
.makeStringAndClear()));
394 css::beans::PropertyValue
* pReverseVal
= xController
->getValue(OUString("PrintReverse"));
397 bool bReverse
= false;
398 pReverseVal
->Value
>>= bReverse
;
399 xController
->setReversePrint( bReverse
);
402 css::beans::PropertyValue
* pPapersizeFromSetupVal
= xController
->getValue(OUString("PapersizeFromSetup"));
403 if( pPapersizeFromSetupVal
)
405 bool bPapersizeFromSetup
= false;
406 pPapersizeFromSetupVal
->Value
>>= bPapersizeFromSetup
;
407 xController
->setPapersizeFromSetup(bPapersizeFromSetup
);
410 // setup NUp printing from properties
411 sal_Int32 nRows
= xController
->getIntProperty("NUpRows", 1);
412 sal_Int32 nCols
= xController
->getIntProperty("NUpColumns", 1);
413 if( nRows
> 1 || nCols
> 1 )
415 PrinterController::MultiPageSetup aMPS
;
416 aMPS
.nRows
= nRows
> 1 ? nRows
: 1;
417 aMPS
.nColumns
= nCols
> 1 ? nCols
: 1;
418 sal_Int32 nValue
= xController
->getIntProperty("NUpPageMarginLeft", aMPS
.nLeftMargin
);
420 aMPS
.nLeftMargin
= nValue
;
421 nValue
= xController
->getIntProperty("NUpPageMarginRight", aMPS
.nRightMargin
);
423 aMPS
.nRightMargin
= nValue
;
424 nValue
= xController
->getIntProperty( "NUpPageMarginTop", aMPS
.nTopMargin
);
426 aMPS
.nTopMargin
= nValue
;
427 nValue
= xController
->getIntProperty( "NUpPageMarginBottom", aMPS
.nBottomMargin
);
429 aMPS
.nBottomMargin
= nValue
;
430 nValue
= xController
->getIntProperty( "NUpHorizontalSpacing", aMPS
.nHorizontalSpacing
);
432 aMPS
.nHorizontalSpacing
= nValue
;
433 nValue
= xController
->getIntProperty( "NUpVerticalSpacing", aMPS
.nVerticalSpacing
);
435 aMPS
.nVerticalSpacing
= nValue
;
436 aMPS
.bDrawBorder
= xController
->getBoolProperty( "NUpDrawBorder", aMPS
.bDrawBorder
);
437 aMPS
.nOrder
= static_cast<NupOrderType
>(xController
->getIntProperty( "NUpSubPageOrder", (sal_Int32
)aMPS
.nOrder
));
438 aMPS
.aPaperSize
= xController
->getPrinter()->PixelToLogic( xController
->getPrinter()->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM
) );
439 css::beans::PropertyValue
* pPgSizeVal
= xController
->getValue( OUString( "NUpPaperSize" ) );
440 css::awt::Size aSizeVal
;
441 if( pPgSizeVal
&& (pPgSizeVal
->Value
>>= aSizeVal
) )
443 aMPS
.aPaperSize
.Width() = aSizeVal
.Width
;
444 aMPS
.aPaperSize
.Height() = aSizeVal
.Height
;
447 xController
->setMultipage( aMPS
);
450 // in direct print case check whether there is anything to print.
451 // if not, show an errorbox (if appropriate)
452 if( xController
->isShowDialogs() && xController
->isDirectPrint() )
454 if( xController
->getFilteredPageCount() == 0 )
456 ScopedVclPtrInstance
<MessageDialog
> aBox(
457 nullptr, "ErrorNoContentDialog",
458 "vcl/ui/errornocontentdialog.ui");
464 // check if the printer brings up its own dialog
465 // in that case leave the work to that dialog
466 if( ! xController
->getPrinter()->GetCapabilities( PrinterCapType::ExternalDialog
) &&
467 ! xController
->isDirectPrint() &&
468 xController
->isShowDialogs()
473 ScopedVclPtrInstance
< PrintDialog
> aDlg( nullptr, xController
);
474 if( ! aDlg
->Execute() )
476 xController
->abortJob();
479 if( aDlg
->isPrintToFile() )
481 OUString aFile
= queryFile( xController
->getPrinter().get() );
482 if( aFile
.isEmpty() )
484 xController
->abortJob();
487 xController
->setValue( "LocalFileName",
488 css::uno::makeAny( aFile
) );
490 else if( aDlg
->isSingleJobs() )
492 xController
->setValue( "PrintCollateAsSingleJobs",
493 css::uno::makeAny( true ) );
496 catch (const std::bad_alloc
&)
501 xController
->pushPropertiesToPrinter();
505 bool Printer::ExecutePrintJob(std::shared_ptr
<PrinterController
> xController
)
508 css::beans::PropertyValue
* pJobNameVal
= xController
->getValue( OUString( "JobName" ) );
510 pJobNameVal
->Value
>>= aJobName
;
512 return xController
->getPrinter()->StartJob( aJobName
, xController
);
515 void Printer::FinishPrintJob(const std::shared_ptr
<PrinterController
>& xController
)
517 xController
->resetPaperToLastConfigured();
518 xController
->jobFinished( xController
->getJobState() );
521 void Printer::ImplPrintJob(const std::shared_ptr
<PrinterController
>& xController
,
522 const JobSetup
& i_rInitSetup
)
524 if (PreparePrintJob(xController
, i_rInitSetup
))
526 ExecutePrintJob(xController
);
528 FinishPrintJob(xController
);
531 bool Printer::StartJob( const OUString
& i_rJobName
, std::shared_ptr
<vcl::PrinterController
>& i_xController
)
533 mnError
= PRINTER_OK
;
535 if ( IsDisplayPrinter() )
538 if ( IsJobActive() || IsPrinting() )
541 sal_uInt32 nCopies
= mnCopyCount
;
542 bool bCollateCopy
= mbCollateCopy
;
543 bool bUserCopy
= false;
547 const sal_uInt32 nDevCopy
= GetCapabilities( bCollateCopy
548 ? PrinterCapType::CollateCopies
549 : PrinterCapType::Copies
);
551 // need to do copies by hand ?
552 if ( nCopies
> nDevCopy
)
556 bCollateCopy
= false;
560 bCollateCopy
= false;
562 ImplSVData
* pSVData
= ImplGetSVData();
563 mpPrinter
= pSVData
->mpDefInst
->CreatePrinter( mpInfoPrinter
);
568 bool bSinglePrintJobs
= false;
569 css::beans::PropertyValue
* pSingleValue
= i_xController
->getValue(OUString("PrintCollateAsSingleJobs"));
572 pSingleValue
->Value
>>= bSinglePrintJobs
;
575 css::beans::PropertyValue
* pFileValue
= i_xController
->getValue(OUString("LocalFileName"));
579 pFileValue
->Value
>>= aFile
;
580 if( !aFile
.isEmpty() )
584 bSinglePrintJobs
= false;
588 OUString
* pPrintFile
= nullptr;
590 pPrintFile
= &maPrintFile
;
591 mpPrinterOptions
->ReadFromConfig( mbPrintFile
);
593 maJobName
= i_rJobName
;
597 if( GetCapabilities( PrinterCapType::UsePullModel
) )
600 // SAL layer does all necessary page printing
601 // and also handles showing a dialog
602 // that also means it must call jobStarted when the dialog is finished
603 // it also must set the JobState of the Controller
604 if( mpPrinter
->StartJob( pPrintFile
,
606 Application::GetDisplayName(),
607 &maJobSetup
.ImplGetData(),
614 mnError
= ImplSalPrinterErrorCodeToVCL(mpPrinter
->GetErrorCode());
616 mnError
= PRINTER_GENERALERROR
;
617 pSVData
->mpDefInst
->DestroyPrinter( mpPrinter
);
624 GDIMetaFile aDummyFile
;
625 i_xController
->setLastPage(true);
626 i_xController
->getFilteredPageFile(0, aDummyFile
);
633 // possibly a dialog has been shown
634 // now the real job starts
635 i_xController
->setJobState( css::view::PrintableState_JOB_STARTED
);
636 i_xController
->jobStarted();
639 int nOuterRepeatCount
= 1;
640 int nInnerRepeatCount
= 1;
644 nOuterRepeatCount
= mnCopyCount
;
646 nInnerRepeatCount
= mnCopyCount
;
648 if( bSinglePrintJobs
)
652 nOuterRepeatCount
= nInnerRepeatCount
= 1;
655 for( int nJobIteration
= 0; nJobIteration
< nJobs
; nJobIteration
++ )
658 if( mpPrinter
->StartJob( pPrintFile
,
660 Application::GetDisplayName(),
663 i_xController
->isDirectPrint(),
664 &maJobSetup
.ImplGetData() ) )
666 bool bAborted
= false;
668 i_xController
->createProgressDialog();
669 const int nPages
= i_xController
->getFilteredPageCount();
670 // abort job, if no pages will be printed.
673 i_xController
->abortJob();
676 for( int nOuterIteration
= 0; nOuterIteration
< nOuterRepeatCount
&& ! bAborted
; nOuterIteration
++ )
678 for( int nPage
= 0; nPage
< nPages
&& ! bAborted
; nPage
++ )
680 for( int nInnerIteration
= 0; nInnerIteration
< nInnerRepeatCount
&& ! bAborted
; nInnerIteration
++ )
682 if( nPage
== nPages
-1 &&
683 nOuterIteration
== nOuterRepeatCount
-1 &&
684 nInnerIteration
== nInnerRepeatCount
-1 &&
685 nJobIteration
== nJobs
-1 )
687 i_xController
->setLastPage(true);
689 i_xController
->printFilteredPage(nPage
);
690 if (i_xController
->isProgressCanceled())
692 i_xController
->abortJob();
694 if (i_xController
->getJobState() ==
695 css::view::PrintableState_JOB_ABORTED
)
705 if( nJobIteration
< nJobs
-1 )
707 mpPrinter
= pSVData
->mpDefInst
->CreatePrinter( mpInfoPrinter
);
711 maJobName
= i_rJobName
;
725 mnError
= mpPrinter
? ImplSalPrinterErrorCodeToVCL(mpPrinter
->GetErrorCode()) : 0;
727 mnError
= PRINTER_GENERALERROR
;
728 i_xController
->setJobState( mnError
== PRINTER_ABORT
729 ? css::view::PrintableState_JOB_ABORTED
730 : css::view::PrintableState_JOB_FAILED
);
732 pSVData
->mpDefInst
->DestroyPrinter( mpPrinter
);
742 if (i_xController
->getJobState() == css::view::PrintableState_JOB_STARTED
)
743 i_xController
->setJobState(css::view::PrintableState_JOB_SPOOLED
);
746 // make last used printer persistent for UI jobs
747 if (i_xController
->isShowDialogs() && !i_xController
->isDirectPrint())
749 SettingsConfigItem
* pItem
= SettingsConfigItem::get();
750 pItem
->setValue( "PrintDialog",
759 PrinterController::~PrinterController()
763 css::view::PrintableState
PrinterController::getJobState() const
765 return mpImplData
->meJobState
;
768 void PrinterController::setJobState( css::view::PrintableState i_eState
)
770 mpImplData
->meJobState
= i_eState
;
773 const VclPtr
<Printer
>& PrinterController::getPrinter() const
775 return mpImplData
->mxPrinter
;
778 void PrinterController::setPrinter( const VclPtr
<Printer
>& i_rPrinter
)
780 mpImplData
->mxPrinter
= i_rPrinter
;
782 css::uno::makeAny( OUString( i_rPrinter
->GetName() ) ) );
783 mpImplData
->mnDefaultPaperBin
= mpImplData
->mxPrinter
->GetPaperBin();
784 mpImplData
->mxPrinter
->Push();
785 mpImplData
->mxPrinter
->SetMapMode(MapMode(MapUnit::Map100thMM
));
786 mpImplData
->maDefaultPageSize
= mpImplData
->mxPrinter
->GetPaperSize();
787 mpImplData
->mxPrinter
->Pop();
788 mpImplData
->mnFixedPaperBin
= -1;
791 void PrinterController::resetPrinterOptions( bool i_bFileOutput
)
794 aOpt
.ReadFromConfig( i_bFileOutput
);
795 mpImplData
->mxPrinter
->SetPrinterOptions( aOpt
);
798 bool PrinterController::setupPrinter( vcl::Window
* i_pParent
)
802 // Important to hold printer alive while doing setup etc.
803 VclPtr
< Printer
> xPrinter
= mpImplData
->mxPrinter
;
808 xPrinter
->SetMapMode(MapMode(MapUnit::Map100thMM
));
811 Size
aPaperSize(xPrinter
->GetPaperSize());
812 sal_uInt16 nPaperBin
= xPrinter
->GetPaperBin();
814 // reset paper size back to last configured size, not
815 // whatever happens to be the current page
816 // (but only if the printer config has changed, otherwise
817 // don't override printer page auto-detection - tdf#91362)
818 if (getPrinterModified())
820 resetPaperToLastConfigured();
824 bRet
= xPrinter
->Setup( i_pParent
, getPapersizeFromSetup() );
825 SAL_WARN_IF(xPrinter
!= mpImplData
->mxPrinter
, "vcl.gdi",
826 "Printer changed underneath us during setup");
827 xPrinter
= mpImplData
->mxPrinter
;
829 Size
aNewPaperSize(xPrinter
->GetPaperSize());
832 bool bInvalidateCache
= false;
834 // was papersize overridden ? if so we need to take action if we're
835 // configured to use the driver papersize
836 if (aNewPaperSize
!= mpImplData
->maDefaultPageSize
)
838 mpImplData
->maDefaultPageSize
= aNewPaperSize
;
839 bInvalidateCache
= getPapersizeFromSetup();
842 // was bin overridden ? if so we need to take action
843 sal_uInt16 nNewPaperBin
= xPrinter
->GetPaperBin();
844 if (nNewPaperBin
!= nPaperBin
)
846 mpImplData
->mnFixedPaperBin
= nNewPaperBin
;
847 bInvalidateCache
= true;
850 if (bInvalidateCache
)
852 mpImplData
->maPageCache
.invalidate();
857 //restore to whatever it was before we entered this method
858 if (aPaperSize
!= aNewPaperSize
)
859 xPrinter
->SetPaperSizeUser(aPaperSize
, !mpImplData
->isFixedPageSize());
866 PrinterController::PageSize
vcl::ImplPrinterControllerData::modifyJobSetup( const css::uno::Sequence
< css::beans::PropertyValue
>& i_rProps
)
868 PrinterController::PageSize aPageSize
;
869 aPageSize
.aSize
= mxPrinter
->GetPaperSize();
870 css::awt::Size aSetSize
, aIsSize
;
871 sal_Int32 nPaperBin
= mnDefaultPaperBin
;
872 for( sal_Int32 nProperty
= 0, nPropertyCount
= i_rProps
.getLength(); nProperty
< nPropertyCount
; ++nProperty
)
874 if ( i_rProps
[ nProperty
].Name
== "PreferredPageSize" )
876 i_rProps
[ nProperty
].Value
>>= aSetSize
;
878 else if ( i_rProps
[ nProperty
].Name
== "PageSize" )
880 i_rProps
[ nProperty
].Value
>>= aIsSize
;
882 else if ( i_rProps
[ nProperty
].Name
== "PageIncludesNonprintableArea" )
885 i_rProps
[ nProperty
].Value
>>= bVal
;
886 aPageSize
.bFullPaper
= bVal
;
888 else if ( i_rProps
[ nProperty
].Name
== "PrinterPaperTray" )
891 i_rProps
[ nProperty
].Value
>>= nBin
;
892 if( nBin
>= 0 && nBin
< static_cast<sal_Int32
>(mxPrinter
->GetPaperBinCount()) )
897 Size
aCurSize( mxPrinter
->GetPaperSize() );
898 if( aSetSize
.Width
&& aSetSize
.Height
)
900 Size
aSetPaperSize( aSetSize
.Width
, aSetSize
.Height
);
901 Size
aRealPaperSize( getRealPaperSize( aSetPaperSize
, true/*bNoNUP*/ ) );
902 if( aRealPaperSize
!= aCurSize
)
906 if( aIsSize
.Width
&& aIsSize
.Height
)
908 aPageSize
.aSize
.Width() = aIsSize
.Width
;
909 aPageSize
.aSize
.Height() = aIsSize
.Height
;
911 Size
aRealPaperSize( getRealPaperSize( aPageSize
.aSize
, true/*bNoNUP*/ ) );
912 if( aRealPaperSize
!= aCurSize
)
913 mxPrinter
->SetPaperSizeUser( aRealPaperSize
, ! isFixedPageSize() );
916 // paper bin set from properties in print dialog overrides
917 // application default for a page
918 if ( mnFixedPaperBin
!= -1 )
919 nPaperBin
= mnFixedPaperBin
;
921 if( nPaperBin
!= -1 && nPaperBin
!= mxPrinter
->GetPaperBin() )
922 mxPrinter
->SetPaperBin( nPaperBin
);
929 //when printing is finished, set the paper size of the printer to either what
930 //the user explicitly set as the desired paper size, or fallback to whatever
931 //the printer had before printing started. That way it doesn't contain the last
932 //paper size of a multiple paper size using document when we are in our normal
933 //auto accept document paper size mode and end up overwriting the original
934 //paper size setting for file->printer_settings just by pressing "ok" in the
936 void vcl::ImplPrinterControllerData::resetPaperToLastConfigured()
939 mxPrinter
->SetMapMode(MapMode(MapUnit::Map100thMM
));
940 Size
aCurSize(mxPrinter
->GetPaperSize());
941 if (aCurSize
!= maDefaultPageSize
)
942 mxPrinter
->SetPaperSizeUser(maDefaultPageSize
, !isFixedPageSize());
946 int PrinterController::getPageCountProtected() const
948 const MapMode
aMapMode( MapUnit::Map100thMM
);
950 mpImplData
->mxPrinter
->Push();
951 mpImplData
->mxPrinter
->SetMapMode( aMapMode
);
952 int nPages
= getPageCount();
953 mpImplData
->mxPrinter
->Pop();
957 css::uno::Sequence
< css::beans::PropertyValue
> PrinterController::getPageParametersProtected( int i_nPage
) const
959 const MapMode
aMapMode( MapUnit::Map100thMM
);
961 mpImplData
->mxPrinter
->Push();
962 mpImplData
->mxPrinter
->SetMapMode( aMapMode
);
963 css::uno::Sequence
< css::beans::PropertyValue
> aResult( getPageParameters( i_nPage
) );
964 mpImplData
->mxPrinter
->Pop();
968 PrinterController::PageSize
PrinterController::getPageFile( int i_nUnfilteredPage
, GDIMetaFile
& o_rMtf
, bool i_bMayUseCache
)
970 // update progress if necessary
971 if( mpImplData
->mpProgress
)
973 // do nothing if printing is canceled
974 if( mpImplData
->mpProgress
->isCanceled() )
975 return PrinterController::PageSize();
976 mpImplData
->mpProgress
->tick();
977 Application::Reschedule( true );
982 PrinterController::PageSize aPageSize
;
983 if( mpImplData
->maPageCache
.get( i_nUnfilteredPage
, o_rMtf
, aPageSize
) )
989 mpImplData
->maPageCache
.invalidate();
993 // get page parameters
994 css::uno::Sequence
< css::beans::PropertyValue
> aPageParm( getPageParametersProtected( i_nUnfilteredPage
) );
995 const MapMode
aMapMode( MapUnit::Map100thMM
);
997 mpImplData
->mxPrinter
->Push();
998 mpImplData
->mxPrinter
->SetMapMode( aMapMode
);
1000 // modify job setup if necessary
1001 PrinterController::PageSize aPageSize
= mpImplData
->modifyJobSetup( aPageParm
);
1003 o_rMtf
.SetPrefSize( aPageSize
.aSize
);
1004 o_rMtf
.SetPrefMapMode( aMapMode
);
1006 mpImplData
->mxPrinter
->EnableOutput( false );
1008 o_rMtf
.Record( mpImplData
->mxPrinter
.get() );
1010 printPage( i_nUnfilteredPage
);
1014 mpImplData
->mxPrinter
->Pop();
1016 if( i_bMayUseCache
)
1017 mpImplData
->maPageCache
.insert( i_nUnfilteredPage
, o_rMtf
, aPageSize
);
1019 // reset "FirstPage" property to false now we've gotten at least our first one
1020 mpImplData
->mbFirstPage
= false;
1025 static void appendSubPage( GDIMetaFile
& o_rMtf
, const tools::Rectangle
& i_rClipRect
, GDIMetaFile
& io_rSubPage
, bool i_bDrawBorder
)
1027 // intersect all clipregion actions with our clip rect
1028 io_rSubPage
.WindStart();
1029 io_rSubPage
.Clip( i_rClipRect
);
1032 o_rMtf
.AddAction( new MetaPushAction( PushFlags::ALL
) );
1034 // clip to page rect
1035 o_rMtf
.AddAction( new MetaClipRegionAction( vcl::Region( i_rClipRect
), true ) );
1037 // append the subpage
1038 io_rSubPage
.WindStart();
1039 io_rSubPage
.Play( o_rMtf
);
1042 o_rMtf
.AddAction( new MetaPopAction() );
1048 o_rMtf
.AddAction( new MetaPushAction( PushFlags::LINECOLOR
| PushFlags::FILLCOLOR
| PushFlags::CLIPREGION
| PushFlags::MAPMODE
) );
1049 o_rMtf
.AddAction( new MetaMapModeAction( MapMode( MapUnit::Map100thMM
) ) );
1051 tools::Rectangle
aBorderRect( i_rClipRect
);
1052 o_rMtf
.AddAction( new MetaLineColorAction( Color( COL_BLACK
), true ) );
1053 o_rMtf
.AddAction( new MetaFillColorAction( Color( COL_TRANSPARENT
), false ) );
1054 o_rMtf
.AddAction( new MetaRectAction( aBorderRect
) );
1057 o_rMtf
.AddAction( new MetaPopAction() );
1061 PrinterController::PageSize
PrinterController::getFilteredPageFile( int i_nFilteredPage
, GDIMetaFile
& o_rMtf
, bool i_bMayUseCache
)
1063 const MultiPageSetup
& rMPS( mpImplData
->maMultiPage
);
1064 int nSubPages
= rMPS
.nRows
* rMPS
.nColumns
;
1068 // reverse sheet order
1069 if( mpImplData
->mbReversePageOrder
)
1071 int nDocPages
= getFilteredPageCount();
1072 i_nFilteredPage
= nDocPages
- 1 - i_nFilteredPage
;
1075 // there is no filtering to be done (and possibly the page size of the
1076 // original page is to be set), when N-Up is "neutral" that is there is
1077 // only one subpage and the margins are 0
1078 if( nSubPages
== 1 &&
1079 rMPS
.nLeftMargin
== 0 && rMPS
.nRightMargin
== 0 &&
1080 rMPS
.nTopMargin
== 0 && rMPS
.nBottomMargin
== 0 )
1082 PrinterController::PageSize aPageSize
= getPageFile( i_nFilteredPage
, o_rMtf
, i_bMayUseCache
);
1083 if (mpImplData
->meJobState
!= css::view::PrintableState_JOB_STARTED
)
1084 { // rhbz#657394: check that we are still printing...
1085 return PrinterController::PageSize();
1087 Size aPaperSize
= mpImplData
->getRealPaperSize( aPageSize
.aSize
, true );
1088 mpImplData
->mxPrinter
->SetMapMode( MapMode( MapUnit::Map100thMM
) );
1089 mpImplData
->mxPrinter
->SetPaperSizeUser( aPaperSize
, ! mpImplData
->isFixedPageSize() );
1090 if( aPaperSize
!= aPageSize
.aSize
)
1092 // user overridden page size, center Metafile
1094 long nDX
= (aPaperSize
.Width() - aPageSize
.aSize
.Width()) / 2;
1095 long nDY
= (aPaperSize
.Height() - aPageSize
.aSize
.Height()) / 2;
1096 o_rMtf
.Move( nDX
, nDY
, mpImplData
->mxPrinter
->GetDPIX(), mpImplData
->mxPrinter
->GetDPIY() );
1098 o_rMtf
.SetPrefSize( aPaperSize
);
1099 aPageSize
.aSize
= aPaperSize
;
1104 // set last page property really only on the very last page to be rendered
1105 // that is on the last subpage of a NUp run
1106 bool bIsLastPage
= mpImplData
->mbLastPage
;
1107 mpImplData
->mbLastPage
= false;
1109 Size
aPaperSize( mpImplData
->getRealPaperSize( mpImplData
->maMultiPage
.aPaperSize
, false ) );
1111 // multi page area: page size minus margins + one time spacing right and down
1112 // the added spacing is so each subpage can be calculated including its spacing
1113 Size
aMPArea( aPaperSize
);
1114 aMPArea
.Width() -= rMPS
.nLeftMargin
+ rMPS
.nRightMargin
;
1115 aMPArea
.Width() += rMPS
.nHorizontalSpacing
;
1116 aMPArea
.Height() -= rMPS
.nTopMargin
+ rMPS
.nBottomMargin
;
1117 aMPArea
.Height() += rMPS
.nVerticalSpacing
;
1119 // determine offsets
1120 long nAdvX
= aMPArea
.Width() / rMPS
.nColumns
;
1121 long nAdvY
= aMPArea
.Height() / rMPS
.nRows
;
1123 // determine size of a "cell" subpage, leave a little space around pages
1124 Size
aSubPageSize( nAdvX
- rMPS
.nHorizontalSpacing
, nAdvY
- rMPS
.nVerticalSpacing
);
1127 o_rMtf
.SetPrefSize( aPaperSize
);
1128 o_rMtf
.SetPrefMapMode( MapMode( MapUnit::Map100thMM
) );
1129 o_rMtf
.AddAction( new MetaMapModeAction( MapMode( MapUnit::Map100thMM
) ) );
1131 int nDocPages
= getPageCountProtected();
1132 if (mpImplData
->meJobState
!= css::view::PrintableState_JOB_STARTED
)
1133 { // rhbz#657394: check that we are still printing...
1134 return PrinterController::PageSize();
1136 for( int nSubPage
= 0; nSubPage
< nSubPages
; nSubPage
++ )
1138 // map current sub page to real page
1139 int nPage
= i_nFilteredPage
* nSubPages
+ nSubPage
;
1140 if( nSubPage
== nSubPages
-1 ||
1141 nPage
== nDocPages
-1 )
1143 mpImplData
->mbLastPage
= bIsLastPage
;
1145 if( nPage
>= 0 && nPage
< nDocPages
)
1147 GDIMetaFile aPageFile
;
1148 PrinterController::PageSize aPageSize
= getPageFile( nPage
, aPageFile
, i_bMayUseCache
);
1149 if( aPageSize
.aSize
.Width() && aPageSize
.aSize
.Height() )
1151 long nCellX
= 0, nCellY
= 0;
1152 switch( rMPS
.nOrder
)
1154 case NupOrderType::LRTB
:
1155 nCellX
= (nSubPage
% rMPS
.nColumns
);
1156 nCellY
= (nSubPage
/ rMPS
.nColumns
);
1158 case NupOrderType::TBLR
:
1159 nCellX
= (nSubPage
/ rMPS
.nRows
);
1160 nCellY
= (nSubPage
% rMPS
.nRows
);
1162 case NupOrderType::RLTB
:
1163 nCellX
= rMPS
.nColumns
- 1 - (nSubPage
% rMPS
.nColumns
);
1164 nCellY
= (nSubPage
/ rMPS
.nColumns
);
1166 case NupOrderType::TBRL
:
1167 nCellX
= rMPS
.nColumns
- 1 - (nSubPage
/ rMPS
.nRows
);
1168 nCellY
= (nSubPage
% rMPS
.nRows
);
1171 // scale the metafile down to a sub page size
1172 double fScaleX
= double(aSubPageSize
.Width())/double(aPageSize
.aSize
.Width());
1173 double fScaleY
= double(aSubPageSize
.Height())/double(aPageSize
.aSize
.Height());
1174 double fScale
= std::min( fScaleX
, fScaleY
);
1175 aPageFile
.Scale( fScale
, fScale
);
1176 aPageFile
.WindStart();
1178 // move the subpage so it is centered in its "cell"
1179 long nOffX
= (aSubPageSize
.Width() - long(double(aPageSize
.aSize
.Width()) * fScale
)) / 2;
1180 long nOffY
= (aSubPageSize
.Height() - long(double(aPageSize
.aSize
.Height()) * fScale
)) / 2;
1181 long nX
= rMPS
.nLeftMargin
+ nOffX
+ nAdvX
* nCellX
;
1182 long nY
= rMPS
.nTopMargin
+ nOffY
+ nAdvY
* nCellY
;
1183 aPageFile
.Move( nX
, nY
, mpImplData
->mxPrinter
->GetDPIX(), mpImplData
->mxPrinter
->GetDPIY() );
1184 aPageFile
.WindStart();
1185 // calculate border rectangle
1186 tools::Rectangle
aSubPageRect( Point( nX
, nY
),
1187 Size( long(double(aPageSize
.aSize
.Width())*fScale
),
1188 long(double(aPageSize
.aSize
.Height())*fScale
) ) );
1190 // append subpage to page
1191 appendSubPage( o_rMtf
, aSubPageRect
, aPageFile
, rMPS
.bDrawBorder
);
1197 // subsequent getPageFile calls have changed the paper, reset it to current value
1198 mpImplData
->mxPrinter
->SetMapMode( MapMode( MapUnit::Map100thMM
) );
1199 mpImplData
->mxPrinter
->SetPaperSizeUser( aPaperSize
, ! mpImplData
->isFixedPageSize() );
1201 return PrinterController::PageSize( aPaperSize
, true );
1204 int PrinterController::getFilteredPageCount()
1206 int nDiv
= mpImplData
->maMultiPage
.nRows
* mpImplData
->maMultiPage
.nColumns
;
1209 return (getPageCountProtected() + (nDiv
-1)) / nDiv
;
1212 DrawModeFlags
PrinterController::removeTransparencies( GDIMetaFile
& i_rIn
, GDIMetaFile
& o_rOut
)
1214 DrawModeFlags nRestoreDrawMode
= mpImplData
->mxPrinter
->GetDrawMode();
1215 sal_Int32 nMaxBmpDPIX
= mpImplData
->mxPrinter
->GetDPIX();
1216 sal_Int32 nMaxBmpDPIY
= mpImplData
->mxPrinter
->GetDPIY();
1218 const PrinterOptions
& rPrinterOptions
= mpImplData
->mxPrinter
->GetPrinterOptions();
1220 static const sal_Int32 OPTIMAL_BMP_RESOLUTION
= 300;
1221 static const sal_Int32 NORMAL_BMP_RESOLUTION
= 200;
1223 if( rPrinterOptions
.IsReduceBitmaps() )
1225 // calculate maximum resolution for bitmap graphics
1226 if( PrinterBitmapMode::Optimal
== rPrinterOptions
.GetReducedBitmapMode() )
1228 nMaxBmpDPIX
= std::min( sal_Int32(OPTIMAL_BMP_RESOLUTION
), nMaxBmpDPIX
);
1229 nMaxBmpDPIY
= std::min( sal_Int32(OPTIMAL_BMP_RESOLUTION
), nMaxBmpDPIY
);
1231 else if( PrinterBitmapMode::Normal
== rPrinterOptions
.GetReducedBitmapMode() )
1233 nMaxBmpDPIX
= std::min( sal_Int32(NORMAL_BMP_RESOLUTION
), nMaxBmpDPIX
);
1234 nMaxBmpDPIY
= std::min( sal_Int32(NORMAL_BMP_RESOLUTION
), nMaxBmpDPIY
);
1238 nMaxBmpDPIX
= std::min( sal_Int32(rPrinterOptions
.GetReducedBitmapResolution()), nMaxBmpDPIX
);
1239 nMaxBmpDPIY
= std::min( sal_Int32(rPrinterOptions
.GetReducedBitmapResolution()), nMaxBmpDPIY
);
1243 // convert to greyscales
1244 if( rPrinterOptions
.IsConvertToGreyscales() )
1246 mpImplData
->mxPrinter
->SetDrawMode( mpImplData
->mxPrinter
->GetDrawMode() |
1247 ( DrawModeFlags::GrayLine
| DrawModeFlags::GrayFill
| DrawModeFlags::GrayText
|
1248 DrawModeFlags::GrayBitmap
| DrawModeFlags::GrayGradient
) );
1251 // disable transparency output
1252 if( rPrinterOptions
.IsReduceTransparency() && ( PrinterTransparencyMode::NONE
== rPrinterOptions
.GetReducedTransparencyMode() ) )
1254 mpImplData
->mxPrinter
->SetDrawMode( mpImplData
->mxPrinter
->GetDrawMode() | DrawModeFlags::NoTransparency
);
1257 Color
aBg( COL_TRANSPARENT
); // default: let RemoveTransparenciesFromMetaFile do its own background logic
1258 if( mpImplData
->maMultiPage
.nRows
* mpImplData
->maMultiPage
.nColumns
> 1 )
1260 // in N-Up printing we have no "page" background operation
1261 // we also have no way to determine the paper color
1262 // so let's go for white, which will kill 99.9% of the real cases
1263 aBg
= Color( COL_WHITE
);
1265 mpImplData
->mxPrinter
->RemoveTransparenciesFromMetaFile( i_rIn
, o_rOut
, nMaxBmpDPIX
, nMaxBmpDPIY
,
1266 rPrinterOptions
.IsReduceTransparency(),
1267 rPrinterOptions
.GetReducedTransparencyMode() == PrinterTransparencyMode::Auto
,
1268 rPrinterOptions
.IsReduceBitmaps() && rPrinterOptions
.IsReducedBitmapIncludesTransparency(),
1271 return nRestoreDrawMode
;
1274 void PrinterController::printFilteredPage( int i_nPage
)
1276 if( mpImplData
->meJobState
!= css::view::PrintableState_JOB_STARTED
)
1279 GDIMetaFile aPageFile
;
1280 PrinterController::PageSize aPageSize
= getFilteredPageFile( i_nPage
, aPageFile
);
1282 if (mpImplData
->meJobState
!= css::view::PrintableState_JOB_STARTED
)
1283 { // rhbz#657394: check that we are still printing...
1287 if( mpImplData
->mpProgress
)
1289 // do nothing if printing is canceled
1290 if( mpImplData
->mpProgress
->isCanceled() )
1292 setJobState( css::view::PrintableState_JOB_ABORTED
);
1297 // in N-Up printing set the correct page size
1298 mpImplData
->mxPrinter
->SetMapMode( MapUnit::Map100thMM
);
1299 // aPageSize was filtered through mpImplData->getRealPaperSize already by getFilteredPageFile()
1300 mpImplData
->mxPrinter
->SetPaperSizeUser( aPageSize
.aSize
, ! mpImplData
->isFixedPageSize() );
1301 if( mpImplData
->mnFixedPaperBin
!= -1 &&
1302 mpImplData
->mxPrinter
->GetPaperBin() != mpImplData
->mnFixedPaperBin
)
1304 mpImplData
->mxPrinter
->SetPaperBin( mpImplData
->mnFixedPaperBin
);
1307 // if full paper is meant to be used, move the output to accommodate for pageoffset
1308 if( aPageSize
.bFullPaper
)
1310 Point
aPageOffset( mpImplData
->mxPrinter
->GetPageOffset() );
1311 aPageFile
.WindStart();
1312 aPageFile
.Move( -aPageOffset
.X(), -aPageOffset
.Y(), mpImplData
->mxPrinter
->GetDPIX(), mpImplData
->mxPrinter
->GetDPIY() );
1315 GDIMetaFile aCleanedFile
;
1316 DrawModeFlags nRestoreDrawMode
= removeTransparencies( aPageFile
, aCleanedFile
);
1318 mpImplData
->mxPrinter
->EnableOutput();
1320 // actually print the page
1321 mpImplData
->mxPrinter
->ImplStartPage();
1323 mpImplData
->mxPrinter
->Push();
1324 aCleanedFile
.WindStart();
1325 aCleanedFile
.Play( mpImplData
->mxPrinter
.get() );
1326 mpImplData
->mxPrinter
->Pop();
1328 mpImplData
->mxPrinter
->ImplEndPage();
1330 mpImplData
->mxPrinter
->SetDrawMode( nRestoreDrawMode
);
1333 void PrinterController::jobStarted()
1337 void PrinterController::jobFinished( css::view::PrintableState
)
1341 void PrinterController::abortJob()
1343 setJobState( css::view::PrintableState_JOB_ABORTED
);
1344 // applications (well, sw) depend on a page request with "IsLastPage" = true
1345 // to free resources, else they (well, sw) will crash eventually
1346 setLastPage( true );
1347 mpImplData
->mpProgress
.disposeAndClear();
1349 getPageFile( 0, aMtf
);
1352 void PrinterController::setLastPage( bool i_bLastPage
)
1354 mpImplData
->mbLastPage
= i_bLastPage
;
1357 void PrinterController::setReversePrint( bool i_bReverse
)
1359 mpImplData
->mbReversePageOrder
= i_bReverse
;
1362 bool PrinterController::getReversePrint() const
1364 return mpImplData
->mbReversePageOrder
;
1367 void PrinterController::setPapersizeFromSetup( bool i_bPapersizeFromSetup
)
1369 mpImplData
->mbPapersizeFromSetup
= i_bPapersizeFromSetup
;
1372 bool PrinterController::getPapersizeFromSetup() const
1374 return mpImplData
->mbPapersizeFromSetup
;
1377 void PrinterController::setPrinterModified( bool i_bPrinterModified
)
1379 mpImplData
->mbPrinterModified
= i_bPrinterModified
;
1382 bool PrinterController::getPrinterModified() const
1384 return mpImplData
->mbPrinterModified
;
1387 css::uno::Sequence
< css::beans::PropertyValue
> PrinterController::getJobProperties( const css::uno::Sequence
< css::beans::PropertyValue
>& i_rMergeList
) const
1389 std::unordered_set
< OUString
, OUStringHash
> aMergeSet
;
1390 size_t nResultLen
= size_t(i_rMergeList
.getLength()) + mpImplData
->maUIProperties
.size() + 3;
1391 for( int i
= 0; i
< i_rMergeList
.getLength(); i
++ )
1392 aMergeSet
.insert( i_rMergeList
[i
].Name
);
1394 css::uno::Sequence
< css::beans::PropertyValue
> aResult( nResultLen
);
1395 for( int i
= 0; i
< i_rMergeList
.getLength(); i
++ )
1396 aResult
[i
] = i_rMergeList
[i
];
1397 int nCur
= i_rMergeList
.getLength();
1398 for(css::beans::PropertyValue
& rPropVal
: mpImplData
->maUIProperties
)
1400 if( aMergeSet
.find( rPropVal
.Name
) == aMergeSet
.end() )
1401 aResult
[nCur
++] = rPropVal
;
1403 // append IsFirstPage
1404 if( aMergeSet
.find( OUString( "IsFirstPage" ) ) == aMergeSet
.end() )
1406 css::beans::PropertyValue aVal
;
1407 aVal
.Name
= "IsFirstPage";
1408 aVal
.Value
<<= mpImplData
->mbFirstPage
;
1409 aResult
[nCur
++] = aVal
;
1411 // append IsLastPage
1412 if( aMergeSet
.find( OUString( "IsLastPage" ) ) == aMergeSet
.end() )
1414 css::beans::PropertyValue aVal
;
1415 aVal
.Name
= "IsLastPage";
1416 aVal
.Value
<<= mpImplData
->mbLastPage
;
1417 aResult
[nCur
++] = aVal
;
1420 if( aMergeSet
.find( OUString( "IsPrinter" ) ) == aMergeSet
.end() )
1422 css::beans::PropertyValue aVal
;
1423 aVal
.Name
= "IsPrinter";
1424 aVal
.Value
<<= true;
1425 aResult
[nCur
++] = aVal
;
1427 aResult
.realloc( nCur
);
1431 const css::uno::Sequence
< css::beans::PropertyValue
>& PrinterController::getUIOptions() const
1433 return mpImplData
->maUIOptions
;
1436 css::beans::PropertyValue
* PrinterController::getValue( const OUString
& i_rProperty
)
1438 std::unordered_map
< OUString
, size_t, OUStringHash
>::const_iterator it
=
1439 mpImplData
->maPropertyToIndex
.find( i_rProperty
);
1440 return it
!= mpImplData
->maPropertyToIndex
.end() ? &mpImplData
->maUIProperties
[it
->second
] : nullptr;
1443 const css::beans::PropertyValue
* PrinterController::getValue( const OUString
& i_rProperty
) const
1445 std::unordered_map
< OUString
, size_t, OUStringHash
>::const_iterator it
=
1446 mpImplData
->maPropertyToIndex
.find( i_rProperty
);
1447 return it
!= mpImplData
->maPropertyToIndex
.end() ? &mpImplData
->maUIProperties
[it
->second
] : nullptr;
1450 void PrinterController::setValue( const OUString
& i_rPropertyName
, const css::uno::Any
& i_rValue
)
1452 css::beans::PropertyValue aVal
;
1453 aVal
.Name
= i_rPropertyName
;
1454 aVal
.Value
= i_rValue
;
1459 void PrinterController::setValue( const css::beans::PropertyValue
& i_rPropertyValue
)
1461 std::unordered_map
< OUString
, size_t, OUStringHash
>::const_iterator it
=
1462 mpImplData
->maPropertyToIndex
.find( i_rPropertyValue
.Name
);
1463 if( it
!= mpImplData
->maPropertyToIndex
.end() )
1464 mpImplData
->maUIProperties
[ it
->second
] = i_rPropertyValue
;
1467 // insert correct index into property map
1468 mpImplData
->maPropertyToIndex
[ i_rPropertyValue
.Name
] = mpImplData
->maUIProperties
.size();
1469 mpImplData
->maUIProperties
.push_back( i_rPropertyValue
);
1470 mpImplData
->maUIPropertyEnabled
.push_back( true );
1474 void PrinterController::setUIOptions( const css::uno::Sequence
< css::beans::PropertyValue
>& i_rOptions
)
1476 SAL_WARN_IF( mpImplData
->maUIOptions
.getLength() != 0, "vcl.gdi", "setUIOptions called twice !" );
1478 mpImplData
->maUIOptions
= i_rOptions
;
1480 for( int i
= 0; i
< i_rOptions
.getLength(); i
++ )
1482 css::uno::Sequence
< css::beans::PropertyValue
> aOptProp
;
1483 i_rOptions
[i
].Value
>>= aOptProp
;
1484 bool bIsEnabled
= true;
1485 bool bHaveProperty
= false;
1487 vcl::ImplPrinterControllerData::ControlDependency aDep
;
1488 css::uno::Sequence
< sal_Bool
> aChoicesDisabled
;
1489 for( int n
= 0; n
< aOptProp
.getLength(); n
++ )
1491 const css::beans::PropertyValue
& rEntry( aOptProp
[ n
] );
1492 if ( rEntry
.Name
== "Property" )
1494 css::beans::PropertyValue aVal
;
1495 rEntry
.Value
>>= aVal
;
1496 DBG_ASSERT( mpImplData
->maPropertyToIndex
.find( aVal
.Name
)
1497 == mpImplData
->maPropertyToIndex
.end(), "duplicate property entry" );
1499 aPropName
= aVal
.Name
;
1500 bHaveProperty
= true;
1502 else if ( rEntry
.Name
== "Enabled" )
1505 rEntry
.Value
>>= bValue
;
1506 bIsEnabled
= bValue
;
1508 else if ( rEntry
.Name
== "DependsOnName" )
1510 rEntry
.Value
>>= aDep
.maDependsOnName
;
1512 else if ( rEntry
.Name
== "DependsOnEntry" )
1514 rEntry
.Value
>>= aDep
.mnDependsOnEntry
;
1516 else if ( rEntry
.Name
== "ChoicesDisabled" )
1518 rEntry
.Value
>>= aChoicesDisabled
;
1523 vcl::ImplPrinterControllerData::PropertyToIndexMap::const_iterator it
=
1524 mpImplData
->maPropertyToIndex
.find( aPropName
);
1526 if( it
!= mpImplData
->maPropertyToIndex
.end() )
1528 mpImplData
->maUIPropertyEnabled
[ it
->second
] = bIsEnabled
;
1530 if( !aDep
.maDependsOnName
.isEmpty() )
1531 mpImplData
->maControlDependencies
[ aPropName
] = aDep
;
1532 if( aChoicesDisabled
.getLength() > 0 )
1533 mpImplData
->maChoiceDisableMap
[ aPropName
] = aChoicesDisabled
;
1538 bool PrinterController::isUIOptionEnabled( const OUString
& i_rProperty
) const
1540 bool bEnabled
= false;
1541 std::unordered_map
< OUString
, size_t, OUStringHash
>::const_iterator prop_it
=
1542 mpImplData
->maPropertyToIndex
.find( i_rProperty
);
1543 if( prop_it
!= mpImplData
->maPropertyToIndex
.end() )
1545 bEnabled
= mpImplData
->maUIPropertyEnabled
[prop_it
->second
];
1549 // check control dependencies
1550 vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it
=
1551 mpImplData
->maControlDependencies
.find( i_rProperty
);
1552 if( it
!= mpImplData
->maControlDependencies
.end() )
1554 // check if the dependency is enabled
1555 // if the dependency is disabled, we are too
1556 bEnabled
= isUIOptionEnabled( it
->second
.maDependsOnName
);
1560 // does the dependency have the correct value ?
1561 const css::beans::PropertyValue
* pVal
= getValue( it
->second
.maDependsOnName
);
1562 OSL_ENSURE( pVal
, "unknown property in dependency" );
1565 sal_Int32 nDepVal
= 0;
1566 bool bDepVal
= false;
1567 if( pVal
->Value
>>= nDepVal
)
1569 bEnabled
= (nDepVal
== it
->second
.mnDependsOnEntry
) || (it
->second
.mnDependsOnEntry
== -1);
1571 else if( pVal
->Value
>>= bDepVal
)
1573 // could be a dependency on a checked boolean
1574 // in this case the dependency is on a non zero for checked value
1575 bEnabled
= ( bDepVal
&& it
->second
.mnDependsOnEntry
!= 0) ||
1576 ( ! bDepVal
&& it
->second
.mnDependsOnEntry
== 0);
1580 // if the type does not match something is awry
1581 OSL_FAIL( "strange type in control dependency" );
1592 bool PrinterController::isUIChoiceEnabled( const OUString
& i_rProperty
, sal_Int32 i_nValue
) const
1594 bool bEnabled
= true;
1595 ImplPrinterControllerData::ChoiceDisableMap::const_iterator it
=
1596 mpImplData
->maChoiceDisableMap
.find( i_rProperty
);
1597 if(it
!= mpImplData
->maChoiceDisableMap
.end() )
1599 const css::uno::Sequence
< sal_Bool
>& rDisabled( it
->second
);
1600 if( i_nValue
>= 0 && i_nValue
< rDisabled
.getLength() )
1601 bEnabled
= ! rDisabled
[i_nValue
];
1606 OUString
PrinterController::getDependency( const OUString
& i_rProperty
) const
1608 OUString aDependency
;
1610 vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it
=
1611 mpImplData
->maControlDependencies
.find( i_rProperty
);
1612 if( it
!= mpImplData
->maControlDependencies
.end() )
1613 aDependency
= it
->second
.maDependsOnName
;
1618 OUString
PrinterController::makeEnabled( const OUString
& i_rProperty
)
1620 OUString aDependency
;
1622 vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it
=
1623 mpImplData
->maControlDependencies
.find( i_rProperty
);
1624 if( it
!= mpImplData
->maControlDependencies
.end() )
1626 if( isUIOptionEnabled( it
->second
.maDependsOnName
) )
1628 aDependency
= it
->second
.maDependsOnName
;
1629 const css::beans::PropertyValue
* pVal
= getValue( aDependency
);
1630 OSL_ENSURE( pVal
, "unknown property in dependency" );
1633 sal_Int32 nDepVal
= 0;
1634 bool bDepVal
= false;
1635 if( pVal
->Value
>>= nDepVal
)
1637 if( it
->second
.mnDependsOnEntry
!= -1 )
1639 setValue( aDependency
, css::uno::makeAny( sal_Int32( it
->second
.mnDependsOnEntry
) ) );
1642 else if( pVal
->Value
>>= bDepVal
)
1644 setValue( aDependency
, css::uno::makeAny( it
->second
.mnDependsOnEntry
!= 0 ) );
1648 // if the type does not match something is awry
1649 OSL_FAIL( "strange type in control dependency" );
1658 void PrinterController::createProgressDialog()
1660 if( ! mpImplData
->mpProgress
)
1663 css::beans::PropertyValue
* pMonitor
= getValue( OUString( "MonitorVisible" ) );
1665 pMonitor
->Value
>>= bShow
;
1668 const css::beans::PropertyValue
* pVal
= getValue( OUString( "IsApi" ) );
1672 pVal
->Value
>>= bApi
;
1677 if( bShow
&& ! Application::IsHeadlessModeEnabled() )
1679 mpImplData
->mpProgress
= VclPtr
<PrintProgressDialog
>::Create( nullptr, getPageCountProtected() );
1680 mpImplData
->mpProgress
->Show();
1684 mpImplData
->mpProgress
->reset();
1687 bool PrinterController::isProgressCanceled() const
1689 return mpImplData
->mpProgress
&& mpImplData
->mpProgress
->isCanceled();
1692 void PrinterController::setMultipage( const MultiPageSetup
& i_rMPS
)
1694 mpImplData
->maMultiPage
= i_rMPS
;
1697 const PrinterController::MultiPageSetup
& PrinterController::getMultipage() const
1699 return mpImplData
->maMultiPage
;
1702 void PrinterController::resetPaperToLastConfigured()
1704 mpImplData
->resetPaperToLastConfigured();
1707 void PrinterController::pushPropertiesToPrinter()
1709 sal_Int32 nCopyCount
= 1;
1710 // set copycount and collate
1711 const css::beans::PropertyValue
* pVal
= getValue( OUString( "CopyCount" ) );
1713 pVal
->Value
>>= nCopyCount
;
1714 bool bCollate
= false;
1715 pVal
= getValue( OUString( "Collate" ) );
1717 pVal
->Value
>>= bCollate
;
1718 mpImplData
->mxPrinter
->SetCopyCount( static_cast<sal_uInt16
>(nCopyCount
), bCollate
);
1721 pVal
= getValue( OUString( "DuplexMode" ) );
1724 sal_Int16 nDuplex
= css::view::DuplexMode::UNKNOWN
;
1725 pVal
->Value
>>= nDuplex
;
1728 case css::view::DuplexMode::OFF
: mpImplData
->mxPrinter
->SetDuplexMode( DuplexMode::Off
); break;
1729 case css::view::DuplexMode::LONGEDGE
: mpImplData
->mxPrinter
->SetDuplexMode( DuplexMode::LongEdge
); break;
1730 case css::view::DuplexMode::SHORTEDGE
: mpImplData
->mxPrinter
->SetDuplexMode( DuplexMode::ShortEdge
); break;
1735 bool PrinterController::isShowDialogs() const
1737 bool bApi
= getBoolProperty( "IsApi", false );
1738 return ! bApi
&& ! Application::IsHeadlessModeEnabled();
1741 bool PrinterController::isDirectPrint() const
1743 bool bDirect
= getBoolProperty( "IsDirect", false );
1747 bool PrinterController::getBoolProperty( const OUString
& i_rProperty
, bool i_bFallback
) const
1749 bool bRet
= i_bFallback
;
1750 const css::beans::PropertyValue
* pVal
= getValue( i_rProperty
);
1752 pVal
->Value
>>= bRet
;
1756 sal_Int32
PrinterController::getIntProperty( const OUString
& i_rProperty
, sal_Int32 i_nFallback
) const
1758 sal_Int32 nRet
= i_nFallback
;
1759 const css::beans::PropertyValue
* pVal
= getValue( i_rProperty
);
1761 pVal
->Value
>>= nRet
;
1766 * PrinterOptionsHelper
1768 css::uno::Any
PrinterOptionsHelper::getValue( const OUString
& i_rPropertyName
) const
1771 std::unordered_map
< OUString
, css::uno::Any
, OUStringHash
>::const_iterator it
=
1772 m_aPropertyMap
.find( i_rPropertyName
);
1773 if( it
!= m_aPropertyMap
.end() )
1778 bool PrinterOptionsHelper::getBoolValue( const OUString
& i_rPropertyName
, bool i_bDefault
) const
1781 css::uno::Any
aVal( getValue( i_rPropertyName
) );
1782 return (aVal
>>= bRet
) ? bRet
: i_bDefault
;
1785 sal_Int64
PrinterOptionsHelper::getIntValue( const OUString
& i_rPropertyName
, sal_Int64 i_nDefault
) const
1788 css::uno::Any
aVal( getValue( i_rPropertyName
) );
1789 return (aVal
>>= nRet
) ? nRet
: i_nDefault
;
1792 OUString
PrinterOptionsHelper::getStringValue( const OUString
& i_rPropertyName
) const
1795 css::uno::Any
aVal( getValue( i_rPropertyName
) );
1796 return (aVal
>>= aRet
) ? aRet
: OUString();
1799 bool PrinterOptionsHelper::processProperties( const css::uno::Sequence
< css::beans::PropertyValue
>& i_rNewProp
)
1801 bool bChanged
= false;
1803 sal_Int32 nElements
= i_rNewProp
.getLength();
1804 const css::beans::PropertyValue
* pVals
= i_rNewProp
.getConstArray();
1805 for( sal_Int32 i
= 0; i
< nElements
; i
++ )
1807 bool bElementChanged
= false;
1808 std::unordered_map
< OUString
, css::uno::Any
, OUStringHash
>::iterator it
=
1809 m_aPropertyMap
.find( pVals
[ i
].Name
);
1810 if( it
!= m_aPropertyMap
.end() )
1812 if( it
->second
!= pVals
[ i
].Value
)
1813 bElementChanged
= true;
1816 bElementChanged
= true;
1818 if( bElementChanged
)
1820 m_aPropertyMap
[ pVals
[i
].Name
] = pVals
[i
].Value
;
1827 void PrinterOptionsHelper::appendPrintUIOptions( css::uno::Sequence
< css::beans::PropertyValue
>& io_rProps
) const
1829 if( !m_aUIProperties
.empty() )
1831 sal_Int32 nIndex
= io_rProps
.getLength();
1832 io_rProps
.realloc( nIndex
+1 );
1833 css::beans::PropertyValue aVal
;
1834 aVal
.Name
= "ExtraPrintUIOptions";
1835 aVal
.Value
<<= comphelper::containerToSequence(m_aUIProperties
);
1836 io_rProps
[ nIndex
] = aVal
;
1840 css::uno::Any
PrinterOptionsHelper::setUIControlOpt(const css::uno::Sequence
< OUString
>& i_rIDs
,
1841 const OUString
& i_rTitle
,
1842 const css::uno::Sequence
< OUString
>& i_rHelpIds
,
1843 const OUString
& i_rType
,
1844 const css::beans::PropertyValue
* i_pVal
,
1845 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
1847 sal_Int32 nElements
=
1848 2 // ControlType + ID
1849 + (i_rTitle
.isEmpty() ? 0 : 1) // Text
1850 + (i_rHelpIds
.getLength() ? 1 : 0) // HelpId
1851 + (i_pVal
? 1 : 0) // Property
1852 + i_rControlOptions
.maAddProps
.size() // additional props
1853 + (i_rControlOptions
.maGroupHint
.isEmpty() ? 0 : 1) // grouping
1854 + (i_rControlOptions
.mbInternalOnly
? 1 : 0) // internal hint
1855 + (i_rControlOptions
.mbEnabled
? 0 : 1) // enabled
1857 if( !i_rControlOptions
.maDependsOnName
.isEmpty() )
1860 if( i_rControlOptions
.mnDependsOnEntry
!= -1 )
1862 if( i_rControlOptions
.mbAttachToDependency
)
1866 css::uno::Sequence
< css::beans::PropertyValue
> aCtrl( nElements
);
1867 sal_Int32 nUsed
= 0;
1868 if( !i_rTitle
.isEmpty() )
1870 aCtrl
[nUsed
].Name
= "Text";
1871 aCtrl
[nUsed
++].Value
<<= i_rTitle
;
1873 if( i_rHelpIds
.getLength() )
1875 aCtrl
[nUsed
].Name
= "HelpId";
1876 aCtrl
[nUsed
++].Value
<<= i_rHelpIds
;
1878 aCtrl
[nUsed
].Name
= "ControlType";
1879 aCtrl
[nUsed
++].Value
<<= i_rType
;
1880 aCtrl
[nUsed
].Name
= "ID";
1881 aCtrl
[nUsed
++].Value
<<= i_rIDs
;
1884 aCtrl
[nUsed
].Name
= "Property";
1885 aCtrl
[nUsed
++].Value
<<= *i_pVal
;
1887 if( !i_rControlOptions
.maDependsOnName
.isEmpty() )
1889 aCtrl
[nUsed
].Name
= "DependsOnName";
1890 aCtrl
[nUsed
++].Value
<<= i_rControlOptions
.maDependsOnName
;
1891 if( i_rControlOptions
.mnDependsOnEntry
!= -1 )
1893 aCtrl
[nUsed
].Name
= "DependsOnEntry";
1894 aCtrl
[nUsed
++].Value
<<= i_rControlOptions
.mnDependsOnEntry
;
1896 if( i_rControlOptions
.mbAttachToDependency
)
1898 aCtrl
[nUsed
].Name
= "AttachToDependency";
1899 aCtrl
[nUsed
++].Value
<<= i_rControlOptions
.mbAttachToDependency
;
1902 if( !i_rControlOptions
.maGroupHint
.isEmpty() )
1904 aCtrl
[nUsed
].Name
= "GroupingHint";
1905 aCtrl
[nUsed
++].Value
<<= i_rControlOptions
.maGroupHint
;
1907 if( i_rControlOptions
.mbInternalOnly
)
1909 aCtrl
[nUsed
].Name
= "InternalUIOnly";
1910 aCtrl
[nUsed
++].Value
<<= true;
1912 if( ! i_rControlOptions
.mbEnabled
)
1914 aCtrl
[nUsed
].Name
= "Enabled";
1915 aCtrl
[nUsed
++].Value
<<= false;
1918 sal_Int32 nAddProps
= i_rControlOptions
.maAddProps
.size();
1919 for( sal_Int32 i
= 0; i
< nAddProps
; i
++ )
1920 aCtrl
[ nUsed
++ ] = i_rControlOptions
.maAddProps
[i
];
1922 SAL_WARN_IF( nUsed
!= nElements
, "vcl.gdi", "nUsed != nElements, probable heap corruption" );
1924 return css::uno::makeAny( aCtrl
);
1927 css::uno::Any
PrinterOptionsHelper::setGroupControlOpt(const OUString
& i_rID
,
1928 const OUString
& i_rTitle
,
1929 const OUString
& i_rHelpId
)
1931 css::uno::Sequence
< OUString
> aHelpId
;
1932 if( !i_rHelpId
.isEmpty() )
1934 aHelpId
.realloc( 1 );
1935 *aHelpId
.getArray() = i_rHelpId
;
1937 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
1938 return setUIControlOpt(aIds
, i_rTitle
, aHelpId
, "Group");
1941 css::uno::Any
PrinterOptionsHelper::setSubgroupControlOpt(const OUString
& i_rID
,
1942 const OUString
& i_rTitle
,
1943 const OUString
& i_rHelpId
,
1944 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
1946 css::uno::Sequence
< OUString
> aHelpId
;
1947 if( !i_rHelpId
.isEmpty() )
1949 aHelpId
.realloc( 1 );
1950 *aHelpId
.getArray() = i_rHelpId
;
1952 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
1953 return setUIControlOpt(aIds
, i_rTitle
, aHelpId
, "Subgroup", nullptr, i_rControlOptions
);
1956 css::uno::Any
PrinterOptionsHelper::setBoolControlOpt(const OUString
& i_rID
,
1957 const OUString
& i_rTitle
,
1958 const OUString
& i_rHelpId
,
1959 const OUString
& i_rProperty
,
1961 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
1963 css::uno::Sequence
< OUString
> aHelpId
;
1964 if( !i_rHelpId
.isEmpty() )
1966 aHelpId
.realloc( 1 );
1967 *aHelpId
.getArray() = i_rHelpId
;
1969 css::beans::PropertyValue aVal
;
1970 aVal
.Name
= i_rProperty
;
1971 aVal
.Value
<<= i_bValue
;
1972 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
1973 return setUIControlOpt(aIds
, i_rTitle
, aHelpId
, "Bool", &aVal
, i_rControlOptions
);
1976 css::uno::Any
PrinterOptionsHelper::setChoiceRadiosControlOpt(const css::uno::Sequence
< OUString
>& i_rIDs
,
1977 const OUString
& i_rTitle
,
1978 const css::uno::Sequence
< OUString
>& i_rHelpId
,
1979 const OUString
& i_rProperty
,
1980 const css::uno::Sequence
< OUString
>& i_rChoices
,
1982 const css::uno::Sequence
< sal_Bool
>& i_rDisabledChoices
,
1983 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
1985 UIControlOptions
aOpt( i_rControlOptions
);
1986 sal_Int32 nUsed
= aOpt
.maAddProps
.size();
1987 aOpt
.maAddProps
.resize( nUsed
+ 1 + (i_rDisabledChoices
.getLength() ? 1 : 0) );
1988 aOpt
.maAddProps
[nUsed
].Name
= "Choices";
1989 aOpt
.maAddProps
[nUsed
].Value
<<= i_rChoices
;
1990 if( i_rDisabledChoices
.getLength() )
1992 aOpt
.maAddProps
[nUsed
+1].Name
= "ChoicesDisabled";
1993 aOpt
.maAddProps
[nUsed
+1].Value
<<= i_rDisabledChoices
;
1996 css::beans::PropertyValue aVal
;
1997 aVal
.Name
= i_rProperty
;
1998 aVal
.Value
<<= i_nValue
;
1999 return setUIControlOpt(i_rIDs
, i_rTitle
, i_rHelpId
, "Radio", &aVal
, aOpt
);
2002 css::uno::Any
PrinterOptionsHelper::setChoiceListControlOpt(const OUString
& i_rID
,
2003 const OUString
& i_rTitle
,
2004 const css::uno::Sequence
< OUString
>& i_rHelpId
,
2005 const OUString
& i_rProperty
,
2006 const css::uno::Sequence
< OUString
>& i_rChoices
,
2008 const css::uno::Sequence
< sal_Bool
>& i_rDisabledChoices
,
2009 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
2011 UIControlOptions
aOpt( i_rControlOptions
);
2012 sal_Int32 nUsed
= aOpt
.maAddProps
.size();
2013 aOpt
.maAddProps
.resize( nUsed
+ 1 + (i_rDisabledChoices
.getLength() ? 1 : 0) );
2014 aOpt
.maAddProps
[nUsed
].Name
= "Choices";
2015 aOpt
.maAddProps
[nUsed
].Value
<<= i_rChoices
;
2016 if( i_rDisabledChoices
.getLength() )
2018 aOpt
.maAddProps
[nUsed
+1].Name
= "ChoicesDisabled";
2019 aOpt
.maAddProps
[nUsed
+1].Value
<<= i_rDisabledChoices
;
2022 css::beans::PropertyValue aVal
;
2023 aVal
.Name
= i_rProperty
;
2024 aVal
.Value
<<= i_nValue
;
2025 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
2026 return setUIControlOpt(aIds
, i_rTitle
, i_rHelpId
, "List", &aVal
, aOpt
);
2029 css::uno::Any
PrinterOptionsHelper::setRangeControlOpt(const OUString
& i_rID
,
2030 const OUString
& i_rTitle
,
2031 const OUString
& i_rHelpId
,
2032 const OUString
& i_rProperty
,
2034 sal_Int32 i_nMinValue
,
2035 sal_Int32 i_nMaxValue
,
2036 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
2038 UIControlOptions
aOpt( i_rControlOptions
);
2039 if( i_nMaxValue
>= i_nMinValue
)
2041 sal_Int32 nUsed
= aOpt
.maAddProps
.size();
2042 aOpt
.maAddProps
.resize( nUsed
+ 2 );
2043 aOpt
.maAddProps
[nUsed
].Name
= "MinValue";
2044 aOpt
.maAddProps
[nUsed
++].Value
<<= i_nMinValue
;
2045 aOpt
.maAddProps
[nUsed
].Name
= "MaxValue";
2046 aOpt
.maAddProps
[nUsed
++].Value
<<= i_nMaxValue
;
2049 css::uno::Sequence
< OUString
> aHelpId
;
2050 if( !i_rHelpId
.isEmpty() )
2052 aHelpId
.realloc( 1 );
2053 *aHelpId
.getArray() = i_rHelpId
;
2055 css::beans::PropertyValue aVal
;
2056 aVal
.Name
= i_rProperty
;
2057 aVal
.Value
<<= i_nValue
;
2058 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
2059 return setUIControlOpt(aIds
, i_rTitle
, aHelpId
, "Range", &aVal
, aOpt
);
2062 css::uno::Any
PrinterOptionsHelper::setEditControlOpt(const OUString
& i_rID
,
2063 const OUString
& i_rTitle
,
2064 const OUString
& i_rHelpId
,
2065 const OUString
& i_rProperty
,
2066 const OUString
& i_rValue
,
2067 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
2069 css::uno::Sequence
< OUString
> aHelpId
;
2070 if( !i_rHelpId
.isEmpty() )
2072 aHelpId
.realloc( 1 );
2073 *aHelpId
.getArray() = i_rHelpId
;
2075 css::beans::PropertyValue aVal
;
2076 aVal
.Name
= i_rProperty
;
2077 aVal
.Value
<<= i_rValue
;
2078 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
2079 return setUIControlOpt(aIds
, i_rTitle
, aHelpId
, "Edit", &aVal
, i_rControlOptions
);
2082 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */