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