xref: /AOO41X/main/UnoControls/source/controls/progressbar.cxx (revision 0b4ced1d4e3a9bc987eae61b8e131e5e85d0fb11)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 //____________________________________________________________________________________________________________
24 //  my own includes
25 //____________________________________________________________________________________________________________
26 
27 #include "progressbar.hxx"
28 
29 //____________________________________________________________________________________________________________
30 //  includes of other projects
31 //____________________________________________________________________________________________________________
32 #include <com/sun/star/awt/GradientStyle.hpp>
33 #include <com/sun/star/awt/RasterOperation.hpp>
34 #include <com/sun/star/awt/Gradient.hpp>
35 #include <com/sun/star/awt/XGraphics.hpp>
36 #include <tools/debug.hxx>
37 #include <cppuhelper/typeprovider.hxx>
38 
39 #include <math.h>
40 #include <limits.h>
41 
42 //____________________________________________________________________________________________________________
43 //  includes of my project
44 //____________________________________________________________________________________________________________
45 
46 //____________________________________________________________________________________________________________
47 //  namespace
48 //____________________________________________________________________________________________________________
49 
50 using namespace ::cppu                  ;
51 using namespace ::osl                   ;
52 using namespace ::rtl                   ;
53 using namespace ::com::sun::star::uno   ;
54 using namespace ::com::sun::star::lang  ;
55 using namespace ::com::sun::star::awt   ;
56 
57 namespace unocontrols{
58 
59 //____________________________________________________________________________________________________________
60 //  construct/destruct
61 //____________________________________________________________________________________________________________
62 
ProgressBar(const Reference<XMultiServiceFactory> & xFactory)63 ProgressBar::ProgressBar( const Reference< XMultiServiceFactory >& xFactory )
64     : BaseControl           (    xFactory                   )
65     , m_bHorizontal         (    DEFAULT_HORIZONTAL         )
66     , m_aBlockSize          (    DEFAULT_BLOCKDIMENSION     )
67     , m_nForegroundColor    (    DEFAULT_FOREGROUNDCOLOR    )
68     , m_nBackgroundColor    (    DEFAULT_BACKGROUNDCOLOR    )
69     , m_nMinRange           (    DEFAULT_MINRANGE           )
70     , m_nMaxRange           (    DEFAULT_MAXRANGE           )
71     , m_nBlockValue         (    DEFAULT_BLOCKVALUE         )
72     , m_nValue              (    DEFAULT_VALUE              )
73 {
74 }
75 
~ProgressBar()76 ProgressBar::~ProgressBar()
77 {
78 }
79 
80 //____________________________________________________________________________________________________________
81 //  XInterface
82 //____________________________________________________________________________________________________________
83 
queryInterface(const Type & rType)84 Any SAL_CALL ProgressBar::queryInterface( const Type& rType ) throw( RuntimeException )
85 {
86     // Attention:
87     //  Don't use mutex or guard in this method!!! Is a method of XInterface.
88     Any aReturn ;
89     Reference< XInterface > xDel = BaseControl::impl_getDelegator();
90     if ( xDel.is() )
91     {
92         // If an delegator exist, forward question to his queryInterface.
93         // Delegator will ask his own queryAggregation!
94         aReturn = xDel->queryInterface( rType );
95     }
96     else
97     {
98         // If an delegator unknown, forward question to own queryAggregation.
99         aReturn = queryAggregation( rType );
100     }
101 
102     return aReturn ;
103 }
104 
105 //____________________________________________________________________________________________________________
106 //  XInterface
107 //____________________________________________________________________________________________________________
108 
acquire()109 void SAL_CALL ProgressBar::acquire() throw()
110 {
111     // Attention:
112     //  Don't use mutex or guard in this method!!! Is a method of XInterface.
113 
114     // Forward to baseclass
115     BaseControl::acquire();
116 }
117 
118 //____________________________________________________________________________________________________________
119 //  XInterface
120 //____________________________________________________________________________________________________________
121 
release()122 void SAL_CALL ProgressBar::release() throw()
123 {
124     // Attention:
125     //  Don't use mutex or guard in this method!!! Is a method of XInterface.
126 
127     // Forward to baseclass
128     BaseControl::release();
129 }
130 
131 //____________________________________________________________________________________________________________
132 //  XTypeProvider
133 //____________________________________________________________________________________________________________
134 
getTypes()135 Sequence< Type > SAL_CALL ProgressBar::getTypes() throw( RuntimeException )
136 {
137     // Optimize this method !
138     // We initialize a static variable only one time. And we don't must use a mutex at every call!
139     // For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL!
140     static OTypeCollection* pTypeCollection = NULL ;
141 
142     if ( pTypeCollection == NULL )
143     {
144         // Ready for multithreading; get global mutex for first call of this method only! see before
145         MutexGuard aGuard( Mutex::getGlobalMutex() );
146 
147         // Control these pointer again ... it can be, that another instance will be faster then these!
148         if ( pTypeCollection == NULL )
149         {
150             // Create a static typecollection ...
151             static OTypeCollection aTypeCollection  (   ::getCppuType(( const Reference< XControlModel  >*)NULL )   ,
152                                                         ::getCppuType(( const Reference< XProgressBar   >*)NULL )   ,
153                                                         BaseControl::getTypes()
154                                                     );
155             // ... and set his address to static pointer!
156             pTypeCollection = &aTypeCollection ;
157         }
158     }
159 
160     return pTypeCollection->getTypes();
161 }
162 
163 //____________________________________________________________________________________________________________
164 //  XAggregation
165 //____________________________________________________________________________________________________________
166 
queryAggregation(const Type & aType)167 Any SAL_CALL ProgressBar::queryAggregation( const Type& aType ) throw( RuntimeException )
168 {
169     // Ask for my own supported interfaces ...
170     // Attention: XTypeProvider and XInterface are supported by OComponentHelper!
171     Any aReturn ( ::cppu::queryInterface(   aType                                   ,
172                                             static_cast< XControlModel* > ( this )  ,
173                                             static_cast< XProgressBar*  > ( this )
174                                         )
175                 );
176 
177     // If searched interface not supported by this class ...
178     if ( aReturn.hasValue() == sal_False )
179     {
180         // ... ask baseclasses.
181         aReturn = BaseControl::queryAggregation( aType );
182     }
183 
184     return aReturn ;
185 }
186 
187 //____________________________________________________________________________________________________________
188 //  XProgressBar
189 //____________________________________________________________________________________________________________
190 
setForegroundColor(sal_Int32 nColor)191 void SAL_CALL ProgressBar::setForegroundColor( sal_Int32 nColor ) throw( RuntimeException )
192 {
193     // Ready for multithreading
194     MutexGuard  aGuard (m_aMutex) ;
195 
196     // Safe color for later use.
197     m_nForegroundColor = nColor ;
198 
199     // Repaint control
200     impl_paint ( 0, 0, impl_getGraphicsPeer() ) ;
201 }
202 
203 //____________________________________________________________________________________________________________
204 //  XProgressBar
205 //____________________________________________________________________________________________________________
206 
setBackgroundColor(sal_Int32 nColor)207 void SAL_CALL ProgressBar::setBackgroundColor ( sal_Int32 nColor ) throw( RuntimeException )
208 {
209     // Ready for multithreading
210     MutexGuard  aGuard (m_aMutex) ;
211 
212     // Safe color for later use.
213     m_nBackgroundColor = nColor ;
214 
215     // Repaint control
216     impl_paint ( 0, 0, impl_getGraphicsPeer() ) ;
217 }
218 
219 //____________________________________________________________________________________________________________
220 //  XProgressBar
221 //____________________________________________________________________________________________________________
222 
setValue(sal_Int32 nValue)223 void SAL_CALL ProgressBar::setValue ( sal_Int32 nValue ) throw( RuntimeException )
224 {
225     // This method is defined for follow things:
226     //      1) Values >= _nMinRange
227     //      2) Values <= _nMaxRange
228 
229     // Ready for multithreading
230     MutexGuard aGuard (m_aMutex) ;
231 
232     // save impossible cases
233     // This method is only defined for valid values
234     DBG_ASSERT ( (( nValue >= m_nMinRange ) && ( nValue <= m_nMaxRange )), "ProgressBar::setValue()\nNot valid value.\n" ) ;
235 
236     // If new value not valid ... do nothing in release version!
237     if (
238         ( nValue >= m_nMinRange ) &&
239         ( nValue <= m_nMaxRange )
240        )
241     {
242         // New value is ok => save this
243         m_nValue = nValue ;
244 
245         // Repaint to display changes
246         impl_paint ( 0, 0, impl_getGraphicsPeer() ) ;
247     }
248 }
249 
250 //____________________________________________________________________________________________________________
251 //  XProgressBar
252 //____________________________________________________________________________________________________________
253 
setRange(sal_Int32 nMin,sal_Int32 nMax)254 void SAL_CALL ProgressBar::setRange ( sal_Int32 nMin, sal_Int32 nMax ) throw( RuntimeException )
255 {
256     // This method is defined for follow things:
257     //      1) All values of sal_Int32
258     //      2) Min < Max
259     //      3) Min > Max
260 
261     // save impossible cases
262     // This method is only defined for valid values
263     // If you ignore this, the release version wil produce an error "division by zero" in "ProgressBar::setValue()"!
264     DBG_ASSERT ( ( nMin != nMax ) , "ProgressBar::setRange()\nValues for MIN and MAX are the same. This is not allowed!\n" ) ;
265 
266     // Ready for multithreading
267     MutexGuard  aGuard (m_aMutex) ;
268 
269     // control the values for min and max
270     if ( nMin < nMax )
271     {
272         // Take correct Min and Max
273         m_nMinRange = nMin  ;
274         m_nMaxRange = nMax  ;
275     }
276     else
277     {
278         // Change Min and Max automaticly
279         m_nMinRange = nMax  ;
280         m_nMaxRange = nMin  ;
281     }
282 
283     // assure that m_nValue is within the range
284     if (!(m_nMinRange < m_nValue  &&  m_nValue < m_nMaxRange))
285         m_nValue = m_nMinRange;
286 
287     impl_recalcRange () ;
288 
289     // Do not repaint the control at this place!!!
290     // An old "m_nValue" is set and can not be correct for this new range.
291     // Next call of "ProgressBar::setValue()" do this.
292 }
293 
294 //____________________________________________________________________________________________________________
295 //  XProgressBar
296 //____________________________________________________________________________________________________________
297 
getValue()298 sal_Int32 SAL_CALL ProgressBar::getValue () throw( RuntimeException )
299 {
300     // Ready for multithreading
301     MutexGuard aGuard (m_aMutex) ;
302 
303     return ( m_nValue ) ;
304 }
305 
306 //____________________________________________________________________________________________________________
307 //  XWindow
308 //____________________________________________________________________________________________________________
309 
setPosSize(sal_Int32 nX,sal_Int32 nY,sal_Int32 nWidth,sal_Int32 nHeight,sal_Int16 nFlags)310 void SAL_CALL ProgressBar::setPosSize ( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int16 nFlags ) throw( RuntimeException )
311 {
312     // Take old size BEFORE you set the new values at baseclass!
313     // You will control changes. At the other way, the values are the same!
314     Rectangle aBasePosSize = getPosSize () ;
315     BaseControl::setPosSize (nX, nY, nWidth, nHeight, nFlags) ;
316 
317     // Do only, if size has changed.
318     if (
319         ( nWidth  != aBasePosSize.Width     ) ||
320         ( nHeight != aBasePosSize.Height    )
321        )
322     {
323         impl_recalcRange    (                           ) ;
324         impl_paint          ( 0, 0, impl_getGraphicsPeer () ) ;
325     }
326 }
327 
328 //____________________________________________________________________________________________________________
329 //  XControl
330 //____________________________________________________________________________________________________________
331 
setModel(const Reference<XControlModel> &)332 sal_Bool SAL_CALL ProgressBar::setModel( const Reference< XControlModel >& /*xModel*/ ) throw( RuntimeException )
333 {
334     // A model is not possible for this control.
335     return sal_False ;
336 }
337 
338 //____________________________________________________________________________________________________________
339 //  XControl
340 //____________________________________________________________________________________________________________
341 
getModel()342 Reference< XControlModel > SAL_CALL ProgressBar::getModel() throw( RuntimeException )
343 {
344     // A model is not possible for this control.
345     return Reference< XControlModel >();
346 }
347 
348 //____________________________________________________________________________________________________________
349 //  impl but public method to register service
350 //____________________________________________________________________________________________________________
351 
impl_getStaticSupportedServiceNames()352 const Sequence< OUString > ProgressBar::impl_getStaticSupportedServiceNames()
353 {
354     MutexGuard aGuard( Mutex::getGlobalMutex() );
355     Sequence< OUString > seqServiceNames( 1 );
356     seqServiceNames.getArray() [0] = OUString::createFromAscii( SERVICENAME_PROGRESSBAR );
357     return seqServiceNames ;
358 }
359 
360 //____________________________________________________________________________________________________________
361 //  impl but public method to register service
362 //____________________________________________________________________________________________________________
363 
impl_getStaticImplementationName()364 const OUString ProgressBar::impl_getStaticImplementationName()
365 {
366     return OUString::createFromAscii( IMPLEMENTATIONNAME_PROGRESSBAR );
367 }
368 
369 //____________________________________________________________________________________________________________
370 //  protected method
371 //____________________________________________________________________________________________________________
372 
impl_paint(sal_Int32 nX,sal_Int32 nY,const Reference<XGraphics> & rGraphics)373 void ProgressBar::impl_paint ( sal_Int32 nX, sal_Int32 nY, const Reference< XGraphics > & rGraphics )
374 {
375     // save impossible cases
376     DBG_ASSERT ( rGraphics.is(), "ProgressBar::paint()\nCalled with invalid Reference< XGraphics > ." ) ;
377 
378     // This paint method ist not buffered !!
379     // Every request paint the completely control. ( but only, if peer exist )
380     if ( rGraphics.is () )
381     {
382         MutexGuard  aGuard (m_aMutex) ;
383 
384         // Clear background
385         // (same color for line and fill)
386         rGraphics->setFillColor ( m_nBackgroundColor                        ) ;
387         rGraphics->setLineColor ( m_nBackgroundColor                        ) ;
388         rGraphics->drawRect     ( nX, nY, impl_getWidth(), impl_getHeight() ) ;
389 
390         // same color for line and fill for blocks
391         rGraphics->setFillColor ( m_nForegroundColor ) ;
392         rGraphics->setLineColor ( m_nForegroundColor ) ;
393 
394         sal_Int32   nBlockStart     =   0                                                                           ;   // = left site of new block
395         sal_Int32   nBlockCount     =   m_nBlockValue!=0.00 ? (sal_Int32)((m_nValue-m_nMinRange)/m_nBlockValue) : 0 ;   // = number of next block
396 
397         // Draw horizontal progressbar
398         // decision in "recalcRange()"
399         if (m_bHorizontal)
400         {
401             // Step to left side of window
402             nBlockStart = nX ;
403 
404             for ( sal_Int16 i=1; i<=nBlockCount; ++i )
405             {
406                 // step free field
407                 nBlockStart +=  FREESPACE   ;
408                 // paint block
409                 rGraphics->drawRect (nBlockStart, nY+FREESPACE, m_aBlockSize.Width, m_aBlockSize.Height) ;
410                 // step next free field
411                 nBlockStart +=  m_aBlockSize.Width ;
412             }
413         }
414         // draw vertikal progressbar
415         // decision in "recalcRange()"
416         else
417         {
418             // step to bottom side of window
419             nBlockStart  =  nY+impl_getHeight() ;
420             nBlockStart -=  m_aBlockSize.Height ;
421 
422             for ( sal_Int16 i=1; i<=nBlockCount; ++i )
423             {
424                 // step free field
425                 nBlockStart -=  FREESPACE   ;
426                 // paint block
427                 rGraphics->drawRect (nX+FREESPACE, nBlockStart, m_aBlockSize.Width, m_aBlockSize.Height) ;
428                 // step next free field
429                 nBlockStart -=  m_aBlockSize.Height;
430             }
431         }
432 
433         // Paint shadow border around the progressbar
434         rGraphics->setLineColor ( LINECOLOR_SHADOW                          ) ;
435         rGraphics->drawLine     ( nX, nY, impl_getWidth(), nY               ) ;
436         rGraphics->drawLine     ( nX, nY, nX             , impl_getHeight() ) ;
437 
438         rGraphics->setLineColor ( LINECOLOR_BRIGHT                                                              ) ;
439         rGraphics->drawLine     ( impl_getWidth()-1, impl_getHeight()-1, impl_getWidth()-1, nY                  ) ;
440         rGraphics->drawLine     ( impl_getWidth()-1, impl_getHeight()-1, nX               , impl_getHeight()-1  ) ;
441     }
442 }
443 
444 //____________________________________________________________________________________________________________
445 //  protected method
446 //____________________________________________________________________________________________________________
447 
impl_recalcRange()448 void ProgressBar::impl_recalcRange ()
449 {
450     MutexGuard  aGuard (m_aMutex) ;
451 
452     sal_Int32 nWindowWidth  = impl_getWidth()  ;
453     sal_Int32 nWindowHeight = impl_getHeight() ;
454     double    fBlockHeight                     ;
455     double    fBlockWidth                      ;
456     double    fMaxBlocks                       ;
457 
458     if( nWindowWidth > nWindowHeight )
459     {
460         m_bHorizontal = sal_True                            ;
461         fBlockHeight  = (nWindowHeight-(2*FREESPACE))       ;
462         fBlockWidth   = fBlockHeight                        ;
463         fMaxBlocks    = nWindowWidth/(fBlockWidth+FREESPACE);
464     }
465     else
466     {
467         m_bHorizontal = sal_False                             ;
468         fBlockWidth   = (nWindowWidth-(2*FREESPACE))          ;
469         fBlockHeight  = fBlockWidth                           ;
470         fMaxBlocks    = nWindowHeight/(fBlockHeight+FREESPACE);
471     }
472 
473     double fRange       = m_nMaxRange-m_nMinRange    ;
474     double fBlockValue  = fRange/fMaxBlocks          ;
475 
476     m_nBlockValue       = fBlockValue            ;
477     m_aBlockSize.Height = (sal_Int32)fBlockHeight;
478     m_aBlockSize.Width  = (sal_Int32)fBlockWidth ;
479 /*
480         // Calculate count of blocks for actual size
481         // (prevent error "division by zero")
482         if ( nHeight == 0 )
483         {
484             nHeight = 1 ;
485         }
486 
487         nMaxBlock    =  nWidth / nHeight    ;
488         nMaxBlock   *=  2                   ;
489 
490         // prevent error "division by zero"
491         if ( nMaxBlock == 0 )
492         {
493             nMaxBlock = 1 ;
494         }
495 
496         // Calculate new value and new size for ONE block.
497 
498         // Do not a calculation like this: "m_nBlockValue=(m_nMaxRange-m_nMinRange)/nMaxBlock"  !
499         // If difference between m_nMaxRange and m_nMinRange to large, it give an overflow and a
500         // following error "division by zero" in method "paint() ... nBlockCount=nDifference/m_nBlockValue ..."
501 
502         // Overflow ? => example: _I32_MAX - _I32_MIN = -1 and not _UI32_MAX !!!
503 
504         m_nBlockValue       =   ( m_nMaxRange / nMaxBlock ) - ( m_nMinRange / nMaxBlock ) ;
505         m_aBlockSize.Height =   ( nHeight - ( FREESPACE * 2 )                           ) ;
506         m_aBlockSize.Width  =   ( ( nWidth / nMaxBlock ) - FREESPACE                    ) ;
507     }
508     else
509     {
510         // Don't forget to save this state! Used in "ProgressBar::paint()"
511         m_bHorizontal = sal_False ;
512 
513         double fBlockWidth  = (nHeight-(2*FREESPACE))       ;
514         double fBlockHeight = fBlockWidth                   ;
515         double fRange       = m_nMaxRange-m_nMinRange       ;
516         double fBlockValue  = fRange/(fBlockWidth+FREESPACE);
517 
518         m_nBlockValue       = fBlockValue            ;
519         m_aBlockSize.Height = (sal_Int32)fBlockHeight;
520         m_aBlockSize.Width  = (sal_Int32)fBlockWidth ;
521 
522         // Calculate count of blocks for actual size
523         // (prevent error "division by zero")
524         if ( nWidth == 0 )
525         {
526             nWidth = 1 ;
527         }
528 
529         nMaxBlock    =  nHeight / nWidth    ;
530         nMaxBlock   *=  2                   ;
531 
532         // prevent error "division by zero"
533         if ( nMaxBlock == 0 )
534         {
535             nMaxBlock = 1 ;
536         }
537 
538         // Calculate new value and new size for ONE block.
539 
540         // Do not a calculation like this: "m_nBlockValue=(m_nMaxRange-m_nMinRange)/nMaxBlock"  !
541         // If difference between m_nMaxRange and m_nMinRange to large, it give an overflow and a
542         // following error "division by zero" in method "paint() ... nBlockCount=nDifference/m_nBlockValue ..."
543 
544         // Overflow ? => example: _I32_MAX - _I32_MIN = -1 and not _UI32_MAX !!!
545 
546         m_nBlockValue       =   ( m_nMaxRange / nMaxBlock ) - ( m_nMinRange / nMaxBlock ) ;
547         m_aBlockSize.Height =   ( ( nHeight / nMaxBlock ) - FREESPACE                   ) ;
548         m_aBlockSize.Width  =   ( nWidth - ( FREESPACE * 2 )                            ) ;
549 
550     }
551 */
552 }
553 
554 }   // namespace unocontrols
555