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

Generated on Mon Sep 17 16:16:50 2007 for KD Chart 2 by  doxygen 1.5.1