KDChartTernaryAxis.cpp

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