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: statusindicatorfactory.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_framework.hxx"
34 //-----------------------------------------------
38 #include <helper/statusindicatorfactory.hxx>
39 #include <helper/statusindicator.hxx>
40 #include <helper/vclstatusindicator.hxx>
41 #include <threadhelp/writeguard.hxx>
42 #include <threadhelp/readguard.hxx>
44 #include <properties.h>
46 //-----------------------------------------------
48 #include <com/sun/star/awt/Rectangle.hpp>
50 #ifndef _COM_SUN_STAR_AWT_XCONTROLS_HPP_
51 #include <com/sun/star/awt/XControl.hpp>
53 #include <com/sun/star/awt/XLayoutConstrains.hpp>
54 #include <com/sun/star/awt/DeviceInfo.hpp>
55 #include <com/sun/star/awt/PosSize.hpp>
56 #include <com/sun/star/awt/WindowAttribute.hpp>
57 #include <com/sun/star/awt/XTopWindow.hpp>
58 #include <com/sun/star/awt/XWindow2.hpp>
59 #include <com/sun/star/beans/XPropertySet.hpp>
60 #include <com/sun/star/frame/XLayoutManager.hpp>
62 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
63 #include <toolkit/unohlp.hxx>
66 //-----------------------------------------------
67 // includes of other projects
68 #include <comphelper/sequenceashashmap.hxx>
69 #include <comphelper/mediadescriptor.hxx>
70 #include <vcl/svapp.hxx>
71 #include <vos/mutex.hxx>
73 //-----------------------------------------------
78 //-----------------------------------------------
81 sal_Int32
StatusIndicatorFactory::m_nInReschedule
= 0; /// static counter for rescheduling
82 static ::rtl::OUString PROGRESS_RESOURCE
= ::rtl::OUString::createFromAscii("private:resource/progressbar/progressbar");
84 //-----------------------------------------------
85 DEFINE_XINTERFACE_5(StatusIndicatorFactory
,
87 DIRECT_INTERFACE(css::lang::XTypeProvider
),
88 DIRECT_INTERFACE(css::lang::XServiceInfo
),
89 DIRECT_INTERFACE(css::lang::XInitialization
),
90 DIRECT_INTERFACE(css::task::XStatusIndicatorFactory
),
91 DIRECT_INTERFACE(css::util::XUpdatable
))
93 DEFINE_XTYPEPROVIDER_5(StatusIndicatorFactory
,
94 css::lang::XTypeProvider
,
95 css::lang::XServiceInfo
,
96 css::lang::XInitialization
,
97 css::task::XStatusIndicatorFactory
,
98 css::util::XUpdatable
)
100 DEFINE_XSERVICEINFO_MULTISERVICE(StatusIndicatorFactory
,
101 ::cppu::OWeakObject
,
102 SERVICENAME_STATUSINDICATORFACTORY
,
103 IMPLEMENTATIONNAME_STATUSINDICATORFACTORY
)
105 DEFINE_INIT_SERVICE(StatusIndicatorFactory
,
108 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
109 to create a new instance of this class by our own supported service factory.
110 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
115 //-----------------------------------------------
116 StatusIndicatorFactory::StatusIndicatorFactory(const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
118 , ::cppu::OWeakObject ( )
121 , m_bAllowReschedule (sal_False
)
122 , m_bAllowParentShow (sal_False
)
123 , m_bDisableReschedule(sal_False
)
127 //-----------------------------------------------
128 StatusIndicatorFactory::~StatusIndicatorFactory()
130 impl_stopWakeUpThread();
133 //-----------------------------------------------
134 void SAL_CALL
StatusIndicatorFactory::initialize(const css::uno::Sequence
< css::uno::Any
>& lArguments
)
135 throw(css::uno::Exception
,
136 css::uno::RuntimeException
)
138 ::comphelper::SequenceAsHashMap
lArgs(lArguments
);
140 // SAFE -> ----------------------------------
141 WriteGuard
aWriteLock(m_aLock
);
143 m_xFrame
= lArgs
.getUnpackedValueOrDefault(STATUSINDICATORFACTORY_PROPNAME_FRAME
, css::uno::Reference
< css::frame::XFrame
>());
144 m_xPluggWindow
= lArgs
.getUnpackedValueOrDefault(STATUSINDICATORFACTORY_PROPNAME_WINDOW
, css::uno::Reference
< css::awt::XWindow
>() );
145 m_bAllowParentShow
= lArgs
.getUnpackedValueOrDefault(STATUSINDICATORFACTORY_PROPNAME_ALLOWPARENTSHOW
, (sal_Bool
)sal_False
);
146 m_bDisableReschedule
= lArgs
.getUnpackedValueOrDefault(STATUSINDICATORFACTORY_PROPNAME_DISABLERESCHEDULE
, (sal_Bool
)sal_False
);
149 // <- SAFE ----------------------------------
151 impl_createProgress();
154 //-----------------------------------------------
155 css::uno::Reference
< css::task::XStatusIndicator
> SAL_CALL
StatusIndicatorFactory::createStatusIndicator()
156 throw(css::uno::RuntimeException
)
158 StatusIndicator
* pIndicator
= new StatusIndicator(this);
159 css::uno::Reference
< css::task::XStatusIndicator
> xIndicator(static_cast< ::cppu::OWeakObject
* >(pIndicator
), css::uno::UNO_QUERY_THROW
);
164 //-----------------------------------------------
165 void SAL_CALL
StatusIndicatorFactory::update()
166 throw(css::uno::RuntimeException
)
168 // SAFE -> ----------------------------------
169 WriteGuard
aWriteLock(m_aLock
);
170 m_bAllowReschedule
= sal_True
;
172 // <- SAFE ----------------------------------
175 //-----------------------------------------------
176 void StatusIndicatorFactory::start(const css::uno::Reference
< css::task::XStatusIndicator
>& xChild
,
177 const ::rtl::OUString
& sText
,
180 // SAFE -> ----------------------------------
181 WriteGuard
aWriteLock(m_aLock
);
183 // create new info structure for this child or move it to the front of our stack
184 IndicatorStack::iterator pItem
= ::std::find(m_aStack
.begin(), m_aStack
.end(), xChild
);
185 if (pItem
!= m_aStack
.end())
186 m_aStack
.erase(pItem
);
187 IndicatorInfo
aInfo(xChild
, sText
, nRange
);
188 m_aStack
.push_back (aInfo
);
190 m_xActiveChild
= xChild
;
191 css::uno::Reference
< css::task::XStatusIndicator
> xProgress
= m_xProgress
;
194 // <- SAFE ----------------------------------
196 implts_makeParentVisibleIfAllowed();
199 xProgress
->start(sText
, nRange
);
201 impl_startWakeUpThread();
202 impl_reschedule(sal_True
);
205 //-----------------------------------------------
206 void StatusIndicatorFactory::reset(const css::uno::Reference
< css::task::XStatusIndicator
>& xChild
)
208 // SAFE -> ----------------------------------
209 ReadGuard
aReadLock(m_aLock
);
211 // reset the internal info structure related to this child
212 IndicatorStack::iterator pItem
= ::std::find(m_aStack
.begin(), m_aStack
.end(), xChild
);
213 if (pItem
!= m_aStack
.end())
216 pItem
->m_sText
= ::rtl::OUString();
219 css::uno::Reference
< css::task::XStatusIndicator
> xActive
= m_xActiveChild
;
220 css::uno::Reference
< css::task::XStatusIndicator
> xProgress
= m_xProgress
;
223 // <- SAFE ----------------------------------
225 // not the top most child => dont change UI
226 // But dont forget Reschedule!
228 (xChild
== xActive
) &&
233 impl_reschedule(sal_True
);
236 //-----------------------------------------------
237 void StatusIndicatorFactory::end(const css::uno::Reference
< css::task::XStatusIndicator
>& xChild
)
239 // SAFE -> ----------------------------------
240 WriteGuard
aWriteLock(m_aLock
);
242 // remove this child from our stack
243 IndicatorStack::iterator pItem
= ::std::find(m_aStack
.begin(), m_aStack
.end(), xChild
);
244 if (pItem
!= m_aStack
.end())
245 m_aStack
.erase(pItem
);
247 // activate next child ... or finish the progress if there is no further one.
248 m_xActiveChild
.clear();
249 ::rtl::OUString sText
;
250 sal_Int32 nValue
= 0;
251 IndicatorStack::reverse_iterator pNext
= m_aStack
.rbegin();
252 if (pNext
!= m_aStack
.rend())
254 m_xActiveChild
= pNext
->m_xIndicator
;
255 sText
= pNext
->m_sText
;
256 nValue
= pNext
->m_nValue
;
259 css::uno::Reference
< css::task::XStatusIndicator
> xActive
= m_xActiveChild
;
260 css::uno::Reference
< css::task::XStatusIndicator
> xProgress
= m_xProgress
;
263 // <- SAFE ----------------------------------
267 // There is at least one further child indicator.
268 // Actualize our progress, so it shows these values from now.
271 xProgress
->setText (sText
);
272 xProgress
->setValue(nValue
);
277 // Our stack is empty. No further child exists.
278 // Se we must "end" our progress realy
281 // Now hide the progress bar again.
284 impl_stopWakeUpThread();
287 impl_reschedule(sal_True
);
290 //-----------------------------------------------
291 void StatusIndicatorFactory::setText(const css::uno::Reference
< css::task::XStatusIndicator
>& xChild
,
292 const ::rtl::OUString
& sText
)
294 // SAFE -> ----------------------------------
295 WriteGuard
aWriteLock(m_aLock
);
297 IndicatorStack::iterator pItem
= ::std::find(m_aStack
.begin(), m_aStack
.end(), xChild
);
298 if (pItem
!= m_aStack
.end())
299 pItem
->m_sText
= sText
;
301 css::uno::Reference
< css::task::XStatusIndicator
> xActive
= m_xActiveChild
;
302 css::uno::Reference
< css::task::XStatusIndicator
> xProgress
= m_xProgress
;
305 // SAFE -> ----------------------------------
307 // paint only the top most indicator
308 // but dont forget to Reschedule!
310 (xChild
== xActive
) &&
314 xProgress
->setText(sText
);
317 impl_reschedule(sal_True
);
320 //-----------------------------------------------
321 void StatusIndicatorFactory::setValue( const css::uno::Reference
< css::task::XStatusIndicator
>& xChild
,
324 // SAFE -> ----------------------------------
325 WriteGuard
aWriteLock(m_aLock
);
327 sal_Int32 nOldValue
= 0;
328 IndicatorStack::iterator pItem
= ::std::find(m_aStack
.begin(), m_aStack
.end(), xChild
);
329 if (pItem
!= m_aStack
.end())
331 nOldValue
= pItem
->m_nValue
;
332 pItem
->m_nValue
= nValue
;
335 css::uno::Reference
< css::task::XStatusIndicator
> xActive
= m_xActiveChild
;
336 css::uno::Reference
< css::task::XStatusIndicator
> xProgress
= m_xProgress
;
339 // SAFE -> ----------------------------------
342 (xChild
== xActive
) &&
343 (nOldValue
!= nValue
) &&
347 xProgress
->setValue(nValue
);
350 impl_reschedule(sal_False
);
353 //-----------------------------------------------
354 void StatusIndicatorFactory::implts_makeParentVisibleIfAllowed()
356 // SAFE -> ----------------------------------
357 ReadGuard
aReadLock(m_aLock
);
359 if (!m_bAllowParentShow
)
362 css::uno::Reference
< css::frame::XFrame
> xFrame (m_xFrame
.get() , css::uno::UNO_QUERY
);
363 css::uno::Reference
< css::awt::XWindow
> xPluggWindow(m_xPluggWindow
.get(), css::uno::UNO_QUERY
);
366 // <- SAFE ----------------------------------
368 css::uno::Reference
< css::awt::XWindow
> xParentWindow
;
370 xParentWindow
= xFrame
->getContainerWindow();
372 xParentWindow
= xPluggWindow
;
374 // dont disturb user in case he put the loading document into the background!
375 // Supress any setVisible() or toFront() call in case the initial show was
377 css::uno::Reference
< css::awt::XWindow2
> xVisibleCheck(xParentWindow
, css::uno::UNO_QUERY
);
378 sal_Bool bIsVisible
= sal_False
;
379 if (xVisibleCheck
.is())
380 bIsVisible
= xVisibleCheck
->isVisible();
388 // Check if the layout manager has been set to invisible state. It this case we are also
389 // not allowed to set the frame visible!
390 css::uno::Reference
< css::beans::XPropertySet
> xPropSet(xFrame
, css::uno::UNO_QUERY
);
393 css::uno::Reference
< css::frame::XLayoutManager
> xLayoutManager
;
394 xPropSet
->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER
) >>= xLayoutManager
;
395 if (xLayoutManager
.is())
397 if ( !xLayoutManager
->isVisible() )
402 // Ok the window should be made visible ... becuase it isnt currently visible.
404 // We need a Hack for our applications: They get her progress from the frame directly
405 // on saving documents. Because there is no progress set on the MediaDescriptor.
406 // But that's wrong. In case the document was opened hidden, they shouldnt use any progress .-(
407 // They only possible workaround: dont show the parent window here, if the document was opened hidden.
408 sal_Bool bHiddenDoc
= sal_False
;
411 css::uno::Reference
< css::frame::XController
> xController
;
412 css::uno::Reference
< css::frame::XModel
> xModel
;
413 xController
= xFrame
->getController();
414 if (xController
.is())
415 xModel
= xController
->getModel();
418 ::comphelper::MediaDescriptor
lDocArgs(xModel
->getArgs());
419 bHiddenDoc
= lDocArgs
.getUnpackedValueOrDefault(
420 ::comphelper::MediaDescriptor::PROP_HIDDEN(),
421 (sal_Bool
)sal_False
);
428 // OK: The document was not opened in hidden mode ...
429 // and the window isnt already visible.
430 // Show it and bring it to front.
431 // But before we have to be sure, that our internal used helper progress
435 if (xParentWindow
.is())
436 xParentWindow
->setVisible(sal_True
);
438 #i75167# dont disturb window manager handling .-)
439 css::uno::Reference< css::awt::XTopWindow > xParentWindowTop(xParentWindow, css::uno::UNO_QUERY);
440 if (xParentWindowTop.is())
441 xParentWindowTop->toFront();
445 //-----------------------------------------------
446 void StatusIndicatorFactory::impl_createProgress()
448 // SAFE -> ----------------------------------
449 ReadGuard
aReadLock(m_aLock
);
451 css::uno::Reference
< css::frame::XFrame
> xFrame (m_xFrame
.get() , css::uno::UNO_QUERY
);
452 css::uno::Reference
< css::awt::XWindow
> xWindow(m_xPluggWindow
.get(), css::uno::UNO_QUERY
);
453 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
456 // <- SAFE ----------------------------------
458 css::uno::Reference
< css::task::XStatusIndicator
> xProgress
;
462 // use vcl based progress implementation in plugged mode
463 VCLStatusIndicator
* pVCLProgress
= new VCLStatusIndicator(xSMGR
, xWindow
);
464 xProgress
= css::uno::Reference
< css::task::XStatusIndicator
>(static_cast< css::task::XStatusIndicator
* >(pVCLProgress
), css::uno::UNO_QUERY
);
469 // use frame layouted progress implementation
470 css::uno::Reference
< css::beans::XPropertySet
> xPropSet(xFrame
, css::uno::UNO_QUERY
);
473 css::uno::Reference
< css::frame::XLayoutManager
> xLayoutManager
;
474 xPropSet
->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER
) >>= xLayoutManager
;
475 if (xLayoutManager
.is())
477 xLayoutManager
->lock();
478 xLayoutManager
->createElement( PROGRESS_RESOURCE
);
479 xLayoutManager
->hideElement( PROGRESS_RESOURCE
);
481 css::uno::Reference
< css::ui::XUIElement
> xProgressBar
= xLayoutManager
->getElement(PROGRESS_RESOURCE
);
482 if (xProgressBar
.is())
483 xProgress
= css::uno::Reference
< css::task::XStatusIndicator
>(xProgressBar
->getRealInterface(), css::uno::UNO_QUERY
);
484 xLayoutManager
->unlock();
489 // SAFE -> ----------------------------------
490 WriteGuard
aWriteLock(m_aLock
);
491 m_xProgress
= xProgress
;
493 // <- SAFE ----------------------------------
496 //-----------------------------------------------
497 void StatusIndicatorFactory::impl_showProgress()
499 // SAFE -> ----------------------------------
500 ReadGuard
aReadLock(m_aLock
);
502 css::uno::Reference
< css::frame::XFrame
> xFrame (m_xFrame
.get() , css::uno::UNO_QUERY
);
503 css::uno::Reference
< css::awt::XWindow
> xWindow(m_xPluggWindow
.get(), css::uno::UNO_QUERY
);
504 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
507 // <- SAFE ----------------------------------
509 css::uno::Reference
< css::task::XStatusIndicator
> xProgress
;
513 // use frame layouted progress implementation
514 css::uno::Reference
< css::beans::XPropertySet
> xPropSet(xFrame
, css::uno::UNO_QUERY
);
517 css::uno::Reference
< css::frame::XLayoutManager
> xLayoutManager
;
518 xPropSet
->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER
) >>= xLayoutManager
;
519 if (xLayoutManager
.is())
521 // Be sure that we have always a progress. It can be that our frame
522 // was recycled and therefore the progress was destroyed!
523 // CreateElement does nothing if there is already a valid progress.
524 xLayoutManager
->createElement( PROGRESS_RESOURCE
);
525 xLayoutManager
->showElement( PROGRESS_RESOURCE
);
527 css::uno::Reference
< css::ui::XUIElement
> xProgressBar
= xLayoutManager
->getElement(PROGRESS_RESOURCE
);
528 if (xProgressBar
.is())
529 xProgress
= css::uno::Reference
< css::task::XStatusIndicator
>(xProgressBar
->getRealInterface(), css::uno::UNO_QUERY
);
533 // SAFE -> ----------------------------------
534 WriteGuard
aWriteLock(m_aLock
);
535 m_xProgress
= xProgress
;
537 // <- SAFE ----------------------------------
541 //-----------------------------------------------
542 void StatusIndicatorFactory::impl_hideProgress()
544 // SAFE -> ----------------------------------
545 ReadGuard
aReadLock(m_aLock
);
547 css::uno::Reference
< css::frame::XFrame
> xFrame (m_xFrame
.get() , css::uno::UNO_QUERY
);
548 css::uno::Reference
< css::awt::XWindow
> xWindow(m_xPluggWindow
.get(), css::uno::UNO_QUERY
);
549 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
552 // <- SAFE ----------------------------------
556 // use frame layouted progress implementation
557 css::uno::Reference
< css::beans::XPropertySet
> xPropSet(xFrame
, css::uno::UNO_QUERY
);
560 css::uno::Reference
< css::frame::XLayoutManager
> xLayoutManager
;
561 xPropSet
->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER
) >>= xLayoutManager
;
562 if (xLayoutManager
.is())
563 xLayoutManager
->hideElement( PROGRESS_RESOURCE
);
568 //-----------------------------------------------
569 void StatusIndicatorFactory::impl_reschedule(sal_Bool bForce
)
572 ReadGuard
aReadLock(m_aLock
);
573 if (m_bDisableReschedule
)
578 sal_Bool bReschedule
= bForce
;
582 WriteGuard
aWriteLock(m_aLock
);
583 bReschedule
= m_bAllowReschedule
;
584 m_bAllowReschedule
= sal_False
;
593 WriteGuard
aGlobalLock(LockHelper::getGlobalLock());
595 if (m_nInReschedule
== 0)
598 aGlobalLock
.unlock();
601 Application::Reschedule(true);
609 //-----------------------------------------------
610 void StatusIndicatorFactory::impl_startWakeUpThread()
613 WriteGuard
aWriteLock(m_aLock
);
615 if (m_bDisableReschedule
)
620 m_pWakeUp
= new WakeUpThread(this);
627 //-----------------------------------------------
628 void StatusIndicatorFactory::impl_stopWakeUpThread()
631 WriteGuard
aWriteLock(m_aLock
);
634 // Thread kill itself after terminate()!
635 m_pWakeUp
->terminate();
642 } // namespace framework