Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / bastyp / progress.cxx
blobf31b125c25da7e51dfc433589698343b34abdbc2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <sfx2/progress.hxx>
31 #include <com/sun/star/uno/Reference.hxx>
32 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
34 #include <basic/sbx.hxx>
36 #include <svl/eitem.hxx>
37 #include <tools/time.hxx>
39 #include "appdata.hxx"
40 #include <sfx2/request.hxx>
41 #include <sfx2/frame.hxx>
42 #include <sfx2/viewfrm.hxx>
43 #include <sfx2/viewsh.hxx>
44 #include <sfx2/objsh.hxx>
45 #include <sfx2/app.hxx>
46 #include <sfx2/dispatch.hxx>
47 #include "sfxtypes.hxx"
48 #include <sfx2/docfile.hxx>
49 #include "workwin.hxx"
50 #include "sfx2/sfxresid.hxx"
51 #include "bastyp.hrc"
52 #include <sfx2/msg.hxx>
54 #include <time.h>
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::frame;
58 using namespace ::com::sun::star::task;
60 struct SfxProgress_Impl
62 Reference < XStatusIndicator > xStatusInd;
63 String aText, aStateText;
64 sal_uIntPtr nMax;
65 clock_t nCreate;
66 clock_t nNextReschedule;
67 sal_Bool bLocked, bAllDocs;
68 sal_Bool bWaitMode;
69 sal_Bool bAllowRescheduling;
70 sal_Bool bRunning;
71 sal_Bool bIsStatusText;
73 SfxProgress* pActiveProgress;
74 SfxObjectShellRef xObjSh;
75 SfxWorkWindow* pWorkWin;
76 SfxViewFrame* pView;
78 SfxProgress_Impl( const String& );
79 void Enable_Impl( sal_Bool );
83 //========================================================================
85 #define Progress
86 #include "sfxslots.hxx"
88 //========================================================================
89 extern sal_uInt32 Get10ThSec();
91 // -----------------------------------------------------------------------
93 void SfxProgress_Impl::Enable_Impl( sal_Bool bEnable )
95 SfxObjectShell* pDoc = bAllDocs ? NULL : (SfxObjectShell*) xObjSh;
96 SfxViewFrame *pFrame= SfxViewFrame::GetFirst(pDoc);
97 while ( pFrame )
99 pFrame->Enable(bEnable);
100 pFrame->GetDispatcher()->Lock( !bEnable );
101 pFrame = SfxViewFrame::GetNext(*pFrame, pDoc);
104 if ( pView )
106 pView->Enable( bEnable );
107 pView->GetDispatcher()->Lock( !bEnable );
110 if ( !pDoc )
111 SFX_APP()->GetAppDispatcher_Impl()->Lock( !bEnable );
114 // -----------------------------------------------------------------------
116 SfxProgress_Impl::SfxProgress_Impl( const String &/*rTitle*/ )
117 : pActiveProgress( 0 )
121 // -----------------------------------------------------------------------
123 SfxProgress::SfxProgress
125 SfxObjectShell* pObjSh, /* The action is performed on the
126 SfxObjectShell which can be NULL.
127 When it is then the application will be
128 used */
130 const String& rText, /* Text, which appears before the Statusmonitor
131 in the status line */
133 sal_uIntPtr nRange, /* Max value for range */
135 sal_Bool bAll, /* Disable all documents or only the document of the ViewFram */
136 sal_Bool bWait /* Activate the wait-Pointer initially (TRUE) */
139 /* [Description]
141 The constructor of the class SfxProgress switches the SfxObjectShell
142 passed as parameter and SfxViewFrames which display this document in
143 a progress mode. Ie as long as one of those SfxViewFrame instances is
144 active the associated SfxDispatcher and associated Window is disabled.
145 A progress-bar will be displayed in the status bar,
148 : pImp( new SfxProgress_Impl( rText ) ),
149 nVal(0),
150 bSuspended(sal_True)
152 pImp->bRunning = sal_True;
153 pImp->bAllowRescheduling = Application::IsInExecute();
155 pImp->xObjSh = pObjSh;
156 pImp->aText = rText;
157 pImp->nMax = nRange;
158 pImp->bLocked = sal_False;
159 pImp->bWaitMode = bWait;
160 pImp->bIsStatusText = sal_False;
161 pImp->nCreate = Get10ThSec();
162 pImp->nNextReschedule = pImp->nCreate;
163 DBG( DbgOutf( "SfxProgress: created for '%s' at %luds",
164 rText.GetBuffer(), pImp->nCreate ) );
165 pImp->bAllDocs = bAll;
166 pImp->pWorkWin = 0;
167 pImp->pView = 0;
169 pImp->pActiveProgress = GetActiveProgress( pObjSh );
170 if ( pObjSh )
171 pObjSh->SetProgress_Impl(this);
172 else if( !pImp->pActiveProgress )
173 SFX_APP()->SetProgress_Impl(this);
174 Resume();
177 // -----------------------------------------------------------------------
179 SfxProgress::~SfxProgress()
181 /* [Description]
183 The destructor of the class SfxProgress restores the old status,
184 the documents are released again and the status bar shows the items again.
188 Stop();
189 if ( pImp->xStatusInd.is() )
190 pImp->xStatusInd->end();
192 if( pImp->bIsStatusText == sal_True )
193 GetpApp()->HideStatusText( );
194 delete pImp;
197 // -----------------------------------------------------------------------
199 void SfxProgress::Stop()
201 /* [Description]
203 Early Exit of <SfxProgress>.
207 if( pImp->pActiveProgress )
209 if ( pImp->xObjSh.Is() && pImp->xObjSh->GetProgress() == this )
210 pImp->xObjSh->SetProgress_Impl(0);
211 return;
214 if ( !pImp->bRunning )
215 return;
216 pImp->bRunning = sal_False;
217 DBG( DbgOutf( "SfxProgress: destroyed at %luds", Get10ThSec() ) );
219 Suspend();
220 if ( pImp->xObjSh.Is() )
221 pImp->xObjSh->SetProgress_Impl(0);
222 else
223 SFX_APP()->SetProgress_Impl(0);
224 if ( pImp->bLocked )
225 pImp->Enable_Impl(sal_True);
228 // -----------------------------------------------------------------------
230 void SfxProgress::SetText
232 const String& /* new Text */
235 /* [Description]
237 Changes the text that appears to the left next to progress bar.
241 if( pImp->pActiveProgress ) return;
242 if ( pImp->xStatusInd.is() )
244 pImp->xStatusInd->reset();
245 pImp->xStatusInd->start( pImp->aText, pImp->nMax );
249 // -----------------------------------------------------------------------
251 // Required in App data
252 static sal_uIntPtr nLastTime = 0;
254 long TimeOut_Impl( void*, void* pArgV )
256 Timer *pArg = (Timer*)pArgV;
257 if( Time::GetSystemTicks() - nLastTime > 3000 )
259 GetpApp()->HideStatusText();
260 nLastTime = 0;
261 delete pArg;
263 else pArg->Start();
264 return 0;
267 // -----------------------------------------------------------------------
269 sal_Bool SfxProgress::SetStateText
271 sal_uLong nNewVal, /* New value for the progress-bar */
272 const String& rNewVal, /* Status as Text */
273 sal_uLong nNewRange /* new maximum value, 0 for retaining the old */
277 pImp->aStateText = rNewVal;
278 return SetState( nNewVal, nNewRange );
281 // -----------------------------------------------------------------------
283 sal_Bool SfxProgress::SetState
285 sal_uLong nNewVal, /* new value for the progress bar */
287 sal_uLong nNewRange /* new maximum value, 0 for retaining the old */
289 /* [Description]
291 Setting the current status, after a time delay Reschedule is called.
293 [Return value]
295 sal_Bool TRUE
296 Proceed with the action
298 FALSE
299 Cancel action
303 if( pImp->pActiveProgress ) return sal_True;
305 nVal = nNewVal;
307 // new Range?
308 if ( nNewRange && nNewRange != pImp->nMax )
310 DBG( DbgOutf( "SfxProgress: range changed from %lu to %lu",
311 pImp->nMax, nNewRange ) );
312 pImp->nMax = nNewRange;
315 if ( !pImp->xStatusInd.is() )
317 // get the active ViewFrame of the document this progress is working on
318 // if it doesn't work on a document, take the current ViewFrame
319 SfxObjectShell* pObjSh = pImp->xObjSh;
320 pImp->pView = SfxViewFrame::Current();
321 DBG_ASSERT( pImp->pView || pObjSh, "Can't make progress bar!");
322 if ( pObjSh && ( !pImp->pView || pObjSh != pImp->pView->GetObjectShell() ) )
324 // current document does not belong to current ViewFrame; take it's first visible ViewFrame
325 SfxViewFrame* pDocView = SfxViewFrame::GetFirst( pObjSh );
326 if ( pDocView )
327 pImp->pView = pDocView;
328 else
330 // don't show status indicator for hidden documents (only valid while loading)
331 SfxMedium* pMedium = pObjSh->GetMedium();
332 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pHiddenItem, SfxBoolItem, SID_HIDDEN, sal_False );
333 if ( !pHiddenItem || !pHiddenItem->GetValue() )
336 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pIndicatorItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, sal_False );
337 Reference< XStatusIndicator > xInd;
338 if ( pIndicatorItem && (pIndicatorItem->GetValue()>>=xInd) )
339 pImp->xStatusInd = xInd;
344 else if ( pImp->pView )
346 pImp->pWorkWin = SFX_APP()->GetWorkWindow_Impl( pImp->pView );
347 if ( pImp->pWorkWin )
348 pImp->xStatusInd = pImp->pWorkWin->GetStatusIndicator();
351 if ( pImp->xStatusInd.is() )
353 pImp->xStatusInd->start( pImp->aText, pImp->nMax );
354 pImp->pView = NULL;
358 if ( pImp->xStatusInd.is() )
360 pImp->xStatusInd->setValue( nNewVal );
363 return sal_True;
366 // -----------------------------------------------------------------------
368 void SfxProgress::Resume()
370 /* [Description]
372 Resumed the status of the display after an interrupt.
374 [Cross-reference]
376 <SfxProgress::Suspend()>
380 if( pImp->pActiveProgress ) return;
381 if ( bSuspended )
383 DBG( DbgOutf( "SfxProgress: resumed" ) );
384 if ( pImp->xStatusInd.is() )
386 pImp->xStatusInd->start( pImp->aText, pImp->nMax );
387 pImp->xStatusInd->setValue( nVal );
390 if ( pImp->bWaitMode )
392 if ( pImp->xObjSh.Is() && !pImp->bAllDocs )
394 for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
395 pFrame;
396 pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
397 pFrame->GetWindow().EnterWait();
401 if ( pImp->xObjSh )
403 SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
404 if ( pFrame )
405 pFrame->GetBindings().ENTERREGISTRATIONS();
408 bSuspended = sal_False;
412 // -----------------------------------------------------------------------
414 void SfxProgress::Suspend()
416 /* [Description]
418 Interrupts the status of the display
420 [Cross-reference]
422 <SfxProgress::Resume()>
426 if( pImp->pActiveProgress ) return;
427 if ( !bSuspended )
429 DBG( DbgOutf( "SfxProgress: suspended" ) );
430 bSuspended = sal_True;
432 if ( pImp->xStatusInd.is() )
434 pImp->xStatusInd->reset();
437 if ( pImp->xObjSh.Is() && !pImp->bAllDocs )
439 for ( SfxViewFrame *pFrame =
440 SfxViewFrame::GetFirst(pImp->xObjSh);
441 pFrame;
442 pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
443 pFrame->GetWindow().LeaveWait();
445 if ( pImp->xObjSh.Is() )
447 SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
448 if ( pFrame )
449 pFrame->GetBindings().LEAVEREGISTRATIONS();
454 // -----------------------------------------------------------------------
456 void SfxProgress::UnLock()
458 if( pImp->pActiveProgress ) return;
459 if ( !pImp->bLocked )
460 return;
462 DBG( DbgOutf( "SfxProgress: unlocked" ) );
463 pImp->bLocked = sal_False;
464 pImp->Enable_Impl(sal_True);
467 // -----------------------------------------------------------------------
469 void SfxProgress::Reschedule()
471 /* [Description]
473 Reschedule, callable from the outside
477 SFX_STACK(SfxProgress::Reschedule);
479 if( pImp->pActiveProgress ) return;
480 SfxApplication* pApp = SFX_APP();
481 if ( pImp->bLocked && 0 == pApp->Get_Impl()->nRescheduleLocks )
483 SfxAppData_Impl *pAppData = pApp->Get_Impl();
484 ++pAppData->nInReschedule;
485 Application::Reschedule();
486 --pAppData->nInReschedule;
490 // -----------------------------------------------------------------------
492 SfxProgress* SfxProgress::GetActiveProgress
494 SfxObjectShell* pDocSh /* the <SfxObjectShell>, which should be
495 queried after a current <SfxProgress>,
496 or 0 if an current SfxProgress for the
497 entire application should be obtained.
498 The pointer only needs at the time of
499 the call to be valid.
503 /* [Description]
505 This method is used to check whether and which <SfxProgress> is currently
506 active for a specific instance of SfxObjectShell or even an entire
507 application. This can for example be used to check for Time-Out-Events, etc.
509 Instead of a pointer to the SfxProgress the SfxObjectShell may be
510 pointed at the SfxProgress of the application, with the query
511 'SfxProgress:: GetActiveProgress (pMyDocSh)' thus the current
512 SfxProgress of 'pMyDocSh' is delivered, otherwise the SfxProgress of
513 the application or a 0-pointer.
515 [Note]
517 If no SfxProgress is running in the application and also not at the
518 specified SfxObjectShell, then this method will always return 0,
519 even if one SfxProgress runs on another SfxObjectShell.
521 [Cross-reference]
523 <SfxApplication::GetProgress()const>
524 <SfxObjectShell::GetProgress()const>
528 if ( !SfxApplication::Get() )
529 return 0;
531 SfxProgress *pProgress = 0;
532 if ( pDocSh )
533 pProgress = pDocSh->GetProgress();
534 if ( !pProgress )
535 pProgress = SFX_APP()->GetProgress();
536 return pProgress;
539 // -----------------------------------------------------------------------
541 void SfxProgress::EnterLock()
543 SFX_APP()->Get_Impl()->nRescheduleLocks++;
546 // -----------------------------------------------------------------------
548 void SfxProgress::LeaveLock()
550 SfxAppData_Impl *pImp = SFX_APP()->Get_Impl();
551 DBG_ASSERT( 0 != pImp->nRescheduleLocks, "SFxProgress::LeaveLock but no locks" );
552 pImp->nRescheduleLocks--;
555 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */