xref: /trunk/main/UnoControls/source/controls/statusindicator.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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