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"
52 #include <sfx2/msg.hxx>
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
;
66 clock_t nNextReschedule
;
67 sal_Bool bLocked
, bAllDocs
;
69 sal_Bool bAllowRescheduling
;
71 sal_Bool bIsStatusText
;
73 SfxProgress
* pActiveProgress
;
74 SfxObjectShellRef xObjSh
;
75 SfxWorkWindow
* pWorkWin
;
78 SfxProgress_Impl( const String
& );
79 void Enable_Impl( sal_Bool
);
83 //========================================================================
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
);
99 pFrame
->Enable(bEnable
);
100 pFrame
->GetDispatcher()->Lock( !bEnable
);
101 pFrame
= SfxViewFrame::GetNext(*pFrame
, pDoc
);
106 pView
->Enable( bEnable
);
107 pView
->GetDispatcher()->Lock( !bEnable
);
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
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) */
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
) ),
152 pImp
->bRunning
= sal_True
;
153 pImp
->bAllowRescheduling
= Application::IsInExecute();
155 pImp
->xObjSh
= pObjSh
;
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
;
169 pImp
->pActiveProgress
= GetActiveProgress( pObjSh
);
171 pObjSh
->SetProgress_Impl(this);
172 else if( !pImp
->pActiveProgress
)
173 SFX_APP()->SetProgress_Impl(this);
177 // -----------------------------------------------------------------------
179 SfxProgress::~SfxProgress()
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.
189 if ( pImp
->xStatusInd
.is() )
190 pImp
->xStatusInd
->end();
192 if( pImp
->bIsStatusText
== sal_True
)
193 GetpApp()->HideStatusText( );
197 // -----------------------------------------------------------------------
199 void SfxProgress::Stop()
203 Early Exit of <SfxProgress>.
207 if( pImp
->pActiveProgress
)
209 if ( pImp
->xObjSh
.Is() && pImp
->xObjSh
->GetProgress() == this )
210 pImp
->xObjSh
->SetProgress_Impl(0);
214 if ( !pImp
->bRunning
)
216 pImp
->bRunning
= sal_False
;
217 DBG( DbgOutf( "SfxProgress: destroyed at %luds", Get10ThSec() ) );
220 if ( pImp
->xObjSh
.Is() )
221 pImp
->xObjSh
->SetProgress_Impl(0);
223 SFX_APP()->SetProgress_Impl(0);
225 pImp
->Enable_Impl(sal_True
);
228 // -----------------------------------------------------------------------
230 void SfxProgress::SetText
232 const String
& /* new Text */
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();
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 */
291 Setting the current status, after a time delay Reschedule is called.
296 Proceed with the action
303 if( pImp
->pActiveProgress
) return sal_True
;
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
);
327 pImp
->pView
= pDocView
;
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
);
358 if ( pImp
->xStatusInd
.is() )
360 pImp
->xStatusInd
->setValue( nNewVal
);
366 // -----------------------------------------------------------------------
368 void SfxProgress::Resume()
372 Resumed the status of the display after an interrupt.
376 <SfxProgress::Suspend()>
380 if( pImp
->pActiveProgress
) return;
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
);
396 pFrame
= SfxViewFrame::GetNext( *pFrame
, pImp
->xObjSh
) )
397 pFrame
->GetWindow().EnterWait();
403 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst(pImp
->xObjSh
);
405 pFrame
->GetBindings().ENTERREGISTRATIONS();
408 bSuspended
= sal_False
;
412 // -----------------------------------------------------------------------
414 void SfxProgress::Suspend()
418 Interrupts the status of the display
422 <SfxProgress::Resume()>
426 if( pImp
->pActiveProgress
) return;
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
);
442 pFrame
= SfxViewFrame::GetNext( *pFrame
, pImp
->xObjSh
) )
443 pFrame
->GetWindow().LeaveWait();
445 if ( pImp
->xObjSh
.Is() )
447 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst(pImp
->xObjSh
);
449 pFrame
->GetBindings().LEAVEREGISTRATIONS();
454 // -----------------------------------------------------------------------
456 void SfxProgress::UnLock()
458 if( pImp
->pActiveProgress
) return;
459 if ( !pImp
->bLocked
)
462 DBG( DbgOutf( "SfxProgress: unlocked" ) );
463 pImp
->bLocked
= sal_False
;
464 pImp
->Enable_Impl(sal_True
);
467 // -----------------------------------------------------------------------
469 void SfxProgress::Reschedule()
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.
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.
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.
523 <SfxApplication::GetProgress()const>
524 <SfxObjectShell::GetProgress()const>
528 if ( !SfxApplication::Get() )
531 SfxProgress
*pProgress
= 0;
533 pProgress
= pDocSh
->GetProgress();
535 pProgress
= SFX_APP()->GetProgress();
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: */