KDChartBarDiagram_p.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.  All rights reserved.
00003 **
00004 ** This file is part of the KD Chart library.
00005 **
00006 ** Licensees holding valid commercial KD Chart licenses may use this file in
00007 ** accordance with the KD Chart Commercial License Agreement provided with
00008 ** the Software.
00009 **
00010 **
00011 ** This file may be distributed and/or modified under the terms of the
00012 ** GNU General Public License version 2 and version 3 as published by the
00013 ** Free Software Foundation and appearing in the file LICENSE.GPL included.
00014 **
00015 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 **
00018 ** Contact info@kdab.com if any conditions of this licensing are not
00019 ** clear to you.
00020 **
00021 **********************************************************************/
00022 
00023 #include "KDChartBarDiagram.h"
00024 #include "KDChartDataValueAttributes.h"
00025 
00026 #include "KDChartBarDiagram_p.h"
00027 
00028 using namespace KDChart;
00029 
00030 BarDiagram::Private::Private( const Private& rhs )
00031     : AbstractCartesianDiagram::Private( rhs )
00032 {
00033 }
00034 
00035 void BarDiagram::BarDiagramType::paintBars( PaintContext* ctx, const QModelIndex& index, const QRectF& bar, double& maxDepth )
00036 {
00037     QRectF isoRect;
00038     QPolygonF topPoints, sidePoints;
00039     ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( index );
00040     double usedDepth = 0;
00041 
00042     //Pending Michel: configure threeDBrush settings - shadowColor etc...
00043     QBrush indexBrush ( diagram()->brush( index ) );
00044     QPen indexPen( diagram()->pen( index ) );
00045     PainterSaver painterSaver( ctx->painter() );
00046     if ( diagram()->antiAliasing() )
00047         ctx->painter()->setRenderHint ( QPainter::Antialiasing );
00048     ctx->painter()->setBrush( indexBrush );
00049     ctx->painter()->setPen( PrintingParameters::scalePen( indexPen ) );
00050     if ( threeDAttrs.isEnabled() ) {
00051         bool stackedMode = false;
00052         bool percentMode = false;
00053         bool paintTop = true;
00054         if ( maxDepth )
00055             threeDAttrs.setDepth( -maxDepth );
00056         QPointF boundRight =  ctx->coordinatePlane()->translate( diagram()->dataBoundaries().second );
00057         //fixme adjust the painting to reasonable depth value
00058         switch ( type() )
00059         {
00060         case BarDiagram::Normal:
00061             usedDepth = threeDAttrs.depth()/4;
00062             stackedMode = false;
00063             percentMode = false;
00064             break;
00065         case BarDiagram::Stacked:
00066             usedDepth = threeDAttrs.depth();
00067             stackedMode = true;
00068             percentMode = false;
00069             break;
00070         case BarDiagram::Percent:
00071             usedDepth = threeDAttrs.depth();
00072             stackedMode = false;
00073             percentMode = true;
00074             break;
00075         default:
00076             Q_ASSERT_X ( false, "dataBoundaries()",
00077                          "Type item does not match a defined bar chart Type." );
00078         }
00079         isoRect = bar.translated( usedDepth, -usedDepth );
00080         // we need to find out if the height is negative
00081         // and in this case paint it up and down
00082         //qDebug() << isoRect.height();
00083         if (  isoRect.height() < 0 ) {
00084           topPoints << isoRect.bottomLeft() << isoRect.bottomRight()
00085                     << bar.bottomRight() << bar.bottomLeft();
00086           if ( stackedMode ) {
00087               // fix it when several negative stacked values
00088               if (  index.column() == 0 ) {
00089                   paintTop = true;
00090               }
00091               else
00092                   paintTop = false;
00093           }
00094 
00095         } else {
00096             reverseMapper().addRect( index.row(), index.column(), isoRect );
00097             ctx->painter()->drawRect( isoRect );
00098             topPoints << bar.topLeft() << bar.topRight() << isoRect.topRight() << isoRect.topLeft();
00099         }
00100 
00101         if ( percentMode && isoRect.height() == 0 )
00102             paintTop = false;
00103 
00104         bool needToSetClippingOffForTop = false;
00105         if ( paintTop ){
00106             // Draw the top, if at least one of the top's points is
00107             // either inside or near at the edge of the coordinate plane:
00108             bool drawIt = false;
00109             bool hasPointOutside = false;
00110             const QRectF r( ctx->rectangle().adjusted(0,-1,1,0) );
00111             KDAB_FOREACH( QPointF pt, topPoints ) {
00112                 if( r.contains( pt ) )
00113                     drawIt = true;
00114                 else
00115                     hasPointOutside = true;
00116             }
00117             if( drawIt ){
00118                 const PainterSaver p( ctx->painter() );
00119                 needToSetClippingOffForTop = hasPointOutside && ctx->painter()->hasClipping();
00120                 if( needToSetClippingOffForTop )
00121                     ctx->painter()->setClipping( false );
00122                 reverseMapper().addPolygon( index.row(), index.column(), topPoints );
00123                 ctx->painter()->drawPolygon( topPoints );
00124             }
00125         }
00126 
00127 
00128 
00129         sidePoints << bar.topRight() << isoRect.topRight() << isoRect.bottomRight() << bar.bottomRight();
00130         if (  bar.height() != 0 ){
00131             const PainterSaver p( ctx->painter() );
00132             if( needToSetClippingOffForTop )
00133                 ctx->painter()->setClipping( false );
00134             reverseMapper().addPolygon( index.row(), index.column(), sidePoints );
00135             ctx->painter()->drawPolygon( sidePoints );
00136         }
00137     }
00138 
00139     if( bar.height() != 0 )
00140     {
00141         reverseMapper().addRect( index.row(), index.column(), bar );
00142         ctx->painter()->drawRect( bar );
00143     }
00144     // reset
00145     //diagram()->maxDepth = threeDAttrs.depth();
00146 }
00147 
00148 AttributesModel* BarDiagram::BarDiagramType::attributesModel() const
00149 {
00150     return m_private->attributesModel;
00151 }
00152 
00153 QModelIndex BarDiagram::BarDiagramType::attributesModelRootIndex() const
00154 {
00155     return m_private->diagram->attributesModelRootIndex();
00156 }
00157 
00158 BarDiagram* BarDiagram::BarDiagramType::diagram() const
00159 {
00160     return m_private->diagram;
00161 }
00162 
00163 void BarDiagram::BarDiagramType::appendDataValueTextInfoToList(
00164             AbstractDiagram * diagram,
00165             DataValueTextInfoList & list,
00166             const QModelIndex & index,
00167             const PositionPoints& points,
00168             const Position& autoPositionPositive,
00169             const Position& autoPositionNegative,
00170             const qreal value )
00171 {
00172     m_private->appendDataValueTextInfoToList( diagram, list, index, 0,
00173                                               points,
00174                                               autoPositionPositive, autoPositionNegative, value );
00175 }
00176 
00177 void BarDiagram::BarDiagramType::paintDataValueTextsAndMarkers(
00178     AbstractDiagram* diagram,
00179     PaintContext* ctx,
00180     const DataValueTextInfoList & list,
00181     bool paintMarkers )
00182 {
00183     m_private->paintDataValueTextsAndMarkers( diagram, ctx, list, paintMarkers );
00184 }
00185 
00186 
00187 void BarDiagram::BarDiagramType::calculateValueAndGapWidths( int rowCount,int colCount,
00188                                              double groupWidth,
00189                                              double& outBarWidth,
00190                                              double& outSpaceBetweenBars,
00191                                              double& outSpaceBetweenGroups )
00192 {
00193 
00194     Q_UNUSED( rowCount );
00195 
00196     BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) );
00197 
00198     // Pending Michel Fixme
00199     /* We are colCount groups to paint. Each group is centered around the
00200      * horizontal point position on the grid. The full area covers the
00201      * values -1 to colCount + 1. A bar has a relative width of one unit,
00202      * the gaps between bars are 0.5 wide, and the gap between groups is
00203      * also one unit, by default. */
00204 
00205     double units;
00206     if( type() == Normal )
00207         units = colCount // number of bars in group * 1.0
00208                 + (colCount-1) * ba.barGapFactor() // number of bar gaps
00209                 + 1 * ba.groupGapFactor(); // number of group gaps
00210     else
00211         units = 1 + 1 * ba.groupGapFactor();
00212 
00213     double unitWidth = groupWidth / units;
00214     outBarWidth = unitWidth;
00215     outSpaceBetweenBars += unitWidth * ba.barGapFactor();
00216 
00217     // Pending Michel - minLimit: allow space between bars to be reduced until the bars are displayed next to each other.
00218     // is that what we want?
00219     // sebsauer; in the case e.g. CartesianCoordinatePlane::setHorizontalRangeReversed(true) was
00220     // used to reverse the values, we deal with negative outSpaceBetweenBars and unitWidth here
00221     // and since that's correct we don't like to lose e.g. the spacing here.
00222     //if ( outSpaceBetweenBars < 0 )
00223     //    outSpaceBetweenBars = 0;
00224 
00225     outSpaceBetweenGroups += unitWidth * ba.groupGapFactor();
00226 }
00227 
00228 ReverseMapper& BarDiagram::BarDiagramType::reverseMapper()
00229 {
00230     return m_private->reverseMapper;
00231 }
00232 
00233 CartesianDiagramDataCompressor& BarDiagram::BarDiagramType::compressor() const
00234 {
00235     return m_private->compressor;
00236 }