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 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 76 ProgressBar::~ProgressBar() 77 { 78 } 79 80 //____________________________________________________________________________________________________________ 81 // XInterface 82 //____________________________________________________________________________________________________________ 83 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 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 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 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 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 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 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 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 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 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 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 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 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 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 364 const OUString ProgressBar::impl_getStaticImplementationName() 365 { 366 return OUString::createFromAscii( IMPLEMENTATIONNAME_PROGRESSBAR ); 367 } 368 369 //____________________________________________________________________________________________________________ 370 // protected method 371 //____________________________________________________________________________________________________________ 372 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 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