KD Chart 2  [rev.2.5]
KDChartStackedLyingBarDiagram_p.cpp
Go to the documentation of this file.
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 <QModelIndex>
00024 
00025 #include "KDChartBarDiagram.h"
00026 #include "KDChartTextAttributes.h"
00027 #include "KDChartAttributesModel.h"
00028 #include "KDChartAbstractCartesianDiagram.h"
00029 #include "KDChartStackedLyingBarDiagram_p.h"
00030 
00031 using namespace KDChart;
00032 
00033 StackedLyingBarDiagram::StackedLyingBarDiagram( BarDiagram* d )
00034     : BarDiagramType( d )
00035 {
00036 }
00037 
00038 BarDiagram::BarType StackedLyingBarDiagram::type() const
00039 {
00040     return BarDiagram::Stacked;
00041 }
00042 
00043 const QPair<QPointF, QPointF> StackedLyingBarDiagram::calculateDataBoundaries() const
00044 {
00045     const int rowCount = compressor().modelDataRows();
00046     const int colCount = compressor().modelDataColumns();
00047 
00048     const qreal xMin = 0;
00049     const qreal xMax = rowCount;
00050     qreal yMin = 0;
00051     qreal yMax = 0;
00052 
00053     bool isFirst = true;
00054     for( int row = 0; row < rowCount; ++row ) {
00055         // calculate sum of values per column - Find out stacked Min/Max
00056         qreal stackedValues = 0.0;
00057         qreal negativeStackedValues = 0.0;
00058         for ( int col = 0; col < colCount; ++col ) {
00059             const CartesianDiagramDataCompressor::CachePosition position( row, col );
00060             const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00061 
00062             if( point.value > 0.0 )
00063                 stackedValues += point.value;
00064             else
00065                 negativeStackedValues += point.value;
00066 
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 ( isFirst ) {
00071                 yMin = negativeStackedValues < 0.0 ? negativeStackedValues : stackedValues;
00072                 yMax = stackedValues > 0.0 ? stackedValues : negativeStackedValues;
00073                 isFirst = false;
00074             } else {
00075                 yMin = qMin( qMin( yMin, stackedValues ), negativeStackedValues );
00076                 yMax = qMax( qMax( yMax, stackedValues ), negativeStackedValues );
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; // extend the range to zero
00087         } else if ( yMin > 0.0 ) {
00088             yMin = 0.0; // dito
00089         }
00090     }
00091 
00092     return QPair< QPointF, QPointF >( QPointF( yMin, xMin ), QPointF( yMax, xMax ) );
00093 }
00094 
00095 void StackedLyingBarDiagram::paint( PaintContext* ctx )
00096 {
00097     reverseMapper().clear();
00098 
00099     const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries(); // cached
00100 
00101     const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ;
00102     const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second );
00103 
00104     const int rowCount = compressor().modelDataRows();
00105     const int colCount = compressor().modelDataColumns();
00106 
00107     BarAttributes ba = diagram()->barAttributes();
00108     qreal barWidth = 0;
00109     qreal maxDepth = 0;
00110     qreal width = boundLeft.y() - boundRight.y();
00111     qreal groupWidth = width/ (rowCount + 2);
00112     qreal spaceBetweenBars = 0;
00113     qreal spaceBetweenGroups = 0;
00114 
00115     if ( ba.useFixedBarWidth() ) {
00116         barWidth = ba.fixedBarWidth();
00117         groupWidth += barWidth;
00118 
00119         // Pending Michel set a min and max value for the groupWidth
00120         // related to the area.width
00121         if ( groupWidth < 0 )
00122             groupWidth = 0;
00123 
00124         if ( groupWidth  * rowCount > width )
00125             groupWidth = width / rowCount;
00126     }
00127 
00128     // maxLimit: allow the space between bars to be larger until area.width()
00129     // is covered by the groups.
00130     qreal maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
00131 
00132 
00133     //Pending Michel: FixMe
00134     if ( ba.useFixedDataValueGap() ) {
00135         if ( ctx->rectangle().width() > maxLimit )
00136             spaceBetweenBars += ba.fixedDataValueGap();
00137         else
00138             spaceBetweenBars = ((width/rowCount) - groupWidth)/(colCount-1);
00139     }
00140 
00141     if ( ba.useFixedValueBlockGap() )
00142         spaceBetweenGroups += ba.fixedValueBlockGap();
00143 
00144     calculateValueAndGapWidths( rowCount, colCount,groupWidth,
00145                                 barWidth, spaceBetweenBars, spaceBetweenGroups );
00146 
00147     LabelPaintCache lpc;
00148     for( int row = rowCount - 1; row >= 0; --row )
00149     {
00150         qreal offset = spaceBetweenGroups;
00151         if( ba.useFixedBarWidth() )
00152             offset -= ba.fixedBarWidth();
00153         
00154         if( offset < 0 )
00155             offset = 0;
00156 
00157         for( int col = 0; col < colCount; ++col )
00158         {
00159                 qreal threeDOffset = 0.0;
00160             const CartesianDiagramDataCompressor::CachePosition position( row, col );
00161             const CartesianDiagramDataCompressor::DataPoint p = compressor().data( position );
00162  
00163             const QModelIndex index = attributesModel()->mapToSource( p.index );
00164             ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( index );
00165             const qreal value = p.value;
00166             qreal stackedValues = 0.0;
00167             qreal key = 0.0;
00168 
00169             if ( threeDAttrs.isEnabled() ){
00170                 if ( barWidth > 0 ) {
00171                     barWidth =  (width - ((offset+(threeDAttrs.depth()))*rowCount))/ rowCount;
00172                         threeDOffset = threeDAttrs.depth();
00173                 }
00174                 if ( barWidth <= 0 ) {
00175                     barWidth = 0.1;
00176                     threeDOffset = (width - (offset*rowCount))/ rowCount;
00177                 }
00178             }else{
00179                 barWidth = (width - (offset*rowCount))/ rowCount;
00180             }
00181 
00182             for ( int k = col; k >= 0; --k )
00183             {
00184                 const CartesianDiagramDataCompressor::CachePosition position( row, k );
00185                 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00186                 if( ( p.value >= 0.0 && point.value >= 0.0 ) || ( p.value < 0.0 && point.value < 0.0 ) )
00187                     stackedValues += point.value;
00188                 key = point.key;
00189             }
00190             QPointF point = ctx->coordinatePlane()->translate( QPointF( stackedValues, rowCount - key ) );
00191             point.ry() += offset / 2 + threeDOffset;
00192             const QPointF previousPoint = ctx->coordinatePlane()->translate( QPointF( stackedValues - value, rowCount - key ) );
00193             const qreal barHeight = point.x() - previousPoint.x();
00194             point.rx() -= barHeight;
00195 
00196             const QRectF rect( point, QSizeF( barHeight , barWidth ) );
00197             addLabel( &lpc, index, PositionPoints( rect ), Position::North,
00198                       Position::South, value );
00199             paintBars( ctx, index, rect, maxDepth );
00200         }
00201     }
00202     paintDataValueTextsAndMarkers( ctx, lpc, false );
00203 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines

Klarälvdalens Datakonsult AB (KDAB)
Qt-related services and products
http://www.kdab.com/
http://www.kdab.com/products/kd-chart/