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 automatically
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