KD Chart 2 [rev.2.4]
|
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 "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 //fixme adjust the painting to reasonable depth value 00057 switch ( type() ) 00058 { 00059 case BarDiagram::Normal: 00060 usedDepth = threeDAttrs.depth()/4; 00061 stackedMode = false; 00062 percentMode = false; 00063 break; 00064 case BarDiagram::Stacked: 00065 usedDepth = threeDAttrs.depth(); 00066 stackedMode = true; 00067 percentMode = false; 00068 break; 00069 case BarDiagram::Percent: 00070 usedDepth = threeDAttrs.depth(); 00071 stackedMode = false; 00072 percentMode = true; 00073 break; 00074 default: 00075 Q_ASSERT_X ( false, "dataBoundaries()", 00076 "Type item does not match a defined bar chart Type." ); 00077 } 00078 isoRect = bar.translated( usedDepth, -usedDepth ); 00079 // we need to find out if the height is negative 00080 // and in this case paint it up and down 00081 //qDebug() << isoRect.height(); 00082 if ( isoRect.height() < 0 ) { 00083 topPoints << isoRect.bottomLeft() << isoRect.bottomRight() 00084 << bar.bottomRight() << bar.bottomLeft(); 00085 if ( stackedMode ) { 00086 // fix it when several negative stacked values 00087 if ( index.column() == 0 ) { 00088 paintTop = true; 00089 } 00090 else 00091 paintTop = false; 00092 } 00093 00094 } else { 00095 reverseMapper().addRect( index.row(), index.column(), isoRect ); 00096 ctx->painter()->drawRect( isoRect ); 00097 topPoints << bar.topLeft() << bar.topRight() << isoRect.topRight() << isoRect.topLeft(); 00098 } 00099 00100 if ( percentMode && isoRect.height() == 0 ) 00101 paintTop = false; 00102 00103 bool needToSetClippingOffForTop = false; 00104 if ( paintTop ){ 00105 // Draw the top, if at least one of the top's points is 00106 // either inside or near at the edge of the coordinate plane: 00107 bool drawIt = false; 00108 bool hasPointOutside = false; 00109 const QRectF r( ctx->rectangle().adjusted(0,-1,1,0) ); 00110 KDAB_FOREACH( QPointF pt, topPoints ) { 00111 if( r.contains( pt ) ) 00112 drawIt = true; 00113 else 00114 hasPointOutside = true; 00115 } 00116 if( drawIt ){ 00117 const PainterSaver p( ctx->painter() ); 00118 needToSetClippingOffForTop = hasPointOutside && ctx->painter()->hasClipping(); 00119 if( needToSetClippingOffForTop ) 00120 ctx->painter()->setClipping( false ); 00121 reverseMapper().addPolygon( index.row(), index.column(), topPoints ); 00122 ctx->painter()->drawPolygon( topPoints ); 00123 } 00124 } 00125 00126 00127 00128 sidePoints << bar.topRight() << isoRect.topRight() << isoRect.bottomRight() << bar.bottomRight(); 00129 if ( bar.height() != 0 ){ 00130 const PainterSaver p( ctx->painter() ); 00131 if( needToSetClippingOffForTop ) 00132 ctx->painter()->setClipping( false ); 00133 reverseMapper().addPolygon( index.row(), index.column(), sidePoints ); 00134 ctx->painter()->drawPolygon( sidePoints ); 00135 } 00136 } 00137 00138 if( bar.height() != 0 ) 00139 { 00140 reverseMapper().addRect( index.row(), index.column(), bar ); 00141 ctx->painter()->drawRect( bar ); 00142 } 00143 // reset 00144 //diagram()->maxDepth = threeDAttrs.depth(); 00145 } 00146 00147 AttributesModel* BarDiagram::BarDiagramType::attributesModel() const 00148 { 00149 return m_private->attributesModel; 00150 } 00151 00152 QModelIndex BarDiagram::BarDiagramType::attributesModelRootIndex() const 00153 { 00154 return m_private->diagram->attributesModelRootIndex(); 00155 } 00156 00157 BarDiagram* BarDiagram::BarDiagramType::diagram() const 00158 { 00159 return m_private->diagram; 00160 } 00161 00162 void BarDiagram::BarDiagramType::appendDataValueTextInfoToList( 00163 AbstractDiagram * diagram, 00164 DataValueTextInfoList & list, 00165 const QModelIndex & index, 00166 const PositionPoints& points, 00167 const Position& autoPositionPositive, 00168 const Position& autoPositionNegative, 00169 const qreal value ) 00170 { 00171 m_private->appendDataValueTextInfoToList( diagram, list, index, 0, 00172 points, 00173 autoPositionPositive, autoPositionNegative, value ); 00174 } 00175 00176 void BarDiagram::BarDiagramType::paintDataValueTextsAndMarkers( 00177 AbstractDiagram* diagram, 00178 PaintContext* ctx, 00179 const DataValueTextInfoList & list, 00180 bool paintMarkers ) 00181 { 00182 m_private->paintDataValueTextsAndMarkers( diagram, ctx, list, paintMarkers ); 00183 } 00184 00185 00186 void BarDiagram::BarDiagramType::calculateValueAndGapWidths( int rowCount,int colCount, 00187 double groupWidth, 00188 double& outBarWidth, 00189 double& outSpaceBetweenBars, 00190 double& outSpaceBetweenGroups ) 00191 { 00192 00193 Q_UNUSED( rowCount ); 00194 00195 BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) ); 00196 00197 // Pending Michel Fixme 00198 /* We are colCount groups to paint. Each group is centered around the 00199 * horizontal point position on the grid. The full area covers the 00200 * values -1 to colCount + 1. A bar has a relative width of one unit, 00201 * the gaps between bars are 0.5 wide, and the gap between groups is 00202 * also one unit, by default. */ 00203 00204 double units; 00205 if( type() == Normal ) 00206 units = colCount // number of bars in group * 1.0 00207 + (colCount-1) * ba.barGapFactor() // number of bar gaps 00208 + 1 * ba.groupGapFactor(); // number of group gaps 00209 else 00210 units = 1 + 1 * ba.groupGapFactor(); 00211 00212 double unitWidth = groupWidth / units; 00213 outBarWidth = unitWidth; 00214 outSpaceBetweenBars += unitWidth * ba.barGapFactor(); 00215 00216 // Pending Michel - minLimit: allow space between bars to be reduced until the bars are displayed next to each other. 00217 // is that what we want? 00218 // sebsauer; in the case e.g. CartesianCoordinatePlane::setHorizontalRangeReversed(true) was 00219 // used to reverse the values, we deal with negative outSpaceBetweenBars and unitWidth here 00220 // and since that's correct we don't like to lose e.g. the spacing here. 00221 //if ( outSpaceBetweenBars < 0 ) 00222 // outSpaceBetweenBars = 0; 00223 00224 outSpaceBetweenGroups += unitWidth * ba.groupGapFactor(); 00225 } 00226 00227 ReverseMapper& BarDiagram::BarDiagramType::reverseMapper() 00228 { 00229 return m_private->reverseMapper; 00230 } 00231 00232 CartesianDiagramDataCompressor& BarDiagram::BarDiagramType::compressor() const 00233 { 00234 return m_private->compressor; 00235 }