File indexing completed on 2024-05-12 15:54:18

0001 /*
0002  * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB.  All rights reserved.
0003  *
0004  * This file is part of the KD Chart library.
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU General Public License as
0008  * published by the Free Software Foundation; either version 2 of
0009  * the License, or (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License
0017  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
0018  */
0019 
0020 #include "KChartMeasure.h"
0021 
0022 #include <KChartAbstractArea.h>
0023 #include <KChartCartesianCoordinatePlane.h>
0024 #include <KChartTextAttributes.h>
0025 #include <KChartFrameAttributes.h>
0026 #include <KChartBackgroundAttributes.h>
0027 #include "KChartMath_p.h"
0028 
0029 #include <QWidget>
0030 
0031 namespace KChart {
0032 
0033 
0034 Measure::Measure()
0035   : mValue( 0.0 ),
0036     mMode( KChartEnums::MeasureCalculationModeAuto ),
0037     mArea( nullptr ),
0038     mOrientation( KChartEnums::MeasureOrientationAuto )
0039 {
0040     // this bloc left empty intentionally
0041 }
0042 
0043 Measure::Measure( qreal value,
0044     KChartEnums::MeasureCalculationMode mode,
0045     KChartEnums::MeasureOrientation orientation )
0046   : mValue( value ),
0047     mMode( mode ),
0048     mArea( nullptr ),
0049     mOrientation( orientation )
0050 {
0051     // this bloc left empty intentionally
0052 }
0053 
0054 Measure::Measure( const Measure& r )
0055   : mValue( r.value() ),
0056     mMode( r.calculationMode() ),
0057     mArea( r.referenceArea() ),
0058     mOrientation( r.referenceOrientation() )
0059 {
0060     // this bloc left empty intentionally
0061 }
0062 
0063 Measure & Measure::operator=( const Measure& r )
0064 {
0065     if ( this != &r ) {
0066         mValue = r.value();
0067         mMode  = r.calculationMode();
0068         mArea  = r.referenceArea();
0069         mOrientation = r.referenceOrientation();
0070     }
0071 
0072     return *this;
0073 }
0074 
0075 
0076 qreal Measure::calculatedValue( const QSizeF& autoSize,
0077                                 KChartEnums::MeasureOrientation autoOrientation) const
0078 {
0079     if ( mMode == KChartEnums::MeasureCalculationModeAbsolute ) {
0080         return mValue;
0081     } else {
0082         qreal value = 0.0;
0083         const QObject theAutoArea;
0084         const QObject* autoArea = &theAutoArea;
0085         const QObject* area = mArea ? mArea : autoArea;
0086         KChartEnums::MeasureOrientation orientation = mOrientation;
0087         switch ( mMode ) {
0088             case KChartEnums::MeasureCalculationModeAuto:
0089                 area = autoArea;
0090                 orientation = autoOrientation;
0091                 break;
0092             case KChartEnums::MeasureCalculationModeAutoArea:
0093                 area = autoArea;
0094                 break;
0095             case KChartEnums::MeasureCalculationModeAutoOrientation:
0096                 orientation = autoOrientation;
0097                 break;
0098             case KChartEnums::MeasureCalculationModeAbsolute: // fall through intended
0099             case KChartEnums::MeasureCalculationModeRelative:
0100                 break;
0101         }
0102         if ( area ) {
0103             QSizeF size;
0104             if ( area == autoArea )
0105                 size = autoSize;
0106             else
0107                 size = sizeOfArea( area );
0108             //qDebug() << ( area == autoArea ) << "size" << size;
0109             qreal referenceValue = 0;
0110             switch ( orientation ) {
0111                 case KChartEnums::MeasureOrientationAuto: // fall through intended
0112                 case KChartEnums::MeasureOrientationMinimum:
0113                     referenceValue = qMin( size.width(), size.height() );
0114                     break;
0115                 case KChartEnums::MeasureOrientationMaximum:
0116                     referenceValue = qMax( size.width(), size.height() );
0117                     break;
0118                 case KChartEnums::MeasureOrientationHorizontal:
0119                     referenceValue = size.width();
0120                     break;
0121                 case KChartEnums::MeasureOrientationVertical:
0122                     referenceValue = size.height();
0123                     break;
0124             }
0125             value = mValue / 1000.0 * referenceValue;
0126         }
0127         return value;
0128     }
0129 }
0130 
0131 
0132 qreal Measure::calculatedValue( const QObject* autoArea,
0133                                 KChartEnums::MeasureOrientation autoOrientation) const
0134 {
0135     return calculatedValue( sizeOfArea( autoArea ), autoOrientation);
0136 }
0137 
0138 
0139 const QSizeF Measure::sizeOfArea( const QObject* area ) const
0140 {
0141     QSizeF size;
0142     const CartesianCoordinatePlane* plane = dynamic_cast<const CartesianCoordinatePlane*>( area );
0143     if ( false ) {
0144         size = plane->visibleDiagramArea().size();
0145     } else {
0146         const AbstractArea* kdcArea = dynamic_cast<const AbstractArea*>(area);
0147         if ( kdcArea ) {
0148             size = kdcArea->geometry().size();
0149             //qDebug() << "Measure::sizeOfArea() found kdcArea with size" << size;
0150         } else {
0151             const QWidget* widget = dynamic_cast<const QWidget*>(area);
0152             if ( widget ) {
0153                 /* ATTENTION: Using the layout does not work: The Legend will never get the right size then!
0154                 const QLayout * layout = widget->layout();
0155                 if ( layout ) {
0156                     size = layout->geometry().size();
0157                     //qDebug() << "Measure::sizeOfArea() found widget with layout size" << size;
0158                 } else*/
0159                 {
0160                     size = widget->geometry().size();
0161                     //qDebug() << "Measure::sizeOfArea() found widget with size" << size;
0162                 }
0163             } else if ( mMode != KChartEnums::MeasureCalculationModeAbsolute ) {
0164                 size = QSizeF(1.0, 1.0);
0165                 //qDebug("Measure::sizeOfArea() got no valid area.");
0166             }
0167         }
0168     }
0169     const QPair< qreal, qreal > factors
0170             = GlobalMeasureScaling::instance()->currentFactors();
0171     return QSizeF(size.width() * factors.first, size.height() * factors.second);
0172 }
0173 
0174 
0175 bool Measure::operator==( const Measure& r ) const
0176 {
0177     return( mValue == r.value() &&
0178             mMode  == r.calculationMode() &&
0179             mArea  == r.referenceArea() &&
0180             mOrientation == r.referenceOrientation() );
0181 }
0182 
0183 GlobalMeasureScaling::GlobalMeasureScaling() :
0184     m_paintDevice( nullptr )
0185 {
0186     mFactors.push( qMakePair(qreal(1.0), qreal(1.0)) );
0187 }
0188 
0189 GlobalMeasureScaling::~GlobalMeasureScaling()
0190 {
0191     // this space left empty intentionally
0192 }
0193 
0194 GlobalMeasureScaling* GlobalMeasureScaling::instance()
0195 {
0196     static GlobalMeasureScaling instance;
0197     return &instance;
0198 }
0199 
0200 void GlobalMeasureScaling::setFactors(qreal factorX, qreal factorY)
0201 {
0202     instance()->mFactors.push( qMakePair(factorX, factorY) );
0203 }
0204 
0205 void GlobalMeasureScaling::resetFactors()
0206 {
0207     // never remove the initial (1.0. 1.0) setting
0208     if ( instance()->mFactors.count() > 1 )
0209         instance()->mFactors.pop();
0210 }
0211 
0212 const QPair< qreal, qreal > GlobalMeasureScaling::currentFactors()
0213 {
0214     return instance()->mFactors.top();
0215 }
0216 
0217 void GlobalMeasureScaling::setPaintDevice( QPaintDevice* paintDevice )
0218 {
0219     instance()->m_paintDevice = paintDevice;
0220 }
0221 
0222 QPaintDevice* GlobalMeasureScaling::paintDevice()
0223 {
0224     return instance()->m_paintDevice;
0225 }
0226 
0227 }
0228 
0229 #if !defined(QT_NO_DEBUG_STREAM)
0230 QDebug operator<<(QDebug dbg, const KChart::Measure& m)
0231 {
0232     dbg << "KChart::Measure("
0233         << "value="<<m.value()
0234         << "calculationmode="<<m.calculationMode()
0235         << "referencearea="<<m.referenceArea()
0236         << "referenceorientation="<<m.referenceOrientation()
0237         << ")";
0238     return dbg;
0239 }
0240 #endif /* QT_NO_DEBUG_STREAM */