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: progressbar.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 ************************************************************************/
30 //____________________________________________________________________________________________________________
32 //____________________________________________________________________________________________________________
34 #include "progressbar.hxx"
36 //____________________________________________________________________________________________________________
37 // includes of other projects
38 //____________________________________________________________________________________________________________
39 #include <com/sun/star/awt/GradientStyle.hpp>
40 #include <com/sun/star/awt/RasterOperation.hpp>
41 #include <com/sun/star/awt/Gradient.hpp>
42 #include <com/sun/star/awt/XGraphics.hpp>
43 #include <tools/debug.hxx>
44 #include <cppuhelper/typeprovider.hxx>
49 //____________________________________________________________________________________________________________
50 // includes of my project
51 //____________________________________________________________________________________________________________
53 //____________________________________________________________________________________________________________
55 //____________________________________________________________________________________________________________
57 using namespace ::cppu
;
58 using namespace ::osl
;
59 using namespace ::rtl
;
60 using namespace ::com::sun::star::uno
;
61 using namespace ::com::sun::star::lang
;
62 using namespace ::com::sun::star::awt
;
64 namespace unocontrols
{
66 //____________________________________________________________________________________________________________
68 //____________________________________________________________________________________________________________
70 ProgressBar::ProgressBar( const Reference
< XMultiServiceFactory
>& xFactory
)
71 : BaseControl ( xFactory
)
72 , m_bHorizontal ( DEFAULT_HORIZONTAL
)
73 , m_aBlockSize ( DEFAULT_BLOCKDIMENSION
)
74 , m_nForegroundColor ( DEFAULT_FOREGROUNDCOLOR
)
75 , m_nBackgroundColor ( DEFAULT_BACKGROUNDCOLOR
)
76 , m_nMinRange ( DEFAULT_MINRANGE
)
77 , m_nMaxRange ( DEFAULT_MAXRANGE
)
78 , m_nBlockValue ( DEFAULT_BLOCKVALUE
)
79 , m_nValue ( DEFAULT_VALUE
)
83 ProgressBar::~ProgressBar()
87 //____________________________________________________________________________________________________________
89 //____________________________________________________________________________________________________________
91 Any SAL_CALL
ProgressBar::queryInterface( const Type
& rType
) throw( RuntimeException
)
94 // Don't use mutex or guard in this method!!! Is a method of XInterface.
96 Reference
< XInterface
> xDel
= BaseControl::impl_getDelegator();
99 // If an delegator exist, forward question to his queryInterface.
100 // Delegator will ask his own queryAggregation!
101 aReturn
= xDel
->queryInterface( rType
);
105 // If an delegator unknown, forward question to own queryAggregation.
106 aReturn
= queryAggregation( rType
);
112 //____________________________________________________________________________________________________________
114 //____________________________________________________________________________________________________________
116 void SAL_CALL
ProgressBar::acquire() throw()
119 // Don't use mutex or guard in this method!!! Is a method of XInterface.
121 // Forward to baseclass
122 BaseControl::acquire();
125 //____________________________________________________________________________________________________________
127 //____________________________________________________________________________________________________________
129 void SAL_CALL
ProgressBar::release() throw()
132 // Don't use mutex or guard in this method!!! Is a method of XInterface.
134 // Forward to baseclass
135 BaseControl::release();
138 //____________________________________________________________________________________________________________
140 //____________________________________________________________________________________________________________
142 Sequence
< Type
> SAL_CALL
ProgressBar::getTypes() throw( RuntimeException
)
144 // Optimize this method !
145 // We initialize a static variable only one time. And we don't must use a mutex at every call!
146 // For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL!
147 static OTypeCollection
* pTypeCollection
= NULL
;
149 if ( pTypeCollection
== NULL
)
151 // Ready for multithreading; get global mutex for first call of this method only! see before
152 MutexGuard
aGuard( Mutex::getGlobalMutex() );
154 // Control these pointer again ... it can be, that another instance will be faster then these!
155 if ( pTypeCollection
== NULL
)
157 // Create a static typecollection ...
158 static OTypeCollection
aTypeCollection ( ::getCppuType(( const Reference
< XControlModel
>*)NULL
) ,
159 ::getCppuType(( const Reference
< XProgressBar
>*)NULL
) ,
160 BaseControl::getTypes()
162 // ... and set his address to static pointer!
163 pTypeCollection
= &aTypeCollection
;
167 return pTypeCollection
->getTypes();
170 //____________________________________________________________________________________________________________
172 //____________________________________________________________________________________________________________
174 Any SAL_CALL
ProgressBar::queryAggregation( const Type
& aType
) throw( RuntimeException
)
176 // Ask for my own supported interfaces ...
177 // Attention: XTypeProvider and XInterface are supported by OComponentHelper!
178 Any
aReturn ( ::cppu::queryInterface( aType
,
179 static_cast< XControlModel
* > ( this ) ,
180 static_cast< XProgressBar
* > ( this )
184 // If searched interface not supported by this class ...
185 if ( aReturn
.hasValue() == sal_False
)
187 // ... ask baseclasses.
188 aReturn
= BaseControl::queryAggregation( aType
);
194 //____________________________________________________________________________________________________________
196 //____________________________________________________________________________________________________________
198 void SAL_CALL
ProgressBar::setForegroundColor( sal_Int32 nColor
) throw( RuntimeException
)
200 // Ready for multithreading
201 MutexGuard
aGuard (m_aMutex
) ;
203 // Safe color for later use.
204 m_nForegroundColor
= nColor
;
207 impl_paint ( 0, 0, impl_getGraphicsPeer() ) ;
210 //____________________________________________________________________________________________________________
212 //____________________________________________________________________________________________________________
214 void SAL_CALL
ProgressBar::setBackgroundColor ( sal_Int32 nColor
) throw( RuntimeException
)
216 // Ready for multithreading
217 MutexGuard
aGuard (m_aMutex
) ;
219 // Safe color for later use.
220 m_nBackgroundColor
= nColor
;
223 impl_paint ( 0, 0, impl_getGraphicsPeer() ) ;
226 //____________________________________________________________________________________________________________
228 //____________________________________________________________________________________________________________
230 void SAL_CALL
ProgressBar::setValue ( sal_Int32 nValue
) throw( RuntimeException
)
232 // This method is defined for follow things:
233 // 1) Values >= _nMinRange
234 // 2) Values <= _nMaxRange
236 // Ready for multithreading
237 MutexGuard
aGuard (m_aMutex
) ;
239 // save impossible cases
240 // This method is only defined for valid values
241 DBG_ASSERT ( (( nValue
>= m_nMinRange
) && ( nValue
<= m_nMaxRange
)), "ProgressBar::setValue()\nNot valid value.\n" ) ;
243 // If new value not valid ... do nothing in release version!
245 ( nValue
>= m_nMinRange
) &&
246 ( nValue
<= m_nMaxRange
)
249 // New value is ok => save this
252 // Repaint to display changes
253 impl_paint ( 0, 0, impl_getGraphicsPeer() ) ;
257 //____________________________________________________________________________________________________________
259 //____________________________________________________________________________________________________________
261 void SAL_CALL
ProgressBar::setRange ( sal_Int32 nMin
, sal_Int32 nMax
) throw( RuntimeException
)
263 // This method is defined for follow things:
264 // 1) All values of sal_Int32
268 // save impossible cases
269 // This method is only defined for valid values
270 // If you ignore this, the release version wil produce an error "division by zero" in "ProgressBar::setValue()"!
271 DBG_ASSERT ( ( nMin
!= nMax
) , "ProgressBar::setRange()\nValues for MIN and MAX are the same. This is not allowed!\n" ) ;
273 // Ready for multithreading
274 MutexGuard
aGuard (m_aMutex
) ;
276 // control the values for min and max
279 // Take correct Min and Max
285 // Change Min and Max automaticly
290 // assure that m_nValue is within the range
291 if (!(m_nMinRange
< m_nValue
&& m_nValue
< m_nMaxRange
))
292 m_nValue
= m_nMinRange
;
294 impl_recalcRange () ;
296 // Do not repaint the control at this place!!!
297 // An old "m_nValue" is set and can not be correct for this new range.
298 // Next call of "ProgressBar::setValue()" do this.
301 //____________________________________________________________________________________________________________
303 //____________________________________________________________________________________________________________
305 sal_Int32 SAL_CALL
ProgressBar::getValue () throw( RuntimeException
)
307 // Ready for multithreading
308 MutexGuard
aGuard (m_aMutex
) ;
310 return ( m_nValue
) ;
313 //____________________________________________________________________________________________________________
315 //____________________________________________________________________________________________________________
317 void SAL_CALL
ProgressBar::setPosSize ( sal_Int32 nX
, sal_Int32 nY
, sal_Int32 nWidth
, sal_Int32 nHeight
, sal_Int16 nFlags
) throw( RuntimeException
)
319 // Take old size BEFORE you set the new values at baseclass!
320 // You will control changes. At the other way, the values are the same!
321 Rectangle aBasePosSize
= getPosSize () ;
322 BaseControl::setPosSize (nX
, nY
, nWidth
, nHeight
, nFlags
) ;
324 // Do only, if size has changed.
326 ( nWidth
!= aBasePosSize
.Width
) ||
327 ( nHeight
!= aBasePosSize
.Height
)
330 impl_recalcRange ( ) ;
331 impl_paint ( 0, 0, impl_getGraphicsPeer () ) ;
335 //____________________________________________________________________________________________________________
337 //____________________________________________________________________________________________________________
339 sal_Bool SAL_CALL
ProgressBar::setModel( const Reference
< XControlModel
>& /*xModel*/ ) throw( RuntimeException
)
341 // A model is not possible for this control.
345 //____________________________________________________________________________________________________________
347 //____________________________________________________________________________________________________________
349 Reference
< XControlModel
> SAL_CALL
ProgressBar::getModel() throw( RuntimeException
)
351 // A model is not possible for this control.
352 return Reference
< XControlModel
>();
355 //____________________________________________________________________________________________________________
356 // impl but public method to register service
357 //____________________________________________________________________________________________________________
359 const Sequence
< OUString
> ProgressBar::impl_getStaticSupportedServiceNames()
361 MutexGuard
aGuard( Mutex::getGlobalMutex() );
362 Sequence
< OUString
> seqServiceNames( 1 );
363 seqServiceNames
.getArray() [0] = OUString::createFromAscii( SERVICENAME_PROGRESSBAR
);
364 return seqServiceNames
;
367 //____________________________________________________________________________________________________________
368 // impl but public method to register service
369 //____________________________________________________________________________________________________________
371 const OUString
ProgressBar::impl_getStaticImplementationName()
373 return OUString::createFromAscii( IMPLEMENTATIONNAME_PROGRESSBAR
);
376 //____________________________________________________________________________________________________________
378 //____________________________________________________________________________________________________________
380 void ProgressBar::impl_paint ( sal_Int32 nX
, sal_Int32 nY
, const Reference
< XGraphics
> & rGraphics
)
382 // save impossible cases
383 DBG_ASSERT ( rGraphics
.is(), "ProgressBar::paint()\nCalled with invalid Reference< XGraphics > ." ) ;
385 // This paint method ist not buffered !!
386 // Every request paint the completely control. ( but only, if peer exist )
387 if ( rGraphics
.is () )
389 MutexGuard
aGuard (m_aMutex
) ;
392 // (same color for line and fill)
393 rGraphics
->setFillColor ( m_nBackgroundColor
) ;
394 rGraphics
->setLineColor ( m_nBackgroundColor
) ;
395 rGraphics
->drawRect ( nX
, nY
, impl_getWidth(), impl_getHeight() ) ;
397 // same color for line and fill for blocks
398 rGraphics
->setFillColor ( m_nForegroundColor
) ;
399 rGraphics
->setLineColor ( m_nForegroundColor
) ;
401 sal_Int32 nBlockStart
= 0 ; // = left site of new block
402 sal_Int32 nBlockCount
= m_nBlockValue
!=0.00 ? (sal_Int32
)((m_nValue
-m_nMinRange
)/m_nBlockValue
) : 0 ; // = number of next block
404 // Draw horizontal progressbar
405 // decision in "recalcRange()"
408 // Step to left side of window
411 for ( sal_Int16 i
=1; i
<=nBlockCount
; ++i
)
414 nBlockStart
+= FREESPACE
;
416 rGraphics
->drawRect (nBlockStart
, nY
+FREESPACE
, m_aBlockSize
.Width
, m_aBlockSize
.Height
) ;
417 // step next free field
418 nBlockStart
+= m_aBlockSize
.Width
;
421 // draw vertikal progressbar
422 // decision in "recalcRange()"
425 // step to bottom side of window
426 nBlockStart
= nY
+impl_getHeight() ;
427 nBlockStart
-= m_aBlockSize
.Height
;
429 for ( sal_Int16 i
=1; i
<=nBlockCount
; ++i
)
432 nBlockStart
-= FREESPACE
;
434 rGraphics
->drawRect (nX
+FREESPACE
, nBlockStart
, m_aBlockSize
.Width
, m_aBlockSize
.Height
) ;
435 // step next free field
436 nBlockStart
-= m_aBlockSize
.Height
;
440 // Paint shadow border around the progressbar
441 rGraphics
->setLineColor ( LINECOLOR_SHADOW
) ;
442 rGraphics
->drawLine ( nX
, nY
, impl_getWidth(), nY
) ;
443 rGraphics
->drawLine ( nX
, nY
, nX
, impl_getHeight() ) ;
445 rGraphics
->setLineColor ( LINECOLOR_BRIGHT
) ;
446 rGraphics
->drawLine ( impl_getWidth()-1, impl_getHeight()-1, impl_getWidth()-1, nY
) ;
447 rGraphics
->drawLine ( impl_getWidth()-1, impl_getHeight()-1, nX
, impl_getHeight()-1 ) ;
451 //____________________________________________________________________________________________________________
453 //____________________________________________________________________________________________________________
455 void ProgressBar::impl_recalcRange ()
457 MutexGuard
aGuard (m_aMutex
) ;
459 sal_Int32 nWindowWidth
= impl_getWidth() ;
460 sal_Int32 nWindowHeight
= impl_getHeight() ;
461 double fBlockHeight
;
465 if( nWindowWidth
> nWindowHeight
)
467 m_bHorizontal
= sal_True
;
468 fBlockHeight
= (nWindowHeight
-(2*FREESPACE
)) ;
469 fBlockWidth
= fBlockHeight
;
470 fMaxBlocks
= nWindowWidth
/(fBlockWidth
+FREESPACE
);
474 m_bHorizontal
= sal_False
;
475 fBlockWidth
= (nWindowWidth
-(2*FREESPACE
)) ;
476 fBlockHeight
= fBlockWidth
;
477 fMaxBlocks
= nWindowHeight
/(fBlockHeight
+FREESPACE
);
480 double fRange
= m_nMaxRange
-m_nMinRange
;
481 double fBlockValue
= fRange
/fMaxBlocks
;
483 m_nBlockValue
= fBlockValue
;
484 m_aBlockSize
.Height
= (sal_Int32
)fBlockHeight
;
485 m_aBlockSize
.Width
= (sal_Int32
)fBlockWidth
;
487 // Calculate count of blocks for actual size
488 // (prevent error "division by zero")
494 nMaxBlock = nWidth / nHeight ;
497 // prevent error "division by zero"
498 if ( nMaxBlock == 0 )
503 // Calculate new value and new size for ONE block.
505 // Do not a calculation like this: "m_nBlockValue=(m_nMaxRange-m_nMinRange)/nMaxBlock" !
506 // If difference between m_nMaxRange and m_nMinRange to large, it give an overflow and a
507 // following error "division by zero" in method "paint() ... nBlockCount=nDifference/m_nBlockValue ..."
509 // Overflow ? => example: _I32_MAX - _I32_MIN = -1 and not _UI32_MAX !!!
511 m_nBlockValue = ( m_nMaxRange / nMaxBlock ) - ( m_nMinRange / nMaxBlock ) ;
512 m_aBlockSize.Height = ( nHeight - ( FREESPACE * 2 ) ) ;
513 m_aBlockSize.Width = ( ( nWidth / nMaxBlock ) - FREESPACE ) ;
517 // Don't forget to save this state! Used in "ProgressBar::paint()"
518 m_bHorizontal = sal_False ;
520 double fBlockWidth = (nHeight-(2*FREESPACE)) ;
521 double fBlockHeight = fBlockWidth ;
522 double fRange = m_nMaxRange-m_nMinRange ;
523 double fBlockValue = fRange/(fBlockWidth+FREESPACE);
525 m_nBlockValue = fBlockValue ;
526 m_aBlockSize.Height = (sal_Int32)fBlockHeight;
527 m_aBlockSize.Width = (sal_Int32)fBlockWidth ;
529 // Calculate count of blocks for actual size
530 // (prevent error "division by zero")
536 nMaxBlock = nHeight / nWidth ;
539 // prevent error "division by zero"
540 if ( nMaxBlock == 0 )
545 // Calculate new value and new size for ONE block.
547 // Do not a calculation like this: "m_nBlockValue=(m_nMaxRange-m_nMinRange)/nMaxBlock" !
548 // If difference between m_nMaxRange and m_nMinRange to large, it give an overflow and a
549 // following error "division by zero" in method "paint() ... nBlockCount=nDifference/m_nBlockValue ..."
551 // Overflow ? => example: _I32_MAX - _I32_MIN = -1 and not _UI32_MAX !!!
553 m_nBlockValue = ( m_nMaxRange / nMaxBlock ) - ( m_nMinRange / nMaxBlock ) ;
554 m_aBlockSize.Height = ( ( nHeight / nMaxBlock ) - FREESPACE ) ;
555 m_aBlockSize.Width = ( nWidth - ( FREESPACE * 2 ) ) ;
561 } // namespace unocontrols