File indexing completed on 2024-12-15 04:02:36
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 "KChartTernaryAxis.h" 0010 0011 #include <QPainter> 0012 0013 #include <KChartChart.h> 0014 #include <KChartPaintContext.h> 0015 0016 #include "TernaryConstants.h" 0017 #include "KChartTernaryCoordinatePlane.h" 0018 #include "KChartAbstractTernaryDiagram.h" 0019 0020 0021 #include "KChartLayoutItems.h" 0022 #include "KChartTextLabelCache.h" 0023 0024 using namespace KChart; 0025 0026 // m_label and m_fifty do not have to be pointers, once the class is 0027 // pimpled (PrerenderedLabel is not published API) 0028 0029 TernaryAxis::TernaryAxis ( AbstractTernaryDiagram* diagram) 0030 : AbstractAxis( diagram ) 0031 , m_position( KChartEnums::PositionUnknown ) 0032 , m_label( new PrerenderedLabel ) 0033 , m_fifty( new PrerenderedLabel ) 0034 { 0035 resetTitleTextAttributes(); 0036 setPosition( KChartEnums::PositionSouth ); // arbitrary 0037 m_fifty->setText( QObject::tr( "50%" ) ); // const 0038 // FIXME is this consistent with other diagram/axis/plane implementations? 0039 diagram->addAxis( this ); 0040 } 0041 0042 TernaryAxis::~TernaryAxis() 0043 { 0044 delete m_label; m_label = nullptr; 0045 delete m_fifty; m_fifty = nullptr; 0046 } 0047 0048 void TernaryAxis::paintAll (QPainter &) 0049 { 0050 // not used 0051 } 0052 0053 void TernaryAxis::paint (QPainter *) 0054 { 0055 // not used 0056 } 0057 0058 void TernaryAxis::paintCtx (PaintContext * paintContext) 0059 { 0060 QPainter* p = paintContext->painter(); 0061 TernaryCoordinatePlane* plane = 0062 (TernaryCoordinatePlane*) paintContext->coordinatePlane(); 0063 // QObject* refArea = plane->parent(); 0064 0065 // paint the axis label (across the triangle, that one): 0066 QList<PrerenderedLabel*> labels; 0067 labels << m_label << m_fifty; 0068 for ( PrerenderedLabel* label : qAsConst(labels) ) { 0069 const QPixmap& pixmap = label->pixmap(); 0070 const QPointF point = plane->translate( label->position() ) 0071 - label->referencePointLocation(); 0072 p->drawPixmap( point, pixmap ); 0073 } 0074 } 0075 0076 bool TernaryAxis::isEmpty() const 0077 { 0078 // todo: what's this method for? 0079 return false; 0080 } 0081 0082 QRect TernaryAxis::geometry () const 0083 { 0084 return m_geometry; 0085 } 0086 0087 void TernaryAxis::setGeometry (const QRect &rect) 0088 { 0089 m_geometry = rect; 0090 } 0091 0092 QSize TernaryAxis::minimumSize () const 0093 { 0094 // todo: return realistic sizes 0095 return QSize( 100, 100 ); 0096 } 0097 0098 QSize TernaryAxis::maximumSize () const 0099 { 0100 return QSize( 300, 200 ); 0101 } 0102 0103 QSize TernaryAxis::sizeHint () const 0104 { 0105 return QSize( 150, 100 ); 0106 } 0107 0108 Qt::Orientations TernaryAxis::expandingDirections () const 0109 { 0110 return Qt::Vertical | Qt::Horizontal; 0111 } 0112 0113 const Position TernaryAxis::position () const 0114 { 0115 return m_position; 0116 } 0117 0118 void TernaryAxis::setPosition (Position p) 0119 { 0120 if ( p == position() ) return; 0121 0122 if ( p != KChartEnums::PositionWest 0123 && p != KChartEnums::PositionEast 0124 && p != KChartEnums::PositionSouth ) 0125 { 0126 qDebug() << "TernaryAxis::setPosition: only south, east and west are supported " 0127 "positions for ternary axes."; 0128 return; 0129 } 0130 0131 if ( m_title.isEmpty() ) 0132 switch ( p.value() ) { 0133 case KChartEnums::PositionSouth: 0134 m_label->setText( tr( "A" ) ); 0135 break; 0136 case KChartEnums::PositionWest: 0137 m_label->setText( tr( "C" ) ); 0138 break; 0139 case KChartEnums::PositionEast: 0140 m_label->setText( tr( "B" ) ); 0141 break; 0142 default: 0143 break; 0144 } 0145 0146 m_position = p; 0147 updatePrerenderedLabels(); // position has changed 0148 } 0149 0150 void TernaryAxis::setTitleText( const QString& text ) 0151 { 0152 m_title = text; // do not remove 0153 m_label->setText( text ); 0154 } 0155 0156 QString TernaryAxis::titleText() const 0157 { 0158 return m_label->text(); 0159 } 0160 0161 void TernaryAxis::setTitleTextAttributes( const TextAttributes &a ) 0162 { 0163 m_titleAttributes = a; 0164 updatePrerenderedLabels(); 0165 } 0166 0167 TextAttributes TernaryAxis::titleTextAttributes() const 0168 { 0169 return m_titleAttributes; 0170 } 0171 0172 void TernaryAxis::resetTitleTextAttributes() 0173 { 0174 TextAttributes a; 0175 m_titleAttributes = a; 0176 updatePrerenderedLabels(); 0177 } 0178 0179 bool TernaryAxis::hasDefaultTitleTextAttributes() const 0180 { 0181 TextAttributes a; 0182 return m_titleAttributes == a; 0183 } 0184 0185 void TernaryAxis::updatePrerenderedLabels() 0186 { 0187 TextAttributes attributes = titleTextAttributes(); 0188 qreal axisLabelAngle = 0.0; 0189 qreal fiftyMarkAngle = 0.0; 0190 QPointF axisLabelPosition; 0191 QPointF fiftyMarkPosition; 0192 KChartEnums::PositionValue fiftyMarkReferencePoint = KChartEnums::PositionUnknown; 0193 0194 switch ( position().value() ) { 0195 case KChartEnums::PositionSouth: 0196 // this is the axis on the other side of A 0197 axisLabelAngle = 0.0; 0198 fiftyMarkAngle = 0.0; 0199 axisLabelPosition = TriangleTop; 0200 fiftyMarkPosition = 0.5 * AxisVector_B_C - RelMarkerLength * Norm_B_C; 0201 fiftyMarkReferencePoint = KChartEnums::PositionNorth; 0202 break; 0203 case KChartEnums::PositionEast: 0204 // this is the axis on the other side of B 0205 axisLabelAngle = 240.0; 0206 fiftyMarkAngle = 60; 0207 axisLabelPosition = TriangleBottomLeft; 0208 fiftyMarkPosition = AxisVector_B_C + 0.5 * AxisVector_C_A - RelMarkerLength * Norm_C_A; 0209 fiftyMarkReferencePoint = KChartEnums::PositionSouth; 0210 break; 0211 case KChartEnums::PositionWest: 0212 // this is the axis on the other side of C 0213 axisLabelAngle = 120.0; 0214 fiftyMarkAngle = 300.0; 0215 axisLabelPosition = TriangleBottomRight; 0216 fiftyMarkPosition = 0.5 * AxisVector_B_A + RelMarkerLength * Norm_B_A; 0217 fiftyMarkReferencePoint = KChartEnums::PositionSouth; 0218 break; 0219 case KChartEnums::PositionUnknown: 0220 break; // initial value 0221 default: 0222 qDebug() << "TernaryAxis::updatePrerenderedLabel: unknown location"; 0223 }; 0224 0225 m_label->setFont( attributes.font() ); 0226 // m_label->setText( titleText() ); // done by setTitleText() 0227 m_label->setAngle( axisLabelAngle ); 0228 m_label->setPosition( axisLabelPosition ); 0229 m_label->setReferencePoint( KChartEnums::PositionSouth ); 0230 QFont font = attributes.font(); 0231 font.setPointSizeF( 0.85 * font.pointSizeF() ); 0232 m_fifty->setFont( font ); 0233 m_fifty->setAngle( fiftyMarkAngle ); 0234 m_fifty->setPosition( fiftyMarkPosition ); 0235 m_fifty->setReferencePoint( fiftyMarkReferencePoint ); 0236 } 0237 0238 QPair<QSizeF, QSizeF> TernaryAxis::requiredMargins() const 0239 { 0240 QSizeF topleft( 0.0, 0.0 ); 0241 QSizeF bottomRight( 0.0, 0.0 ); 0242 0243 switch ( position().value() ) { 0244 case KChartEnums::PositionSouth: 0245 // the label of the south axis is, in fact, up north. 0246 topleft.setHeight( m_label->pixmap().height() ); 0247 bottomRight.setHeight( m_fifty->pixmap().height() ); 0248 break; 0249 case KChartEnums::PositionWest: 0250 bottomRight.setWidth( m_label->pixmap().width() 0251 - m_label->referencePointLocation().x() ); 0252 bottomRight.setHeight( m_label->pixmap().height() 0253 - m_label->referencePointLocation().y() ); 0254 break; 0255 case KChartEnums::PositionEast: 0256 topleft.setWidth( m_label->pixmap().width() 0257 - ( m_label->pixmap().width() 0258 - m_label->referencePointLocation().x() ) ); 0259 bottomRight.setHeight( m_label->pixmap().height() 0260 - ( m_label->pixmap().height() 0261 - m_label->referencePointLocation().y() ) ); 0262 break; 0263 default: 0264 qDebug() << "TernaryAxis::requiredMargins: unknown location"; 0265 } 0266 // qDebug() << "TernaryAxis::requiredMargins:" << topleft << bottomRight; 0267 return QPair<QSizeF, QSizeF>( topleft, bottomRight ); 0268 }