KD Chart 2
[rev.2.5]
|
00001 /**************************************************************************** 00002 ** Copyright (C) 2001-2012 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.txt 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.h> 00028 #include <KDChartPaintContext.h> 00029 00030 #include "TernaryConstants.h" 00031 #include "KDChartTernaryCoordinatePlane.h" 00032 #include "KDChartAbstractTernaryDiagram.h" 00033 00034 00035 #include "KDChartLayoutItems.h" 00036 #include "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_fifty; 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 titleArea; 00079 00080 // paint the axis label (across the triangle, that one): 00081 QList<PrerenderedLabel*> labels; 00082 labels << m_label << m_fifty; 00083 Q_FOREACH( PrerenderedLabel* label, labels ) { 00084 const QPixmap& pixmap = label->pixmap(); 00085 QPointF point = plane->translate( label->position() ) 00086 - label->referencePointLocation(); 00087 p->drawPixmap( point, pixmap ); 00088 } 00089 } 00090 00091 bool TernaryAxis::isEmpty() const 00092 { 00093 // todo: what's this method for? 00094 return false; 00095 } 00096 00097 QRect TernaryAxis::geometry () const 00098 { 00099 return m_geometry; 00100 } 00101 00102 void TernaryAxis::setGeometry (const QRect &rect) 00103 { 00104 m_geometry = rect; 00105 } 00106 00107 QSize TernaryAxis::minimumSize () const 00108 { 00109 // todo: return realistic sizes 00110 return QSize( 100, 100 ); 00111 } 00112 00113 QSize TernaryAxis::maximumSize () const 00114 { 00115 return QSize( 300, 200 ); 00116 } 00117 00118 QSize TernaryAxis::sizeHint () const 00119 { 00120 return QSize( 150, 100 ); 00121 } 00122 00123 Qt::Orientations TernaryAxis::expandingDirections () const 00124 { 00125 return Qt::Vertical | Qt::Horizontal; 00126 } 00127 00128 const Position TernaryAxis::position () const 00129 { 00130 return m_position; 00131 } 00132 00133 void TernaryAxis::setPosition (Position p) 00134 { 00135 if ( p == position() ) return; 00136 00137 if ( p != KDChartEnums::PositionWest 00138 && p != KDChartEnums::PositionEast 00139 && p != KDChartEnums::PositionSouth ) 00140 { 00141 qDebug() << "TernaryAxis::setPosition: only south, east and west are supported " 00142 "positions for ternary axes."; 00143 return; 00144 } 00145 00146 if ( m_title.isEmpty() ) 00147 switch( p.value() ) { 00148 case KDChartEnums::PositionSouth: 00149 m_label->setText( tr( "A" ) ); 00150 break; 00151 case KDChartEnums::PositionWest: 00152 m_label->setText( tr( "C" ) ); 00153 break; 00154 case KDChartEnums::PositionEast: 00155 m_label->setText( tr( "B" ) ); 00156 break; 00157 default: 00158 break; 00159 } 00160 00161 m_position = p; 00162 updatePrerenderedLabels(); // position has changed 00163 } 00164 00165 void TernaryAxis::setTitleText( const QString& text ) 00166 { 00167 m_title = text; // do not remove 00168 m_label->setText( text ); 00169 } 00170 00171 QString TernaryAxis::titleText() const 00172 { 00173 return m_label->text(); 00174 } 00175 00176 void TernaryAxis::setTitleTextAttributes( const TextAttributes &a ) 00177 { 00178 m_titleAttributes = a; 00179 updatePrerenderedLabels(); 00180 } 00181 00182 TextAttributes TernaryAxis::titleTextAttributes() const 00183 { 00184 return m_titleAttributes; 00185 } 00186 00187 void TernaryAxis::resetTitleTextAttributes() 00188 { 00189 TextAttributes a; 00190 m_titleAttributes = a; 00191 updatePrerenderedLabels(); 00192 } 00193 00194 bool TernaryAxis::hasDefaultTitleTextAttributes() const 00195 { 00196 TextAttributes a; 00197 return m_titleAttributes == a; 00198 } 00199 00200 void TernaryAxis::updatePrerenderedLabels() 00201 { 00202 TextAttributes attributes = titleTextAttributes(); 00203 qreal axisLabelAngle = 0.0; 00204 qreal fiftyMarkAngle = 0.0; 00205 QPointF axisLabelPosition; 00206 QPointF fiftyMarkPosition; 00207 KDChartEnums::PositionValue fiftyMarkReferencePoint = KDChartEnums::PositionUnknown; 00208 00209 switch( position().value() ) { 00210 case KDChartEnums::PositionSouth: 00211 // this is the axis on the other side of A 00212 axisLabelAngle = 0.0; 00213 fiftyMarkAngle = 0.0; 00214 axisLabelPosition = TriangleTop; 00215 fiftyMarkPosition = 0.5 * AxisVector_B_C - RelMarkerLength * Norm_B_C; 00216 fiftyMarkReferencePoint = KDChartEnums::PositionNorth; 00217 break; 00218 case KDChartEnums::PositionEast: 00219 // this is the axis on the other side of B 00220 axisLabelAngle = 240.0; 00221 fiftyMarkAngle = 60; 00222 axisLabelPosition = TriangleBottomLeft; 00223 fiftyMarkPosition = AxisVector_B_C + 0.5 * AxisVector_C_A - RelMarkerLength * Norm_C_A; 00224 fiftyMarkReferencePoint = KDChartEnums::PositionSouth; 00225 break; 00226 case KDChartEnums::PositionWest: 00227 // this is the axis on the other side of C 00228 axisLabelAngle = 120.0; 00229 fiftyMarkAngle = 300.0; 00230 axisLabelPosition = TriangleBottomRight; 00231 fiftyMarkPosition = 0.5 * AxisVector_B_A + RelMarkerLength * Norm_B_A; 00232 fiftyMarkReferencePoint = KDChartEnums::PositionSouth; 00233 break; 00234 case KDChartEnums::PositionUnknown: 00235 break; // initial value 00236 default: 00237 qDebug() << "TernaryAxis::updatePrerenderedLabel: unknown location"; 00238 }; 00239 00240 m_label->setFont( attributes.font() ); 00241 // m_label->setText( titleText() ); // done by setTitleText() 00242 m_label->setAngle( axisLabelAngle ); 00243 m_label->setPosition( axisLabelPosition ); 00244 m_label->setReferencePoint( KDChartEnums::PositionSouth ); 00245 QFont font = attributes.font(); 00246 font.setPointSizeF( 0.85 * font.pointSizeF() ); 00247 m_fifty->setFont( font ); 00248 m_fifty->setAngle( fiftyMarkAngle ); 00249 m_fifty->setPosition( fiftyMarkPosition ); 00250 m_fifty->setReferencePoint( fiftyMarkReferencePoint ); 00251 } 00252 00253 QPair<QSizeF, QSizeF> TernaryAxis::requiredMargins() const 00254 { 00255 QSizeF topleft( 0.0, 0.0 ); 00256 QSizeF bottomRight( 0.0, 0.0 ); 00257 00258 switch( position().value() ) { 00259 case KDChartEnums::PositionSouth: 00260 // the label of the south axis is, in fact, up north. 00261 topleft.setHeight( m_label->pixmap().height() ); 00262 bottomRight.setHeight( m_fifty->pixmap().height() ); 00263 break; 00264 case KDChartEnums::PositionWest: 00265 bottomRight.setWidth( m_label->pixmap().width() 00266 - m_label->referencePointLocation().x() ); 00267 bottomRight.setHeight( m_label->pixmap().height() 00268 - m_label->referencePointLocation().y() ); 00269 break; 00270 case KDChartEnums::PositionEast: 00271 topleft.setWidth( m_label->pixmap().width() 00272 - ( m_label->pixmap().width() 00273 - m_label->referencePointLocation().x() ) ); 00274 bottomRight.setHeight( m_label->pixmap().height() 00275 - ( m_label->pixmap().height() 00276 - m_label->referencePointLocation().y() ) ); 00277 break; 00278 default: 00279 qDebug() << "TernaryAxis::requiredMargins: unknown location"; 00280 } 00281 // qDebug() << "TernaryAxis::requiredMargins:" << topleft << bottomRight; 00282 return QPair<QSizeF, QSizeF>( topleft, bottomRight ); 00283 }