1 /*
2  * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB.  All rights reserved.
3  *
4  * This file is part of the KD Chart library.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "KChartMeasure.h"
21 
22 #include <KChartAbstractArea.h>
23 #include <KChartCartesianCoordinatePlane.h>
24 #include <KChartTextAttributes.h>
25 #include <KChartFrameAttributes.h>
26 #include <KChartBackgroundAttributes.h>
27 #include "KChartMath_p.h"
28 
29 #include <QWidget>
30 
31 namespace KChart {
32 
33 
Measure()34 Measure::Measure()
35   : mValue( 0.0 ),
36     mMode( KChartEnums::MeasureCalculationModeAuto ),
37     mArea( nullptr ),
38     mOrientation( KChartEnums::MeasureOrientationAuto )
39 {
40     // this bloc left empty intentionally
41 }
42 
Measure(qreal value,KChartEnums::MeasureCalculationMode mode,KChartEnums::MeasureOrientation orientation)43 Measure::Measure( qreal value,
44     KChartEnums::MeasureCalculationMode mode,
45     KChartEnums::MeasureOrientation orientation )
46   : mValue( value ),
47     mMode( mode ),
48     mArea( nullptr ),
49     mOrientation( orientation )
50 {
51     // this bloc left empty intentionally
52 }
53 
Measure(const Measure & r)54 Measure::Measure( const Measure& r )
55   : mValue( r.value() ),
56     mMode( r.calculationMode() ),
57     mArea( r.referenceArea() ),
58     mOrientation( r.referenceOrientation() )
59 {
60     // this bloc left empty intentionally
61 }
62 
operator =(const Measure & r)63 Measure & Measure::operator=( const Measure& r )
64 {
65     if ( this != &r ) {
66         mValue = r.value();
67         mMode  = r.calculationMode();
68         mArea  = r.referenceArea();
69         mOrientation = r.referenceOrientation();
70     }
71 
72     return *this;
73 }
74 
75 
calculatedValue(const QSizeF & autoSize,KChartEnums::MeasureOrientation autoOrientation) const76 qreal Measure::calculatedValue( const QSizeF& autoSize,
77                                 KChartEnums::MeasureOrientation autoOrientation) const
78 {
79     if ( mMode == KChartEnums::MeasureCalculationModeAbsolute ) {
80         return mValue;
81     } else {
82         qreal value = 0.0;
83         const QObject theAutoArea;
84         const QObject* autoArea = &theAutoArea;
85         const QObject* area = mArea ? mArea : autoArea;
86         KChartEnums::MeasureOrientation orientation = mOrientation;
87         switch ( mMode ) {
88             case KChartEnums::MeasureCalculationModeAuto:
89                 area = autoArea;
90                 orientation = autoOrientation;
91                 break;
92             case KChartEnums::MeasureCalculationModeAutoArea:
93                 area = autoArea;
94                 break;
95             case KChartEnums::MeasureCalculationModeAutoOrientation:
96                 orientation = autoOrientation;
97                 break;
98             case KChartEnums::MeasureCalculationModeAbsolute: // fall through intended
99             case KChartEnums::MeasureCalculationModeRelative:
100                 break;
101         }
102         if ( area ) {
103             QSizeF size;
104             if ( area == autoArea )
105                 size = autoSize;
106             else
107                 size = sizeOfArea( area );
108             //qDebug() << ( area == autoArea ) << "size" << size;
109             qreal referenceValue = 0;
110             switch ( orientation ) {
111                 case KChartEnums::MeasureOrientationAuto: // fall through intended
112                 case KChartEnums::MeasureOrientationMinimum:
113                     referenceValue = qMin( size.width(), size.height() );
114                     break;
115                 case KChartEnums::MeasureOrientationMaximum:
116                     referenceValue = qMax( size.width(), size.height() );
117                     break;
118                 case KChartEnums::MeasureOrientationHorizontal:
119                     referenceValue = size.width();
120                     break;
121                 case KChartEnums::MeasureOrientationVertical:
122                     referenceValue = size.height();
123                     break;
124             }
125             value = mValue / 1000.0 * referenceValue;
126         }
127         return value;
128     }
129 }
130 
131 
calculatedValue(const QObject * autoArea,KChartEnums::MeasureOrientation autoOrientation) const132 qreal Measure::calculatedValue( const QObject* autoArea,
133                                 KChartEnums::MeasureOrientation autoOrientation) const
134 {
135     return calculatedValue( sizeOfArea( autoArea ), autoOrientation);
136 }
137 
138 
sizeOfArea(const QObject * area) const139 const QSizeF Measure::sizeOfArea( const QObject* area ) const
140 {
141     QSizeF size;
142     const CartesianCoordinatePlane* plane = dynamic_cast<const CartesianCoordinatePlane*>( area );
143     if ( false ) {
144         size = plane->visibleDiagramArea().size();
145     } else {
146         const AbstractArea* kdcArea = dynamic_cast<const AbstractArea*>(area);
147         if ( kdcArea ) {
148             size = kdcArea->geometry().size();
149             //qDebug() << "Measure::sizeOfArea() found kdcArea with size" << size;
150         } else {
151             const QWidget* widget = dynamic_cast<const QWidget*>(area);
152             if ( widget ) {
153                 /* ATTENTION: Using the layout does not work: The Legend will never get the right size then!
154                 const QLayout * layout = widget->layout();
155                 if ( layout ) {
156                     size = layout->geometry().size();
157                     //qDebug() << "Measure::sizeOfArea() found widget with layout size" << size;
158                 } else*/
159                 {
160                     size = widget->geometry().size();
161                     //qDebug() << "Measure::sizeOfArea() found widget with size" << size;
162                 }
163             } else if ( mMode != KChartEnums::MeasureCalculationModeAbsolute ) {
164                 size = QSizeF(1.0, 1.0);
165                 //qDebug("Measure::sizeOfArea() got no valid area.");
166             }
167         }
168     }
169     const QPair< qreal, qreal > factors
170             = GlobalMeasureScaling::instance()->currentFactors();
171     return QSizeF(size.width() * factors.first, size.height() * factors.second);
172 }
173 
174 
operator ==(const Measure & r) const175 bool Measure::operator==( const Measure& r ) const
176 {
177     return( mValue == r.value() &&
178             mMode  == r.calculationMode() &&
179             mArea  == r.referenceArea() &&
180             mOrientation == r.referenceOrientation() );
181 }
182 
GlobalMeasureScaling()183 GlobalMeasureScaling::GlobalMeasureScaling() :
184     m_paintDevice( nullptr )
185 {
186     mFactors.push( qMakePair(qreal(1.0), qreal(1.0)) );
187 }
188 
~GlobalMeasureScaling()189 GlobalMeasureScaling::~GlobalMeasureScaling()
190 {
191     // this space left empty intentionally
192 }
193 
instance()194 GlobalMeasureScaling* GlobalMeasureScaling::instance()
195 {
196     static GlobalMeasureScaling instance;
197     return &instance;
198 }
199 
setFactors(qreal factorX,qreal factorY)200 void GlobalMeasureScaling::setFactors(qreal factorX, qreal factorY)
201 {
202     instance()->mFactors.push( qMakePair(factorX, factorY) );
203 }
204 
resetFactors()205 void GlobalMeasureScaling::resetFactors()
206 {
207     // never remove the initial (1.0. 1.0) setting
208     if ( instance()->mFactors.count() > 1 )
209         instance()->mFactors.pop();
210 }
211 
currentFactors()212 const QPair< qreal, qreal > GlobalMeasureScaling::currentFactors()
213 {
214     return instance()->mFactors.top();
215 }
216 
setPaintDevice(QPaintDevice * paintDevice)217 void GlobalMeasureScaling::setPaintDevice( QPaintDevice* paintDevice )
218 {
219     instance()->m_paintDevice = paintDevice;
220 }
221 
paintDevice()222 QPaintDevice* GlobalMeasureScaling::paintDevice()
223 {
224     return instance()->m_paintDevice;
225 }
226 
227 }
228 
229 #if !defined(QT_NO_DEBUG_STREAM)
operator <<(QDebug dbg,const KChart::Measure & m)230 QDebug operator<<(QDebug dbg, const KChart::Measure& m)
231 {
232     dbg << "KChart::Measure("
233         << "value="<<m.value()
234         << "calculationmode="<<m.calculationMode()
235         << "referencearea="<<m.referenceArea()
236         << "referenceorientation="<<m.referenceOrientation()
237         << ")";
238     return dbg;
239 }
240 #endif /* QT_NO_DEBUG_STREAM */
241