| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| //____________________________________________________________________________________________________________ |
| // my own includes |
| //____________________________________________________________________________________________________________ |
| |
| #include "progressbar.hxx" |
| |
| //____________________________________________________________________________________________________________ |
| // includes of other projects |
| //____________________________________________________________________________________________________________ |
| #include <com/sun/star/awt/GradientStyle.hpp> |
| #include <com/sun/star/awt/RasterOperation.hpp> |
| #include <com/sun/star/awt/Gradient.hpp> |
| #include <com/sun/star/awt/XGraphics.hpp> |
| #include <tools/debug.hxx> |
| #include <cppuhelper/typeprovider.hxx> |
| |
| #include <math.h> |
| #include <limits.h> |
| |
| //____________________________________________________________________________________________________________ |
| // includes of my project |
| //____________________________________________________________________________________________________________ |
| |
| //____________________________________________________________________________________________________________ |
| // namespace |
| //____________________________________________________________________________________________________________ |
| |
| using namespace ::cppu ; |
| using namespace ::osl ; |
| using namespace ::rtl ; |
| using namespace ::com::sun::star::uno ; |
| using namespace ::com::sun::star::lang ; |
| using namespace ::com::sun::star::awt ; |
| |
| namespace unocontrols{ |
| |
| //____________________________________________________________________________________________________________ |
| // construct/destruct |
| //____________________________________________________________________________________________________________ |
| |
| ProgressBar::ProgressBar( const Reference< XMultiServiceFactory >& xFactory ) |
| : BaseControl ( xFactory ) |
| , m_bHorizontal ( DEFAULT_HORIZONTAL ) |
| , m_aBlockSize ( DEFAULT_BLOCKDIMENSION ) |
| , m_nForegroundColor ( DEFAULT_FOREGROUNDCOLOR ) |
| , m_nBackgroundColor ( DEFAULT_BACKGROUNDCOLOR ) |
| , m_nMinRange ( DEFAULT_MINRANGE ) |
| , m_nMaxRange ( DEFAULT_MAXRANGE ) |
| , m_nBlockValue ( DEFAULT_BLOCKVALUE ) |
| , m_nValue ( DEFAULT_VALUE ) |
| { |
| } |
| |
| ProgressBar::~ProgressBar() |
| { |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XInterface |
| //____________________________________________________________________________________________________________ |
| |
| Any SAL_CALL ProgressBar::queryInterface( const Type& rType ) throw( RuntimeException ) |
| { |
| // Attention: |
| // Don't use mutex or guard in this method!!! Is a method of XInterface. |
| Any aReturn ; |
| Reference< XInterface > xDel = BaseControl::impl_getDelegator(); |
| if ( xDel.is() ) |
| { |
| // If an delegator exist, forward question to his queryInterface. |
| // Delegator will ask his own queryAggregation! |
| aReturn = xDel->queryInterface( rType ); |
| } |
| else |
| { |
| // If an delegator unknown, forward question to own queryAggregation. |
| aReturn = queryAggregation( rType ); |
| } |
| |
| return aReturn ; |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XInterface |
| //____________________________________________________________________________________________________________ |
| |
| void SAL_CALL ProgressBar::acquire() throw() |
| { |
| // Attention: |
| // Don't use mutex or guard in this method!!! Is a method of XInterface. |
| |
| // Forward to baseclass |
| BaseControl::acquire(); |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XInterface |
| //____________________________________________________________________________________________________________ |
| |
| void SAL_CALL ProgressBar::release() throw() |
| { |
| // Attention: |
| // Don't use mutex or guard in this method!!! Is a method of XInterface. |
| |
| // Forward to baseclass |
| BaseControl::release(); |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XTypeProvider |
| //____________________________________________________________________________________________________________ |
| |
| Sequence< Type > SAL_CALL ProgressBar::getTypes() throw( RuntimeException ) |
| { |
| // Optimize this method ! |
| // We initialize a static variable only one time. And we don't must use a mutex at every call! |
| // For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL! |
| static OTypeCollection* pTypeCollection = NULL ; |
| |
| if ( pTypeCollection == NULL ) |
| { |
| // Ready for multithreading; get global mutex for first call of this method only! see before |
| MutexGuard aGuard( Mutex::getGlobalMutex() ); |
| |
| // Control these pointer again ... it can be, that another instance will be faster then these! |
| if ( pTypeCollection == NULL ) |
| { |
| // Create a static typecollection ... |
| static OTypeCollection aTypeCollection ( ::getCppuType(( const Reference< XControlModel >*)NULL ) , |
| ::getCppuType(( const Reference< XProgressBar >*)NULL ) , |
| BaseControl::getTypes() |
| ); |
| // ... and set his address to static pointer! |
| pTypeCollection = &aTypeCollection ; |
| } |
| } |
| |
| return pTypeCollection->getTypes(); |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XAggregation |
| //____________________________________________________________________________________________________________ |
| |
| Any SAL_CALL ProgressBar::queryAggregation( const Type& aType ) throw( RuntimeException ) |
| { |
| // Ask for my own supported interfaces ... |
| // Attention: XTypeProvider and XInterface are supported by OComponentHelper! |
| Any aReturn ( ::cppu::queryInterface( aType , |
| static_cast< XControlModel* > ( this ) , |
| static_cast< XProgressBar* > ( this ) |
| ) |
| ); |
| |
| // If searched interface not supported by this class ... |
| if ( aReturn.hasValue() == sal_False ) |
| { |
| // ... ask baseclasses. |
| aReturn = BaseControl::queryAggregation( aType ); |
| } |
| |
| return aReturn ; |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XProgressBar |
| //____________________________________________________________________________________________________________ |
| |
| void SAL_CALL ProgressBar::setForegroundColor( sal_Int32 nColor ) throw( RuntimeException ) |
| { |
| // Ready for multithreading |
| MutexGuard aGuard (m_aMutex) ; |
| |
| // Safe color for later use. |
| m_nForegroundColor = nColor ; |
| |
| // Repaint control |
| impl_paint ( 0, 0, impl_getGraphicsPeer() ) ; |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XProgressBar |
| //____________________________________________________________________________________________________________ |
| |
| void SAL_CALL ProgressBar::setBackgroundColor ( sal_Int32 nColor ) throw( RuntimeException ) |
| { |
| // Ready for multithreading |
| MutexGuard aGuard (m_aMutex) ; |
| |
| // Safe color for later use. |
| m_nBackgroundColor = nColor ; |
| |
| // Repaint control |
| impl_paint ( 0, 0, impl_getGraphicsPeer() ) ; |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XProgressBar |
| //____________________________________________________________________________________________________________ |
| |
| void SAL_CALL ProgressBar::setValue ( sal_Int32 nValue ) throw( RuntimeException ) |
| { |
| // This method is defined for follow things: |
| // 1) Values >= _nMinRange |
| // 2) Values <= _nMaxRange |
| |
| // Ready for multithreading |
| MutexGuard aGuard (m_aMutex) ; |
| |
| // save impossible cases |
| // This method is only defined for valid values |
| DBG_ASSERT ( (( nValue >= m_nMinRange ) && ( nValue <= m_nMaxRange )), "ProgressBar::setValue()\nNot valid value.\n" ) ; |
| |
| // If new value not valid ... do nothing in release version! |
| if ( |
| ( nValue >= m_nMinRange ) && |
| ( nValue <= m_nMaxRange ) |
| ) |
| { |
| // New value is ok => save this |
| m_nValue = nValue ; |
| |
| // Repaint to display changes |
| impl_paint ( 0, 0, impl_getGraphicsPeer() ) ; |
| } |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XProgressBar |
| //____________________________________________________________________________________________________________ |
| |
| void SAL_CALL ProgressBar::setRange ( sal_Int32 nMin, sal_Int32 nMax ) throw( RuntimeException ) |
| { |
| // This method is defined for follow things: |
| // 1) All values of sal_Int32 |
| // 2) Min < Max |
| // 3) Min > Max |
| |
| // save impossible cases |
| // This method is only defined for valid values |
| // If you ignore this, the release version wil produce an error "division by zero" in "ProgressBar::setValue()"! |
| DBG_ASSERT ( ( nMin != nMax ) , "ProgressBar::setRange()\nValues for MIN and MAX are the same. This is not allowed!\n" ) ; |
| |
| // Ready for multithreading |
| MutexGuard aGuard (m_aMutex) ; |
| |
| // control the values for min and max |
| if ( nMin < nMax ) |
| { |
| // Take correct Min and Max |
| m_nMinRange = nMin ; |
| m_nMaxRange = nMax ; |
| } |
| else |
| { |
| // Change Min and Max automatically |
| m_nMinRange = nMax ; |
| m_nMaxRange = nMin ; |
| } |
| |
| // assure that m_nValue is within the range |
| if (!(m_nMinRange < m_nValue && m_nValue < m_nMaxRange)) |
| m_nValue = m_nMinRange; |
| |
| impl_recalcRange () ; |
| |
| // Do not repaint the control at this place!!! |
| // An old "m_nValue" is set and can not be correct for this new range. |
| // Next call of "ProgressBar::setValue()" do this. |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XProgressBar |
| //____________________________________________________________________________________________________________ |
| |
| sal_Int32 SAL_CALL ProgressBar::getValue () throw( RuntimeException ) |
| { |
| // Ready for multithreading |
| MutexGuard aGuard (m_aMutex) ; |
| |
| return ( m_nValue ) ; |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XWindow |
| //____________________________________________________________________________________________________________ |
| |
| void SAL_CALL ProgressBar::setPosSize ( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int16 nFlags ) throw( RuntimeException ) |
| { |
| // Take old size BEFORE you set the new values at baseclass! |
| // You will control changes. At the other way, the values are the same! |
| Rectangle aBasePosSize = getPosSize () ; |
| BaseControl::setPosSize (nX, nY, nWidth, nHeight, nFlags) ; |
| |
| // Do only, if size has changed. |
| if ( |
| ( nWidth != aBasePosSize.Width ) || |
| ( nHeight != aBasePosSize.Height ) |
| ) |
| { |
| impl_recalcRange ( ) ; |
| impl_paint ( 0, 0, impl_getGraphicsPeer () ) ; |
| } |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XControl |
| //____________________________________________________________________________________________________________ |
| |
| sal_Bool SAL_CALL ProgressBar::setModel( const Reference< XControlModel >& /*xModel*/ ) throw( RuntimeException ) |
| { |
| // A model is not possible for this control. |
| return sal_False ; |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // XControl |
| //____________________________________________________________________________________________________________ |
| |
| Reference< XControlModel > SAL_CALL ProgressBar::getModel() throw( RuntimeException ) |
| { |
| // A model is not possible for this control. |
| return Reference< XControlModel >(); |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // impl but public method to register service |
| //____________________________________________________________________________________________________________ |
| |
| const Sequence< OUString > ProgressBar::impl_getStaticSupportedServiceNames() |
| { |
| MutexGuard aGuard( Mutex::getGlobalMutex() ); |
| Sequence< OUString > seqServiceNames( 1 ); |
| seqServiceNames.getArray() [0] = OUString::createFromAscii( SERVICENAME_PROGRESSBAR ); |
| return seqServiceNames ; |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // impl but public method to register service |
| //____________________________________________________________________________________________________________ |
| |
| const OUString ProgressBar::impl_getStaticImplementationName() |
| { |
| return OUString::createFromAscii( IMPLEMENTATIONNAME_PROGRESSBAR ); |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // protected method |
| //____________________________________________________________________________________________________________ |
| |
| void ProgressBar::impl_paint ( sal_Int32 nX, sal_Int32 nY, const Reference< XGraphics > & rGraphics ) |
| { |
| // save impossible cases |
| DBG_ASSERT ( rGraphics.is(), "ProgressBar::paint()\nCalled with invalid Reference< XGraphics > ." ) ; |
| |
| // This paint method ist not buffered !! |
| // Every request paint the completely control. ( but only, if peer exist ) |
| if ( rGraphics.is () ) |
| { |
| MutexGuard aGuard (m_aMutex) ; |
| |
| // Clear background |
| // (same color for line and fill) |
| rGraphics->setFillColor ( m_nBackgroundColor ) ; |
| rGraphics->setLineColor ( m_nBackgroundColor ) ; |
| rGraphics->drawRect ( nX, nY, impl_getWidth(), impl_getHeight() ) ; |
| |
| // same color for line and fill for blocks |
| rGraphics->setFillColor ( m_nForegroundColor ) ; |
| rGraphics->setLineColor ( m_nForegroundColor ) ; |
| |
| sal_Int32 nBlockStart = 0 ; // = left site of new block |
| sal_Int32 nBlockCount = m_nBlockValue!=0.00 ? (sal_Int32)((m_nValue-m_nMinRange)/m_nBlockValue) : 0 ; // = number of next block |
| |
| // Draw horizontal progressbar |
| // decision in "recalcRange()" |
| if (m_bHorizontal) |
| { |
| // Step to left side of window |
| nBlockStart = nX ; |
| |
| for ( sal_Int16 i=1; i<=nBlockCount; ++i ) |
| { |
| // step free field |
| nBlockStart += FREESPACE ; |
| // paint block |
| rGraphics->drawRect (nBlockStart, nY+FREESPACE, m_aBlockSize.Width, m_aBlockSize.Height) ; |
| // step next free field |
| nBlockStart += m_aBlockSize.Width ; |
| } |
| } |
| // draw vertikal progressbar |
| // decision in "recalcRange()" |
| else |
| { |
| // step to bottom side of window |
| nBlockStart = nY+impl_getHeight() ; |
| nBlockStart -= m_aBlockSize.Height ; |
| |
| for ( sal_Int16 i=1; i<=nBlockCount; ++i ) |
| { |
| // step free field |
| nBlockStart -= FREESPACE ; |
| // paint block |
| rGraphics->drawRect (nX+FREESPACE, nBlockStart, m_aBlockSize.Width, m_aBlockSize.Height) ; |
| // step next free field |
| nBlockStart -= m_aBlockSize.Height; |
| } |
| } |
| |
| // Paint shadow border around the progressbar |
| rGraphics->setLineColor ( LINECOLOR_SHADOW ) ; |
| rGraphics->drawLine ( nX, nY, impl_getWidth(), nY ) ; |
| rGraphics->drawLine ( nX, nY, nX , impl_getHeight() ) ; |
| |
| rGraphics->setLineColor ( LINECOLOR_BRIGHT ) ; |
| rGraphics->drawLine ( impl_getWidth()-1, impl_getHeight()-1, impl_getWidth()-1, nY ) ; |
| rGraphics->drawLine ( impl_getWidth()-1, impl_getHeight()-1, nX , impl_getHeight()-1 ) ; |
| } |
| } |
| |
| //____________________________________________________________________________________________________________ |
| // protected method |
| //____________________________________________________________________________________________________________ |
| |
| void ProgressBar::impl_recalcRange () |
| { |
| MutexGuard aGuard (m_aMutex) ; |
| |
| sal_Int32 nWindowWidth = impl_getWidth() ; |
| sal_Int32 nWindowHeight = impl_getHeight() ; |
| double fBlockHeight ; |
| double fBlockWidth ; |
| double fMaxBlocks ; |
| |
| if( nWindowWidth > nWindowHeight ) |
| { |
| m_bHorizontal = sal_True ; |
| fBlockHeight = (nWindowHeight-(2*FREESPACE)) ; |
| fBlockWidth = fBlockHeight ; |
| fMaxBlocks = nWindowWidth/(fBlockWidth+FREESPACE); |
| } |
| else |
| { |
| m_bHorizontal = sal_False ; |
| fBlockWidth = (nWindowWidth-(2*FREESPACE)) ; |
| fBlockHeight = fBlockWidth ; |
| fMaxBlocks = nWindowHeight/(fBlockHeight+FREESPACE); |
| } |
| |
| double fRange = m_nMaxRange-m_nMinRange ; |
| double fBlockValue = fRange/fMaxBlocks ; |
| |
| m_nBlockValue = fBlockValue ; |
| m_aBlockSize.Height = (sal_Int32)fBlockHeight; |
| m_aBlockSize.Width = (sal_Int32)fBlockWidth ; |
| /* |
| // Calculate count of blocks for actual size |
| // (prevent error "division by zero") |
| if ( nHeight == 0 ) |
| { |
| nHeight = 1 ; |
| } |
| |
| nMaxBlock = nWidth / nHeight ; |
| nMaxBlock *= 2 ; |
| |
| // prevent error "division by zero" |
| if ( nMaxBlock == 0 ) |
| { |
| nMaxBlock = 1 ; |
| } |
| |
| // Calculate new value and new size for ONE block. |
| |
| // Do not a calculation like this: "m_nBlockValue=(m_nMaxRange-m_nMinRange)/nMaxBlock" ! |
| // If difference between m_nMaxRange and m_nMinRange to large, it give an overflow and a |
| // following error "division by zero" in method "paint() ... nBlockCount=nDifference/m_nBlockValue ..." |
| |
| // Overflow ? => example: _I32_MAX - _I32_MIN = -1 and not _UI32_MAX !!! |
| |
| m_nBlockValue = ( m_nMaxRange / nMaxBlock ) - ( m_nMinRange / nMaxBlock ) ; |
| m_aBlockSize.Height = ( nHeight - ( FREESPACE * 2 ) ) ; |
| m_aBlockSize.Width = ( ( nWidth / nMaxBlock ) - FREESPACE ) ; |
| } |
| else |
| { |
| // Don't forget to save this state! Used in "ProgressBar::paint()" |
| m_bHorizontal = sal_False ; |
| |
| double fBlockWidth = (nHeight-(2*FREESPACE)) ; |
| double fBlockHeight = fBlockWidth ; |
| double fRange = m_nMaxRange-m_nMinRange ; |
| double fBlockValue = fRange/(fBlockWidth+FREESPACE); |
| |
| m_nBlockValue = fBlockValue ; |
| m_aBlockSize.Height = (sal_Int32)fBlockHeight; |
| m_aBlockSize.Width = (sal_Int32)fBlockWidth ; |
| |
| // Calculate count of blocks for actual size |
| // (prevent error "division by zero") |
| if ( nWidth == 0 ) |
| { |
| nWidth = 1 ; |
| } |
| |
| nMaxBlock = nHeight / nWidth ; |
| nMaxBlock *= 2 ; |
| |
| // prevent error "division by zero" |
| if ( nMaxBlock == 0 ) |
| { |
| nMaxBlock = 1 ; |
| } |
| |
| // Calculate new value and new size for ONE block. |
| |
| // Do not a calculation like this: "m_nBlockValue=(m_nMaxRange-m_nMinRange)/nMaxBlock" ! |
| // If difference between m_nMaxRange and m_nMinRange to large, it give an overflow and a |
| // following error "division by zero" in method "paint() ... nBlockCount=nDifference/m_nBlockValue ..." |
| |
| // Overflow ? => example: _I32_MAX - _I32_MIN = -1 and not _UI32_MAX !!! |
| |
| m_nBlockValue = ( m_nMaxRange / nMaxBlock ) - ( m_nMinRange / nMaxBlock ) ; |
| m_aBlockSize.Height = ( ( nHeight / nMaxBlock ) - FREESPACE ) ; |
| m_aBlockSize.Width = ( nWidth - ( FREESPACE * 2 ) ) ; |
| |
| } |
| */ |
| } |
| |
| } // namespace unocontrols |