Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "progressbar.hxx"
21 :
22 : #include <com/sun/star/awt/GradientStyle.hpp>
23 : #include <com/sun/star/awt/RasterOperation.hpp>
24 : #include <com/sun/star/awt/Gradient.hpp>
25 : #include <com/sun/star/awt/XGraphics.hpp>
26 : #include <tools/debug.hxx>
27 : #include <cppuhelper/typeprovider.hxx>
28 :
29 : #include <math.h>
30 : #include <limits.h>
31 :
32 : using namespace ::cppu;
33 : using namespace ::osl;
34 : using namespace ::com::sun::star::uno;
35 : using namespace ::com::sun::star::lang;
36 : using namespace ::com::sun::star::awt;
37 :
38 : namespace unocontrols{
39 :
40 : // construct/destruct
41 :
42 0 : ProgressBar::ProgressBar( const Reference< XComponentContext >& rxContext )
43 : : BaseControl ( rxContext )
44 : , m_bHorizontal ( PROGRESSBAR_DEFAULT_HORIZONTAL )
45 : , m_aBlockSize ( PROGRESSBAR_DEFAULT_BLOCKDIMENSION )
46 : , m_nForegroundColor ( PROGRESSBAR_DEFAULT_FOREGROUNDCOLOR )
47 : , m_nBackgroundColor ( PROGRESSBAR_DEFAULT_BACKGROUNDCOLOR )
48 : , m_nMinRange ( PROGRESSBAR_DEFAULT_MINRANGE )
49 : , m_nMaxRange ( PROGRESSBAR_DEFAULT_MAXRANGE )
50 : , m_nBlockValue ( PROGRESSBAR_DEFAULT_BLOCKVALUE )
51 0 : , m_nValue ( PROGRESSBAR_DEFAULT_VALUE )
52 : {
53 0 : }
54 :
55 0 : ProgressBar::~ProgressBar()
56 : {
57 0 : }
58 :
59 : // XInterface
60 :
61 0 : Any SAL_CALL ProgressBar::queryInterface( const Type& rType ) throw( RuntimeException, std::exception )
62 : {
63 : // Attention:
64 : // Don't use mutex or guard in this method!!! Is a method of XInterface.
65 0 : Any aReturn;
66 0 : Reference< XInterface > xDel = BaseControl::impl_getDelegator();
67 0 : if ( xDel.is() )
68 : {
69 : // If an delegator exist, forward question to his queryInterface.
70 : // Delegator will ask his own queryAggregation!
71 0 : aReturn = xDel->queryInterface( rType );
72 : }
73 : else
74 : {
75 : // If an delegator unknown, forward question to own queryAggregation.
76 0 : aReturn = queryAggregation( rType );
77 : }
78 :
79 0 : return aReturn;
80 : }
81 :
82 : // XInterface
83 :
84 0 : void SAL_CALL ProgressBar::acquire() throw()
85 : {
86 : // Attention:
87 : // Don't use mutex or guard in this method!!! Is a method of XInterface.
88 :
89 : // Forward to baseclass
90 0 : BaseControl::acquire();
91 0 : }
92 :
93 : // XInterface
94 :
95 0 : void SAL_CALL ProgressBar::release() throw()
96 : {
97 : // Attention:
98 : // Don't use mutex or guard in this method!!! Is a method of XInterface.
99 :
100 : // Forward to baseclass
101 0 : BaseControl::release();
102 0 : }
103 :
104 : // XTypeProvider
105 :
106 0 : Sequence< Type > SAL_CALL ProgressBar::getTypes() throw( RuntimeException, std::exception )
107 : {
108 : // Optimize this method !
109 : // We initialize a static variable only one time. And we don't must use a mutex at every call!
110 : // For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL!
111 : static OTypeCollection* pTypeCollection = NULL;
112 :
113 0 : if ( pTypeCollection == NULL )
114 : {
115 : // Ready for multithreading; get global mutex for first call of this method only! see before
116 0 : MutexGuard aGuard( Mutex::getGlobalMutex() );
117 :
118 : // Control these pointer again ... it can be, that another instance will be faster then these!
119 0 : if ( pTypeCollection == NULL )
120 : {
121 : // Create a static typecollection ...
122 0 : static OTypeCollection aTypeCollection ( cppu::UnoType<XControlModel>::get(),
123 0 : cppu::UnoType<XProgressBar>::get(),
124 : BaseControl::getTypes()
125 0 : );
126 : // ... and set his address to static pointer!
127 0 : pTypeCollection = &aTypeCollection;
128 0 : }
129 : }
130 :
131 0 : return pTypeCollection->getTypes();
132 : }
133 :
134 : // XAggregation
135 :
136 0 : Any SAL_CALL ProgressBar::queryAggregation( const Type& aType ) throw( RuntimeException, std::exception )
137 : {
138 : // Ask for my own supported interfaces ...
139 : // Attention: XTypeProvider and XInterface are supported by OComponentHelper!
140 : Any aReturn ( ::cppu::queryInterface( aType ,
141 : static_cast< XControlModel* > ( this ) ,
142 : static_cast< XProgressBar* > ( this )
143 : )
144 0 : );
145 :
146 : // If searched interface not supported by this class ...
147 0 : if ( !aReturn.hasValue() )
148 : {
149 : // ... ask baseclasses.
150 0 : aReturn = BaseControl::queryAggregation( aType );
151 : }
152 :
153 0 : return aReturn;
154 : }
155 :
156 : // XProgressBar
157 :
158 0 : void SAL_CALL ProgressBar::setForegroundColor( sal_Int32 nColor ) throw( RuntimeException, std::exception )
159 : {
160 : // Ready for multithreading
161 0 : MutexGuard aGuard (m_aMutex);
162 :
163 : // Safe color for later use.
164 0 : m_nForegroundColor = nColor;
165 :
166 : // Repaint control
167 0 : impl_paint ( 0, 0, impl_getGraphicsPeer() );
168 0 : }
169 :
170 : // XProgressBar
171 :
172 0 : void SAL_CALL ProgressBar::setBackgroundColor ( sal_Int32 nColor ) throw( RuntimeException, std::exception )
173 : {
174 : // Ready for multithreading
175 0 : MutexGuard aGuard (m_aMutex);
176 :
177 : // Safe color for later use.
178 0 : m_nBackgroundColor = nColor;
179 :
180 : // Repaint control
181 0 : impl_paint ( 0, 0, impl_getGraphicsPeer() );
182 0 : }
183 :
184 : // XProgressBar
185 :
186 0 : void SAL_CALL ProgressBar::setValue ( sal_Int32 nValue ) throw( RuntimeException, std::exception )
187 : {
188 : // This method is defined for follow things:
189 : // 1) Values >= _nMinRange
190 : // 2) Values <= _nMaxRange
191 :
192 : // Ready for multithreading
193 0 : MutexGuard aGuard (m_aMutex);
194 :
195 : // save impossible cases
196 : // This method is only defined for valid values
197 : DBG_ASSERT ( (( nValue >= m_nMinRange ) && ( nValue <= m_nMaxRange )), "ProgressBar::setValue()\nNot valid value.\n" );
198 :
199 : // If new value not valid ... do nothing in release version!
200 0 : if (
201 0 : ( nValue >= m_nMinRange ) &&
202 0 : ( nValue <= m_nMaxRange )
203 : )
204 : {
205 : // New value is ok => save this
206 0 : m_nValue = nValue;
207 :
208 : // Repaint to display changes
209 0 : impl_paint ( 0, 0, impl_getGraphicsPeer() );
210 0 : }
211 0 : }
212 :
213 : // XProgressBar
214 :
215 0 : void SAL_CALL ProgressBar::setRange ( sal_Int32 nMin, sal_Int32 nMax ) throw( RuntimeException, std::exception )
216 : {
217 : // This method is defined for follow things:
218 : // 1) All values of sal_Int32
219 : // 2) Min < Max
220 : // 3) Min > Max
221 :
222 : // save impossible cases
223 : // This method is only defined for valid values
224 : // If you ignore this, the release version wil produce an error "division by zero" in "ProgressBar::setValue()"!
225 : DBG_ASSERT ( ( nMin != nMax ) , "ProgressBar::setRange()\nValues for MIN and MAX are the same. This is not allowed!\n" );
226 :
227 : // Ready for multithreading
228 0 : MutexGuard aGuard (m_aMutex);
229 :
230 : // control the values for min and max
231 0 : if ( nMin < nMax )
232 : {
233 : // Take correct Min and Max
234 0 : m_nMinRange = nMin;
235 0 : m_nMaxRange = nMax;
236 : }
237 : else
238 : {
239 : // Change Min and Max automatically
240 0 : m_nMinRange = nMax;
241 0 : m_nMaxRange = nMin;
242 : }
243 :
244 : // assure that m_nValue is within the range
245 0 : if (!(m_nMinRange < m_nValue && m_nValue < m_nMaxRange))
246 0 : m_nValue = m_nMinRange;
247 :
248 0 : impl_recalcRange ();
249 :
250 : // Do not repaint the control at this place!!!
251 : // An old "m_nValue" is set and can not be correct for this new range.
252 : // Next call of "ProgressBar::setValue()" do this.
253 0 : }
254 :
255 : // XProgressBar
256 :
257 0 : sal_Int32 SAL_CALL ProgressBar::getValue () throw( RuntimeException, std::exception )
258 : {
259 : // Ready for multithreading
260 0 : MutexGuard aGuard (m_aMutex);
261 :
262 0 : return ( m_nValue );
263 : }
264 :
265 : // XWindow
266 :
267 0 : void SAL_CALL ProgressBar::setPosSize (
268 : sal_Int32 nX,
269 : sal_Int32 nY,
270 : sal_Int32 nWidth,
271 : sal_Int32 nHeight,
272 : sal_Int16 nFlags
273 : ) throw( RuntimeException, std::exception )
274 : {
275 : // Take old size BEFORE you set the new values at baseclass!
276 : // You will control changes. At the other way, the values are the same!
277 0 : Rectangle aBasePosSize = getPosSize ();
278 0 : BaseControl::setPosSize (nX, nY, nWidth, nHeight, nFlags);
279 :
280 : // Do only, if size has changed.
281 0 : if (
282 0 : ( nWidth != aBasePosSize.Width ) ||
283 0 : ( nHeight != aBasePosSize.Height )
284 : )
285 : {
286 0 : impl_recalcRange ( );
287 0 : impl_paint ( 0, 0, impl_getGraphicsPeer () );
288 : }
289 0 : }
290 :
291 : // XControl
292 :
293 0 : sal_Bool SAL_CALL ProgressBar::setModel( const Reference< XControlModel >& /*xModel*/ ) throw( RuntimeException, std::exception )
294 : {
295 : // A model is not possible for this control.
296 0 : return false;
297 : }
298 :
299 : // XControl
300 :
301 0 : Reference< XControlModel > SAL_CALL ProgressBar::getModel() throw( RuntimeException, std::exception )
302 : {
303 : // A model is not possible for this control.
304 0 : return Reference< XControlModel >();
305 : }
306 :
307 : // impl but public method to register service
308 :
309 0 : const Sequence< OUString > ProgressBar::impl_getStaticSupportedServiceNames()
310 : {
311 0 : return css::uno::Sequence<OUString>();
312 : }
313 :
314 : // impl but public method to register service
315 :
316 0 : const OUString ProgressBar::impl_getStaticImplementationName()
317 : {
318 0 : return OUString("stardiv.UnoControls.ProgressBar");
319 : }
320 :
321 : // protected method
322 :
323 0 : void ProgressBar::impl_paint ( sal_Int32 nX, sal_Int32 nY, const Reference< XGraphics > & rGraphics )
324 : {
325 : // save impossible cases
326 : DBG_ASSERT ( rGraphics.is(), "ProgressBar::paint()\nCalled with invalid Reference< XGraphics > ." );
327 :
328 : // This paint method ist not buffered !!
329 : // Every request paint the completely control. ( but only, if peer exist )
330 0 : if ( rGraphics.is () )
331 : {
332 0 : MutexGuard aGuard (m_aMutex);
333 :
334 : // Clear background
335 : // (same color for line and fill)
336 0 : rGraphics->setFillColor ( m_nBackgroundColor );
337 0 : rGraphics->setLineColor ( m_nBackgroundColor );
338 0 : rGraphics->drawRect ( nX, nY, impl_getWidth(), impl_getHeight() );
339 :
340 : // same color for line and fill for blocks
341 0 : rGraphics->setFillColor ( m_nForegroundColor );
342 0 : rGraphics->setLineColor ( m_nForegroundColor );
343 :
344 0 : sal_Int32 nBlockStart = 0; // = left site of new block
345 0 : sal_Int32 nBlockCount = m_nBlockValue!=0.00 ? (sal_Int32)((m_nValue-m_nMinRange)/m_nBlockValue) : 0; // = number of next block
346 :
347 : // Draw horizontal progressbar
348 : // decision in "recalcRange()"
349 0 : if (m_bHorizontal)
350 : {
351 : // Step to left side of window
352 0 : nBlockStart = nX;
353 :
354 0 : for ( sal_Int16 i=1; i<=nBlockCount; ++i )
355 : {
356 : // step free field
357 0 : nBlockStart += PROGRESSBAR_FREESPACE;
358 : // paint block
359 0 : rGraphics->drawRect (nBlockStart, nY+PROGRESSBAR_FREESPACE, m_aBlockSize.Width, m_aBlockSize.Height);
360 : // step next free field
361 0 : nBlockStart += m_aBlockSize.Width;
362 : }
363 : }
364 : // draw vertikal progressbar
365 : // decision in "recalcRange()"
366 : else
367 : {
368 : // step to bottom side of window
369 0 : nBlockStart = nY+impl_getHeight();
370 0 : nBlockStart -= m_aBlockSize.Height;
371 :
372 0 : for ( sal_Int16 i=1; i<=nBlockCount; ++i )
373 : {
374 : // step free field
375 0 : nBlockStart -= PROGRESSBAR_FREESPACE;
376 : // paint block
377 0 : rGraphics->drawRect (nX+PROGRESSBAR_FREESPACE, nBlockStart, m_aBlockSize.Width, m_aBlockSize.Height);
378 : // step next free field
379 0 : nBlockStart -= m_aBlockSize.Height;
380 : }
381 : }
382 :
383 : // Paint shadow border around the progressbar
384 0 : rGraphics->setLineColor ( PROGRESSBAR_LINECOLOR_SHADOW );
385 0 : rGraphics->drawLine ( nX, nY, impl_getWidth(), nY );
386 0 : rGraphics->drawLine ( nX, nY, nX , impl_getHeight() );
387 :
388 0 : rGraphics->setLineColor ( PROGRESSBAR_LINECOLOR_BRIGHT );
389 0 : rGraphics->drawLine ( impl_getWidth()-1, impl_getHeight()-1, impl_getWidth()-1, nY );
390 0 : rGraphics->drawLine ( impl_getWidth()-1, impl_getHeight()-1, nX , impl_getHeight()-1 );
391 : }
392 0 : }
393 :
394 : // protected method
395 :
396 0 : void ProgressBar::impl_recalcRange ()
397 : {
398 0 : MutexGuard aGuard (m_aMutex);
399 :
400 0 : sal_Int32 nWindowWidth = impl_getWidth();
401 0 : sal_Int32 nWindowHeight = impl_getHeight();
402 : double fBlockHeight;
403 : double fBlockWidth;
404 : double fMaxBlocks;
405 :
406 0 : if( nWindowWidth > nWindowHeight )
407 : {
408 0 : m_bHorizontal = true;
409 0 : fBlockHeight = (nWindowHeight-(2*PROGRESSBAR_FREESPACE));
410 0 : fBlockWidth = fBlockHeight;
411 0 : fMaxBlocks = nWindowWidth/(fBlockWidth+PROGRESSBAR_FREESPACE);
412 : }
413 : else
414 : {
415 0 : m_bHorizontal = false;
416 0 : fBlockWidth = (nWindowWidth-(2*PROGRESSBAR_FREESPACE));
417 0 : fBlockHeight = fBlockWidth;
418 0 : fMaxBlocks = nWindowHeight/(fBlockHeight+PROGRESSBAR_FREESPACE);
419 : }
420 :
421 0 : double fRange = m_nMaxRange-m_nMinRange;
422 0 : double fBlockValue = fRange/fMaxBlocks;
423 :
424 0 : m_nBlockValue = fBlockValue;
425 0 : m_aBlockSize.Height = (sal_Int32)fBlockHeight;
426 0 : m_aBlockSize.Width = (sal_Int32)fBlockWidth;
427 0 : }
428 :
429 : } // namespace unocontrols
430 :
431 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|