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