KissCount/lib/libkdchart/src/KDChartBarDiagram_p.cpp

237 lines
8.7 KiB
C++
Raw Normal View History

2012-01-28 15:54:17 +01:00
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "KDChartBarDiagram.h"
#include "KDChartDataValueAttributes.h"
#include "KDChartBarDiagram_p.h"
using namespace KDChart;
BarDiagram::Private::Private( const Private& rhs )
: AbstractCartesianDiagram::Private( rhs )
{
}
void BarDiagram::BarDiagramType::paintBars( PaintContext* ctx, const QModelIndex& index, const QRectF& bar, double& maxDepth )
{
QRectF isoRect;
QPolygonF topPoints, sidePoints;
ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( index );
double usedDepth = 0;
//Pending Michel: configure threeDBrush settings - shadowColor etc...
QBrush indexBrush ( diagram()->brush( index ) );
QPen indexPen( diagram()->pen( index ) );
PainterSaver painterSaver( ctx->painter() );
if ( diagram()->antiAliasing() )
ctx->painter()->setRenderHint ( QPainter::Antialiasing );
ctx->painter()->setBrush( indexBrush );
ctx->painter()->setPen( PrintingParameters::scalePen( indexPen ) );
if ( threeDAttrs.isEnabled() ) {
bool stackedMode = false;
bool percentMode = false;
bool paintTop = true;
if ( maxDepth )
threeDAttrs.setDepth( -maxDepth );
QPointF boundRight = ctx->coordinatePlane()->translate( diagram()->dataBoundaries().second );
//fixme adjust the painting to reasonable depth value
switch ( type() )
{
case BarDiagram::Normal:
usedDepth = threeDAttrs.depth()/4;
stackedMode = false;
percentMode = false;
break;
case BarDiagram::Stacked:
usedDepth = threeDAttrs.depth();
stackedMode = true;
percentMode = false;
break;
case BarDiagram::Percent:
usedDepth = threeDAttrs.depth();
stackedMode = false;
percentMode = true;
break;
default:
Q_ASSERT_X ( false, "dataBoundaries()",
"Type item does not match a defined bar chart Type." );
}
isoRect = bar.translated( usedDepth, -usedDepth );
// we need to find out if the height is negative
// and in this case paint it up and down
//qDebug() << isoRect.height();
if ( isoRect.height() < 0 ) {
topPoints << isoRect.bottomLeft() << isoRect.bottomRight()
<< bar.bottomRight() << bar.bottomLeft();
if ( stackedMode ) {
// fix it when several negative stacked values
if ( index.column() == 0 ) {
paintTop = true;
}
else
paintTop = false;
}
} else {
reverseMapper().addRect( index.row(), index.column(), isoRect );
ctx->painter()->drawRect( isoRect );
topPoints << bar.topLeft() << bar.topRight() << isoRect.topRight() << isoRect.topLeft();
}
if ( percentMode && isoRect.height() == 0 )
paintTop = false;
bool needToSetClippingOffForTop = false;
if ( paintTop ){
// Draw the top, if at least one of the top's points is
// either inside or near at the edge of the coordinate plane:
bool drawIt = false;
bool hasPointOutside = false;
const QRectF r( ctx->rectangle().adjusted(0,-1,1,0) );
KDAB_FOREACH( QPointF pt, topPoints ) {
if( r.contains( pt ) )
drawIt = true;
else
hasPointOutside = true;
}
if( drawIt ){
const PainterSaver p( ctx->painter() );
needToSetClippingOffForTop = hasPointOutside && ctx->painter()->hasClipping();
if( needToSetClippingOffForTop )
ctx->painter()->setClipping( false );
reverseMapper().addPolygon( index.row(), index.column(), topPoints );
ctx->painter()->drawPolygon( topPoints );
}
}
sidePoints << bar.topRight() << isoRect.topRight() << isoRect.bottomRight() << bar.bottomRight();
if ( bar.height() != 0 ){
const PainterSaver p( ctx->painter() );
if( needToSetClippingOffForTop )
ctx->painter()->setClipping( false );
reverseMapper().addPolygon( index.row(), index.column(), sidePoints );
ctx->painter()->drawPolygon( sidePoints );
}
}
if( bar.height() != 0 )
{
reverseMapper().addRect( index.row(), index.column(), bar );
ctx->painter()->drawRect( bar );
}
// reset
//diagram()->maxDepth = threeDAttrs.depth();
}
AttributesModel* BarDiagram::BarDiagramType::attributesModel() const
{
return m_private->attributesModel;
}
QModelIndex BarDiagram::BarDiagramType::attributesModelRootIndex() const
{
return m_private->diagram->attributesModelRootIndex();
}
BarDiagram* BarDiagram::BarDiagramType::diagram() const
{
return m_private->diagram;
}
void BarDiagram::BarDiagramType::appendDataValueTextInfoToList(
AbstractDiagram * diagram,
DataValueTextInfoList & list,
const QModelIndex & index,
const PositionPoints& points,
const Position& autoPositionPositive,
const Position& autoPositionNegative,
const qreal value )
{
m_private->appendDataValueTextInfoToList( diagram, list, index, 0,
points,
autoPositionPositive, autoPositionNegative, value );
}
void BarDiagram::BarDiagramType::paintDataValueTextsAndMarkers(
AbstractDiagram* diagram,
PaintContext* ctx,
const DataValueTextInfoList & list,
bool paintMarkers )
{
m_private->paintDataValueTextsAndMarkers( diagram, ctx, list, paintMarkers );
}
void BarDiagram::BarDiagramType::calculateValueAndGapWidths( int rowCount,int colCount,
double groupWidth,
double& outBarWidth,
double& outSpaceBetweenBars,
double& outSpaceBetweenGroups )
{
Q_UNUSED( rowCount );
BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) );
// Pending Michel Fixme
/* We are colCount groups to paint. Each group is centered around the
* horizontal point position on the grid. The full area covers the
* values -1 to colCount + 1. A bar has a relative width of one unit,
* the gaps between bars are 0.5 wide, and the gap between groups is
* also one unit, by default. */
double units;
if( type() == Normal )
units = colCount // number of bars in group * 1.0
+ (colCount-1) * ba.barGapFactor() // number of bar gaps
+ 1 * ba.groupGapFactor(); // number of group gaps
else
units = 1 + 1 * ba.groupGapFactor();
double unitWidth = groupWidth / units;
outBarWidth = unitWidth;
outSpaceBetweenBars += unitWidth * ba.barGapFactor();
// Pending Michel - minLimit: allow space between bars to be reduced until the bars are displayed next to each other.
// is that what we want?
// sebsauer; in the case e.g. CartesianCoordinatePlane::setHorizontalRangeReversed(true) was
// used to reverse the values, we deal with negative outSpaceBetweenBars and unitWidth here
// and since that's correct we don't like to lose e.g. the spacing here.
//if ( outSpaceBetweenBars < 0 )
// outSpaceBetweenBars = 0;
outSpaceBetweenGroups += unitWidth * ba.groupGapFactor();
}
ReverseMapper& BarDiagram::BarDiagramType::reverseMapper()
{
return m_private->reverseMapper;
}
CartesianDiagramDataCompressor& BarDiagram::BarDiagramType::compressor() const
{
return m_private->compressor;
}