1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 //____________________________________________________________________________________________________________
29 //	my own includes
30 //____________________________________________________________________________________________________________
31 
32 #include "statusindicator.hxx"
33 
34 //____________________________________________________________________________________________________________
35 //	includes of other projects
36 //____________________________________________________________________________________________________________
37 #include <com/sun/star/awt/InvalidateStyle.hpp>
38 #include <com/sun/star/awt/WindowAttribute.hpp>
39 #include <cppuhelper/typeprovider.hxx>
40 #include <tools/debug.hxx>
41 
42 //____________________________________________________________________________________________________________
43 //	includes of my project
44 //____________________________________________________________________________________________________________
45 #include "progressbar.hxx"
46 
47 //____________________________________________________________________________________________________________
48 //	namespace
49 //____________________________________________________________________________________________________________
50 
51 using namespace	::cppu					;
52 using namespace	::osl					;
53 using namespace	::rtl					;
54 using namespace	::com::sun::star::uno	;
55 using namespace	::com::sun::star::lang	;
56 using namespace	::com::sun::star::awt	;
57 using namespace	::com::sun::star::task	;
58 
59 namespace unocontrols{
60 
61 //____________________________________________________________________________________________________________
62 //	construct/destruct
63 //____________________________________________________________________________________________________________
64 
65 StatusIndicator::StatusIndicator( const Reference< XMultiServiceFactory >& xFactory )
66 	: BaseContainerControl	( xFactory	)
67 {
68 	// Its not allowed to work with member in this method (refcounter !!!)
69 	// But with a HACK (++refcount) its "OK" :-(
70 	++m_refCount ;
71 
72 	// Create instances for fixedtext and progress ...
73 	m_xText			= Reference< XFixedText > 	( xFactory->createInstance( OUString::createFromAscii( FIXEDTEXT_SERVICENAME	) ), UNO_QUERY );
74 	m_xProgressBar	= Reference< XProgressBar >	( xFactory->createInstance( OUString::createFromAscii( SERVICENAME_PROGRESSBAR	) ), UNO_QUERY );
75 	// ... cast controls to Reference< XControl > and set model ...
76 	// ( ProgressBar has no model !!! )
77 	Reference< XControl > xTextControl		( m_xText		, UNO_QUERY );
78 	Reference< XControl > xProgressControl	( m_xProgressBar, UNO_QUERY );
79 	xTextControl->setModel( Reference< XControlModel >( xFactory->createInstance( OUString::createFromAscii( FIXEDTEXT_MODELNAME ) ), UNO_QUERY ) );
80 	// ... and add controls to basecontainercontrol!
81 	addControl( OUString::createFromAscii( CONTROLNAME_TEXT			), xTextControl   	);
82 	addControl( OUString::createFromAscii( CONTROLNAME_PROGRESSBAR	), xProgressControl	);
83 	// FixedText make it automaticly visible by himself ... but not the progressbar !!!
84 	// it must be set explicitly
85 	Reference< XWindow > xProgressWindow( m_xProgressBar, UNO_QUERY );
86 	xProgressWindow->setVisible( sal_True );
87 	// Reset to defaults !!!
88 	// (progressbar take automaticly its own defaults)
89 	m_xText->setText( OUString::createFromAscii( DEFAULT_TEXT ) );
90 
91 	--m_refCount ;
92 }
93 
94 StatusIndicator::~StatusIndicator()
95 {
96 	// Release all references
97 	m_xText			= Reference< XFixedText >();
98 	m_xProgressBar	= Reference< XProgressBar >();
99 }
100 
101 //____________________________________________________________________________________________________________
102 //	XInterface
103 //____________________________________________________________________________________________________________
104 
105 Any SAL_CALL StatusIndicator::queryInterface( const Type& rType ) throw( RuntimeException )
106 {
107 	// Attention:
108 	//	Don't use mutex or guard in this method!!! Is a method of XInterface.
109 	Any aReturn ;
110 	Reference< XInterface > xDel = BaseContainerControl::impl_getDelegator();
111 	if ( xDel.is() )
112 	{
113 		// If an delegator exist, forward question to his queryInterface.
114 		// Delegator will ask his own queryAggregation!
115 		aReturn = xDel->queryInterface( rType );
116 	}
117 	else
118 	{
119 		// If an delegator unknown, forward question to own queryAggregation.
120 		aReturn = queryAggregation( rType );
121 	}
122 
123 	return aReturn ;
124 }
125 
126 //____________________________________________________________________________________________________________
127 //	XInterface
128 //____________________________________________________________________________________________________________
129 
130 void SAL_CALL StatusIndicator::acquire() throw()
131 {
132 	// Attention:
133 	//	Don't use mutex or guard in this method!!! Is a method of XInterface.
134 
135 	// Forward to baseclass
136 	BaseControl::acquire();
137 }
138 
139 //____________________________________________________________________________________________________________
140 //	XInterface
141 //____________________________________________________________________________________________________________
142 
143 void SAL_CALL StatusIndicator::release() throw()
144 {
145 	// Attention:
146 	//	Don't use mutex or guard in this method!!! Is a method of XInterface.
147 
148 	// Forward to baseclass
149 	BaseControl::release();
150 }
151 
152 //____________________________________________________________________________________________________________
153 //	XTypeProvider
154 //____________________________________________________________________________________________________________
155 
156 Sequence< Type > SAL_CALL StatusIndicator::getTypes() throw( RuntimeException )
157 {
158 	// Optimize this method !
159 	// We initialize a static variable only one time. And we don't must use a mutex at every call!
160 	// For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL!
161 	static OTypeCollection* pTypeCollection = NULL ;
162 
163 	if ( pTypeCollection == NULL )
164 	{
165 		// Ready for multithreading; get global mutex for first call of this method only! see before
166 		MutexGuard aGuard( Mutex::getGlobalMutex() );
167 
168 		// Control these pointer again ... it can be, that another instance will be faster then these!
169 		if ( pTypeCollection == NULL )
170 		{
171 			// Create a static typecollection ...
172 			static OTypeCollection aTypeCollection	(	::getCppuType(( const Reference< XLayoutConstrains	>*)NULL )	,
173 												  		::getCppuType(( const Reference< XStatusIndicator	>*)NULL )	,
174 														BaseContainerControl::getTypes()
175 													);
176 			// ... and set his address to static pointer!
177 			pTypeCollection = &aTypeCollection ;
178 		}
179 	}
180 
181 	return pTypeCollection->getTypes();
182 }
183 
184 //____________________________________________________________________________________________________________
185 //	XAggregation
186 //____________________________________________________________________________________________________________
187 
188 Any SAL_CALL StatusIndicator::queryAggregation( const Type& aType ) throw( RuntimeException )
189 {
190 	// Ask for my own supported interfaces ...
191 	// Attention: XTypeProvider and XInterface are supported by OComponentHelper!
192 	Any aReturn	( ::cppu::queryInterface(	aType					   					,
193 									   		static_cast< XLayoutConstrains*	> ( this )	,
194 									   		static_cast< XStatusIndicator*	> ( this )
195 										)
196 				);
197 
198 	// If searched interface not supported by this class ...
199 	if ( aReturn.hasValue() == sal_False )
200 	{
201 		// ... ask baseclasses.
202 		aReturn = BaseControl::queryAggregation( aType );
203 	}
204 
205 	return aReturn ;
206 }
207 
208 //____________________________________________________________________________________________________________
209 //	XStatusIndicator
210 //____________________________________________________________________________________________________________
211 
212 void SAL_CALL StatusIndicator::start( const OUString& sText, sal_Int32 nRange ) throw( RuntimeException )
213 {
214 	// Ready for multithreading
215 	MutexGuard aGuard( m_aMutex );
216 
217 	// Initialize status controls with given values.
218 	m_xText->setText( sText );
219 	m_xProgressBar->setRange( 0, nRange );
220     // force repaint ... fixedtext has changed !
221 	impl_recalcLayout ( WindowEvent(static_cast< OWeakObject* >(this),0,0,impl_getWidth(),impl_getHeight(),0,0,0,0) ) ;
222 }
223 
224 //____________________________________________________________________________________________________________
225 //	XStatusIndicator
226 //____________________________________________________________________________________________________________
227 
228 void SAL_CALL StatusIndicator::end() throw( RuntimeException )
229 {
230 	// Ready for multithreading
231 	MutexGuard aGuard( m_aMutex );
232 
233 	// Clear values of status controls.
234 	m_xText->setText( OUString() );
235 	m_xProgressBar->setValue( 0 );
236 	setVisible( sal_False );
237 }
238 
239 //____________________________________________________________________________________________________________
240 //	XStatusIndicator
241 //____________________________________________________________________________________________________________
242 
243 void SAL_CALL StatusIndicator::setText( const OUString& sText ) throw( RuntimeException )
244 {
245 	// Ready for multithreading
246 	MutexGuard aGuard( m_aMutex );
247 
248 	// Take text on right control
249 	m_xText->setText( sText );
250 }
251 
252 //____________________________________________________________________________________________________________
253 //	XStatusIndicator
254 //____________________________________________________________________________________________________________
255 
256 void SAL_CALL StatusIndicator::setValue( sal_Int32 nValue ) throw( RuntimeException )
257 {
258 	// Ready for multithreading
259 	MutexGuard aGuard( m_aMutex );
260 
261 	// Take value on right control
262 	m_xProgressBar->setValue( nValue );
263 }
264 
265 //____________________________________________________________________________________________________________
266 //	XStatusIndicator
267 //____________________________________________________________________________________________________________
268 
269 void SAL_CALL StatusIndicator::reset() throw( RuntimeException )
270 {
271 	// Ready for multithreading
272 	MutexGuard aGuard( m_aMutex );
273 
274 	// Clear values of status controls.
275 	// (Don't hide the window! User will reset current values ... but he will not finish using of indicator!)
276 	m_xText->setText( OUString() );
277 	m_xProgressBar->setValue( 0 );
278 }
279 
280 //____________________________________________________________________________________________________________
281 //	XLayoutConstrains
282 //____________________________________________________________________________________________________________
283 
284 Size SAL_CALL StatusIndicator::getMinimumSize () throw( RuntimeException )
285 {
286 	return Size (DEFAULT_WIDTH, DEFAULT_HEIGHT) ;
287 }
288 
289 //____________________________________________________________________________________________________________
290 //	XLayoutConstrains
291 //____________________________________________________________________________________________________________
292 
293 Size SAL_CALL StatusIndicator::getPreferredSize () throw( RuntimeException )
294 {
295 	// Ready for multithreading
296 	ClearableMutexGuard aGuard ( m_aMutex ) ;
297 
298 	// get information about required place of child controls
299 	Reference< XLayoutConstrains >	xTextLayout	( m_xText, UNO_QUERY );
300 	Size							aTextSize	= xTextLayout->getPreferredSize();
301 
302 	aGuard.clear () ;
303 
304 	// calc preferred size of status indicator
305     sal_Int32 nWidth  = impl_getWidth()                 ;
306     sal_Int32 nHeight = (2*FREEBORDER)+aTextSize.Height ;
307 
308     // norm to minimum
309 	if ( nWidth<DEFAULT_WIDTH )
310 	{
311 		nWidth = DEFAULT_WIDTH ;
312 	}
313 	if ( nHeight<DEFAULT_HEIGHT )
314 	{
315 		nHeight = DEFAULT_HEIGHT ;
316 	}
317 
318 	// return to caller
319 	return Size ( nWidth, nHeight ) ;
320 }
321 
322 //____________________________________________________________________________________________________________
323 //	XLayoutConstrains
324 //____________________________________________________________________________________________________________
325 
326 Size SAL_CALL StatusIndicator::calcAdjustedSize ( const Size& /*rNewSize*/ ) throw( RuntimeException )
327 {
328 	return getPreferredSize () ;
329 }
330 
331 //____________________________________________________________________________________________________________
332 //	XControl
333 //____________________________________________________________________________________________________________
334 
335 void SAL_CALL StatusIndicator::createPeer ( const Reference< XToolkit > & rToolkit, const Reference< XWindowPeer > & rParent	) throw( RuntimeException )
336 {
337 	if( getPeer().is() == sal_False )
338 	{
339 		BaseContainerControl::createPeer( rToolkit, rParent );
340 
341 		// If user forget to call "setPosSize()", we have still a correct size.
342 		// And a "MinimumSize" IS A "MinimumSize"!
343 		// We change not the position of control at this point.
344 		Size aDefaultSize = getMinimumSize () ;
345 		setPosSize ( 0, 0, aDefaultSize.Width, aDefaultSize.Height, PosSize::SIZE ) ;
346 	}
347 }
348 
349 //____________________________________________________________________________________________________________
350 //	XControl
351 //____________________________________________________________________________________________________________
352 
353 sal_Bool SAL_CALL StatusIndicator::setModel ( const Reference< XControlModel > & /*rModel*/ ) throw( RuntimeException )
354 {
355 	// We have no model.
356 	return sal_False ;
357 }
358 
359 //____________________________________________________________________________________________________________
360 //	XControl
361 //____________________________________________________________________________________________________________
362 
363 Reference< XControlModel > SAL_CALL StatusIndicator::getModel () throw( RuntimeException )
364 {
365 	// We have no model.
366 	// return (XControlModel*)this ;
367 	return Reference< XControlModel >  () ;
368 }
369 
370 //____________________________________________________________________________________________________________
371 //	XComponent
372 //____________________________________________________________________________________________________________
373 
374 void SAL_CALL StatusIndicator::dispose () throw( RuntimeException )
375 {
376 	// Ready for multithreading
377 	MutexGuard aGuard ( m_aMutex ) ;
378 
379 	// "removeControl()" control the state of a reference
380 	Reference< XControl >  xTextControl		( m_xText		, UNO_QUERY );
381 	Reference< XControl >  xProgressControl	( m_xProgressBar, UNO_QUERY );
382 
383 	removeControl( xTextControl		);
384 	removeControl( xProgressControl	);
385 
386 	// do'nt use "...->clear ()" or "... = XFixedText ()"
387 	// when other hold a reference at this object !!!
388 	xTextControl->dispose();
389 	xProgressControl->dispose();
390 	BaseContainerControl::dispose();
391 }
392 
393 //____________________________________________________________________________________________________________
394 //	XWindow
395 //____________________________________________________________________________________________________________
396 
397 void SAL_CALL StatusIndicator::setPosSize ( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int16 nFlags ) throw( RuntimeException )
398 {
399 	Rectangle	aBasePosSize = getPosSize () ;
400 	BaseContainerControl::setPosSize (nX, nY, nWidth, nHeight, nFlags) ;
401 
402 	// if position or size changed
403 	if (
404 		( nWidth  != aBasePosSize.Width	) ||
405 		( nHeight != aBasePosSize.Height)
406 	   )
407 	{
408 		// calc new layout for controls
409 		impl_recalcLayout ( WindowEvent(static_cast< OWeakObject* >(this),0,0,nWidth,nHeight,0,0,0,0) ) ;
410 		// clear background (!)
411 		// [Childs was repainted in "recalcLayout" by setPosSize() automaticly!]
412 		getPeer()->invalidate(2);
413 		// and repaint the control
414 		impl_paint ( 0, 0, impl_getGraphicsPeer() ) ;
415 	}
416 }
417 
418 //____________________________________________________________________________________________________________
419 //	impl but public method to register service
420 //____________________________________________________________________________________________________________
421 
422 const Sequence< OUString > StatusIndicator::impl_getStaticSupportedServiceNames()
423 {
424 	MutexGuard aGuard( Mutex::getGlobalMutex() );
425     Sequence< OUString > seqServiceNames( 1 );
426     seqServiceNames.getArray() [0] = OUString::createFromAscii( SERVICENAME_STATUSINDICATOR );
427     return seqServiceNames ;
428 }
429 
430 //____________________________________________________________________________________________________________
431 //	impl but public method to register service
432 //____________________________________________________________________________________________________________
433 
434 const OUString StatusIndicator::impl_getStaticImplementationName()
435 {
436 	return OUString::createFromAscii( IMPLEMENTATIONNAME_STATUSINDICATOR );
437 }
438 
439 //____________________________________________________________________________________________________________
440 //	protected method
441 //____________________________________________________________________________________________________________
442 
443 WindowDescriptor* StatusIndicator::impl_getWindowDescriptor( const Reference< XWindowPeer >& xParentPeer )
444 {
445 	// - used from "createPeer()" to set the values of an ::com::sun::star::awt::WindowDescriptor !!!
446 	// - if you will change the descriptor-values, you must override this virtuell function
447 	// - the caller must release the memory for this dynamical descriptor !!!
448 
449 	WindowDescriptor* pDescriptor = new WindowDescriptor ;
450 
451 	pDescriptor->Type				=	WindowClass_SIMPLE								;
452 	pDescriptor->WindowServiceName	=	OUString::createFromAscii( "floatingwindow" )	;
453 	pDescriptor->ParentIndex		=	-1												;
454 	pDescriptor->Parent				=	xParentPeer										;
455 	pDescriptor->Bounds				=	getPosSize ()									;
456 
457 	return pDescriptor ;
458 }
459 
460 //____________________________________________________________________________________________________________
461 //	protected method
462 //____________________________________________________________________________________________________________
463 
464 void StatusIndicator::impl_paint ( sal_Int32 nX, sal_Int32 nY, const Reference< XGraphics > & rGraphics )
465 {
466 	// This paint method ist not buffered !!
467 	// Every request paint the completely control. ( but only, if peer exist )
468  	if ( rGraphics.is () )
469 	{
470 		MutexGuard	aGuard (m_aMutex) ;
471 
472         // background = gray
473         Reference< XWindowPeer > xPeer( impl_getPeerWindow(), UNO_QUERY );
474         if( xPeer.is() == sal_True )
475             xPeer->setBackground( BACKGROUNDCOLOR );
476 
477         // FixedText background = gray
478         Reference< XControl > xTextControl( m_xText, UNO_QUERY );
479         xPeer = xTextControl->getPeer();
480         if( xPeer.is() == sal_True )
481             xPeer->setBackground( BACKGROUNDCOLOR );
482 
483         // Progress background = gray
484         xPeer = Reference< XWindowPeer >( m_xProgressBar, UNO_QUERY );
485         if( xPeer.is() == sal_True )
486             xPeer->setBackground( BACKGROUNDCOLOR );
487 
488         // paint shadow border
489         rGraphics->setLineColor ( LINECOLOR_BRIGHT                          );
490         rGraphics->drawLine     ( nX, nY, impl_getWidth(), nY               );
491         rGraphics->drawLine     ( nX, nY, nX             , impl_getHeight() );
492 
493         rGraphics->setLineColor ( LINECOLOR_SHADOW                                                              );
494         rGraphics->drawLine     ( impl_getWidth()-1, impl_getHeight()-1, impl_getWidth()-1, nY                  );
495         rGraphics->drawLine     ( impl_getWidth()-1, impl_getHeight()-1, nX               , impl_getHeight()-1  );
496 	}
497 }
498 
499 //____________________________________________________________________________________________________________
500 //	protected method
501 //____________________________________________________________________________________________________________
502 
503 void StatusIndicator::impl_recalcLayout ( const WindowEvent& aEvent )
504 {
505 	sal_Int32	nX_ProgressBar			;
506 	sal_Int32	nY_ProgressBar			;
507 	sal_Int32	nWidth_ProgressBar		;
508 	sal_Int32	nHeight_ProgressBar		;
509 	sal_Int32	nX_Text					;
510 	sal_Int32	nY_Text					;
511 	sal_Int32	nWidth_Text				;
512 	sal_Int32	nHeight_Text			;
513 
514 	// Ready for multithreading
515 	MutexGuard aGuard ( m_aMutex ) ;
516 
517 	// get information about required place of child controls
518 	Size							aWindowSize		( aEvent.Width, aEvent.Height );
519 	Reference< XLayoutConstrains >	xTextLayout		( m_xText, UNO_QUERY );
520 	Size							aTextSize		= xTextLayout->getPreferredSize();
521 
522 	if( aWindowSize.Width < DEFAULT_WIDTH )
523 	{
524 		aWindowSize.Width = DEFAULT_WIDTH;
525 	}
526 	if( aWindowSize.Height < DEFAULT_HEIGHT )
527 	{
528 		aWindowSize.Height = DEFAULT_HEIGHT;
529 	}
530 
531 	// calc position and size of child controls
532     nX_Text             = FREEBORDER                                    ;
533     nY_Text             = FREEBORDER                                    ;
534     nWidth_Text         = aTextSize.Width                               ;
535     nHeight_Text        = aTextSize.Height                              ;
536 
537     nX_ProgressBar      = nX_Text+nWidth_Text+FREEBORDER                ;
538     nY_ProgressBar      = nY_Text                                       ;
539     nWidth_ProgressBar  = aWindowSize.Width-nWidth_Text-(3*FREEBORDER)  ;
540     nHeight_ProgressBar = nHeight_Text                                  ;
541 
542     // Set new position and size on all controls
543 	Reference< XWindow >  xTextWindow		( m_xText		, UNO_QUERY );
544 	Reference< XWindow >  xProgressWindow	( m_xProgressBar, UNO_QUERY );
545 
546 	xTextWindow->setPosSize		( nX_Text		, nY_Text		, nWidth_Text		, nHeight_Text	  		, 15 ) ;
547 	xProgressWindow->setPosSize	( nX_ProgressBar, nY_ProgressBar, nWidth_ProgressBar, nHeight_ProgressBar	, 15 ) ;
548 }
549 
550 //____________________________________________________________________________________________________________
551 //	debug methods
552 //____________________________________________________________________________________________________________
553 
554 #if OSL_DEBUG_LEVEL > 1
555 
556 #endif  // #if OSL_DEBUG_LEVEL > 1
557 
558 }	// namespace unocontrols
559