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