KDChartNormalLyingBarDiagram_p.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 "KDChartNormalLyingBarDiagram_p.h"
00031 
00032 #include <QModelIndex>
00033 
00034 #include "KDChartBarDiagram.h"
00035 #include "KDChartTextAttributes.h"
00036 #include "KDChartAttributesModel.h"
00037 #include "KDChartAbstractCartesianDiagram.h"
00038 
00039 using namespace KDChart;
00040 using namespace std;
00041 
00042 NormalLyingBarDiagram::NormalLyingBarDiagram( BarDiagram* d )
00043     : BarDiagramType( d )
00044 {
00045 }
00046 
00047 BarDiagram::BarType NormalLyingBarDiagram::type() const
00048 {
00049     return BarDiagram::Normal;
00050 }
00051 
00052 const QPair<QPointF, QPointF> NormalLyingBarDiagram::calculateDataBoundaries() const
00053 {
00054     const int rowCount = compressor().modelDataRows();
00055     const int colCount = compressor().modelDataColumns();
00056 
00057     double xMin = 0.0;
00058     double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
00059     double yMin = 0.0, yMax = 0.0;
00060 
00061     bool bStarting = true;
00062     for ( int column = 0; column < colCount; ++column )
00063     {
00064         for ( int row = 0; row < rowCount; ++row )
00065         {
00066             const CartesianDiagramDataCompressor::CachePosition position( row, column );
00067             const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00068             const double value = ISNAN( point.value ) ? 0.0 : point.value;
00069             // this is always true yMin can be 0 in case all values
00070             // are the same
00071             // same for yMax it can be zero if all values are negative
00072             if( bStarting ){
00073                 yMin = value;
00074                 yMax = value;
00075                 bStarting = false;
00076             }else{
00077                 yMin = qMin( yMin, value );
00078                 yMax = qMax( yMax, value );
00079             }
00080         }
00081     }
00082 
00083     // special cases
00084     if (  yMax == yMin ) {
00085         if ( yMin == 0.0 )
00086             yMax = 0.1; //we need at least a range
00087         else if( yMax < 0.0 )
00088             yMax = 0.0; // they are the same and negative
00089         else if( yMin > 0.0 )
00090             yMin = 0.0; // they are the same but positive
00091     }
00092     const QPointF bottomLeft ( QPointF( yMin, xMin ) );
00093     const QPointF topRight ( QPointF( yMax, xMax ) );
00094 
00095     return QPair< QPointF, QPointF >( bottomLeft,  topRight );
00096 }
00097 
00098 void NormalLyingBarDiagram::paint(  PaintContext* ctx )
00099 {
00100     reverseMapper().clear();
00101 
00102     const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries(); // cached
00103 
00104     const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ;
00105     const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second );
00106 
00107     const int rowCount = attributesModel()->rowCount(attributesModelRootIndex());
00108     const int colCount = attributesModel()->columnCount(attributesModelRootIndex());
00109 
00110     BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) );
00111     double barWidth = 0;
00112     double maxDepth = 0;
00113     double width = boundLeft.y() - boundRight.y();
00114     double groupWidth = width / (rowCount + 2);
00115     double spaceBetweenBars = 0;
00116     double spaceBetweenGroups = 0;
00117 
00118     if ( ba.useFixedBarWidth() ) {
00119 
00120         barWidth = ba.fixedBarWidth();
00121         groupWidth += barWidth;
00122 
00123         // Pending Michel set a min and max value for the groupWidth
00124         // related to the area.width
00125         if ( groupWidth < 0 )
00126             groupWidth = 0;
00127 
00128         if ( groupWidth  * rowCount > width )
00129             groupWidth = width / rowCount;
00130     }
00131 
00132     // maxLimit: allow the space between bars to be larger until area.width()
00133     // is covered by the groups.
00134     double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
00135 
00136     //Pending Michel: FixMe
00137     if ( ba.useFixedDataValueGap() ) {
00138         if ( width > maxLimit )
00139             spaceBetweenBars += ba.fixedDataValueGap();
00140         else
00141             spaceBetweenBars = ((width/rowCount) - groupWidth)/(colCount-1);
00142     }
00143 
00144     if ( ba.useFixedValueBlockGap() ) {
00145         spaceBetweenGroups += ba.fixedValueBlockGap();
00146     }
00147 
00148     calculateValueAndGapWidths( rowCount, colCount,groupWidth,
00149                                 barWidth, spaceBetweenBars, spaceBetweenGroups );
00150 
00151     DataValueTextInfoList list;
00152 
00153     for( int row = rowCount - 1; row >= 0; --row )
00154     {
00155         double offset = (groupWidth + spaceBetweenGroups) / 2.0 - spaceBetweenBars;
00156 
00157         if ( ba.useFixedDataValueGap() )
00158         {
00159             if ( spaceBetweenBars > 0 )
00160             {
00161                 if ( width > maxLimit )
00162                     offset -= ba.fixedDataValueGap();
00163                 else
00164                     offset -= ((width/rowCount) - groupWidth)/(colCount-1);
00165 
00166             }
00167             else
00168             {
00169                 offset += barWidth/2;
00170             }
00171         }
00172 
00173         for( int column = colCount - 1; column >= 0; --column )
00174         {
00175             offset -= barWidth + spaceBetweenBars;
00176 
00177             // paint one group
00178             const CartesianDiagramDataCompressor::CachePosition position( row,  column );
00179             const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00180             const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00181             const qreal value = point.value;//attributesModel()->data( sourceIndex ).toDouble();
00182             QPointF topPoint = ctx->coordinatePlane()->translate( QPointF( value, rowCount - (point.key + 0.5) ) );
00183             QPointF bottomPoint =  ctx->coordinatePlane()->translate( QPointF( 0, rowCount - point.key ) );
00184             const double barHeight = topPoint.x() - bottomPoint.x();
00185             topPoint.ry() += offset;
00186             topPoint.rx() -= barHeight;
00187             const QRectF rect( topPoint, QSizeF( barHeight, barWidth ) );
00188             appendDataValueTextInfoToList( diagram(), list, sourceIndex, PositionPoints( rect ),
00189                                            Position::NorthEast, Position::SouthWest,
00190                                            point.value );
00191             paintBars( ctx, sourceIndex, rect, maxDepth );
00192         }
00193     }
00194     paintDataValueTextsAndMarkers(  diagram(),  ctx,  list,  false );
00195 }

Generated on Thu Mar 4 23:19:12 2010 for KD Chart 2 by  doxygen 1.5.4