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