KD Chart 2
[rev.2.5]
|
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 }