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