/**************************************************************************** ** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved. ** ** This file is part of the KD Chart library. ** ** Licensees holding valid commercial KD Chart licenses may use this file in ** accordance with the KD Chart Commercial License Agreement provided with ** the Software. ** ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 and version 3 as published by the ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** Contact info@kdab.com if any conditions of this licensing are not ** clear to you. ** **********************************************************************/ #include "KDChartTernaryAxis.h" #include #include #include #include "TernaryConstants.h" #include "KDChartTernaryCoordinatePlane.h" #include "KDChartAbstractTernaryDiagram.h" #include "../src/KDChartLayoutItems.h" #include "PrerenderedElements/KDChartTextLabelCache.h" using namespace KDChart; // m_label and m_fifty do not have to be pointers, once the class is // pimpled (PrerenderedLabel is not published API) TernaryAxis::TernaryAxis ( AbstractTernaryDiagram* diagram) : AbstractAxis( diagram ) , m_position( KDChartEnums::PositionUnknown ) , m_label( new PrerenderedLabel ) , m_fifty( new PrerenderedLabel ) { resetTitleTextAttributes(); setPosition( KDChartEnums::PositionSouth ); // arbitrary m_fifty->setText( QObject::tr( "50%" ) ); // const // FIXME is this consistent with other diagram/axis/plane implementations? diagram->addAxis( this ); } TernaryAxis::~TernaryAxis() { delete m_label; m_label = 0; delete m_label; m_fifty = 0; } void TernaryAxis::paintAll (QPainter &) { // not used } void TernaryAxis::paint (QPainter *) { // not used } void TernaryAxis::paintCtx (PaintContext * paintContext) { QPainter* p = paintContext->painter(); TernaryCoordinatePlane* plane = (TernaryCoordinatePlane*) paintContext->coordinatePlane(); // QObject* refArea = plane->parent(); QRectF drawArea = paintContext->rectangle(); QRectF titleArea; // paint the axis label (across the triangle, that one): QList labels; labels << m_label << m_fifty; Q_FOREACH( PrerenderedLabel* label, labels ) { const QPixmap& pixmap = label->pixmap(); QPointF point = plane->translate( label->position() ) - label->referencePointLocation(); p->drawPixmap( point, pixmap ); } } bool TernaryAxis::isEmpty() const { // todo: what's this method for? return false; } QRect TernaryAxis::geometry () const { return m_geometry; } void TernaryAxis::setGeometry (const QRect &rect) { m_geometry = rect; } QSize TernaryAxis::minimumSize () const { // todo: return realistic sizes return QSize( 100, 100 ); } QSize TernaryAxis::maximumSize () const { return QSize( 300, 200 ); } QSize TernaryAxis::sizeHint () const { return QSize( 150, 100 ); } Qt::Orientations TernaryAxis::expandingDirections () const { return Qt::Vertical | Qt::Horizontal; } const Position TernaryAxis::position () const { return m_position; } void TernaryAxis::setPosition (Position p) { if ( p == position() ) return; if ( p != KDChartEnums::PositionWest && p != KDChartEnums::PositionEast && p != KDChartEnums::PositionSouth ) { qDebug() << "TernaryAxis::setPosition: only south, east and west are supported " "positions for ternary axes."; return; } if ( m_title.isEmpty() ) switch( p.value() ) { case KDChartEnums::PositionSouth: m_label->setText( tr( "A" ) ); break; case KDChartEnums::PositionWest: m_label->setText( tr( "C" ) ); break; case KDChartEnums::PositionEast: m_label->setText( tr( "B" ) ); break; default: break; } m_position = p; updatePrerenderedLabels(); // position has changed } void TernaryAxis::setTitleText( const QString& text ) { m_title = text; // do not remove m_label->setText( text ); } QString TernaryAxis::titleText() const { return m_label->text(); } void TernaryAxis::setTitleTextAttributes( const TextAttributes &a ) { m_titleAttributes = a; updatePrerenderedLabels(); } TextAttributes TernaryAxis::titleTextAttributes() const { return m_titleAttributes; } void TernaryAxis::resetTitleTextAttributes() { TextAttributes a; m_titleAttributes = a; updatePrerenderedLabels(); } bool TernaryAxis::hasDefaultTitleTextAttributes() const { TextAttributes a; return m_titleAttributes == a; } void TernaryAxis::updatePrerenderedLabels() { TextAttributes attributes = titleTextAttributes(); double axisLabelAngle = 0.0; double fiftyMarkAngle = 0.0; QPointF axisLabelPosition; QPointF fiftyMarkPosition; KDChartEnums::PositionValue fiftyMarkReferencePoint = KDChartEnums::PositionUnknown; switch( position().value() ) { case KDChartEnums::PositionSouth: // this is the axis on the other side of A axisLabelAngle = 0.0; fiftyMarkAngle = 0.0; axisLabelPosition = TriangleTop; fiftyMarkPosition = 0.5 * AxisVector_B_C - RelMarkerLength * Norm_B_C; fiftyMarkReferencePoint = KDChartEnums::PositionNorth; break; case KDChartEnums::PositionEast: // this is the axis on the other side of B axisLabelAngle = 240.0; fiftyMarkAngle = 60; axisLabelPosition = TriangleBottomLeft; fiftyMarkPosition = AxisVector_B_C + 0.5 * AxisVector_C_A - RelMarkerLength * Norm_C_A; fiftyMarkReferencePoint = KDChartEnums::PositionSouth; break; case KDChartEnums::PositionWest: // this is the axis on the other side of C axisLabelAngle = 120.0; fiftyMarkAngle = 300.0; axisLabelPosition = TriangleBottomRight; fiftyMarkPosition = 0.5 * AxisVector_B_A + RelMarkerLength * Norm_B_A; fiftyMarkReferencePoint = KDChartEnums::PositionSouth; break; case KDChartEnums::PositionUnknown: break; // initial value default: qDebug() << "TernaryAxis::updatePrerenderedLabel: unknown location"; }; m_label->setFont( attributes.font() ); // m_label->setText( titleText() ); // done by setTitleText() m_label->setAngle( axisLabelAngle ); m_label->setPosition( axisLabelPosition ); m_label->setReferencePoint( KDChartEnums::PositionSouth ); QFont font = attributes.font(); font.setPointSizeF( 0.85 * font.pointSizeF() ); m_fifty->setFont( font ); m_fifty->setAngle( fiftyMarkAngle ); m_fifty->setPosition( fiftyMarkPosition ); m_fifty->setReferencePoint( fiftyMarkReferencePoint ); } QPair TernaryAxis::requiredMargins() const { QSizeF topleft( 0.0, 0.0 ); QSizeF bottomRight( 0.0, 0.0 ); switch( position().value() ) { case KDChartEnums::PositionSouth: // the label of the south axis is, in fact, up north. topleft.setHeight( m_label->pixmap().height() ); bottomRight.setHeight( m_fifty->pixmap().height() ); break; case KDChartEnums::PositionWest: bottomRight.setWidth( m_label->pixmap().width() - m_label->referencePointLocation().x() ); bottomRight.setHeight( m_label->pixmap().height() - m_label->referencePointLocation().y() ); break; case KDChartEnums::PositionEast: topleft.setWidth( m_label->pixmap().width() - ( m_label->pixmap().width() - m_label->referencePointLocation().x() ) ); bottomRight.setHeight( m_label->pixmap().height() - ( m_label->pixmap().height() - m_label->referencePointLocation().y() ) ); break; default: qDebug() << "TernaryAxis::requiredMargins: unknown location"; } // qDebug() << "TernaryAxis::requiredMargins:" << topleft << bottomRight; return QPair( topleft, bottomRight ); }