File indexing completed on 2024-05-12 04:20:28

0001 /*
0002  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
0003  *
0004  * This file is part of the KD Chart library.
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "KChartAbstractAxis.h"
0010 #include "KChartAbstractAxis_p.h"
0011 #include "KChartAbstractDiagram.h"
0012 #include "KChartAbstractCartesianDiagram.h"
0013 #include "KChartEnums.h"
0014 #include "KChartMeasure.h"
0015 #include "KChartMath_p.h"
0016 
0017 using namespace KChart;
0018 
0019 #define d d_func()
0020 
0021 AbstractAxis::Private::Private( AbstractDiagram* diagram, AbstractAxis* axis )
0022     : observer( nullptr )
0023     , mDiagram( diagram )
0024     , mAxis( axis )
0025 {
0026     // Note: We do NOT call setDiagram( diagram, axis );
0027     //       but it is called in AbstractAxis::delayedInit() instead!
0028 }
0029 
0030 AbstractAxis::Private::~Private()
0031 {
0032     delete observer;
0033     observer = nullptr;
0034 }
0035 
0036 bool AbstractAxis::Private::setDiagram( AbstractDiagram* diagram_, bool delayedInit )
0037 {
0038     AbstractDiagram* diagram = delayedInit ? mDiagram : diagram_;
0039     if ( delayedInit ) {
0040         mDiagram = nullptr;
0041     }
0042 
0043     // do not set a diagram again that was already set
0044     if ( diagram &&
0045         ((diagram == mDiagram) || secondaryDiagrams.contains( diagram )) )
0046         return false;
0047 
0048     bool bNewDiagramStored = false;
0049     if ( ! mDiagram ) {
0050         mDiagram = diagram;
0051         delete observer;
0052         if ( mDiagram ) {
0053             observer = new DiagramObserver( mDiagram, mAxis );
0054             const bool con = connect( observer, &DiagramObserver::diagramDataChanged,
0055                     mAxis, &AbstractAxis::coordinateSystemChanged );
0056             Q_UNUSED( con )
0057             Q_ASSERT( con );
0058             bNewDiagramStored = true;
0059         } else {
0060             observer = nullptr;
0061         }
0062     } else {
0063         if ( diagram )
0064             secondaryDiagrams.enqueue( diagram );
0065     }
0066     return bNewDiagramStored;
0067 }
0068 
0069 void AbstractAxis::Private::unsetDiagram( AbstractDiagram* diagram )
0070 {
0071     if ( diagram == mDiagram ) {
0072         mDiagram = nullptr;
0073         delete observer;
0074         observer = nullptr;
0075     } else {
0076         secondaryDiagrams.removeAll( diagram );
0077     }
0078     if ( !secondaryDiagrams.isEmpty() ) {
0079         AbstractDiagram *nextDiagram = secondaryDiagrams.dequeue();
0080         setDiagram( nextDiagram );
0081     }
0082 }
0083 
0084 bool AbstractAxis::Private::hasDiagram( AbstractDiagram* diagram ) const
0085 {
0086     return diagram == mDiagram || secondaryDiagrams.contains( diagram );
0087 }
0088 
0089 void AbstractAxis::Private::updateLayouts()
0090 {
0091     if ( CartesianAxis* cartesianAxis = qobject_cast< CartesianAxis* >( mAxis ) ) {
0092         cartesianAxis->layoutPlanes();
0093     } else {
0094         mAxis->update();
0095     }
0096 }
0097 
0098 AbstractAxis::AbstractAxis ( AbstractDiagram* diagram )
0099     : AbstractArea( new Private( diagram, this ) )
0100 {
0101     init();
0102     QTimer::singleShot(0, this, SLOT(delayedInit()));
0103 }
0104 
0105 AbstractAxis::~AbstractAxis()
0106 {
0107     d->mDiagram = nullptr;
0108     d->secondaryDiagrams.clear();
0109 }
0110 
0111 
0112 void AbstractAxis::init()
0113 {
0114     Measure m( 14, KChartEnums::MeasureCalculationModeAuto, KChartEnums::MeasureOrientationAuto );
0115     d->textAttributes.setFontSize( m );
0116     m.setValue( 6 );
0117     m.setCalculationMode( KChartEnums::MeasureCalculationModeAbsolute );
0118     d->textAttributes.setMinimalFontSize( m );
0119     if ( d->diagram() )
0120         createObserver( d->diagram() );
0121 }
0122 
0123 void AbstractAxis::delayedInit()
0124 {
0125     // We call setDiagram() here, because the c'tor of Private
0126     // only has stored the pointers, but it did not call setDiagram().
0127     if ( d )
0128         d->setDiagram( nullptr, true /* delayedInit */ );
0129 }
0130 
0131 bool AbstractAxis::compare( const AbstractAxis* other ) const
0132 {
0133     if ( other == this ) {
0134         return true;
0135     }
0136     if ( !other ) {
0137         return false;
0138     }
0139 
0140     return  ( static_cast<const AbstractAreaBase*>(this)->compare( other ) ) &&
0141             (textAttributes() == other->textAttributes()) &&
0142             (labels()         == other->labels()) &&
0143             (shortLabels()    == other->shortLabels());
0144 }
0145 
0146 
0147 const QString AbstractAxis::customizedLabel( const QString& label ) const
0148 {
0149     return label;
0150 }
0151 
0152 
0153 void AbstractAxis::createObserver( AbstractDiagram* diagram )
0154 {
0155     d->setDiagram( diagram );
0156 }
0157 
0158 void AbstractAxis::deleteObserver( AbstractDiagram* diagram )
0159 {
0160     d->unsetDiagram( diagram );
0161 }
0162 
0163 void AbstractAxis::connectSignals()
0164 {
0165     if ( d->observer ) {
0166         const bool con = connect( d->observer, &DiagramObserver::diagramDataChanged,
0167                 this, &AbstractAxis::coordinateSystemChanged );
0168         Q_UNUSED( con );
0169         Q_ASSERT( con );
0170     }
0171 }
0172 
0173 void AbstractAxis::setTextAttributes( const TextAttributes &a )
0174 {
0175     if ( d->textAttributes == a )
0176         return;
0177 
0178     d->textAttributes = a;
0179     d->updateLayouts();
0180 }
0181 
0182 TextAttributes AbstractAxis::textAttributes() const
0183 {
0184     return d->textAttributes;
0185 }
0186 
0187 
0188 void AbstractAxis::setRulerAttributes( const RulerAttributes &a )
0189 {
0190     d->rulerAttributes = a;
0191     d->updateLayouts();
0192 }
0193 
0194 RulerAttributes AbstractAxis::rulerAttributes() const
0195 {
0196     return d->rulerAttributes;
0197 }
0198 
0199 void AbstractAxis::setLabels( const QStringList& list )
0200 {
0201     if ( d->hardLabels == list )
0202         return;
0203 
0204     d->hardLabels = list;
0205     d->updateLayouts();
0206 }
0207 
0208 QStringList AbstractAxis::labels() const
0209 {
0210     return d->hardLabels;
0211 }
0212 
0213 void AbstractAxis::setShortLabels( const QStringList& list )
0214 {
0215     if ( d->hardShortLabels == list )
0216         return;
0217 
0218     d->hardShortLabels = list;
0219     d->updateLayouts();
0220 }
0221 
0222 QStringList AbstractAxis::shortLabels() const
0223 {
0224     return d->hardShortLabels;
0225 }
0226 
0227 const AbstractCoordinatePlane* AbstractAxis::coordinatePlane() const
0228 {
0229     if ( d->diagram() )
0230         return d->diagram()->coordinatePlane();
0231     return nullptr;
0232 }
0233 
0234 const AbstractDiagram * KChart::AbstractAxis::diagram() const
0235 {
0236     return d->diagram();
0237 }
0238 
0239 bool KChart::AbstractAxis::observedBy( AbstractDiagram * diagram ) const
0240 {
0241     return d->hasDiagram( diagram );
0242 }
0243 
0244 void KChart::AbstractAxis::update()
0245 {
0246     if ( d->diagram() )
0247         d->diagram()->update();
0248 }