1 /************************************************************************* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * Copyright 2000, 2010 Oracle and/or its affiliates. 5 * 6 * OpenOffice.org - a multi-platform office productivity suite 7 * 8 * This file is part of OpenOffice.org. 9 * 10 * OpenOffice.org is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU Lesser General Public License version 3 12 * only, as published by the Free Software Foundation. 13 * 14 * OpenOffice.org is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Lesser General Public License version 3 for more details 18 * (a copy is included in the LICENSE file that accompanied this code). 19 * 20 * You should have received a copy of the GNU Lesser General Public License 21 * version 3 along with OpenOffice.org. If not, see 22 * <http://www.openoffice.org/license.html> 23 * for a copy of the LGPLv3 License. 24 * 25 ************************************************************************/ 26 27 // MARKER(update_precomp.py): autogen include statement, do not remove 28 #include "precompiled_dbaccess.hxx" 29 30 #include "progressmixer.hxx" 31 32 /** === begin UNO includes === **/ 33 /** === end UNO includes === **/ 34 35 #include <osl/diagnose.h> 36 37 #include <map> 38 39 //........................................................................ 40 namespace dbmm 41 { 42 //........................................................................ 43 44 /** === begin UNO using === **/ 45 /** === end UNO using === **/ 46 47 #define OVERALL_RANGE 100000 48 49 //==================================================================== 50 //= misc types 51 //==================================================================== 52 struct PhaseData 53 { 54 // the weight of the phase, relative to all other phases 55 PhaseWeight nWeight; 56 // the "local" range of the phase 57 sal_uInt32 nRange; 58 // this is the point in the "overall range" at which this phase starts 59 sal_uInt32 nGlobalStart; 60 /** the "global" range of the phase, i.e. its range after weighting with all other 61 phases 62 */ 63 sal_uInt32 nGlobalRange; 64 65 PhaseData() 66 :nWeight(1) 67 ,nRange(100) 68 ,nGlobalStart(0) 69 ,nGlobalRange(100) 70 { 71 } 72 73 PhaseData( const PhaseWeight _nWeight ) 74 :nWeight( _nWeight ) 75 ,nRange(100) 76 ,nGlobalStart(0) 77 ,nGlobalRange(100) 78 { 79 } 80 }; 81 82 typedef ::std::map< PhaseID, PhaseData > Phases; 83 84 //==================================================================== 85 //= ProgressMixer_Data 86 //==================================================================== 87 struct ProgressMixer_Data 88 { 89 Phases aPhases; 90 Phases::iterator pCurrentPhase; 91 sal_uInt32 nWeightSum; /// the cached sum of the weights 92 double nOverallStretch; 93 IProgressConsumer& rConsumer; 94 95 ProgressMixer_Data( IProgressConsumer& _rConsumer ) 96 :aPhases() 97 ,pCurrentPhase( aPhases.end() ) 98 ,nWeightSum( 0 ) 99 ,nOverallStretch( 0 ) 100 ,rConsumer( _rConsumer ) 101 { 102 } 103 }; 104 105 //-------------------------------------------------------------------- 106 namespace 107 { 108 #if OSL_DEBUG_LEVEL > 0 109 //---------------------------------------------------------------- 110 bool lcl_isRunning( const ProgressMixer_Data& _rData ) 111 { 112 return _rData.pCurrentPhase != _rData.aPhases.end(); 113 } 114 #endif 115 //---------------------------------------------------------------- 116 void lcl_ensureInitialized( ProgressMixer_Data& _rData ) 117 { 118 OSL_PRECOND( _rData.nWeightSum, "lcl_ensureInitialized: we have no phases, this will crash!" ); 119 120 if ( _rData.nOverallStretch ) 121 return; 122 123 _rData.nOverallStretch = 1.0 * OVERALL_RANGE / _rData.nWeightSum; 124 125 // tell the single phases their "overall starting point" 126 PhaseWeight nRunningWeight( 0 ); 127 for ( Phases::iterator phase = _rData.aPhases.begin(); 128 phase != _rData.aPhases.end(); 129 ++phase 130 ) 131 { 132 phase->second.nGlobalStart = (sal_uInt32)( nRunningWeight * _rData.nOverallStretch ); 133 nRunningWeight += phase->second.nWeight; 134 135 sal_uInt32 nNextPhaseStart = (sal_uInt32)( nRunningWeight * _rData.nOverallStretch ); 136 phase->second.nGlobalRange = nNextPhaseStart - phase->second.nGlobalStart; 137 } 138 139 _rData.rConsumer.start( OVERALL_RANGE ); 140 } 141 } 142 143 //==================================================================== 144 //= ProgressMixer 145 //==================================================================== 146 //-------------------------------------------------------------------- 147 ProgressMixer::ProgressMixer( IProgressConsumer& _rConsumer ) 148 :m_pData( new ProgressMixer_Data( _rConsumer ) ) 149 { 150 } 151 152 //-------------------------------------------------------------------- 153 ProgressMixer::~ProgressMixer() 154 { 155 } 156 157 //-------------------------------------------------------------------- 158 void ProgressMixer::registerPhase( const PhaseID _nID, const PhaseWeight _nWeight ) 159 { 160 OSL_PRECOND( !lcl_isRunning( *m_pData ), "ProgressMixer::registerPhase: already running!" ); 161 OSL_ENSURE( m_pData->aPhases.find( _nID ) == m_pData->aPhases.end(), 162 "ProgressMixer::registerPhase: ID already used!" ); 163 m_pData->aPhases[ _nID ] = PhaseData( _nWeight ); 164 m_pData->nWeightSum += _nWeight; 165 } 166 167 //-------------------------------------------------------------------- 168 void ProgressMixer::startPhase( const PhaseID _nID, const sal_uInt32 _nPhaseRange ) 169 { 170 OSL_ENSURE( m_pData->aPhases.find( _nID ) != m_pData->aPhases.end(), 171 "ProgresMixer::startPhase: unknown phase!" ); 172 173 m_pData->aPhases[ _nID ].nRange = _nPhaseRange; 174 m_pData->pCurrentPhase = m_pData->aPhases.find( _nID ); 175 } 176 177 //-------------------------------------------------------------------- 178 void ProgressMixer::advancePhase( const sal_uInt32 _nPhaseProgress ) 179 { 180 OSL_PRECOND( lcl_isRunning( *m_pData ), "ProgresMixer::advancePhase: not running!" ); 181 182 // in case this is the first call, ensure all the ranges/weights are calculated 183 // correctly 184 lcl_ensureInitialized( *m_pData ); 185 186 const PhaseData& rPhase( m_pData->pCurrentPhase->second ); 187 188 double nLocalProgress = 1.0 * _nPhaseProgress / rPhase.nRange; 189 sal_uInt32 nOverallProgress = (sal_uInt32) 190 ( rPhase.nGlobalStart + nLocalProgress * rPhase.nGlobalRange ); 191 192 m_pData->rConsumer.advance( nOverallProgress ); 193 } 194 195 //-------------------------------------------------------------------- 196 void ProgressMixer::endPhase() 197 { 198 OSL_PRECOND( lcl_isRunning( *m_pData ), "ProgresMixer::endPhase: not running!" ); 199 200 // in case this is the first call, ensure all the ranges/weights are calculated 201 // correctly 202 lcl_ensureInitialized( *m_pData ); 203 204 // simply assume the phase's complete range is over 205 advancePhase( m_pData->pCurrentPhase->second.nRange ); 206 207 // if that's the last phase, this is the "global end", too 208 Phases::const_iterator pNextPhase( m_pData->pCurrentPhase ); 209 ++pNextPhase; 210 if ( pNextPhase == m_pData->aPhases.end() ) 211 m_pData->rConsumer.end(); 212 } 213 214 //........................................................................ 215 } // namespace dbmm 216 //........................................................................ 217