merge the formfield patch from ooo-build
[ooovba.git] / sfx2 / source / bastyp / progress.cxx
blob06791f4435534544a5c4fa61aa9edbe74890482a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: progress.cxx,v $
10 * $Revision: 1.29 $
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>
40 #endif
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"
58 #include "bastyp.hrc"
59 #include <sfx2/msg.hxx>
61 #include <time.h>
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 )
69 if ( nArg >= 10240 )
71 aNumber += String::CreateFromInt32( (sal_uInt16)( ( nArg + 512 ) / 1024 ) );
72 aNumber += ' ';
73 aNumber += SfxResId( STR_KB );
75 else
77 aNumber += String::CreateFromInt32( nArg );
78 aNumber += ' ';
79 aNumber += SfxResId( STR_BYTES );
83 struct SfxProgress_Impl : public SfxCancellable
85 Reference < XStatusIndicator > xStatusInd;
86 String aText, aStateText;
87 ULONG nMax;
88 clock_t nCreate;
89 clock_t nNextReschedule;
90 BOOL bLocked, bAllDocs;
91 BOOL bWaitMode;
92 BOOL bAllowRescheduling;
93 BOOL bRunning;
94 BOOL bIsStatusText;
96 SfxProgress* pActiveProgress;
97 SfxObjectShellRef xObjSh;
98 SfxWorkWindow* pWorkWin;
99 SfxViewFrame* pView;
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
114 #define Progress
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);
128 while ( pFrame )
130 pFrame->Enable(bEnable);
131 pFrame->GetDispatcher()->Lock( !bEnable );
132 pFrame = SfxViewFrame::GetNext(*pFrame, pDoc);
135 if ( pView )
137 pView->Enable( bEnable );
138 pView->GetDispatcher()->Lock( !bEnable );
141 if ( !pDoc )
142 SFX_APP()->GetAppDispatcher_Impl()->Lock( !bEnable );
145 // -----------------------------------------------------------------------
147 SfxProgress_Impl::SfxProgress_Impl( const String &rTitle )
148 : SfxCancellable( SFX_APP()->GetCancelManager(), rTitle ),
149 pActiveProgress( 0 )
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
160 verwendet */
162 const String& rText, /* Text, der in der Statuszeile vor den Statusmonitor
163 erscheint */
165 ULONG nRange, /* Maximalwert des Bereiches */
167 BOOL bAll /* alle Dokumente oder nur das Dokument des ViewFrames
168 disablen (FALSE) */
169 ,BOOL bWait /* initial den Wait-Pointer aktivieren (TRUE) */
172 /* [Beschreibung]
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 ) ),
183 nVal(0),
184 bSuspended(TRUE)
186 pImp->bRunning = TRUE;
187 pImp->bAllowRescheduling = Application::IsInExecute();;
189 if ( pObjSh )
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;
205 pImp->aText = rText;
206 pImp->nMax = nRange;
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;
215 pImp->pWorkWin = 0;
216 pImp->pView = 0;
218 pImp->pActiveProgress = GetActiveProgress( pObjSh );
219 if ( pObjSh )
220 pObjSh->SetProgress_Impl(this);
221 else if( !pImp->pActiveProgress )
222 SFX_APP()->SetProgress_Impl(this);
223 Resume();
226 // -----------------------------------------------------------------------
228 SfxProgress::~SfxProgress()
230 /* [Beschreibung]
232 Der Destruktor der Klasse SfxProgress restauriert den alten Zustand;
233 die Dokumente werden wieder freigeschaltet und die Statuszeile zeigt
234 wieder Items an.
238 Stop();
239 if ( pImp->xStatusInd.is() )
240 pImp->xStatusInd->end();
242 if( pImp->bIsStatusText == TRUE )
243 GetpApp()->HideStatusText( );
244 SfxObjectShell* pDoc = pImp->xObjSh;
245 if ( pDoc )
247 for( SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDoc ); pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pDoc ) )
248 pFrame->GetCancelManager()->RemoveCancellable( pImp );//Invalidate( SID_BROWSE_STOP );
250 else
251 SFX_APP()->Invalidate( SID_BROWSE_STOP );
252 delete pImp;
255 // -----------------------------------------------------------------------
257 void SfxProgress::Stop()
259 /* [Beschreibung]
261 Vorzeitiges Beenden des <SfxProgress>.
265 if( pImp->pActiveProgress )
267 if ( pImp->xObjSh.Is() && pImp->xObjSh->GetProgress() == this )
268 pImp->xObjSh->SetProgress_Impl(0);
269 return;
272 if ( !pImp->bRunning )
273 return;
274 pImp->bRunning = FALSE;
275 DBG( DbgOutf( "SfxProgress: destroyed at %luds", Get10ThSec() ) );
277 Suspend();
278 if ( pImp->xObjSh.Is() )
279 pImp->xObjSh->SetProgress_Impl(0);
280 else
281 SFX_APP()->SetProgress_Impl(0);
282 if ( pImp->bLocked )
283 pImp->Enable_Impl(TRUE);
286 // -----------------------------------------------------------------------
288 void SfxProgress::SetText
290 const String& /* neuer Text */
293 /* [Beschreibung]
295 "Andert den Text, der links neben dem Fortschritts-Balken
296 angezeigt wird.
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 );
323 String aString;
324 if( pReq )
325 aString = SfxMedium::GetStatusString( pHint->GetId(), pReq, pHint );
326 if( aString.Len() )
328 GetpApp()->ShowStatusText( aString );
329 if( pThis )
330 pThis->pImp->bIsStatusText = TRUE;
332 return 0;
336 // -----------------------------------------------------------------------
338 // muss in AppDaten
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();
347 nLastTime = 0;
348 delete pArg;
350 else pArg->Start();
351 return 0;
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 */
376 /* [Beschreibung]
378 Setzen des aktuellen Status; nach einem zeitlichen Versatz
379 wird Reschedule aufgerufen.
382 [R"uckgabewert]
384 BOOL TRUE
385 Fortfahren mit der Aktion
387 FALSE
388 Abbrechen der Aktion
392 // wurde via Stop-Button angehalten?
393 if ( pImp->IsCancelled() )
394 return FALSE;
396 if( pImp->pActiveProgress ) return TRUE;
398 // neuen Wert "ubernehmen
399 BOOL bOver=FALSE;
400 nVal = nNewVal;
402 // neuer Range?
403 if ( nNewRange && nNewRange != pImp->nMax )
405 DBG( DbgOutf( "SfxProgress: range changed from %lu to %lu",
406 pImp->nMax, nNewRange ) );
407 pImp->nMax = nNewRange;
408 bOver = TRUE;
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 );
422 if ( pDocView )
423 pImp->pView = pDocView;
424 else
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() )
435 // recycling frame
436 //pImp->pView = pFrame->GetCurrentViewFrame();
438 //else
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 );
458 pImp->pView = NULL;
462 if ( pImp->xStatusInd.is() )
464 pImp->xStatusInd->setValue( nNewVal );
467 return TRUE;
470 // -----------------------------------------------------------------------
472 void SfxProgress::Resume()
474 /* [Beschreibung]
476 Nimmt die Anzeige des Status nach einer Unterbrechung wieder auf.
478 [Querverweise]
479 <SfxProgress::Suspend()>
483 if( pImp->pActiveProgress ) return;
484 if ( bSuspended )
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);
498 pFrame;
499 pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
500 pFrame->GetWindow().EnterWait();
504 if ( pImp->xObjSh )
506 SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
507 if ( pFrame )
508 pFrame->GetBindings().ENTERREGISTRATIONS();
511 bSuspended = FALSE;
515 // -----------------------------------------------------------------------
517 void SfxProgress::Suspend()
519 /* [Beschreibung]
521 Unterbricht die Anzeige des Status
523 [Querverweise]
524 <SfxProgress::Resume()>
528 if( pImp->pActiveProgress ) return;
529 if ( !bSuspended )
531 DBG( DbgOutf( "SfxProgress: suspended" ) );
532 bSuspended = TRUE;
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);
543 pFrame;
544 pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
545 pFrame->GetWindow().LeaveWait();
547 if ( pImp->xObjSh.Is() )
549 SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
550 if ( pFrame )
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();
566 pDocSh;
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;
578 else
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 )
601 return;
603 DBG( DbgOutf( "SfxProgress: unlocked" ) );
604 pImp->bLocked = FALSE;
605 pImp->Enable_Impl(TRUE);
608 // -----------------------------------------------------------------------
610 void SfxProgress::Reschedule()
612 /* [Beschreibung]
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
639 BOOL bWait /* TRUE
640 Wartecursor wird verwendet
642 FALSE
643 Es wird kein Wartecursor verwendet */
646 /* [Beschreibung]
648 Wartecursor-Modus umschalten.
653 if( pImp->pActiveProgress ) return;
654 if ( !bSuspended && pImp->bWaitMode != bWait )
656 if ( bWait )
658 if ( pImp->xObjSh.Is() && !pImp->bAllDocs )
660 for ( SfxViewFrame *pFrame =
661 SfxViewFrame::GetFirst(pImp->xObjSh);
662 pFrame;
663 pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
664 pFrame->GetWindow().EnterWait();
667 else
669 if ( pImp->xObjSh.Is() && !pImp->bAllDocs )
671 for ( SfxViewFrame *pFrame =
672 SfxViewFrame::GetFirst(pImp->xObjSh);
673 pFrame;
674 pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
675 pFrame->GetWindow().LeaveWait();
680 pImp->bWaitMode = bWait;
683 // -----------------------------------------------------------------------
685 BOOL SfxProgress::GetWaitMode() const
687 /* [Beschreibung]
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. */
709 /* [Beschreibung]
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.
723 [Anmerkung]
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.
730 [Querverweise]
732 <SfxApplication::GetProgress()const>
733 <SfxObjectShell::GetProgress()const>
737 if ( !SfxApplication::Is_Impl() )
738 return 0;
740 SfxProgress *pProgress = 0;
741 if ( pDocSh )
742 pProgress = pDocSh->GetProgress();
743 if ( !pProgress )
744 pProgress = SFX_APP()->GetProgress();
745 return pProgress;
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
771 /* [Beschreibung]
773 Interne Methode zum Benachrichtigen des SfxProgress, da\s der angegebene
774 SfxStatusBarManger zerst"ort wird. Damit der Progress ihn loslassen
775 kann.
779 return TRUE;