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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scfilt.hxx"
26 #include "fprogressbar.hxx"
27 #include "global.hxx"
28 #include "progress.hxx"
29 
30 // ============================================================================
31 
ScfProgressSegment(sal_Size nSize)32 ScfProgressBar::ScfProgressSegment::ScfProgressSegment( sal_Size nSize ) :
33     mxProgress( 0 ),
34     mnSize( nSize ),
35     mnPos( 0 )
36 {
37 }
38 
~ScfProgressSegment()39 ScfProgressBar::ScfProgressSegment::~ScfProgressSegment()
40 {
41 }
42 
43 // ============================================================================
44 
ScfProgressBar(SfxObjectShell * pDocShell,const String & rText)45 ScfProgressBar::ScfProgressBar( SfxObjectShell* pDocShell, const String& rText ) :
46     maText( rText )
47 {
48     Init( pDocShell );
49 }
50 
ScfProgressBar(SfxObjectShell * pDocShell,sal_uInt16 nResId)51 ScfProgressBar::ScfProgressBar( SfxObjectShell* pDocShell, sal_uInt16 nResId ) :
52     maText( ScGlobal::GetRscString( nResId ) )
53 {
54     Init( pDocShell );
55 }
56 
ScfProgressBar(ScfProgressBar & rParProgress,ScfProgressSegment * pParSegment)57 ScfProgressBar::ScfProgressBar( ScfProgressBar& rParProgress, ScfProgressSegment* pParSegment )
58 {
59     Init( rParProgress.mpDocShell );
60     mpParentProgress = &rParProgress;
61     mpParentSegment = pParSegment;
62 }
63 
~ScfProgressBar()64 ScfProgressBar::~ScfProgressBar()
65 {
66 }
67 
Init(SfxObjectShell * pDocShell)68 void ScfProgressBar::Init( SfxObjectShell* pDocShell )
69 {
70     mpDocShell = pDocShell;
71     mpParentProgress = 0;
72     mpParentSegment = mpCurrSegment = 0;
73     mnTotalSize = mnTotalPos = mnUnitSize = mnNextUnitPos = 0;
74     mnSysProgressScale = 1;     // used to workaround the ULONG_MAX/100 limit
75     mbInProgress = false;
76 }
77 
GetSegment(sal_Int32 nSegment) const78 ScfProgressBar::ScfProgressSegment* ScfProgressBar::GetSegment( sal_Int32 nSegment ) const
79 {
80     if( nSegment < 0 )
81         return 0;
82     DBG_ASSERT( maSegments.GetObject( nSegment ), "ScfProgressBar::GetSegment - invalid segment index" );
83     return maSegments.GetObject( nSegment );
84 }
85 
SetCurrSegment(ScfProgressSegment * pSegment)86 void ScfProgressBar::SetCurrSegment( ScfProgressSegment* pSegment )
87 {
88     if( mpCurrSegment != pSegment )
89     {
90         mpCurrSegment = pSegment;
91 
92         if( mpParentProgress && mpParentSegment )
93         {
94             mpParentProgress->SetCurrSegment( mpParentSegment );
95         }
96         else if( !mxSysProgress.get() && (mnTotalSize > 0) )
97         {
98             // System progress has an internal limit of ULONG_MAX/100.
99             mnSysProgressScale = 1;
100             sal_uLong nSysTotalSize = static_cast< sal_uLong >( mnTotalSize );
101             while( nSysTotalSize >= ULONG_MAX / 100 )
102             {
103                 nSysTotalSize /= 2;
104                 mnSysProgressScale *= 2;
105             }
106             mxSysProgress.reset( new ScProgress( mpDocShell, maText, nSysTotalSize ) );
107         }
108 
109         if( !mbInProgress && mpCurrSegment && (mnTotalSize > 0) )
110         {
111             mnUnitSize = mnTotalSize / 256 + 1;   // at most 256 calls of system progress
112             mnNextUnitPos = 0;
113             mbInProgress = true;
114         }
115     }
116 }
117 
IncreaseProgressBar(sal_Size nDelta)118 void ScfProgressBar::IncreaseProgressBar( sal_Size nDelta )
119 {
120     sal_Size nNewPos = mnTotalPos + nDelta;
121 
122     // call back to parent progress bar
123     if( mpParentProgress && mpParentSegment )
124     {
125         // calculate new position of parent progress bar
126         sal_Size nParentPos = static_cast< sal_Size >(
127             static_cast< double >( nNewPos ) * mpParentSegment->mnSize / mnTotalSize );
128         mpParentProgress->ProgressAbs( nParentPos );
129     }
130     // modify system progress bar
131     else if( mxSysProgress.get() )
132     {
133         if( nNewPos >= mnNextUnitPos )
134         {
135             mnNextUnitPos = nNewPos + mnUnitSize;
136             mxSysProgress->SetState( static_cast< sal_uLong >( nNewPos / mnSysProgressScale ) );
137         }
138     }
139     else
140     {
141         DBG_ERRORFILE( "ScfProgressBar::IncreaseProgressBar - no progress bar found" );
142     }
143 
144     mnTotalPos = nNewPos;
145 }
146 
AddSegment(sal_Size nSize)147 sal_Int32 ScfProgressBar::AddSegment( sal_Size nSize )
148 {
149     DBG_ASSERT( !mbInProgress, "ScfProgressBar::AddSegment - already in progress mode" );
150     if( nSize == 0 )
151         return SCF_INV_SEGMENT;
152 
153     maSegments.Append( new ScfProgressSegment( nSize ) );
154     mnTotalSize += nSize;
155     return static_cast< sal_Int32 >( maSegments.Count() - 1 );
156 }
157 
GetSegmentProgressBar(sal_Int32 nSegment)158 ScfProgressBar& ScfProgressBar::GetSegmentProgressBar( sal_Int32 nSegment )
159 {
160     ScfProgressSegment* pSegment = GetSegment( nSegment );
161     DBG_ASSERT( !pSegment || (pSegment->mnPos == 0), "ScfProgressBar::GetSegmentProgressBar - segment already started" );
162     if( pSegment && (pSegment->mnPos == 0) )
163     {
164         if( !pSegment->mxProgress.get() )
165             pSegment->mxProgress.reset( new ScfProgressBar( *this, pSegment ) );
166         return *pSegment->mxProgress;
167     }
168     return *this;
169 }
170 
IsFull() const171 bool ScfProgressBar::IsFull() const
172 {
173     DBG_ASSERT( mbInProgress && mpCurrSegment, "ScfProgressBar::IsFull - no segment started" );
174     return mpCurrSegment && (mpCurrSegment->mnPos >= mpCurrSegment->mnSize);
175 }
176 
ActivateSegment(sal_Int32 nSegment)177 void ScfProgressBar::ActivateSegment( sal_Int32 nSegment )
178 {
179     DBG_ASSERT( mnTotalSize > 0, "ScfProgressBar::ActivateSegment - progress range is zero" );
180     if( mnTotalSize > 0 )
181         SetCurrSegment( GetSegment( nSegment ) );
182 }
183 
ProgressAbs(sal_Size nPos)184 void ScfProgressBar::ProgressAbs( sal_Size nPos )
185 {
186     DBG_ASSERT( mbInProgress && mpCurrSegment, "ScfProgressBar::ProgressAbs - no segment started" );
187     if( mpCurrSegment )
188     {
189         DBG_ASSERT( mpCurrSegment->mnPos <= nPos, "ScfProgressBar::ProgressAbs - delta pos < 0" );
190         DBG_ASSERT( nPos <= mpCurrSegment->mnSize, "ScfProgressBar::ProgressAbs - segment overflow" );
191         if( (mpCurrSegment->mnPos < nPos) && (nPos <= mpCurrSegment->mnSize) )
192         {
193             IncreaseProgressBar( nPos - mpCurrSegment->mnPos );
194             mpCurrSegment->mnPos = nPos;
195         }
196     }
197 }
198 
Progress(sal_Size nDelta)199 void ScfProgressBar::Progress( sal_Size nDelta )
200 {
201     ProgressAbs( mpCurrSegment ? (mpCurrSegment->mnPos + nDelta) : 0 );
202 }
203 
204 // ============================================================================
205 
ScfSimpleProgressBar(sal_Size nSize,SfxObjectShell * pDocShell,const String & rText)206 ScfSimpleProgressBar::ScfSimpleProgressBar( sal_Size nSize, SfxObjectShell* pDocShell, const String& rText ) :
207     maProgress( pDocShell, rText )
208 {
209     Init( nSize );
210 }
211 
ScfSimpleProgressBar(sal_Size nSize,SfxObjectShell * pDocShell,sal_uInt16 nResId)212 ScfSimpleProgressBar::ScfSimpleProgressBar( sal_Size nSize, SfxObjectShell* pDocShell, sal_uInt16 nResId ) :
213     maProgress( pDocShell, nResId )
214 {
215     Init( nSize );
216 }
217 
Init(sal_Size nSize)218 void ScfSimpleProgressBar::Init( sal_Size nSize )
219 {
220     sal_Int32 nSegment = maProgress.AddSegment( nSize );
221     if( nSegment >= 0 )
222         maProgress.ActivateSegment( nSegment );
223 }
224 
225 // ============================================================================
226 
227 //UNUSED2008-05  ScfStreamProgressBar::ScfStreamProgressBar( SvStream& rStrm, SfxObjectShell* pDocShell, const String& rText ) :
228 //UNUSED2008-05      mrStrm( rStrm )
229 //UNUSED2008-05  {
230 //UNUSED2008-05      Init( pDocShell, rText );
231 //UNUSED2008-05  }
232 
ScfStreamProgressBar(SvStream & rStrm,SfxObjectShell * pDocShell,sal_uInt16 nResId)233 ScfStreamProgressBar::ScfStreamProgressBar( SvStream& rStrm, SfxObjectShell* pDocShell, sal_uInt16 nResId ) :
234     mrStrm( rStrm )
235 {
236     Init( pDocShell, ScGlobal::GetRscString( nResId ) );
237 }
238 
Progress()239 void ScfStreamProgressBar::Progress()
240 {
241     mxProgress->ProgressAbs( mrStrm.Tell() );
242 }
243 
Init(SfxObjectShell * pDocShell,const String & rText)244 void ScfStreamProgressBar::Init( SfxObjectShell* pDocShell, const String& rText )
245 {
246     sal_Size nPos = mrStrm.Tell();
247     mrStrm.Seek( STREAM_SEEK_TO_END );
248     sal_Size nSize = mrStrm.Tell();
249     mrStrm.Seek( nPos );
250 
251     mxProgress.reset( new ScfSimpleProgressBar( nSize, pDocShell, rText ) );
252     Progress();
253 }
254 
255 // ============================================================================
256 
257