1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: prnmon.cxx,v $
10 * $Revision: 1.25.46.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
33 #include <com/sun/star/view/PrintableState.hpp>
34 #include <com/sun/star/util/XCloseable.hpp>
35 #include <com/sun/star/util/XCloseBroadcaster.hpp>
36 #include <com/sun/star/util/XCloseListener.hpp>
37 #include <com/sun/star/util/CloseVetoException.hpp>
38 #include <vcl/fixed.hxx>
39 #include <vcl/msgbox.hxx>
40 #include <svtools/asynclink.hxx>
42 #include <svtools/printwarningoptions.hxx>
43 #include <svtools/eitem.hxx>
48 #include <sfx2/prnmon.hxx>
49 #include <sfx2/viewsh.hxx>
50 #include <sfx2/viewfrm.hxx>
51 #include <sfx2/objsh.hxx>
52 #include <sfx2/docfile.hxx>
53 #include "sfxtypes.hxx"
54 #include <sfx2/progress.hxx>
55 #include <sfx2/bindings.hxx>
56 #include "sfxresid.hxx"
57 #include <sfx2/event.hxx>
58 #include <sfx2/request.hxx>
59 #include <sfx2/app.hxx>
63 //------------------------------------------------------------------------
65 #define SFX_TITLE_MAXLEN_PRINTMONITOR 22
67 //------------------------------------------------------------------------
69 struct SfxPrintMonitor_Impl
: public ModelessDialog
72 SfxPrintMonitor_Impl( Window
*pParent
, SfxViewShell
*rpViewShell
);
75 SfxViewShell
* pViewShell
;
83 //-------------------------------------------------------------------------
85 struct SfxPrintProgress_Impl
: public SfxListener
87 SfxPrintMonitor_Impl
* pMonitor
;
88 SfxViewShell
* pViewShell
;
90 SfxPrinter
* pOldPrinter
;
94 BOOL bDeleteOnEndPrint
;
97 BOOL bOldEnablePrintFile
;
101 svtools::AsynchronLink aDeleteLink
;
105 DECL_LINK( CancelHdl
, Button
* );
106 DECL_STATIC_LINK( SfxPrintProgress_Impl
, DeleteHdl
, SfxPrintProgress
* );
109 SfxPrintProgress_Impl( SfxViewShell
* pTheViewShell
, SfxPrinter
* pThePrinter
);
110 ~SfxPrintProgress_Impl();
112 void Delete( SfxPrintProgress
* pAntiImpl
) { aDeleteLink
.Call( pAntiImpl
); }
113 SfxViewShell
* GetViewShell() const { return pViewShell
; }
114 BOOL
SetPage( USHORT nPage
, const String
&rPage
);
115 void CreateMonitor();
116 virtual void Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
);
119 void SfxPrintProgress_Impl::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
121 SfxPrintingHint
* pPrintHint
= PTR_CAST( SfxPrintingHint
, &rHint
);
124 if ( pPrintHint
->GetWhich() == -2 )
129 //------------------------------------------------------------------------
131 SfxPrintMonitor_Impl::SfxPrintMonitor_Impl( Window
* pParent
, SfxViewShell
* rpViewShell
) :
132 ModelessDialog( pParent
, SfxResId( DLG_PRINTMONITOR
) ),
133 pViewShell ( rpViewShell
),
134 aDocName ( this, SfxResId( FT_DOCNAME
) ),
135 aPrinting ( this, SfxResId( FT_PRINTING
) ),
136 aPrinter ( this, SfxResId( FT_PRINTER
) ),
137 aPrintInfo ( this, SfxResId( FT_PRINTINFO
) ),
138 aCancel ( this, SfxResId( PB_CANCELPRNMON
) )
140 if( rpViewShell
->GetPrinter()->GetCapabilities( PRINTER_CAPABILITIES_EXTERNALDIALOG
) != 0 )
142 String
aPrep( SfxResId( STR_FT_PREPARATION
) );
143 aPrinting
.SetText( aPrep
);
144 aPrinter
.Show( FALSE
);
149 //------------------------------------------------------------------------
151 IMPL_STATIC_LINK_NOINSTANCE( SfxPrintProgress_Impl
, DeleteHdl
, SfxPrintProgress
*, pAntiImpl
)
157 void actualizePrintCancelState(CancelButton
& rButton
, const SfxObjectShell
* pShell
)
159 sal_Bool bEnableCancelButton
= sal_True
;
161 bEnableCancelButton
= pShell
->Stamp_GetPrintCancelState();
163 if (!bEnableCancelButton
)
169 //------------------------------------------------------------------------
171 SfxPrintProgress_Impl::SfxPrintProgress_Impl( SfxViewShell
* pTheViewShell
,
172 SfxPrinter
* pThePrinter
) :
175 pViewShell ( pTheViewShell
),
176 pPrinter ( pThePrinter
),
177 pOldPrinter ( NULL
),
181 bDeleteOnEndPrint ( FALSE
),
183 bCallbacks ( FALSE
),
184 bOldEnablePrintFile ( FALSE
),
186 bRestoreFlag ( FALSE
),
188 aDeleteLink ( STATIC_LINK( this, SfxPrintProgress_Impl
, DeleteHdl
) )
190 StartListening( *pViewShell
->GetObjectShell() );
193 void SfxPrintProgress_Impl::CreateMonitor()
195 // mark monitor to been shown in first status indication
200 Window
* pParent
= pViewShell
->GetWindow();
201 pMonitor
= new SfxPrintMonitor_Impl( pParent
, pViewShell
);
202 pMonitor
->aDocName
.SetText( pViewShell
->GetObjectShell()->GetTitle( SFX_TITLE_MAXLEN_PRINTMONITOR
) );
203 pMonitor
->aPrinter
.SetText( pViewShell
->GetPrinter()->GetName() );
205 // Stampit enable/dsiable cancel button
206 actualizePrintCancelState( pMonitor
->aCancel
, pViewShell
->GetObjectShell() );
207 pMonitor
->aCancel
.SetClickHdl( LINK( this, SfxPrintProgress_Impl
, CancelHdl
) );
211 //------------------------------------------------------------------------
213 SfxPrintProgress_Impl::~SfxPrintProgress_Impl()
217 //------------------------------------------------------------------------
219 BOOL
SfxPrintProgress_Impl::SetPage( USHORT nPage
, const String
&rPage
)
221 // wurde der Druckauftrag abgebrochen?
222 if ( bCancel
|| !pMonitor
)
225 // Stampit enable/dsiable cancel button
226 actualizePrintCancelState(pMonitor
->aCancel
, pViewShell
->GetObjectShell());
229 String aStrPrintInfo
= String( SfxResId( STR_PAGE
) );
231 aStrPrintInfo
+= String::CreateFromInt32( nLastPage
);
233 aStrPrintInfo
+= rPage
;
234 pMonitor
->aPrintInfo
.SetText( aStrPrintInfo
);
239 //------------------------------------------------------------------------
241 IMPL_LINK( SfxPrintProgress_Impl
, CancelHdl
, Button
*, EMPTYARG
)
243 if ( !pViewShell
->GetPrinter()->IsJobActive() && pViewShell
->GetPrinter()->IsPrinting() )
244 // we are still in StartJob, cancelling now might lead to a crash
250 pViewShell
->GetObjectShell()->Broadcast( SfxPrintingHint( com::sun::star::view::PrintableState_JOB_ABORTED
, NULL
, NULL
) );
251 pViewShell
->GetPrinter()->AbortJob();
254 if ( aCancelHdl
.IsSet() )
255 aCancelHdl
.Call( this );
261 BOOL
SfxPrintMonitor_Impl::Close()
263 BOOL bAgree
= pViewShell
? pViewShell
->GetObjectShell()->Stamp_GetPrintCancelState() : TRUE
;
267 return ModelessDialog::Close();
270 //--------------------------------------------------------------------
272 SfxPrintProgress::SfxPrintProgress( SfxViewShell
* pViewSh
, FASTBOOL bShow
)
273 : SfxProgress( pViewSh
->GetViewFrame()->GetObjectShell(),
274 String(SfxResId(STR_PRINTING
)), 1, FALSE
),
275 pImp( new SfxPrintProgress_Impl( pViewSh
, pViewSh
->GetPrinter() ) )
277 pImp
->pPrinter
->SetEndPrintHdl( LINK( this, SfxPrintProgress
, EndPrintNotify
) );
278 pImp
->pPrinter
->SetErrorHdl( LINK( this, SfxPrintProgress
, PrintErrorNotify
) );
279 pImp
->pPrinter
->SetStartPrintHdl( LINK( this, SfxPrintProgress
, StartPrintNotify
) );
280 pImp
->bCallbacks
= TRUE
;
282 SfxObjectShell
* pDoc
= pViewSh
->GetObjectShell();
283 SFX_ITEMSET_ARG( pDoc
->GetMedium()->GetItemSet(), pItem
, SfxBoolItem
, SID_HIDDEN
, FALSE
);
284 if ( pItem
&& pItem
->GetValue() )
288 pImp
->CreateMonitor();
291 if ( !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() )
293 pImp
->bRestoreFlag
= TRUE
;
294 pImp
->bOldFlag
= pDoc
->IsEnableSetModified();
295 if ( pImp
->bOldFlag
)
296 pDoc
->EnableSetModified( FALSE
);
300 //--------------------------------------------------------------------
302 SfxPrintProgress::~SfxPrintProgress()
304 // k"onnte auch schon weg sein (in EndPrintNotify)
305 DELETEZ(pImp
->pMonitor
);
307 // ggf. Callbacks entfermen
308 if ( pImp
->bCallbacks
)
310 pImp
->pPrinter
->SetEndPrintHdl( Link() );
311 pImp
->pPrinter
->SetErrorHdl( Link() );
312 pImp
->bCallbacks
= FALSE
;
315 // ggf. vorherigen Drucker wieder einsetzen
316 if ( pImp
->pOldPrinter
)
317 pImp
->pViewShell
->SetPrinter( pImp
->pOldPrinter
, SFX_PRINTER_PRINTER
);
319 // ggf. vorherigen Print-To-File-Status zuruecksetzen
320 pImp
->pViewShell
->GetPrinter()->EnablePrintFile( pImp
->bOldEnablePrintFile
);
322 // EndPrint-Notification an Frame
323 //pImp->pViewShell->GetViewFrame()->GetFrame()->Lock_Impl(FALSE);
324 pImp
->EndListening( *(pImp
->pViewShell
->GetObjectShell()) );
326 // the following call might destroy the view or even the document
327 pImp
->pViewShell
->CheckOwnerShip_Impl();
331 //--------------------------------------------------------------------
333 BOOL
SfxPrintProgress::SetState( ULONG nValue
, ULONG nNewRange
)
338 if ( pImp
->pMonitor
)
340 pImp
->pMonitor
->Show();
341 pImp
->pMonitor
->Update();
345 return pImp
->SetPage( (USHORT
)nValue
, GetStateText_Impl() ) &&
346 SfxProgress::SetState( nValue
, nNewRange
);
349 //--------------------------------------------------------------------
351 void SfxPrintProgress::SetText( const String
& rText
)
353 if ( pImp
->pMonitor
)
355 pImp
->pMonitor
->SetText( rText
);
356 pImp
->pMonitor
->Update();
358 SfxProgress::SetText( rText
);
361 //------------------------------------------------------------------------
363 IMPL_LINK_INLINE_START( SfxPrintProgress
, PrintErrorNotify
, void *, EMPTYARG
)
365 if ( pImp
->pMonitor
)
366 pImp
->pMonitor
->Hide();
367 // AbortJob calls EndPrint hdl, so do not delete pImp just now
368 BOOL bWasDeleteOnEndPrint
= pImp
->bDeleteOnEndPrint
;
369 pImp
->bDeleteOnEndPrint
= FALSE
;
370 pImp
->pPrinter
->AbortJob();
371 InfoBox( pImp
->GetViewShell()->GetWindow(),
372 String( SfxResId(STR_ERROR_PRINT
) ) ).Execute();
373 if ( pImp
->bRestoreFlag
&& pImp
->pViewShell
->GetObjectShell()->IsEnableSetModified() != pImp
->bOldFlag
)
374 pImp
->pViewShell
->GetObjectShell()->EnableSetModified( pImp
->bOldFlag
);
375 pImp
->GetViewShell()->GetObjectShell()->Broadcast( SfxPrintingHint( com::sun::star::view::PrintableState_JOB_FAILED
, NULL
, NULL
) );
376 // now we can clean up like normally EndPrint hdl does
377 if( bWasDeleteOnEndPrint
)
379 DELETEZ(pImp
->pMonitor
);
384 IMPL_LINK_INLINE_END( SfxPrintProgress
, PrintErrorNotify
, void *, EMPTYARG
)
386 //------------------------------------------------------------------------
388 IMPL_LINK( SfxPrintProgress
, StartPrintNotify
, void *, EMPTYARG
)
390 SfxObjectShell
*pObjShell
= pImp
->pViewShell
->GetObjectShell();
391 SFX_APP()->NotifyEvent(SfxEventHint(SFX_EVENT_PRINTDOC
, GlobalEventConfig::GetEventName( STR_EVENT_PRINTDOC
), pObjShell
));
392 pObjShell
->Broadcast( SfxPrintingHint( com::sun::star::view::PrintableState_JOB_STARTED
, NULL
, NULL
) );
396 IMPL_LINK( SfxPrintProgress
, EndPrintNotify
, void *, EMPTYARG
)
398 if ( pImp
->pMonitor
)
399 pImp
->pMonitor
->Hide();
401 SfxViewShell
* pViewShell
= pImp
->pViewShell
;
404 pViewShell
->Invalidate( SID_PRINTDOC
);
405 pViewShell
->Invalidate( SID_PRINTDOCDIRECT
);
406 pViewShell
->Invalidate( SID_SETUPPRINTER
);
408 // . . . falls der Printer im System umgestellt wurde, hier Aenderung
410 //! if( pMDI->IsPrinterChanged() ) pMDI->Changed( 0L );
412 // Callbacks rausnehmen
413 pImp
->pPrinter
->SetEndPrintHdl( Link() );
414 pImp
->pPrinter
->SetErrorHdl( Link() );
415 pImp
->bCallbacks
= FALSE
;
417 // ggf. alten Printer wieder einsetzen
418 if ( pImp
->pOldPrinter
)
420 // Fix #59613#: niemals den aktuellen Printer synchron abschiessen !
421 // Da sowieso immer bDeleteOnEndPrint gesetzt wird, wird der der Drucker im
422 // dtor vom Printprogress ( dann aber asynchron !! ) zur"uckgesetzt.
424 pImp->pViewShell->SetPrinter( pImp->pOldPrinter, SFX_PRINTER_PRINTER );
425 pImp->pOldPrinter = 0;
430 // ggf. vorherigen Print-To-File-Status zuruecksetzen
431 pViewShell
->GetPrinter()->EnablePrintFile( pImp
->bOldEnablePrintFile
);
433 // it is possible that after printing the document or view is deleted (because the VieShell got the ownership)
435 if ( pImp
->bRestoreFlag
&& pViewShell
->GetObjectShell()->IsEnableSetModified() != pImp
->bOldFlag
)
436 pViewShell
->GetObjectShell()->EnableSetModified( TRUE
);
438 pViewShell
->GetObjectShell()->Broadcast( SfxPrintingHint( com::sun::star::view::PrintableState_JOB_COMPLETED
, NULL
, NULL
) );
439 if ( pImp
->bDeleteOnEndPrint
)
441 DELETEZ(pImp
->pMonitor
);
446 DBG_ASSERT( !pImp
->pOldPrinter
, "Unable to restore printer!" );
447 pImp
->bRunning
= FALSE
;
453 //------------------------------------------------------------------------
455 void SfxPrintProgress::DeleteOnEndPrint()
457 UnLock(); // jetzt schon, wg. Drucken im Thread
459 // da das Drucken im 'Thread' unter Windows zu undefiniert ist bleibt der
460 // Print-Monitor dort stehen, auf den anderen Plattformen kann man dann
461 // weiterarbeiten, also kommt das Teil weg
462 DELETEZ( pImp
->pMonitor
);
465 pImp
->bDeleteOnEndPrint
= TRUE
;
466 if ( !pImp
->bRunning
)
470 //------------------------------------------------------------------------
472 void SfxPrintProgress::RestoreOnEndPrint( SfxPrinter
*pOldPrinter
,
473 BOOL bOldEnablePrintFile
)
475 pImp
->pOldPrinter
= pOldPrinter
;
476 pImp
->bOldEnablePrintFile
= bOldEnablePrintFile
;
479 //------------------------------------------------------------------------
481 void SfxPrintProgress::RestoreOnEndPrint( SfxPrinter
*pOldPrinter
)
483 RestoreOnEndPrint( pOldPrinter
, FALSE
);
486 //------------------------------------------------------------------------
488 void SfxPrintProgress::SetCancelHdl( const Link
& aCancelHdl
)
490 pImp
->aCancelHdl
= aCancelHdl
;
493 BOOL
SfxPrintProgress::IsAborted() const
495 return pImp
->bAborted
;