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 "KDChartNormalLyingBarDiagram_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 NormalLyingBarDiagram::NormalLyingBarDiagram( BarDiagram* d )
00036 : BarDiagramType( d )
00037 {
00038 }
00039
00040 BarDiagram::BarType NormalLyingBarDiagram::type() const
00041 {
00042 return BarDiagram::Normal;
00043 }
00044
00045 const QPair<QPointF, QPointF> NormalLyingBarDiagram::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( yMin, xMin ) );
00086 const QPointF topRight ( QPointF( yMax, xMax ) );
00087
00088 return QPair< QPointF, QPointF >( bottomLeft, topRight );
00089 }
00090
00091 void NormalLyingBarDiagram::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 = boundLeft.y() - boundRight.y();
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 = rowCount - 1; row >= 0; --row )
00147 {
00148 double offset = (groupWidth + spaceBetweenGroups) / 2.0 - spaceBetweenBars;
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 = colCount - 1; column >= 0; --column )
00167 {
00168 offset -= barWidth + spaceBetweenBars;
00169
00170
00171 const CartesianDiagramDataCompressor::CachePosition position( row, column );
00172 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00173 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00174 const qreal value = point.value;
00175 QPointF topPoint = ctx->coordinatePlane()->translate( QPointF( value, rowCount - (point.key + 0.5) ) );
00176 QPointF bottomPoint = ctx->coordinatePlane()->translate( QPointF( 0, rowCount - point.key ) );
00177 const double barHeight = topPoint.x() - bottomPoint.x();
00178 topPoint.ry() += offset;
00179 topPoint.rx() -= barHeight;
00180 const QRectF rect( topPoint, QSizeF( barHeight, barWidth ) );
00181 appendDataValueTextInfoToList( diagram(), list, sourceIndex, PositionPoints( rect ),
00182 Position::NorthEast, Position::SouthWest,
00183 point.value );
00184 paintBars( ctx, sourceIndex, rect, maxDepth );
00185 }
00186 }
00187 paintDataValueTextsAndMarkers( diagram(), ctx, list, false );
00188 }