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