# KDChartTernaryAxis.cpp

Go to the documentation of this file.

    00001 /* -*- Mode: C++ -*-
    00002    KDChart - a multi-platform charting engine
    00003    */
    00004
    00005 /****************************************************************************
    00006  ** Copyright (C) 2005-2007 Klarälvdalens Datakonsult AB.  All rights reserved.
    00007  **
    00008  ** This file is part of the KD Chart library.
    00009  **
    00010  ** This file may be distributed and/or modified under the terms of the
    00011  ** GNU General Public License version 2 as published by the Free Software
    00012  ** Foundation and appearing in the file LICENSE.GPL included in the
    00013  ** packaging of this file.
    00014  **
    00015  ** Licensees holding valid commercial KD Chart licenses may use this file in
    00016  ** accordance with the KD Chart Commercial License Agreement provided with
    00017  ** the Software.
    00018  **
    00019  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
    00020  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
    00021  **
    00022  ** See http://www.kdab.net/kdchart for
    00023  **   information about KD Chart Commercial License Agreements.
    00024  **
    00025  ** Contact info@kdab.net if any conditions of this
    00026  ** licensing are not clear to you.
    00027  **
    00028  **********************************************************************/
    00029
    00030 #include <QPainter>
    00031
    00032 #include <KDChartChart>
    00033 #include <KDChartPaintContext>
    00034
    00035 #include "TernaryConstants.h"
    00036 #include "KDChartTernaryAxis.h"
    00037 #include "KDChartTernaryCoordinatePlane.h"
    00038 #include "KDChartAbstractTernaryDiagram.h"
    00039
    00040
    00041 #include "../src/KDChartLayoutItems.h"
    00042 #include "PrerenderedElements/KDChartTextLabelCache.h"
    00043
    00044 using namespace KDChart;
    00045
    00046 // m_label and m_fifty do not have to be pointers, once the class is
    00047 // pimpled (PrerenderedLabel is not published API)
    00048
    00049 TernaryAxis::TernaryAxis ( AbstractTernaryDiagram* diagram)
    00050     : AbstractAxis( diagram )
    00051     , m_position( KDChartEnums::PositionUnknown )
    00052     , m_label( new PrerenderedLabel )
    00053     , m_fifty( new PrerenderedLabel )
    00054 {
    00055     resetTitleTextAttributes();
    00056     setPosition( KDChartEnums::PositionSouth ); // arbitrary
    00057     m_fifty->setText( QObject::tr( "50%" ) ); // const
    00058     // FIXME is this consistent with other diagram/axis/plane implementations?
    00059     diagram->addAxis( this );
    00060 }
    00061
    00062 TernaryAxis::~TernaryAxis()
    00063 {
    00064     delete m_label; m_label = 0;
    00065     delete m_label; m_fifty = 0;
    00066 }
    00067
    00068 void  TernaryAxis::paintAll (QPainter &)
    00069 {
    00070     // not used
    00071 }
    00072
    00073 void  TernaryAxis::paint (QPainter *)
    00074 {
    00075     // not used
    00076 }
    00077
    00078 void  TernaryAxis::paintCtx (PaintContext * paintContext)
    00079 {
    00080     QPainter* p = paintContext->painter();
    00081     TernaryCoordinatePlane* plane =
    00082         (TernaryCoordinatePlane*) paintContext->coordinatePlane();
    00083     // QObject* refArea = plane->parent();
    00084     QRectF drawArea = paintContext->rectangle();
    00085     QRectF titleArea;
    00086
    00087     // paint the axis label (across the triangle, that one):
    00088     QList<PrerenderedLabel*> labels;
    00089     labels << m_label << m_fifty;
    00090     Q_FOREACH( PrerenderedLabel* label, labels ) {
    00091         const QPixmap& pixmap = label->pixmap();
    00092         QPointF point = plane->translate( label->position() )
    00093                         - label->referencePointLocation();
    00094         p->drawPixmap( point, pixmap );
    00095     }
    00096 }
    00097
    00098 bool TernaryAxis::isEmpty() const
    00099 {
    00100     // todo: what's this method for?
    00101     return false;
    00102 }
    00103
    00104 QRect TernaryAxis::geometry () const
    00105 {
    00106     return m_geometry;
    00107 }
    00108
    00109 void TernaryAxis::setGeometry (const QRect &rect)
    00110 {
    00111     m_geometry = rect;
    00112 }
    00113
    00114 QSize  TernaryAxis::minimumSize () const
    00115 {
    00116     // todo: return realistic sizes
    00117     return QSize( 100, 100 );
    00118 }
    00119
    00120 QSize  TernaryAxis::maximumSize () const
    00121 {
    00122     return QSize( 300, 200 );
    00123 }
    00124
    00125 QSize  TernaryAxis::sizeHint () const
    00126 {
    00127     return QSize( 150, 100 );
    00128 }
    00129
    00130 Qt::Orientations TernaryAxis::expandingDirections () const
    00131 {
    00132     return Qt::Vertical | Qt::Horizontal;
    00133 }
    00134
    00135 const Position TernaryAxis::position () const
    00136 {
    00137     return m_position;
    00138 }
    00139
    00140 void  TernaryAxis::setPosition (Position p)
    00141 {
    00142     if ( p == position() ) return;
    00143
    00144     if ( p != KDChartEnums::PositionWest
    00145          && p != KDChartEnums::PositionEast
    00146          && p != KDChartEnums::PositionSouth )
    00147     {
    00148         qDebug() << "TernaryAxis::setPosition: only south, east and west are supported "
    00149             "positions for ternary axes.";
    00150         return;
    00151     }
    00152
    00153     if ( m_title.isEmpty() )
    00154         switch( p.value() ) {
    00155         case KDChartEnums::PositionSouth:
    00156             m_label->setText( tr( "A" ) );
    00157             break;
    00158         case KDChartEnums::PositionWest:
    00159             m_label->setText( tr( "C" ) );
    00160             break;
    00161         case KDChartEnums::PositionEast:
    00162             m_label->setText( tr( "B" ) );
    00163             break;
    00164         default:
    00165             break;
    00166         }
    00167
    00168     m_position = p;
    00169     updatePrerenderedLabels(); // position has changed
    00170 }
    00171
    00172 void TernaryAxis::setTitleText( const QString& text )
    00173 {
    00174     m_title = text; // do not remove
    00175     m_label->setText( text );
    00176 }
    00177
    00178 QString TernaryAxis::titleText() const
    00179 {
    00180     return m_label->text();
    00181 }
    00182
    00183 void TernaryAxis::setTitleTextAttributes( const TextAttributes &a )
    00184 {
    00185     m_titleAttributes = a;
    00186     updatePrerenderedLabels();
    00187 }
    00188
    00189 TextAttributes TernaryAxis::titleTextAttributes() const
    00190 {
    00191     return m_titleAttributes;
    00192 }
    00193
    00194 void TernaryAxis::resetTitleTextAttributes()
    00195 {
    00196     TextAttributes a;
    00197     m_titleAttributes = a;
    00198     updatePrerenderedLabels();
    00199 }
    00200
    00201 bool TernaryAxis::hasDefaultTitleTextAttributes() const
    00202 {
    00203     TextAttributes a;
    00204     return m_titleAttributes == a;
    00205 }
    00206
    00207 void TernaryAxis::updatePrerenderedLabels()
    00208 {
    00209     TextAttributes attributes = titleTextAttributes();
    00210     double axisLabelAngle;
    00211     double fiftyMarkAngle;
    00212     QPointF axisLabelPosition;
    00213     QPointF fiftyMarkPosition;
    00214     KDChartEnums::PositionValue fiftyMarkReferencePoint;
    00215
    00216     switch( position().value() ) {
    00217     case KDChartEnums::PositionSouth:
    00218         // this is the axis on the other side of A
    00219         axisLabelAngle = 0.0;
    00220         fiftyMarkAngle = 0.0;
    00221         axisLabelPosition = TriangleTop;
    00222         fiftyMarkPosition = 0.5 * AxisVector_B_C - RelMarkerLength * Norm_B_C;
    00223         fiftyMarkReferencePoint = KDChartEnums::PositionNorth;
    00224         break;
    00225     case KDChartEnums::PositionEast:
    00226         // this is the axis on the other side of B
    00227         axisLabelAngle = 240.0;
    00228         fiftyMarkAngle = 60;
    00229         axisLabelPosition = TriangleBottomLeft;
    00230         fiftyMarkPosition = AxisVector_B_C + 0.5 * AxisVector_C_A - RelMarkerLength * Norm_C_A;
    00231         fiftyMarkReferencePoint = KDChartEnums::PositionSouth;
    00232         break;
    00233     case KDChartEnums::PositionWest:
    00234         // this is the axis on the other side of C
    00235         axisLabelAngle = 120.0;
    00236         fiftyMarkAngle = 300.0;
    00237         axisLabelPosition = TriangleBottomRight;
    00238         fiftyMarkPosition = 0.5 * AxisVector_B_A + RelMarkerLength * Norm_B_A;
    00239         fiftyMarkReferencePoint = KDChartEnums::PositionSouth;
    00240         break;
    00241     case KDChartEnums::PositionUnknown:
    00242         break; // initial value
    00243     default:
    00244         qDebug() << "TernaryAxis::updatePrerenderedLabel: unknown location";
    00245     };
    00246
    00247     m_label->setFont( attributes.font() );
    00248     // m_label->setText( titleText() ); // done by setTitleText()
    00249     m_label->setAngle( axisLabelAngle );
    00250     m_label->setPosition( axisLabelPosition );
    00251     m_label->setReferencePoint( KDChartEnums::PositionSouth );
    00252     QFont font = attributes.font();
    00253     font.setPointSizeF( 0.85 * font.pointSizeF() );
    00254     m_fifty->setFont( font );
    00255     m_fifty->setAngle( fiftyMarkAngle );
    00256     m_fifty->setPosition( fiftyMarkPosition );
    00257     m_fifty->setReferencePoint( fiftyMarkReferencePoint );
    00258 }
    00259
    00260 QPair<QSizeF, QSizeF> TernaryAxis::requiredMargins() const
    00261 {
    00262     QSizeF topleft( 0.0, 0.0 );
    00263     QSizeF bottomRight( 0.0, 0.0 );
    00264
    00265     switch( position().value() ) {
    00266     case KDChartEnums::PositionSouth:
    00267         // the label of the south axis is, in fact, up north.
    00268         topleft.setHeight( m_label->pixmap().height() );
    00269         bottomRight.setHeight( m_fifty->pixmap().height() );
    00270         break;
    00271     case KDChartEnums::PositionWest:
    00272         bottomRight.setWidth( m_label->pixmap().width()
    00273                               - m_label->referencePointLocation().x() );
    00274         bottomRight.setHeight( m_label->pixmap().height()
    00275                                - m_label->referencePointLocation().y() );
    00276         break;
    00277     case KDChartEnums::PositionEast:
    00278         topleft.setWidth( m_label->pixmap().width()
    00279                           - ( m_label->pixmap().width()
    00280                               - m_label->referencePointLocation().x() ) );
    00281         bottomRight.setHeight( m_label->pixmap().height()
    00282                                - ( m_label->pixmap().height()
    00283                                    - m_label->referencePointLocation().y() ) );
    00284         break;
    00285     default:
    00286         qDebug() << "TernaryAxis::requiredMargins: unknown location";
    00287     }
    00288 //     qDebug() << "TernaryAxis::requiredMargins:" << topleft << bottomRight;
    00289     return QPair<QSizeF, QSizeF>( topleft, bottomRight );
    00290 }