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

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