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: progress.cxx,v $
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"
34 #include <sfx2/progress.hxx>
35 #include <com/sun/star/uno/Reference.hxx>
36 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
38 #ifndef _SBX_HXX //autogen
39 #include <basic/sbx.hxx>
42 #include <svtools/eitem.hxx>
43 #include <tools/time.hxx>
45 // wg. nRescheduleLocks
46 #include "appdata.hxx"
47 #include <sfx2/request.hxx>
48 #include <sfx2/frame.hxx>
49 #include <sfx2/viewfrm.hxx>
50 #include <sfx2/viewsh.hxx>
51 #include <sfx2/objsh.hxx>
52 #include <sfx2/app.hxx>
53 #include <sfx2/dispatch.hxx>
54 #include "sfxtypes.hxx"
55 #include <sfx2/docfile.hxx>
56 #include "workwin.hxx"
57 #include "sfxresid.hxx"
59 #include <sfx2/msg.hxx>
63 using namespace ::com::sun::star::uno
;
64 using namespace ::com::sun::star::frame
;
65 using namespace ::com::sun::star::task
;
67 void AddNumber_Impl( String
& aNumber
, sal_uInt32 nArg
)
71 aNumber
+= String::CreateFromInt32( (sal_uInt16
)( ( nArg
+ 512 ) / 1024 ) );
73 aNumber
+= SfxResId( STR_KB
);
77 aNumber
+= String::CreateFromInt32( nArg
);
79 aNumber
+= SfxResId( STR_BYTES
);
83 struct SfxProgress_Impl
: public SfxCancellable
85 Reference
< XStatusIndicator
> xStatusInd
;
86 String aText
, aStateText
;
89 clock_t nNextReschedule
;
90 BOOL bLocked
, bAllDocs
;
92 BOOL bAllowRescheduling
;
96 SfxProgress
* pActiveProgress
;
97 SfxObjectShellRef xObjSh
;
98 SfxWorkWindow
* pWorkWin
;
101 SfxProgress_Impl( const String
& );
102 void Enable_Impl( BOOL
);
106 //========================================================================
108 #define TIMEOUT_PROGRESS 5L /* 10th s */
109 #define MAXPERCENT_PROGRESS 33
111 #define TIMEOUT_RESCHEDULE 10L /* 10th s */
112 #define MAXPERCENT_RESCHEDULE 50
115 #include "sfxslots.hxx"
117 #define aTypeLibInfo aProgressTypeLibImpl
119 //========================================================================
120 extern ULONG
Get10ThSec();
122 // -----------------------------------------------------------------------
124 void SfxProgress_Impl::Enable_Impl( BOOL bEnable
)
126 SfxObjectShell
* pDoc
= bAllDocs
? NULL
: (SfxObjectShell
*) xObjSh
;
127 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst(pDoc
);
130 pFrame
->Enable(bEnable
);
131 pFrame
->GetDispatcher()->Lock( !bEnable
);
132 pFrame
= SfxViewFrame::GetNext(*pFrame
, pDoc
);
137 pView
->Enable( bEnable
);
138 pView
->GetDispatcher()->Lock( !bEnable
);
142 SFX_APP()->GetAppDispatcher_Impl()->Lock( !bEnable
);
145 // -----------------------------------------------------------------------
147 SfxProgress_Impl::SfxProgress_Impl( const String
&rTitle
)
148 : SfxCancellable( SFX_APP()->GetCancelManager(), rTitle
),
151 SFX_APP()->GetCancelManager()->RemoveCancellable(this);
154 // -----------------------------------------------------------------------
156 SfxProgress::SfxProgress
158 SfxObjectShell
* pObjSh
, /* SfxObjectShell, an der die Aktion ausgef"uhrt
159 wird. Kann NULL sein, dann wird die Applikation
162 const String
& rText
, /* Text, der in der Statuszeile vor den Statusmonitor
165 ULONG nRange
, /* Maximalwert des Bereiches */
167 BOOL bAll
/* alle Dokumente oder nur das Dokument des ViewFrames
169 ,BOOL bWait
/* initial den Wait-Pointer aktivieren (TRUE) */
174 Der Konstruktor der Klasse SfxProgress schaltet den als Parameter
175 "ubergebenen SfxObjectShell und SfxViewFrames, welche dieses Dokument
176 anzeigen in einen Progress-Mode. D.h. solange eine dieser SfxViewFrame
177 Instanzen aktiv ist, ist der dazugeh"orige SfxDispatcher und das
178 dazugeh"orige Window disabled. In der Statuszeile wird ein Balken zur
179 Fortschritts-Anzeige angezeigt.
182 : pImp( new SfxProgress_Impl( rText
) ),
186 pImp
->bRunning
= TRUE
;
187 pImp
->bAllowRescheduling
= Application::IsInExecute();;
191 for( SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst( pObjSh
); pFrame
; pFrame
= SfxViewFrame::GetNext( *pFrame
, pObjSh
) )
193 pFrame
->GetCancelManager()->InsertCancellable( pImp
);
195 SfxBindings& rBindings = pFrame->GetBindings();
196 rBindings.Invalidate( SID_BROWSE_STOP );
197 if ( !rBindings.IsInRegistrations() )
198 rBindings.Update( SID_BROWSE_STOP );
199 rBindings.Invalidate( SID_BROWSE_STOP );
204 pImp
->xObjSh
= pObjSh
;
207 pImp
->bLocked
= FALSE
;
208 pImp
->bWaitMode
= bWait
;
209 pImp
->bIsStatusText
= FALSE
;
210 pImp
->nCreate
= Get10ThSec();
211 pImp
->nNextReschedule
= pImp
->nCreate
;
212 DBG( DbgOutf( "SfxProgress: created for '%s' at %luds",
213 rText
.GetBuffer(), pImp
->nCreate
) );
214 pImp
->bAllDocs
= bAll
;
218 pImp
->pActiveProgress
= GetActiveProgress( pObjSh
);
220 pObjSh
->SetProgress_Impl(this);
221 else if( !pImp
->pActiveProgress
)
222 SFX_APP()->SetProgress_Impl(this);
226 // -----------------------------------------------------------------------
228 SfxProgress::~SfxProgress()
232 Der Destruktor der Klasse SfxProgress restauriert den alten Zustand;
233 die Dokumente werden wieder freigeschaltet und die Statuszeile zeigt
239 if ( pImp
->xStatusInd
.is() )
240 pImp
->xStatusInd
->end();
242 if( pImp
->bIsStatusText
== TRUE
)
243 GetpApp()->HideStatusText( );
244 SfxObjectShell
* pDoc
= pImp
->xObjSh
;
247 for( SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst( pDoc
); pFrame
; pFrame
= SfxViewFrame::GetNext( *pFrame
, pDoc
) )
248 pFrame
->GetCancelManager()->RemoveCancellable( pImp
);//Invalidate( SID_BROWSE_STOP );
251 SFX_APP()->Invalidate( SID_BROWSE_STOP
);
255 // -----------------------------------------------------------------------
257 void SfxProgress::Stop()
261 Vorzeitiges Beenden des <SfxProgress>.
265 if( pImp
->pActiveProgress
)
267 if ( pImp
->xObjSh
.Is() && pImp
->xObjSh
->GetProgress() == this )
268 pImp
->xObjSh
->SetProgress_Impl(0);
272 if ( !pImp
->bRunning
)
274 pImp
->bRunning
= FALSE
;
275 DBG( DbgOutf( "SfxProgress: destroyed at %luds", Get10ThSec() ) );
278 if ( pImp
->xObjSh
.Is() )
279 pImp
->xObjSh
->SetProgress_Impl(0);
281 SFX_APP()->SetProgress_Impl(0);
283 pImp
->Enable_Impl(TRUE
);
286 // -----------------------------------------------------------------------
288 void SfxProgress::SetText
290 const String
& /* neuer Text */
295 "Andert den Text, der links neben dem Fortschritts-Balken
300 if( pImp
->pActiveProgress
) return;
301 if ( pImp
->xStatusInd
.is() )
303 pImp
->xStatusInd
->reset();
304 pImp
->xStatusInd
->start( pImp
->aText
, pImp
->nMax
);
308 // -----------------------------------------------------------------------
310 const String
& SfxProgress::GetStateText_Impl() const
312 return pImp
->aStateText
;
315 // -----------------------------------------------------------------------
317 IMPL_STATIC_LINK( SfxProgress, SetStateHdl, PlugInLoadStatus*, pStatus )
319 INetRequest* pReq = 0;
320 const INetHint *pHint = PTR_CAST( INetHint, pStatus->pHint );
321 pReq = PTR_CAST( INetRequest, pStatus->pBC );
325 aString = SfxMedium::GetStatusString( pHint->GetId(), pReq, pHint );
328 GetpApp()->ShowStatusText( aString );
330 pThis->pImp->bIsStatusText = TRUE;
336 // -----------------------------------------------------------------------
339 static ULONG nLastTime
= 0;
341 long TimeOut_Impl( void*, void* pArgV
)
343 Timer
*pArg
= (Timer
*)pArgV
;
344 if( Time::GetSystemTicks() - nLastTime
> 3000 )
346 GetpApp()->HideStatusText();
354 // -----------------------------------------------------------------------
356 BOOL
SfxProgress::SetStateText
358 ULONG nNewVal
, /* neuer Wert f"ur die Fortschritts-Anzeige */
359 const String
& rNewVal
, /* Status als Text */
360 ULONG nNewRange
/* neuer Maximalwert, 0 f"ur Beibehaltung des alten */
364 pImp
->aStateText
= rNewVal
;
365 return SetState( nNewVal
, nNewRange
);
368 // -----------------------------------------------------------------------
370 BOOL
SfxProgress::SetState
372 ULONG nNewVal
, /* neuer Wert f"ur die Fortschritts-Anzeige */
374 ULONG nNewRange
/* neuer Maximalwert, 0 f"ur Beibehaltung des alten */
378 Setzen des aktuellen Status; nach einem zeitlichen Versatz
379 wird Reschedule aufgerufen.
385 Fortfahren mit der Aktion
392 // wurde via Stop-Button angehalten?
393 if ( pImp
->IsCancelled() )
396 if( pImp
->pActiveProgress
) return TRUE
;
398 // neuen Wert "ubernehmen
403 if ( nNewRange
&& nNewRange
!= pImp
->nMax
)
405 DBG( DbgOutf( "SfxProgress: range changed from %lu to %lu",
406 pImp
->nMax
, nNewRange
) );
407 pImp
->nMax
= nNewRange
;
411 if ( !pImp
->xStatusInd
.is() )
413 // get the active ViewFrame of the document this progress is working on
414 // if it doesn't work on a document, take the current ViewFrame
415 SfxObjectShell
* pObjSh
= pImp
->xObjSh
;
416 pImp
->pView
= SfxViewFrame::Current();
417 DBG_ASSERT( pImp
->pView
|| pObjSh
, "Can't make progress bar!");
418 if ( pObjSh
&& ( !pImp
->pView
|| pObjSh
!= pImp
->pView
->GetObjectShell() ) )
420 // current document does not belong to current ViewFrame; take it's first visible ViewFrame
421 SfxViewFrame
* pDocView
= SfxViewFrame::GetFirst( pObjSh
);
423 pImp
->pView
= pDocView
;
426 // don't show status indicator for hidden documents (only valid while loading)
427 SfxMedium
* pMedium
= pObjSh
->GetMedium();
428 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pHiddenItem
, SfxBoolItem
, SID_HIDDEN
, FALSE
);
429 if ( !pHiddenItem
|| !pHiddenItem
->GetValue() )
431 // not in a view, perhaps it's just loading
432 //SfxFrame* pFrame = pMedium->GetLoadTargetFrame();
433 //if ( pFrame && pFrame->GetCurrentViewFrame() )
436 //pImp->pView = pFrame->GetCurrentViewFrame();
440 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pIndicatorItem
, SfxUnoAnyItem
, SID_PROGRESS_STATUSBAR_CONTROL
, FALSE
);
441 Reference
< XStatusIndicator
> xInd
;
442 if ( pIndicatorItem
&& (pIndicatorItem
->GetValue()>>=xInd
) )
443 pImp
->xStatusInd
= xInd
;
448 else if ( pImp
->pView
)
450 pImp
->pWorkWin
= SFX_APP()->GetWorkWindow_Impl( pImp
->pView
);
451 if ( pImp
->pWorkWin
)
452 pImp
->xStatusInd
= pImp
->pWorkWin
->GetStatusIndicator();
455 if ( pImp
->xStatusInd
.is() )
457 pImp
->xStatusInd
->start( pImp
->aText
, pImp
->nMax
);
462 if ( pImp
->xStatusInd
.is() )
464 pImp
->xStatusInd
->setValue( nNewVal
);
470 // -----------------------------------------------------------------------
472 void SfxProgress::Resume()
476 Nimmt die Anzeige des Status nach einer Unterbrechung wieder auf.
479 <SfxProgress::Suspend()>
483 if( pImp
->pActiveProgress
) return;
486 DBG( DbgOutf( "SfxProgress: resumed" ) );
487 if ( pImp
->xStatusInd
.is() )
489 pImp
->xStatusInd
->start( pImp
->aText
, pImp
->nMax
);
490 pImp
->xStatusInd
->setValue( nVal
);
493 if ( pImp
->bWaitMode
)
495 if ( pImp
->xObjSh
.Is() && !pImp
->bAllDocs
)
497 for ( SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst(pImp
->xObjSh
);
499 pFrame
= SfxViewFrame::GetNext( *pFrame
, pImp
->xObjSh
) )
500 pFrame
->GetWindow().EnterWait();
506 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst(pImp
->xObjSh
);
508 pFrame
->GetBindings().ENTERREGISTRATIONS();
515 // -----------------------------------------------------------------------
517 void SfxProgress::Suspend()
521 Unterbricht die Anzeige des Status
524 <SfxProgress::Resume()>
528 if( pImp
->pActiveProgress
) return;
531 DBG( DbgOutf( "SfxProgress: suspended" ) );
534 if ( pImp
->xStatusInd
.is() )
536 pImp
->xStatusInd
->reset();
539 if ( pImp
->xObjSh
.Is() && !pImp
->bAllDocs
)
541 for ( SfxViewFrame
*pFrame
=
542 SfxViewFrame::GetFirst(pImp
->xObjSh
);
544 pFrame
= SfxViewFrame::GetNext( *pFrame
, pImp
->xObjSh
) )
545 pFrame
->GetWindow().LeaveWait();
547 if ( pImp
->xObjSh
.Is() )
549 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst(pImp
->xObjSh
);
551 pFrame
->GetBindings().LEAVEREGISTRATIONS();
556 // -----------------------------------------------------------------------
558 void SfxProgress::Lock()
560 if( pImp
->pActiveProgress
) return;
561 // kein Reschedule bei Embedded-Objekten,
562 // da wir gegen das OLE Protokoll wehrlos sind
563 if ( !pImp
->xObjSh
.Is() )
565 for ( SfxObjectShell
*pDocSh
= SfxObjectShell::GetFirst();
567 pDocSh
= SfxObjectShell::GetNext(*pDocSh
) )
569 SfxObjectCreateMode eMode
= pDocSh
->GetCreateMode();
570 if ( ( eMode
== SFX_CREATE_MODE_EMBEDDED
) ||
571 ( eMode
== SFX_CREATE_MODE_PREVIEW
) )
573 DBG( DbgOutf( "SfxProgress: not locked because EMBEDDED/PREVIEW found" ) );
574 pImp
->bAllowRescheduling
= FALSE
;
580 SfxObjectCreateMode eMode
= pImp
->xObjSh
->GetCreateMode();
581 if ( ( eMode
== SFX_CREATE_MODE_EMBEDDED
) ||
582 ( eMode
== SFX_CREATE_MODE_PREVIEW
) )
584 DBG( DbgOutf( "SfxProgress: not locked because ObjectShell is EMBEDDED/PREVIEW" ) );
585 pImp
->bAllowRescheduling
= FALSE
;
589 pImp
->Enable_Impl( FALSE
);
591 DBG( DbgOutf( "SfxProgress: locked" ) );
592 pImp
->bLocked
= TRUE
;
595 // -----------------------------------------------------------------------
597 void SfxProgress::UnLock()
599 if( pImp
->pActiveProgress
) return;
600 if ( !pImp
->bLocked
)
603 DBG( DbgOutf( "SfxProgress: unlocked" ) );
604 pImp
->bLocked
= FALSE
;
605 pImp
->Enable_Impl(TRUE
);
608 // -----------------------------------------------------------------------
610 void SfxProgress::Reschedule()
614 Reschedule von au"sen rufbar
619 SFX_STACK(SfxProgress::Reschedule
);
621 if( pImp
->pActiveProgress
) return;
622 SfxApplication
* pApp
= SFX_APP();
623 if ( pImp
->bLocked
&& 0 == pApp
->Get_Impl()->nRescheduleLocks
)
625 DBG_ASSERTWARNING( pApp
->IsInAsynchronCall_Impl(),
626 "Reschedule in synchron-call-stack" );
628 SfxAppData_Impl
*pAppData
= pApp
->Get_Impl();
629 ++pAppData
->nInReschedule
;
630 Application::Reschedule();
631 --pAppData
->nInReschedule
;
635 // -----------------------------------------------------------------------
637 void SfxProgress::SetWaitMode
640 Wartecursor wird verwendet
643 Es wird kein Wartecursor verwendet */
648 Wartecursor-Modus umschalten.
653 if( pImp
->pActiveProgress
) return;
654 if ( !bSuspended
&& pImp
->bWaitMode
!= bWait
)
658 if ( pImp
->xObjSh
.Is() && !pImp
->bAllDocs
)
660 for ( SfxViewFrame
*pFrame
=
661 SfxViewFrame::GetFirst(pImp
->xObjSh
);
663 pFrame
= SfxViewFrame::GetNext( *pFrame
, pImp
->xObjSh
) )
664 pFrame
->GetWindow().EnterWait();
669 if ( pImp
->xObjSh
.Is() && !pImp
->bAllDocs
)
671 for ( SfxViewFrame
*pFrame
=
672 SfxViewFrame::GetFirst(pImp
->xObjSh
);
674 pFrame
= SfxViewFrame::GetNext( *pFrame
, pImp
->xObjSh
) )
675 pFrame
->GetWindow().LeaveWait();
680 pImp
->bWaitMode
= bWait
;
683 // -----------------------------------------------------------------------
685 BOOL
SfxProgress::GetWaitMode() const
689 Wartecursor-Modus abfragen.
694 return pImp
->bWaitMode
;
697 // -----------------------------------------------------------------------
699 SfxProgress
* SfxProgress::GetActiveProgress
701 SfxObjectShell
* pDocSh
/* <SfxObjectShell>, die nach einem laufenden
702 <SfxProgress> gefragt werden soll, oder
703 0, wenn ein f"ur die gesamte Applikation
704 laufender SfxProgress erfragt werden soll.
705 Der Pointer braucht nur zum Zeitpunkt des
706 Aufrufs g"ultig zu sein. */
711 Mit dieser Methode kann erfragt werden, ob und welcher <SfxProgress>-
712 f"ur eine bestimmte Instanz von SfxObjectShell oder gar die gesamte
713 Applikation zur Zeit aktiv ist. Dies kann z.B. zum Abfangen von
714 Time-Out-Events etc. verwendet werden.
716 Anstelle eines Pointer auf den SfxProgress der SfxObjectShell wird
717 ggf. der auf den SfxProgress der Applikation geliefert, mit der
718 Abfrage 'SfxProgress::GetActiveProgress(pMyDocSh)' wird also
719 insofern vorhanden der SfxProgress von 'pMyDocSh' geliefert,
720 sonst der SfxProgress der Applikation bzw. ein 0-Pointer.
725 "auft kein SfxProgress an der Applikation und ebenfalls keiner an
726 der angegebenen SfxObjectShell, dann wird immer 0 zur"uckgeliefert,
727 auch wenn an einer anderen SfxObjectShell ein SfxProgress l"uft.
732 <SfxApplication::GetProgress()const>
733 <SfxObjectShell::GetProgress()const>
737 if ( !SfxApplication::Is_Impl() )
740 SfxProgress
*pProgress
= 0;
742 pProgress
= pDocSh
->GetProgress();
744 pProgress
= SFX_APP()->GetProgress();
748 // -----------------------------------------------------------------------
750 void SfxProgress::EnterLock()
752 SFX_APP()->Get_Impl()->nRescheduleLocks
++;
755 // -----------------------------------------------------------------------
757 void SfxProgress::LeaveLock()
759 SfxAppData_Impl
*pImp
= SFX_APP()->Get_Impl();
760 DBG_ASSERT( 0 != pImp
->nRescheduleLocks
, "SFxProgress::LeaveLock but no locks" );
761 pImp
->nRescheduleLocks
--;
764 // -----------------------------------------------------------------------
766 FASTBOOL
SfxProgress::StatusBarManagerGone_Impl
768 SfxStatusBarManager
* // dieser <SfxStatusBarManager> wird zerst"ort
773 Interne Methode zum Benachrichtigen des SfxProgress, da\s der angegebene
774 SfxStatusBarManger zerst"ort wird. Damit der Progress ihn loslassen