/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sfx2.hxx" #include #include #include #ifndef _SBX_HXX //autogen #include #endif #include #include // wg. nRescheduleLocks #include "appdata.hxx" #include #include #include #include #include #include #include #include "sfxtypes.hxx" #include #include "workwin.hxx" #include "sfx2/sfxresid.hxx" #include "bastyp.hrc" #include #include using namespace ::com::sun::star::uno; using namespace ::com::sun::star::frame; using namespace ::com::sun::star::task; void AddNumber_Impl( String& aNumber, sal_uInt32 nArg ) { if ( nArg >= 10240 ) { aNumber += String::CreateFromInt32( (sal_uInt16)( ( nArg + 512 ) / 1024 ) ); aNumber += ' '; aNumber += SfxResId( STR_KB ); } else { aNumber += String::CreateFromInt32( nArg ); aNumber += ' '; aNumber += SfxResId( STR_BYTES ); } } struct SfxProgress_Impl { Reference < XStatusIndicator > xStatusInd; String aText, aStateText; sal_uIntPtr nMax; clock_t nCreate; clock_t nNextReschedule; sal_Bool bLocked, bAllDocs; sal_Bool bWaitMode; sal_Bool bAllowRescheduling; sal_Bool bRunning; sal_Bool bIsStatusText; SfxProgress* pActiveProgress; SfxObjectShellRef xObjSh; SfxWorkWindow* pWorkWin; SfxViewFrame* pView; SfxProgress_Impl( const String& ); void Enable_Impl( sal_Bool ); }; //======================================================================== #define TIMEOUT_PROGRESS 5L /* 10th s */ #define MAXPERCENT_PROGRESS 33 #define TIMEOUT_RESCHEDULE 10L /* 10th s */ #define MAXPERCENT_RESCHEDULE 50 #define Progress #include "sfxslots.hxx" #define aTypeLibInfo aProgressTypeLibImpl //======================================================================== extern sal_uIntPtr Get10ThSec(); // ----------------------------------------------------------------------- void SfxProgress_Impl::Enable_Impl( sal_Bool bEnable ) { SfxObjectShell* pDoc = bAllDocs ? NULL : (SfxObjectShell*) xObjSh; SfxViewFrame *pFrame= SfxViewFrame::GetFirst(pDoc); while ( pFrame ) { pFrame->Enable(bEnable); pFrame->GetDispatcher()->Lock( !bEnable ); pFrame = SfxViewFrame::GetNext(*pFrame, pDoc); } if ( pView ) { pView->Enable( bEnable ); pView->GetDispatcher()->Lock( !bEnable ); } if ( !pDoc ) SFX_APP()->GetAppDispatcher_Impl()->Lock( !bEnable ); } // ----------------------------------------------------------------------- SfxProgress_Impl::SfxProgress_Impl( const String &/*rTitle*/ ) : pActiveProgress( 0 ) { } // ----------------------------------------------------------------------- SfxProgress::SfxProgress ( SfxObjectShell* pObjSh, /* SfxObjectShell, an der die Aktion ausgeführt wird. Kann NULL sein, dann wird die Applikation verwendet */ const String& rText, /* Text, der in der Statuszeile vor den Statusmonitor erscheint */ sal_uIntPtr nRange, /* Maximalwert des Bereiches */ sal_Bool bAll /* alle Dokumente oder nur das Dokument des ViewFrames disablen (sal_False) */ ,sal_Bool bWait /* initial den Wait-Pointer aktivieren (sal_True) */ ) /* [Beschreibung] Der Konstruktor der Klasse SfxProgress schaltet den als Parameter übergebenen SfxObjectShell und SfxViewFrames, welche dieses Dokument anzeigen in einen Progress-Mode. D.h. solange eine dieser SfxViewFrame Instanzen aktiv ist, ist der dazugehörige SfxDispatcher und das dazugehörige Window disabled. In der Statuszeile wird ein Balken zur Fortschritts-Anzeige angezeigt. */ : pImp( new SfxProgress_Impl( rText ) ), nVal(0), bSuspended(sal_True) { pImp->bRunning = sal_True; pImp->bAllowRescheduling = Application::IsInExecute();; pImp->xObjSh = pObjSh; pImp->aText = rText; pImp->nMax = nRange; pImp->bLocked = sal_False; pImp->bWaitMode = bWait; pImp->bIsStatusText = sal_False; pImp->nCreate = Get10ThSec(); pImp->nNextReschedule = pImp->nCreate; DBG( DbgOutf( "SfxProgress: created for '%s' at %luds", rText.GetBuffer(), pImp->nCreate ) ); pImp->bAllDocs = bAll; pImp->pWorkWin = 0; pImp->pView = 0; pImp->pActiveProgress = GetActiveProgress( pObjSh ); if ( pObjSh ) pObjSh->SetProgress_Impl(this); else if( !pImp->pActiveProgress ) SFX_APP()->SetProgress_Impl(this); Resume(); } // ----------------------------------------------------------------------- SfxProgress::~SfxProgress() /* [Beschreibung] Der Destruktor der Klasse SfxProgress restauriert den alten Zustand; die Dokumente werden wieder freigeschaltet und die Statuszeile zeigt wieder Items an. */ { Stop(); if ( pImp->xStatusInd.is() ) pImp->xStatusInd->end(); if( pImp->bIsStatusText == sal_True ) GetpApp()->HideStatusText( ); delete pImp; } // ----------------------------------------------------------------------- void SfxProgress::Stop() /* [Beschreibung] Vorzeitiges Beenden des . */ { if( pImp->pActiveProgress ) { if ( pImp->xObjSh.Is() && pImp->xObjSh->GetProgress() == this ) pImp->xObjSh->SetProgress_Impl(0); return; } if ( !pImp->bRunning ) return; pImp->bRunning = sal_False; DBG( DbgOutf( "SfxProgress: destroyed at %luds", Get10ThSec() ) ); Suspend(); if ( pImp->xObjSh.Is() ) pImp->xObjSh->SetProgress_Impl(0); else SFX_APP()->SetProgress_Impl(0); if ( pImp->bLocked ) pImp->Enable_Impl(sal_True); } // ----------------------------------------------------------------------- void SfxProgress::SetText ( const String& /* neuer Text */ ) /* [Beschreibung] Ändert den Text, der links neben dem Fortschritts-Balken angezeigt wird. */ { if( pImp->pActiveProgress ) return; if ( pImp->xStatusInd.is() ) { pImp->xStatusInd->reset(); pImp->xStatusInd->start( pImp->aText, pImp->nMax ); } } // ----------------------------------------------------------------------- const String& SfxProgress::GetStateText_Impl() const { return pImp->aStateText; } // ----------------------------------------------------------------------- /* IMPL_STATIC_LINK( SfxProgress, SetStateHdl, PlugInLoadStatus*, pStatus ) { INetRequest* pReq = 0; const INetHint *pHint = PTR_CAST( INetHint, pStatus->pHint ); pReq = PTR_CAST( INetRequest, pStatus->pBC ); String aString; if( pReq ) aString = SfxMedium::GetStatusString( pHint->GetId(), pReq, pHint ); if( aString.Len() ) { GetpApp()->ShowStatusText( aString ); if( pThis ) pThis->pImp->bIsStatusText = sal_True; } return 0; } */ // ----------------------------------------------------------------------- // muss in AppDaten static sal_uIntPtr nLastTime = 0; long TimeOut_Impl( void*, void* pArgV ) { Timer *pArg = (Timer*)pArgV; if( Time::GetSystemTicks() - nLastTime > 3000 ) { GetpApp()->HideStatusText(); nLastTime = 0; delete pArg; } else pArg->Start(); return 0; } // ----------------------------------------------------------------------- sal_Bool SfxProgress::SetStateText ( sal_uLong nNewVal, /* neuer Wert für die Fortschritts-Anzeige */ const String& rNewVal, /* Status als Text */ sal_uLong nNewRange /* neuer Maximalwert, 0 für Beibehaltung des alten */ ) { pImp->aStateText = rNewVal; return SetState( nNewVal, nNewRange ); } // ----------------------------------------------------------------------- sal_Bool SfxProgress::SetState ( sal_uLong nNewVal, /* neuer Wert für die Fortschritts-Anzeige */ sal_uLong nNewRange /* neuer Maximalwert, 0 für Beibehaltung des alten */ ) /* [Beschreibung] Setzen des aktuellen Status; nach einem zeitlichen Versatz wird Reschedule aufgerufen. [Rückgabewert] sal_Bool TRUE Fortfahren mit der Aktion FALSE Abbrechen der Aktion */ { // wurde via Stop-Button angehalten? // if ( pImp->IsCancelled() ) // return sal_False; if( pImp->pActiveProgress ) return sal_True; // neuen Wert übernehmen sal_Bool bOver=sal_False; nVal = nNewVal; // neuer Range? if ( nNewRange && nNewRange != pImp->nMax ) { DBG( DbgOutf( "SfxProgress: range changed from %lu to %lu", pImp->nMax, nNewRange ) ); pImp->nMax = nNewRange; bOver = sal_True; } if ( !pImp->xStatusInd.is() ) { // get the active ViewFrame of the document this progress is working on // if it doesn't work on a document, take the current ViewFrame SfxObjectShell* pObjSh = pImp->xObjSh; pImp->pView = SfxViewFrame::Current(); DBG_ASSERT( pImp->pView || pObjSh, "Can't make progress bar!"); if ( pObjSh && ( !pImp->pView || pObjSh != pImp->pView->GetObjectShell() ) ) { // current document does not belong to current ViewFrame; take its first visible ViewFrame SfxViewFrame* pDocView = SfxViewFrame::GetFirst( pObjSh ); if ( pDocView ) pImp->pView = pDocView; else { // don't show status indicator for hidden documents (only valid while loading) SfxMedium* pMedium = pObjSh->GetMedium(); SFX_ITEMSET_ARG( pMedium->GetItemSet(), pHiddenItem, SfxBoolItem, SID_HIDDEN, sal_False ); if ( !pHiddenItem || !pHiddenItem->GetValue() ) { // not in a view, perhaps it's just loading //SfxFrame* pFrame = pMedium->GetLoadTargetFrame(); //if ( pFrame && pFrame->GetCurrentViewFrame() ) //{ // recycling frame //pImp->pView = pFrame->GetCurrentViewFrame(); //} //else { SFX_ITEMSET_ARG( pMedium->GetItemSet(), pIndicatorItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, sal_False ); Reference< XStatusIndicator > xInd; if ( pIndicatorItem && (pIndicatorItem->GetValue()>>=xInd) ) pImp->xStatusInd = xInd; } } } } else if ( pImp->pView ) { pImp->pWorkWin = SFX_APP()->GetWorkWindow_Impl( pImp->pView ); if ( pImp->pWorkWin ) pImp->xStatusInd = pImp->pWorkWin->GetStatusIndicator(); } if ( pImp->xStatusInd.is() ) { pImp->xStatusInd->start( pImp->aText, pImp->nMax ); pImp->pView = NULL; } } if ( pImp->xStatusInd.is() ) { pImp->xStatusInd->setValue( nNewVal ); } return sal_True; } // ----------------------------------------------------------------------- void SfxProgress::Resume() /* [Beschreibung] Nimmt die Anzeige des Status nach einer Unterbrechung wieder auf. [Querverweise] */ { if( pImp->pActiveProgress ) return; if ( bSuspended ) { DBG( DbgOutf( "SfxProgress: resumed" ) ); if ( pImp->xStatusInd.is() ) { pImp->xStatusInd->start( pImp->aText, pImp->nMax ); pImp->xStatusInd->setValue( nVal ); } if ( pImp->bWaitMode ) { if ( pImp->xObjSh.Is() && !pImp->bAllDocs ) { for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh); pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) ) pFrame->GetWindow().EnterWait(); } } if ( pImp->xObjSh ) { SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh); if ( pFrame ) pFrame->GetBindings().ENTERREGISTRATIONS(); } bSuspended = sal_False; } } // ----------------------------------------------------------------------- void SfxProgress::Suspend() /* [Beschreibung] Unterbricht die Anzeige des Status [Querverweise] */ { if( pImp->pActiveProgress ) return; if ( !bSuspended ) { DBG( DbgOutf( "SfxProgress: suspended" ) ); bSuspended = sal_True; if ( pImp->xStatusInd.is() ) { pImp->xStatusInd->reset(); } if ( pImp->xObjSh.Is() && !pImp->bAllDocs ) { for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh); pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) ) pFrame->GetWindow().LeaveWait(); } if ( pImp->xObjSh.Is() ) { SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh); if ( pFrame ) pFrame->GetBindings().LEAVEREGISTRATIONS(); } } } // ----------------------------------------------------------------------- void SfxProgress::Lock() { if( pImp->pActiveProgress ) return; // kein Reschedule bei Embedded-Objekten, // da wir gegen das OLE Protokoll wehrlos sind if ( !pImp->xObjSh.Is() ) { for ( SfxObjectShell *pDocSh = SfxObjectShell::GetFirst(); pDocSh; pDocSh = SfxObjectShell::GetNext(*pDocSh) ) { SfxObjectCreateMode eMode = pDocSh->GetCreateMode(); if ( ( eMode == SFX_CREATE_MODE_EMBEDDED ) || ( eMode == SFX_CREATE_MODE_PREVIEW ) ) { DBG( DbgOutf( "SfxProgress: not locked because EMBEDDED/PREVIEW found" ) ); pImp->bAllowRescheduling = sal_False; } } } else { SfxObjectCreateMode eMode = pImp->xObjSh->GetCreateMode(); if ( ( eMode == SFX_CREATE_MODE_EMBEDDED ) || ( eMode == SFX_CREATE_MODE_PREVIEW ) ) { DBG( DbgOutf( "SfxProgress: not locked because ObjectShell is EMBEDDED/PREVIEW" ) ); pImp->bAllowRescheduling = sal_False; } } pImp->Enable_Impl( sal_False ); DBG( DbgOutf( "SfxProgress: locked" ) ); pImp->bLocked = sal_True; } // ----------------------------------------------------------------------- void SfxProgress::UnLock() { if( pImp->pActiveProgress ) return; if ( !pImp->bLocked ) return; DBG( DbgOutf( "SfxProgress: unlocked" ) ); pImp->bLocked = sal_False; pImp->Enable_Impl(sal_True); } // ----------------------------------------------------------------------- void SfxProgress::Reschedule() /* [Beschreibung] Reschedule von außen rufbar */ { SFX_STACK(SfxProgress::Reschedule); if( pImp->pActiveProgress ) return; SfxApplication* pApp = SFX_APP(); if ( pImp->bLocked && 0 == pApp->Get_Impl()->nRescheduleLocks ) { DBG_ASSERTWARNING( pApp->IsInAsynchronCall_Impl(), "Reschedule in synchron-call-stack" ); SfxAppData_Impl *pAppData = pApp->Get_Impl(); ++pAppData->nInReschedule; Application::Reschedule(); --pAppData->nInReschedule; } } // ----------------------------------------------------------------------- void SfxProgress::SetWaitMode ( sal_Bool bWait /* TRUE Wartecursor wird verwendet FALSE Es wird kein Wartecursor verwendet */ ) /* [Beschreibung] Wartecursor-Modus umschalten. */ { if( pImp->pActiveProgress ) return; if ( !bSuspended && pImp->bWaitMode != bWait ) { if ( bWait ) { if ( pImp->xObjSh.Is() && !pImp->bAllDocs ) { for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh); pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) ) pFrame->GetWindow().EnterWait(); } } else { if ( pImp->xObjSh.Is() && !pImp->bAllDocs ) { for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh); pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) ) pFrame->GetWindow().LeaveWait(); } } } pImp->bWaitMode = bWait; } // ----------------------------------------------------------------------- sal_Bool SfxProgress::GetWaitMode() const /* [Beschreibung] Wartecursor-Modus abfragen. */ { return pImp->bWaitMode; } // ----------------------------------------------------------------------- SfxProgress* SfxProgress::GetActiveProgress ( SfxObjectShell* pDocSh /* , die nach einem laufenden gefragt werden soll, oder 0, wenn ein für die gesamte Applikation laufender SfxProgress erfragt werden soll. Der Pointer braucht nur zum Zeitpunkt des Aufrufs gültig zu sein. */ ) /* [Beschreibung] Mit dieser Methode kann erfragt werden, ob und welcher - für eine bestimmte Instanz von SfxObjectShell oder gar die gesamte Applikation zur Zeit aktiv ist. Dies kann z.B. zum Abfangen von Time-Out-Events etc. verwendet werden. Anstelle eines Pointer auf den SfxProgress der SfxObjectShell wird ggf. der auf den SfxProgress der Applikation geliefert, mit der Abfrage 'SfxProgress::GetActiveProgress(pMyDocSh)' wird also insofern vorhanden der SfxProgress von 'pMyDocSh' geliefert, sonst der SfxProgress der Applikation bzw. ein 0-Pointer. [Anmerkung] Läuft kein SfxProgress an der Applikation und ebenfalls keiner an der angegebenen SfxObjectShell, dann wird immer 0 zurückgeliefert, auch wenn an einer anderen SfxObjectShell ein SfxProgress läuft. [Querverweise] */ { if ( !SfxApplication::Get() ) return 0; SfxProgress *pProgress = 0; if ( pDocSh ) pProgress = pDocSh->GetProgress(); if ( !pProgress ) pProgress = SFX_APP()->GetProgress(); return pProgress; } // ----------------------------------------------------------------------- void SfxProgress::EnterLock() { SFX_APP()->Get_Impl()->nRescheduleLocks++; } // ----------------------------------------------------------------------- void SfxProgress::LeaveLock() { SfxAppData_Impl *pImp = SFX_APP()->Get_Impl(); DBG_ASSERT( 0 != pImp->nRescheduleLocks, "SFxProgress::LeaveLock but no locks" ); pImp->nRescheduleLocks--; } // ----------------------------------------------------------------------- FASTBOOL SfxProgress::StatusBarManagerGone_Impl ( SfxStatusBarManager * // dieser wird zerstört ) /* [Beschreibung] Interne Methode zum Benachrichtigen des SfxProgress, dass der angegebene SfxStatusBarManger zerstört wird. Damit der Progress ihn loslassen kann. */ { return sal_True; } /* vim: set noet sw=4 ts=4: */