KD Chart 2  [rev.2.5]
KDChartBarDiagram_p.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2012 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.txt 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 "KDChartBarDiagram_p.h"
00025 
00026 #include "KDChartDataValueAttributes.h"
00027 #include "KDChartPainterSaver_p.h"
00028 
00029 using namespace KDChart;
00030 
00031 BarDiagram::Private::Private( const Private& rhs )
00032     : AbstractCartesianDiagram::Private( rhs )
00033 {
00034 }
00035 
00036 void BarDiagram::BarDiagramType::paintBars( PaintContext* ctx, const QModelIndex& index, const QRectF& bar, qreal& maxDepth )
00037 {
00038     QRectF isoRect;
00039     QPolygonF topPoints, sidePoints;
00040     ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( index );
00041     qreal usedDepth = 0;
00042 
00043     //Pending Michel: configure threeDBrush settings - shadowColor etc...
00044     QBrush indexBrush( diagram()->brush( index ) );
00045     QPen indexPen( diagram()->pen( index ) );
00046     PainterSaver painterSaver( ctx->painter() );
00047 
00048     ctx->painter()->setRenderHint( QPainter::Antialiasing, diagram()->antiAliasing() );
00049     if( threeDAttrs.isEnabled() )
00050         indexBrush = threeDAttrs.threeDBrush( indexBrush, bar );
00051     ctx->painter()->setBrush( indexBrush );
00052     ctx->painter()->setPen( PrintingParameters::scalePen( indexPen ) );
00053 
00054     if ( threeDAttrs.isEnabled() ) {
00055         bool stackedMode = false;
00056         bool percentMode = false;
00057         bool paintTop = true;
00058         if ( maxDepth )
00059             threeDAttrs.setDepth( -maxDepth );
00060         //fixme adjust the painting to reasonable depth value
00061         switch ( type() )
00062         {
00063         case BarDiagram::Normal:
00064             usedDepth = threeDAttrs.depth()/4;
00065             stackedMode = false;
00066             percentMode = false;
00067             break;
00068         case BarDiagram::Stacked:
00069             usedDepth = threeDAttrs.depth();
00070             stackedMode = true;
00071             percentMode = false;
00072             break;
00073         case BarDiagram::Percent:
00074             usedDepth = threeDAttrs.depth();
00075             stackedMode = false;
00076             percentMode = true;
00077             break;
00078         default:
00079             Q_ASSERT_X ( false, "dataBoundaries()",
00080                          "Type item does not match a defined bar chart Type." );
00081         }
00082         isoRect = bar.translated( usedDepth, -usedDepth );
00083         // we need to find out if the height is negative
00084         // and in this case paint it up and down
00085         //qDebug() << isoRect.height();
00086         if ( isoRect.height() < 0 ) {
00087           topPoints << isoRect.bottomLeft() << isoRect.bottomRight()
00088                     << bar.bottomRight() << bar.bottomLeft();
00089           if ( stackedMode ) {
00090               // fix it when several negative stacked values
00091               if ( index.column() == 0 ) {
00092                   paintTop = true;
00093               }
00094               else
00095                   paintTop = false;
00096           }
00097 
00098         } else {
00099             reverseMapper().addRect( index.row(), index.column(), isoRect );
00100             ctx->painter()->drawRect( isoRect );
00101             topPoints << bar.topLeft() << bar.topRight() << isoRect.topRight() << isoRect.topLeft();
00102         }
00103 
00104         if ( percentMode && isoRect.height() == 0 )
00105             paintTop = false;
00106 
00107         bool needToSetClippingOffForTop = false;
00108         if ( paintTop ){
00109             // Draw the top, if at least one of the top's points is
00110             // either inside or near at the edge of the coordinate plane:
00111             bool drawIt = false;
00112             bool hasPointOutside = false;
00113             const QRectF r( ctx->rectangle().adjusted(0,-1,1,0) );
00114             KDAB_FOREACH( QPointF pt, topPoints ) {
00115                 if( r.contains( pt ) )
00116                     drawIt = true;
00117                 else
00118                     hasPointOutside = true;
00119             }
00120             if( drawIt ){
00121                 const PainterSaver p( ctx->painter() );
00122                 needToSetClippingOffForTop = hasPointOutside && ctx->painter()->hasClipping();
00123                 if( needToSetClippingOffForTop )
00124                     ctx->painter()->setClipping( false );
00125                 reverseMapper().addPolygon( index.row(), index.column(), topPoints );
00126                 ctx->painter()->drawPolygon( topPoints );
00127             }
00128         }
00129 
00130 
00131 
00132         sidePoints << bar.topRight() << isoRect.topRight() << isoRect.bottomRight() << bar.bottomRight();
00133         if ( bar.height() != 0 ){
00134             const PainterSaver p( ctx->painter() );
00135             if( needToSetClippingOffForTop )
00136                 ctx->painter()->setClipping( false );
00137             reverseMapper().addPolygon( index.row(), index.column(), sidePoints );
00138             ctx->painter()->drawPolygon( sidePoints );
00139         }
00140     }
00141 
00142     if( bar.height() != 0 )
00143     {
00144         reverseMapper().addRect( index.row(), index.column(), bar );
00145         ctx->painter()->drawRect( bar );
00146     }
00147     // reset
00148     //diagram()->maxDepth = threeDAttrs.depth();
00149 }
00150 
00151 AttributesModel* BarDiagram::BarDiagramType::attributesModel() const
00152 {
00153     return m_private->attributesModel;
00154 }
00155 
00156 QModelIndex BarDiagram::BarDiagramType::attributesModelRootIndex() const
00157 {
00158     return diagram()->attributesModelRootIndex();
00159 }
00160 
00161 BarDiagram* BarDiagram::BarDiagramType::diagram() const
00162 {
00163     return static_cast< BarDiagram* >( m_private->diagram );
00164 }
00165 
00166 void BarDiagram::BarDiagramType::addLabel( LabelPaintCache* lpc,
00167                                            const QModelIndex& index, const PositionPoints& points,
00168                                            const Position& autoPositionPositive,
00169                                            const Position& autoPositionNegative, qreal value )
00170 {
00171     m_private->addLabel( lpc, index, 0, points,
00172                          autoPositionPositive, autoPositionNegative, value, -45 );
00173 }
00174 
00175 void BarDiagram::BarDiagramType::paintDataValueTextsAndMarkers(
00176     PaintContext* ctx,
00177     const LabelPaintCache& lpc,
00178     bool paintMarkers )
00179 {
00180     m_private->paintDataValueTextsAndMarkers( ctx, lpc, paintMarkers );
00181 }
00182 
00183 
00184 void BarDiagram::BarDiagramType::calculateValueAndGapWidths( int rowCount,int colCount,
00185                                              qreal groupWidth,
00186                                              qreal& outBarWidth,
00187                                              qreal& outSpaceBetweenBars,
00188                                              qreal& outSpaceBetweenGroups )
00189 {
00190 
00191     Q_UNUSED( rowCount );
00192 
00193     BarAttributes ba = diagram()->barAttributes();
00194 
00195     // Pending Michel Fixme
00196     /* We are colCount groups to paint. Each group is centered around the
00197      * horizontal point position on the grid. The full area covers the
00198      * values -1 to colCount + 1. A bar has a relative width of one unit,
00199      * the gaps between bars are 0.5 wide, and the gap between groups is
00200      * also one unit, by default. */
00201 
00202     qreal units;
00203     if( type() == Normal )
00204         units = colCount // number of bars in group * 1.0
00205                 + (colCount-1) * ba.barGapFactor() // number of bar gaps
00206                 + 1 * ba.groupGapFactor(); // number of group gaps
00207     else
00208         units = 1 + 1 * ba.groupGapFactor();
00209 
00210     qreal unitWidth = groupWidth / units;
00211     outBarWidth = unitWidth;
00212     outSpaceBetweenBars += unitWidth * ba.barGapFactor();
00213 
00214     // Pending Michel - minLimit: allow space between bars to be reduced until the bars are displayed next to each other.
00215     // is that what we want?
00216     // sebsauer; in the case e.g. CartesianCoordinatePlane::setHorizontalRangeReversed(true) was
00217     // used to reverse the values, we deal with negative outSpaceBetweenBars and unitWidth here
00218     // and since that's correct we don't like to lose e.g. the spacing here.
00219     //if ( outSpaceBetweenBars < 0 )
00220     //    outSpaceBetweenBars = 0;
00221 
00222     outSpaceBetweenGroups += unitWidth * ba.groupGapFactor();
00223 }
00224 
00225 ReverseMapper& BarDiagram::BarDiagramType::reverseMapper()
00226 {
00227     return m_private->reverseMapper;
00228 }
00229 
00230 CartesianDiagramDataCompressor& BarDiagram::BarDiagramType::compressor() const
00231 {
00232     return m_private->compressor;
00233 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines

Klarälvdalens Datakonsult AB (KDAB)
Qt-related services and products
http://www.kdab.com/
http://www.kdab.com/products/kd-chart/