KDChartStackedLyingBarDiagram_p.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 double xMin = 0;
00049 double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
00050 double yMin = 0, yMax = 0;
00051
00052 bool bStarting = true;
00053 for( int row = 0; row < rowCount; ++row )
00054 {
00055
00056 double stackedValues = 0.0;
00057 double negativeStackedValues = 0.0;
00058 for ( int col = 0; col < colCount ; ++col )
00059 {
00060 const CartesianDiagramDataCompressor::CachePosition position( row, col );
00061 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00062
00063 if( point.value > 0.0 )
00064 stackedValues += point.value;
00065 else
00066 negativeStackedValues += point.value;
00067
00068
00069
00070
00071 if( bStarting ){
00072 yMin = negativeStackedValues < 0.0 ? negativeStackedValues : stackedValues;
00073 yMax = stackedValues > 0.0 ? stackedValues : negativeStackedValues;
00074 bStarting = false;
00075 }else{
00076 yMin = qMin( qMin( yMin, stackedValues ), negativeStackedValues );
00077 yMax = qMax( qMax( yMax, stackedValues ), negativeStackedValues );
00078 }
00079 }
00080 }
00081
00082 if ( yMax == yMin ) {
00083 if ( yMin == 0.0 )
00084 yMax = 0.1;
00085 else if( yMax < 0.0 )
00086 yMax = 0.0;
00087 else if( yMin > 0.0 )
00088 yMin = 0.0;
00089 }
00090 const QPointF bottomLeft ( QPointF( yMin, xMin ) );
00091 const QPointF topRight ( QPointF( yMax, xMax ) );
00092
00093 return QPair< QPointF, QPointF >( bottomLeft, topRight );
00094 }
00095
00096 void StackedLyingBarDiagram::paint( PaintContext* ctx )
00097 {
00098 reverseMapper().clear();
00099
00100 const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries();
00101
00102 const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ;
00103 const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second );
00104
00105 const int rowCount = compressor().modelDataRows();
00106 const int colCount = compressor().modelDataColumns();
00107
00108 BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) );
00109 double barWidth = 0;
00110 double maxDepth = 0;
00111 double width = boundLeft.y() - boundRight.y();
00112 double groupWidth = width/ (rowCount + 2);
00113 double spaceBetweenBars = 0;
00114 double spaceBetweenGroups = 0;
00115
00116 if ( ba.useFixedBarWidth() ) {
00117 barWidth = ba.fixedBarWidth();
00118 groupWidth += barWidth;
00119
00120
00121
00122 if ( groupWidth < 0 )
00123 groupWidth = 0;
00124
00125 if ( groupWidth * rowCount > width )
00126 groupWidth = width / rowCount;
00127 }
00128
00129
00130
00131 double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
00132
00133
00134
00135 if ( ba.useFixedDataValueGap() ) {
00136 if ( ctx->rectangle().width() > maxLimit )
00137 spaceBetweenBars += ba.fixedDataValueGap();
00138 else
00139 spaceBetweenBars = ((width/rowCount) - groupWidth)/(colCount-1);
00140 }
00141
00142 if ( ba.useFixedValueBlockGap() )
00143 spaceBetweenGroups += ba.fixedValueBlockGap();
00144
00145 calculateValueAndGapWidths( rowCount, colCount,groupWidth,
00146 barWidth, spaceBetweenBars, spaceBetweenGroups );
00147
00148 DataValueTextInfoList list;
00149 for( int row = rowCount - 1; row >= 0; --row )
00150 {
00151 double offset = spaceBetweenGroups;
00152 if( ba.useFixedBarWidth() )
00153 offset -= ba.fixedBarWidth();
00154
00155 if( offset < 0 )
00156 offset = 0;
00157
00158 for( int col = 0; col < colCount; ++col )
00159 {
00160 double threeDOffset = 0.0;
00161 const CartesianDiagramDataCompressor::CachePosition position( row, col );
00162 const CartesianDiagramDataCompressor::DataPoint p = compressor().data( position );
00163
00164 const QModelIndex index = attributesModel()->mapToSource( p.index );
00165 ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( index );
00166 const double value = p.value;
00167 double stackedValues = 0.0;
00168 double key = 0.0;
00169
00170 if ( threeDAttrs.isEnabled() ){
00171 if ( barWidth > 0 ) {
00172 barWidth = (width - ((offset+(threeDAttrs.depth()))*rowCount))/ rowCount;
00173 threeDOffset = threeDAttrs.depth();
00174 }
00175 if ( barWidth <= 0 ) {
00176 barWidth = 0.1;
00177 threeDOffset = (width - (offset*rowCount))/ rowCount;
00178 }
00179 }else{
00180 barWidth = (width - (offset*rowCount))/ rowCount;
00181 }
00182
00183 for ( int k = col; k >= 0; --k )
00184 {
00185 const CartesianDiagramDataCompressor::CachePosition position( row, k );
00186 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00187 if( ( p.value >= 0.0 && point.value >= 0.0 ) || ( p.value < 0.0 && point.value < 0.0 ) )
00188 stackedValues += point.value;
00189 key = point.key;
00190 }
00191 QPointF point = ctx->coordinatePlane()->translate( QPointF( stackedValues, rowCount - key ) );
00192 point.ry() += offset / 2 + threeDOffset;
00193 const QPointF previousPoint = ctx->coordinatePlane()->translate( QPointF( stackedValues - value, rowCount - key ) );
00194 const double barHeight = point.x() - previousPoint.x();
00195 point.rx() -= barHeight;
00196
00197 const QRectF rect( point, QSizeF( barHeight , barWidth ) );
00198 appendDataValueTextInfoToList( diagram(), list, index, PositionPoints( rect ),
00199 Position::NorthEast, Position::SouthWest,
00200 value );
00201 paintBars( ctx, index, rect, maxDepth );
00202 }
00203 }
00204 paintDataValueTextsAndMarkers( diagram(), ctx, list, false );
00205 }