KDChartBarDiagram_p.cpp

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

Generated on Thu Mar 4 23:19:10 2010 for KD Chart 2 by  doxygen 1.5.4