kchart

KDChartBarPainter.cpp

00001 /* -*- Mode: C++ -*-
00002    KDChart - a multi-platform charting engine
00003 */
00004 
00005 /****************************************************************************
00006  ** Copyright (C) 2001-2003 Klarälvdalens Datakonsult AB.  All rights reserved.
00007  **
00008  ** This file is part of the KDChart 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 KDChart licenses may use this file in
00016  ** accordance with the KDChart 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.klaralvdalens-datakonsult.se/?page=products for
00023  **   information about KDChart Commercial License Agreements.
00024  **
00025  ** Contact info@klaralvdalens-datakonsult.se if any conditions of this
00026  ** licensing are not clear to you.
00027  **
00028  **********************************************************************/
00029 #include "KDChartBarPainter.h"
00030 #include <KDChartParams.h>
00031 
00032 #include <qpainter.h>
00033 
00034 #include <stdlib.h>
00035 
00047 KDChartBarPainter::KDChartBarPainter( KDChartParams* params ) :
00048   KDChartAxesPainter( params )
00049 {
00050   // This constructor intentionally left blank so far; we cannot setup the
00051   // geometry yet since we do not know the size of the painter.
00052 }
00053 
00054 
00058 KDChartBarPainter::~KDChartBarPainter()
00059 {
00060   // intentionally left blank
00061 }
00062 
00063 bool KDChartBarPainter::isNormalMode() const
00064 {
00065   return KDChartParams::BarNormal == params()->barChartSubType();
00066 }
00067 
00068 int KDChartBarPainter::clipShiftUp( bool normalMode, double areaWidthP1000 ) const
00069 {
00070   const bool bThreeDBars = params()->threeDBars() || (KDChartParams::BarMultiRows == params()->barChartSubType());
00071   return   ( normalMode && !bThreeDBars )
00072     ? static_cast < int > ( areaWidthP1000 * 16.0 )
00073     : 0;
00074 }
00075 
00076 
00077 void KDChartBarPainter::initMyPainter( QPainter* painter )
00078 {
00079   _myPainter = painter;
00080   _painterDX = 0.0;
00081   _painterDY = 0.0;
00082 }
00083 
00084 void KDChartBarPainter::shiftMyPainter( double dx, double dy )
00085 {
00086   if( dx != 0.0 || dy != 0.0 ){
00087     _myPainter->translate(dx, dy);
00088     _painterDX += dx;
00089     _painterDY += dy;
00090   }
00091 }
00092 
00093 void KDChartBarPainter::shiftMyPainterBack()
00094 {
00095   if( _painterDX != 0.0 || _painterDY != 0.0 ){
00096     _myPainter->translate(-_painterDX, -_painterDY);
00097     _painterDX = 0.0;
00098     _painterDY = 0.0;
00099   }
00100 }
00101 
00102 
00103 void KDChartBarPainter::calculateXFront1_2( bool bNormalMode, bool bIsVeryFirstBar, bool bIsFirstDataset, bool _bThreeDBars,
00104                                             double xpos, double valueBlockGap, double datasetGap, double frontBarWidth,
00105                                             int& frontX1, int& frontX2, int& prevFrontX2 ){
00106 
00107 
00108   //Debug ( "xpos %s", QString::number( xpos ).latin1());
00109   //qDebug ( "valueBlockGap %s", QString::number(valueBlockGap ).latin1());
00110   //qDebug ( "datasetGap %s", QString::number(valueBlockGap ).latin1()); 
00111   if( _bThreeDBars || bIsVeryFirstBar || !bNormalMode ){
00112     frontX1 = static_cast<int>( xpos );
00113   }else if( bIsFirstDataset ){
00114     // micro-adjust the gap between the previous bar and this bar
00115     frontX1 = prevFrontX2 + static_cast < int > ( valueBlockGap ) + 1;
00116   }else{
00117     frontX1 = prevFrontX2 + static_cast < int > ( datasetGap ) + 1;//static_cast<int>( xpos );
00118   }
00119   // Note: frontX2 is calculated by using xpos but NOT by using frontX1.
00120   //       So we make sure that (a) the gaps between all bars of one dataset
00121   //       are exactly the same size, and that (b) the bars are automatically
00122   //       adjusted in their width: to match their very position within the abscissa range.
00123   //       Adjusting will result in them being ONE pixel wider sometimes.
00124   frontX2 = static_cast < int > ( xpos + frontBarWidth );
00125 
00126   //qDebug("prevFrontX2: %i    gap: %i    frontX1: %i    frontX2: %i", prevFrontX2, static_cast < int > ( valueBlockGap ), frontX1, frontX2);
00127   //qDebug("xpos: %f", xpos);
00128   prevFrontX2 = frontX2;
00129 }
00130 
00131 
00132 void KDChartBarPainter::specificPaintData( QPainter* painter,
00133                        const QRect& ourClipRect,
00134                        KDChartTableDataBase* data,
00135                        KDChartDataRegionList* regions,
00136                        const KDChartAxisParams* ordinatePara,
00137                        bool bNormalMode,
00138                        uint chart,
00139                        double logWidth,
00140                        double areaWidthP1000,
00141                        double logHeight,
00142                        double axisYOffset,
00143                        double minColumnValue,
00144                        double maxColumnValue,
00145                        double columnValueDistance,
00146                        uint chartDatasetStart,
00147                        uint chartDatasetEnd,
00148                        uint datasetStart,
00149                        uint datasetEnd )
00150 {
00151   /****************Pending Michel***********************
00152    *Rectangles are painted in the following order:     * 
00153    *front , right side, top.                           *
00154    *Store the painted rectangles in order to paint     *
00155    *them in relation to each other for more precision. *
00156    ****************************************************/
00157   QRect frontRectPositive,frontRectNegative, 
00158     rightRectPositive, rightRectNegative, 
00159     excessRectPositive,excessRectNegative;
00160   //Pending: Michel
00161   //qDebug ("painting the rect");
00162   //painter->fillRect( _dataRect, Qt::green);
00163   _areaP1000 = areaWidthP1000;
00164 
00165   if( !data ) return;
00166   // qDebug("datasetStart: %i    datasetEnd: %i", datasetStart, datasetEnd);
00167   const QPen defaultOutlinePen( params()->outlineDataColor(),
00168                 params()->outlineDataLineWidth(),
00169                 params()->outlineDataLineStyle() );
00170 
00171   abscissaInfos ai;
00172   ai.bCenterThePoints = true;
00173   calculateAbscissaInfos( *params(), *data,
00174               datasetStart, datasetEnd,
00175               logWidth, _dataRect,
00176               ai );
00177 
00178   const QRect devRect( painter->window() );
00179 
00180   initMyPainter( painter );
00181 
00182   const bool ordinateIsLogarithmic
00183     = KDChartAxisParams::AxisCalcLogarithmic == ordinatePara->axisCalcMode();
00184 
00185   const bool bMultiRows = KDChartParams::BarMultiRows == params()->barChartSubType();
00186   _bThreeDBars = params()->threeDBars() || bMultiRows;
00187   int numChartDataEntryDatasets = 0;
00188   uint myLastDataEntryDataset = 0;
00189   for( uint iD = chartDatasetStart; iD <= chartDatasetEnd; ++iD ){
00190     if( params()->chartSourceMode( iD ) == KDChartParams::DataEntry ){
00191       ++numChartDataEntryDatasets;
00192       myLastDataEntryDataset = iD;
00193     }
00194   }
00195 
00196   const bool bHadClipping = painter->hasClipping();
00197   if( bMultiRows )
00198     painter->setClipping( false );
00199 
00200   // Number of columns in one dataset: If -1, use all values,
00201   // otherwise use the specified number of values.
00202   int numValues = 0;
00203   if ( params()->numValues() != -1 )
00204     numValues = params()->numValues();
00205   else
00206     numValues = data->usedCols();
00207 
00208   double datasetGap = bMultiRows
00209     ? 0.0
00210     : params()->datasetGap()
00211     * (   params()->datasetGapIsRelative()
00212       ? areaWidthP1000
00213       : 1.0 );
00214   double valueBlockGap = bMultiRows
00215     ? 0.0
00216     : params()->valueBlockGap()
00217     * (   params()->valueBlockGapIsRelative()
00218       ? areaWidthP1000
00219       : 1.0 );
00220 
00221   // This is the same for all three bar types except for multi-bar Surface charts.
00222   double spaceBetweenValueBlocks = bMultiRows
00223     ? 0.0
00224     : valueBlockGap * numValues;
00225 
00226   // Set some geometry values that apply to bar charts only
00227   double totalNumberOfBars = 0.0;
00228   double spaceBetweenDatasets = 0.0;
00229   switch ( params()->barChartSubType() ) {
00230   case KDChartParams::BarNormal: {
00231     totalNumberOfBars = numChartDataEntryDatasets * numValues;
00232     spaceBetweenDatasets = datasetGap
00233       * ( totalNumberOfBars - numValues );
00234     break;
00235   }
00236   case KDChartParams::BarStacked:
00237   case KDChartParams::BarPercent:
00238   case KDChartParams::BarMultiRows:
00239     totalNumberOfBars = numValues;
00240     spaceBetweenDatasets = 0; // always 0 when stacked/percent/multi-rows
00241     break;
00242   default:
00243     qFatal( "Unsupported bar chart type" );
00244   };
00245 
00246   double barWidth;
00247   if( params()->barWidth() == KDCHART_AUTO_SIZE )
00248     barWidth = ( (   logWidth
00249              - spaceBetweenValueBlocks
00250              - spaceBetweenDatasets )
00251          / totalNumberOfBars );
00252   else if( 0 > params()->barWidth() )
00253     barWidth = params()->barWidth() * -areaWidthP1000;
00254   else
00255     barWidth = params()->barWidth();
00256 
00257   const double sideBarWidth = _bThreeDBars
00258     ? ( barWidth - barWidth / (1.0 + params()->cosThreeDBarAngle()) ) *
00259     params()->threeDBarDepth()
00260     : 0.0;
00261   const double frontBarWidth = _bThreeDBars && !bMultiRows
00262     ? barWidth - sideBarWidth
00263     : barWidth;
00264   const double sideBarHeight = sideBarWidth;
00265 
00266   double pixelsPerUnit = 0.0;
00267   if ( params()->barChartSubType() != KDChartParams::BarPercent )  // not used for percent
00268     pixelsPerUnit = logHeight / ( columnValueDistance ? columnValueDistance : 10 );
00269 
00270   //qDebug("\nordinatePara->trueAxisLow()  = %f", ordinatePara->trueAxisLow());
00271   //qDebug(  "ordinatePara->trueAxisHigh() = %f", ordinatePara->trueAxisHigh());
00272   //qDebug(  "sideBarHeight            = %f", sideBarHeight);
00273   //qDebug(  "pixelsPerUnit            = %f", pixelsPerUnit);
00274 
00275   double zeroXAxisI;
00276   if ( params()->barChartSubType() == KDChartParams::BarPercent ) {
00277     if ( minColumnValue == 0.0 )
00278       zeroXAxisI = 0.0;
00279     else if ( maxColumnValue == 0.0 )
00280       zeroXAxisI = logHeight - sideBarHeight;
00281     else
00282       zeroXAxisI = ( logHeight - sideBarHeight ) / 2.0;
00283   } else {
00284     zeroXAxisI = logHeight
00285       - ordinatePara->axisZeroLineStartY()
00286       + _dataRect.y();
00287   }
00288 
00289   double shiftUpperBars =    (params()->barChartSubType() != KDChartParams::BarPercent)
00290     && (ordinatePara->axisTrueLineWidth() % 2)
00291     ? 1.0
00292     : 0.0;
00293 
00294   // Initializing drawing positions
00295   double yposPositivesStart = logHeight;
00296   double yposNegativesStart = logHeight;
00297   if( params()->barChartSubType() == KDChartParams::BarPercent ){
00298     yposPositivesStart += axisYOffset;
00299     yposNegativesStart += axisYOffset;
00300   }
00301 
00302   for ( int iPaintExtraLinesOrTheData = 0;
00303     iPaintExtraLinesOrTheData < 3;
00304     ++iPaintExtraLinesOrTheData )
00305     {
00306       
00307       const bool bDrawExtraLines        = (1 != iPaintExtraLinesOrTheData);
00308       const bool bDrawExtraLinesInFront = (2 == iPaintExtraLinesOrTheData);
00309 
00310       double xpos = 0.0 + valueBlockGap / 2.0;
00311 
00312       double yposPositives = yposPositivesStart;
00313       double yposNegatives = yposNegativesStart;
00314 
00315       /* Pending Michel: no need for this anymore */
00316       //double totalThreeDBarWidth = bMultiRows
00317       //? barWidth + sideBarWidth
00318       //    : barWidth;
00319 
00320       double nShiftX = bMultiRows
00321     ? sideBarWidth
00322     : 0.0;
00323       double nShiftY = bMultiRows
00324     ? sideBarHeight
00325     : 0.0;
00326 
00327       double valueTotal = 0.0; // valueTotal is used for percent bars only
00328 
00329       // iterate over all columns: item1, item2, item3 ...
00330       int prevFrontX2 = 0;
00331       bool bIsVeryFirstBar = true;
00332       for ( int value = 0; value < numValues; ++value ) {
00333 
00334     bool bFirstValidValueUnknown = true;
00335     uint firstValidValue = 0;
00336     uint lastValidPositiveValue  = 0;
00337     double maxValueInThisColumn = 0.0, minValueInThisColumn = 0.0;
00338     if ( params()->barChartSubType() == KDChartParams::BarStacked ||
00339          params()->barChartSubType() == KDChartParams::BarPercent ) {
00340       valueTotal = 0.0;
00341       // iterate over datasets of this axis only:
00342       for ( uint dataset  = datasetStart;
00343         dataset <= datasetEnd;
00344         ++dataset ) {
00345 
00346         QVariant vVal;
00347         if( data->cellCoord( dataset, value, vVal, 1 )
00348         && params()->chartSourceMode( dataset ) == KDChartParams::DataEntry
00349         && QVariant::Double == vVal.type() ){
00350 
00351           const double cellValue
00352         = ordinateIsLogarithmic
00353         ? log10( vVal.toDouble() )
00354         : vVal.toDouble();
00355           //qDebug("value   %u    dataset   %u   logHeight %f", value,dataset,logHeight);
00356 
00357           if( bFirstValidValueUnknown ){
00358         firstValidValue = dataset;
00359         bFirstValidValueUnknown = false;
00360           }
00361           if( 0.0 <= cellValue )
00362         lastValidPositiveValue = dataset;
00363 
00364           maxValueInThisColumn = QMAX( maxValueInThisColumn, cellValue );
00365           minValueInThisColumn = QMIN( minValueInThisColumn, cellValue );
00366           if( params()->barChartSubType() == KDChartParams::BarPercent )
00367         valueTotal += cellValue;
00368           //qDebug("a");
00369         }
00370       }
00371     }
00372 
00373     //qDebug("shiftMyPainter( (numChartDataEntryDatasets-1)*nShiftX, (numChartDataEntryDatasets-1)*-nShiftY );");
00374     shiftMyPainter( (numChartDataEntryDatasets-1)*nShiftX, (numChartDataEntryDatasets-1)*-nShiftY );
00375 
00376     // iterate over all datasets of this chart:
00377     // (but draw only the bars of this axis)
00378     bool bIsFirstDataset = true;
00379     for ( uint dataset = bMultiRows
00380         ? chartDatasetEnd
00381         : chartDatasetStart;
00382           dataset >= chartDatasetStart && dataset <= chartDatasetEnd;
00383           bMultiRows
00384         ? --dataset
00385         : ++dataset ) {
00386       //qDebug("value   %u    dataset   %u   logHeight %f", value,dataset,logHeight);
00387 
00388       const bool bDataEntrySourceMode
00389         = (params()->chartSourceMode( dataset ) == KDChartParams::DataEntry);
00390 
00391 
00392       QVariant coord1;
00393       QVariant coord2;
00394       int propID;
00395       if( data->cellContent( dataset, value, coord1, coord2, propID )
00396           && QVariant::Double == coord1.type() ){
00397 
00398         const double cellValue
00399           = ordinateIsLogarithmic
00400           ? log10( coord1.toDouble() )
00401           : coord1.toDouble();
00402         //qDebug("b");
00403         // there is a numeric value
00404 
00405         double barHeight;
00406         if ( params()->barChartSubType() == KDChartParams::BarPercent )
00407           //     barHeight = ( cellValue / valueTotal ) * logHeight;
00408           barHeight =   ( cellValue / valueTotal )
00409         * fabs( zeroXAxisI - logHeight + sideBarHeight );
00410         else {
00411           barHeight = pixelsPerUnit * cellValue;
00412                       
00413           if( 0.0 <= barHeight ) 
00414         //barHeight = QMAX(0.0, barHeight - sideBarHeight);
00415         barHeight = barHeight - sideBarHeight;                                                  
00416           else 
00417         barHeight -= sideBarHeight;
00418         }
00419         
00420 
00421         // This little adjustment avoids a crash when trying
00422         // to retrieve the bounding rect of a zero size region...
00423         if( 0 == barHeight || 0.0 == barHeight ) {
00424           barHeight = 1.0; // makes sense to have a min size anyway
00425         }
00426 
00427         // draw only the bars belonging to the axis
00428         // which we are processing currently
00429         if( dataset >= datasetStart && dataset <= datasetEnd ) {
00430           //qDebug("b2");
00431 
00432           // calculate Abscissa axis value, if there are X coordinates
00433           // ---------------------------------------------------------
00434           bool skipMe = false;
00435           if( ai.bCellsHaveSeveralCoordinates ){
00436         skipMe = !calculateAbscissaAxisValue( coord2,
00437                               ai, 0, xpos );
00438         // adjust bar position to have it horizontally centered to the point
00439         if( ai.bAbscissaHasTrueAxisDtValues &&
00440             QVariant::DateTime == coord2.type() )
00441           xpos -= frontBarWidth / 2.0;
00442           }
00443 
00444           if( !skipMe ){
00445         // Configure colors
00446         QColor myBarColor(     params()->dataColor(        dataset ) );
00447         QColor myShadow1Color( params()->dataShadow1Color( dataset ) );
00448         QColor myShadow2Color( params()->dataShadow2Color( dataset ) );
00449 
00450         // Get default values for extra lines and their markers
00451         const KDChartParams::LineMarkerStyle
00452           defaultMarkerStyle = params()->lineMarkerStyle( dataset );
00453         const QPen defaultPen(   params()->lineColor().isValid()
00454                      ? params()->lineColor()
00455                      : params()->dataColor( dataset ),
00456                      params()->lineWidth(),
00457                      params()->lineStyle( dataset ) );
00458 
00459         // --------------------------------------------------------
00460         // determine any 'extra' properties assigned to this cell
00461         // by traversing the property set chain (if necessary)
00462         // --------------------------------------------------------
00463         KDChartPropertySet propSet;
00464         bool bCellPropertiesFound =
00465           params()->calculateProperties( propID,
00466                          propSet );
00467         bool bShowThisBar = bDataEntrySourceMode;
00468         if( bCellPropertiesFound ){
00469           if( bShowThisBar && !bDrawExtraLines ){
00470             int  iDummy;
00471             if( propSet.hasOwnShowBar( iDummy, bShowThisBar ) ){
00472               // NOP
00473             }
00474             if( propSet.hasOwnBarColor( iDummy, myBarColor ) ){
00475               // adjust the shadow colors
00476               params()->calculateShadowColors( myBarColor,
00477                                myShadow1Color,
00478                                myShadow2Color );
00479             }
00480           }
00481         }
00482 
00483         if( !bDrawExtraLines || bCellPropertiesFound ){
00484 
00485           QRegion* region = 0;
00486           if( bDataEntrySourceMode && !bDrawExtraLines ){
00487             painter->setPen( defaultOutlinePen );
00488             if ( myBarColor.isValid() )
00489               painter->setBrush( myBarColor );
00490             else
00491               painter->setBrush( NoBrush );
00492 
00493             // Prepare region for detection of mouse clicks
00494             // and for finding anchor positions of data value texts
00495             if ( regions )
00496               region = new QRegion();
00497           }
00498 
00499           // Start drawing
00500           int frontX1 = 0;
00501           int frontX2 = 0;
00502                   bool tooLow = false;
00503                   bool tooHigh = false;
00504                  
00505 
00506           if ( cellValue <= 0 || cellValue < minColumnValue ) /*barHeight < 0*/{
00507             //
00508             //qDebug("Negative values:");
00509             // 
00510                     double maxValueYPos = maxColumnValue * pixelsPerUnit;
00511             //double minValueYPos = minColumnValue * pixelsPerUnit;
00512                     //double minDataValueYPos = maxValueYPos - minValueYPos;
00513             double yZero = yposNegatives - zeroXAxisI - sideBarHeight;
00514                                  
00515             tooLow = (barHeight - yZero + logHeight + axisYOffset) < 0;
00516             //   qDebug("\nbarHeight - yZero + logHeight = : %f - %f + %f + %f",
00517             //barHeight,yZero,logHeight,
00518             //barHeight - yZero + logHeight);
00519             //qDebug("low values-  value= %s", QString::number(cellValue).latin1());
00520                     /*we need to handle those values in case we have a negative view*/ 
00521                     if ( cellValue <= 0 && cellValue > maxColumnValue && minColumnValue < 0 && maxColumnValue < 0 )
00522               tooLow = true;
00523             if ( tooLow && bNormalMode) {
00524               //qDebug("toooo low - value= %s", QString::number(cellValue).latin1());
00525               //                  double height  = -1.0 * ( yZero  - logHeight );
00526               double delta   = 0.0125 * logHeight;
00527               double height  = -1*(-1.0 * (yZero  + sideBarHeight) - 2 * delta)/* + sideBarHeight*/;
00528               double height1 = height - 3.0 * delta;
00529             
00530               int yArrowGap = static_cast < int > ( 2.5 * delta );
00531               calculateXFront1_2( bNormalMode, bIsVeryFirstBar, bIsFirstDataset, _bThreeDBars,
00532                       xpos, valueBlockGap, datasetGap, frontBarWidth,
00533                       frontX1, frontX2, prevFrontX2 );
00534 
00535               const int xm = static_cast < int > ( (frontX1 + frontX2) / 2.0 );
00536               QRect rect( ourClipRect );
00537                                         
00538               rect.setHeight( static_cast<int>( rect.height() + 3.0 * delta ) );
00539               painter->setClipRect( rect );
00540 
00541               //Pending Michel: Make sure the point of the arrow is always at the same distance
00542               //from the X axis reference to the point of the arrow.
00543               int arrowXAxisGap;
00544               QPoint arrowTop(  xm,static_cast<int>( yZero + height1 + 2 * yArrowGap) );
00545               if ( arrowTop.y()== yposNegatives )
00546             arrowXAxisGap = -2;
00547               else
00548             arrowXAxisGap = static_cast <int> (yposNegatives - arrowTop.y() - 2);
00549 
00550               if( bDrawExtraLines ){
00551             drawExtraLinesAndMarkers(
00552                          propSet,
00553                          defaultPen,
00554                          defaultMarkerStyle,
00555                          xm, static_cast<int>( yZero + height1 ),
00556                          painter,
00557                          ai.abscissaPara,
00558                          ordinatePara,
00559                          areaWidthP1000,
00560                          logHeight/1000.0,
00561                          bDrawExtraLinesInFront );
00562               }else if( bShowThisBar ){
00563             if( params()->drawSolidExcessArrows() ) {
00564 
00565                           /* PENDING Michel:
00566                * Here we have two situations.
00567                * The value is too low because over the Min negative value
00568                            * or it is not within the configured view.
00569                */
00570               // Draw solid excess arrows negatives             
00571                 
00572                           QPointArray points( 5 );
00573               
00574               /*this works in a positive view -> 200 500*/ 
00575               points.setPoint( 0, frontX1, cellValue < 0  ? 
00576                        static_cast<int>(yZero+height1 - 3.0*delta)+(2*yArrowGap)+ arrowXAxisGap:
00577                        static_cast<int>( yZero + height1)+(2*yArrowGap)+ arrowXAxisGap);
00578               points.setPoint( 1, frontX2,cellValue < 0 ? 
00579                        static_cast<int>(yZero+height1 - 3.0*delta)+(2*yArrowGap)+ arrowXAxisGap:
00580                        static_cast<int>( yZero + height1)+(2*yArrowGap)+ arrowXAxisGap );
00581               points.setPoint( 2, frontX2, cellValue < 0 ? 
00582                        static_cast<int>(yZero+height1 - 3.0*delta)+(2*yArrowGap)+ arrowXAxisGap:
00583                        static_cast<int>( yZero + height1)+(2*yArrowGap)+ arrowXAxisGap);
00584               points.setPoint( 3, xm, cellValue < 0 ? 
00585                        static_cast<int>( yZero + height1)+(2*yArrowGap)+ arrowXAxisGap:
00586                        static_cast<int>(yZero+height1 - 3.0*delta)+(2*yArrowGap)+ arrowXAxisGap);
00587               points.setPoint( 4, frontX1, cellValue < 0  ? 
00588                        static_cast<int>(yZero+height1 - 3.0*delta)+(2*yArrowGap)+ arrowXAxisGap:
00589                        static_cast<int>( yZero + height1)+(2*yArrowGap)+ arrowXAxisGap);
00590 
00591               /* 0 between start and end -> -500 500*/
00592               if ( minColumnValue < 0 && maxColumnValue > 0 ) {
00593                 points.setPoint(0, points.point(0).x(), static_cast <int> (yposNegatives - zeroXAxisI) ); 
00594                 points.setPoint(1, points.point(1).x(), static_cast <int> (yposNegatives - zeroXAxisI) ); 
00595               }
00596 
00597               /* negative view -> -200 -500 */           
00598               if ( minColumnValue < 0 && maxColumnValue < 0 ) {
00599                             /*value negative or zero > maxColumnValue*/
00600                             if ( cellValue > maxColumnValue ) {
00601                               // the view is under Yaxis 0 level 
00602                               // we need to show a symbol for the bars which are over the Yaxis.
00603                               // calculate the coordinate and direction for the arrow.
00604                               // arrow downward for negative values and upward for positives value
00605                   int diffArrowBase = points.point(2).y() - points.point(3).y();                            
00606                   double maxValueYPos = maxColumnValue * pixelsPerUnit;
00607                   double minValueYPos = minColumnValue * pixelsPerUnit;
00608                   double adjustedArrow = (cellValue == 0 ? minValueYPos - maxValueYPos + diffArrowBase + 2:
00609                               minValueYPos - maxValueYPos - diffArrowBase + 1); 
00610                   points.setPoint( 0, frontX1, points.point(0).y() + static_cast <int> (adjustedArrow));
00611                   points.setPoint( 1, frontX2, points.point(1).y() + static_cast <int> (adjustedArrow ));
00612                   points.setPoint( 2, frontX2, points.point(2).y() + static_cast <int> (adjustedArrow));
00613                   points.setPoint( 3, xm, points.point(3).y() + static_cast <int> (adjustedArrow));
00614                   points.setPoint( 4, frontX1, points.point(4).y() + static_cast <int> (adjustedArrow));
00615                 }
00616                             /*value < mincolumn value*/
00617                             if ( cellValue < minColumnValue ) {
00618                   points.setPoint( 0, frontX1, static_cast <int> (maxValueYPos));
00619                   points.setPoint( 1, frontX2, static_cast <int> (maxValueYPos));
00620                 }
00621               }
00622                             
00623               /*Pending Michel: case setbarWidth */   
00624               //adjust the painting in case we have a user given Width allow it 
00625               //to be larger than the auto calculated width in case we want to overlap 
00626                                              
00627               if ( params()->userWidth() != 0 ) {
00628                 int userwidth = 0;                
00629                 if ( params()->userWidth() < 0 )
00630                   userwidth = static_cast <int> (params()->userWidth() * -areaWidthP1000);
00631                 else
00632                   userwidth = static_cast <int> (params()->userWidth() * areaWidthP1000);
00633                 //if ( userwidth < frontBarWidth ) {
00634                 QRect tmpRect ( points.point(0), points.point(2));          
00635                 points.setPoint(0, static_cast <int>(tmpRect.center().x() - userwidth/2), 
00636                         points.point(0).y());
00637                 points.setPoint(1, static_cast <int>(tmpRect.center().x() + userwidth/2),
00638                         points.point(1).y());
00639                 points.setPoint(2, static_cast <int>(tmpRect.center().x() + userwidth/2), 
00640                         points.point(2).y());
00641                 points.setPoint(4, static_cast <int>(tmpRect.center().x() - userwidth/2), 
00642                         points.point(4).y());
00643                 //}
00644               }
00645         
00646               painter->drawPolygon( points );
00647                                                      
00648                         
00649               //debugging the points
00650               /*
00651                 painter->drawText( points.point(0), "p0");
00652                 painter->drawText( points.point(1), "p1");
00653                 painter->drawText( points.point(2), "p2");
00654                 painter->drawText( points.point(3), "p3");
00655                 painter->drawText( points.point(4), "p4");
00656               */
00657                         
00658               //correct the y position: displaying position for the value label
00659               QPoint tpLeft (points.point(4).x(), points.point(4).y()/* - (2 * yArrowGap)*/);
00660               QPoint tpRight(points.point(2).x(), points.point(2).y()/* - (2 * yArrowGap)*/); 
00661 
00662               //store the front rectangle
00663               excessRectNegative.setTopLeft(tpLeft);
00664               excessRectNegative.setTopRight(tpRight);
00665               excessRectNegative.setBottomRight(points.point(1));
00666               excessRectNegative.setBottomLeft(points.point(0));
00667 
00668               // Don't use points for drawing after this!
00669               if( region ) {
00670                 points.translate( _dataRect.x(), _dataRect.y() );
00671                 *region += QRegion( points );
00672               }
00673             } else {                            
00674               // Draw split excess arrows negatives
00675 
00676               /* PENDING Michel:
00677                * Here we have two situations.
00678                * The value is too low because over the Min negative value
00679                            * The value is not within the configured view..
00680                */
00681               QPointArray points( 5 );
00682               /*this works in a positive view -> 200 500*/ 
00683               points.setPoint( 0, frontX1, cellValue < 0  ? 
00684                        static_cast<int>(yZero+height1 - 3.0*delta) + arrowXAxisGap:
00685                        static_cast<int>( yZero + height1)+(2 * yArrowGap)+ arrowXAxisGap);                   
00686               points.setPoint( 1, frontX2,cellValue < 0 ? 
00687                        static_cast<int>(yZero+height1 - 3.0*delta) + arrowXAxisGap:
00688                        static_cast<int>( yZero + height1)+(2 * yArrowGap)+ arrowXAxisGap);
00689               points.setPoint( 2, frontX2, cellValue < 0 ? 
00690                        static_cast<int>(yZero+height1 - 3.0*delta) + arrowXAxisGap:
00691                        static_cast<int>( yZero + height1)+(2 * yArrowGap)+ arrowXAxisGap);
00692               points.setPoint( 3, xm, cellValue < 0 ? 
00693                        static_cast<int>( yZero + height1) + arrowXAxisGap:
00694                        static_cast<int>(yZero+height1 - 3.0*delta)+(2 * yArrowGap)+ arrowXAxisGap);
00695               points.setPoint( 4, frontX1, cellValue < 0  ? 
00696                        static_cast<int>(yZero+height1 - 3.0*delta) + arrowXAxisGap:
00697                        static_cast<int>( yZero + height1)+(2 * yArrowGap)+ arrowXAxisGap);
00698              
00699               /* 0 between start and end -> -500 500*/
00700               if ( minColumnValue < 0 && maxColumnValue > 0 ) {
00701                 points.setPoint(0, points.point(0).x(), static_cast <int> (yposNegatives - zeroXAxisI) ); 
00702                 points.setPoint(1, points.point(1).x(), static_cast <int> (yposNegatives - zeroXAxisI) ); 
00703               }
00704 
00705               /* negative view -> -200 -500 */          
00706               if ( minColumnValue < 0 && maxColumnValue < 0 ) {
00707                             /*value negative or zero > maxColumnValue*/
00708                             if ( cellValue > maxColumnValue ) {
00709                               // the view is under Yaxis 0 level 
00710                               // we need to show a symbol for the bars which are over the Yaxis.
00711                               // calculate the coordinate and direction for the arrow.
00712                               // arrow downward for negative values and upward for positives value
00713                   int diffArrowBase = points.point(2).y() - points.point(3).y();                            
00714                   double maxValueYPos = maxColumnValue * pixelsPerUnit;
00715                   double minValueYPos = minColumnValue * pixelsPerUnit;
00716                   double adjustedArrow = (cellValue == 0 ? 
00717                               minValueYPos - maxValueYPos + diffArrowBase + 2:
00718                               minValueYPos - maxValueYPos - diffArrowBase + 1); 
00719                   points.setPoint( 0, frontX1, points.point(0).y() + static_cast <int> (adjustedArrow) 
00720                            +(2*yArrowGap));
00721                   points.setPoint( 1, frontX2, points.point(1).y() + static_cast <int> (adjustedArrow ) 
00722                            + (2*yArrowGap));
00723                   points.setPoint( 2, frontX2, points.point(2).y() + static_cast <int> (adjustedArrow) 
00724                            + (2*yArrowGap));
00725                   points.setPoint( 3, xm, points.point(3).y() + static_cast <int> (adjustedArrow) 
00726                            + (2*yArrowGap));
00727                   points.setPoint( 4, frontX1, points.point(4).y() + static_cast <int> (adjustedArrow) 
00728                            + (2*yArrowGap));
00729                 }
00730                             /*value < mincolumn value*/
00731                             if ( cellValue < minColumnValue ) {
00732                   points.setPoint( 0, frontX1, static_cast <int> (maxValueYPos));
00733                   points.setPoint( 1, frontX2, static_cast <int> (maxValueYPos));
00734                 }
00735               }
00736 
00737               //Pending Michel adjust the painting in case we have a user given Width 
00738                           //allow it to be larger than the auto calculated width in case we want 
00739                           //to overlap 
00740               if ( params()->userWidth() != 0 ) {
00741                 int userwidth = 0;                
00742                 if ( params()->userWidth() < 0 )
00743                   userwidth = static_cast <int> (params()->userWidth() * -areaWidthP1000);
00744                 else
00745                   userwidth = static_cast <int> (params()->userWidth() * areaWidthP1000);
00746                 //if ( userwidth < frontBarWidth ) {
00747                 QRect tmpRect ( points.point(0), points.point(2));          
00748                 points.setPoint(0, static_cast <int>(tmpRect.center().x() - userwidth/2), 
00749                         points.point(0).y());
00750                 points.setPoint(1, static_cast <int>(tmpRect.center().x() + userwidth/2),
00751                         points.point(1).y());
00752                 points.setPoint(2, static_cast <int>(tmpRect.center().x() + userwidth/2), 
00753                         points.point(2).y());
00754                 points.setPoint(4, static_cast <int>(tmpRect.center().x() - userwidth/2), 
00755                         points.point(4).y());
00756                 //}
00757               } 
00758 
00759               painter->drawPolygon( points );
00760                                      
00761               //store the excess front rectangle
00762               excessRectNegative.setTopLeft(points.point(4));
00763               excessRectNegative.setTopRight(points.point(2));
00764               excessRectNegative.setBottomRight(points.point(1));
00765               excessRectNegative.setBottomLeft(points.point(0));
00766 
00767 
00768               // Don't use points for drawing after this!
00769               if ( region ) {
00770                 points.translate( _dataRect.x(), _dataRect.y() );
00771                 *region += QRegion( points );
00772               }
00773 
00774               QPointArray points2( 6 );
00775                           points2.setPoint( 0, frontX1, cellValue < 0 ? 
00776                         static_cast<int>( yZero + height1 - 3.0 * delta ) + arrowXAxisGap:
00777                         static_cast<int>(yZero + height1) + arrowXAxisGap);
00778               points2.setPoint( 1, xm,      cellValue < 0 ? 
00779                         static_cast<int>(yZero + height1) + arrowXAxisGap:
00780                         static_cast<int>( yZero + height1 - 3.0 * delta ) + arrowXAxisGap);
00781               points2.setPoint( 2, frontX2, cellValue < 0 ? 
00782                         static_cast<int>(yZero + height1 - 3.0 * delta) + arrowXAxisGap:
00783                         static_cast<int>(yZero + height1) + arrowXAxisGap);
00784               points2.setPoint( 3, frontX2, cellValue < 0 ? 
00785                         static_cast<int>(yZero + height1 - 3.75 * delta) + arrowXAxisGap :
00786                         static_cast<int>(yZero + height1 - 0.75 * delta)  + arrowXAxisGap);
00787               points2.setPoint( 4, xm,      cellValue < 0 ? 
00788                         static_cast<int>(yZero + height1 - 0.75 * delta)  + arrowXAxisGap:
00789                         static_cast<int>(yZero + height1 - 3.75 * delta) + arrowXAxisGap);
00790               points2.setPoint( 5, frontX1, cellValue < 0 ? 
00791                         static_cast<int>(yZero + height1 - 3.75 * delta)  + arrowXAxisGap:
00792                         static_cast<int>(yZero + height1 - 0.75 * delta)  + arrowXAxisGap);   
00793               points2.translate( 0, yArrowGap );
00794               
00795                           if ( minColumnValue < 0 && maxColumnValue < 0 &&  cellValue > maxColumnValue ) {
00796                 // the view is under Yaxis 0 level 
00797                 // we need to show a symbol for the bars which are over the Yaxis.
00798                 // calculate the coordinate and direction for the arrow.
00799                 // arrow downward for negative values and upward for positives value
00800                 int diffArrowBase = points.point(2).y() - points.point(3).y();                            
00801                 double maxValueYPos = maxColumnValue * pixelsPerUnit;
00802                 double minValueYPos = minColumnValue * pixelsPerUnit;
00803                 double adjustedArrow = (cellValue == 0 ? minValueYPos - maxValueYPos + diffArrowBase + 2:
00804                             minValueYPos - maxValueYPos - diffArrowBase + 1); 
00805                 points2.translate( 0, 2*yArrowGap );
00806                 points2.setPoint( 0, frontX1, points2.point(0).y() + static_cast <int> (adjustedArrow) );
00807                 points2.setPoint( 1, xm,  points2.point(1).y() + static_cast <int> (adjustedArrow));
00808                 points2.setPoint( 2, frontX2, points2.point(2).y() + static_cast <int> (adjustedArrow));
00809                 points2.setPoint( 3, frontX2, points2.point(3).y() + static_cast <int> (adjustedArrow));
00810                 points2.setPoint( 4, xm, points2.point(4).y() + static_cast <int> (adjustedArrow));
00811                 points2.setPoint( 5, frontX1, points2.point(5).y() + static_cast <int> (adjustedArrow)); 
00812               }
00813               //Pending Michel adjust the painting in case we have a user given Width 
00814                           //allow it to be larger than the auto calculated width in case we want 
00815                           //to overlap 
00816               if ( params()->userWidth() != 0 ) {
00817                 int userwidth = 0;                
00818                 if ( params()->userWidth() < 0 )
00819                   userwidth = static_cast <int> (params()->userWidth() * -areaWidthP1000);
00820                 else
00821                   userwidth = static_cast <int> (params()->userWidth() * areaWidthP1000);
00822                 //if ( userwidth < frontBarWidth ) {
00823                                 
00824                 points2.setPoint(0, excessRectNegative.topLeft().x(),points2.point(0).y());
00825                 points2.setPoint(2, excessRectNegative.topRight().x(),points2.point(2).y());
00826                 points2.setPoint(3, excessRectNegative.topRight().x(),points2.point(3).y());
00827                 points2.setPoint(5, excessRectNegative.topLeft().x(),points2.point(5).y()); 
00828                 //}
00829               }
00830 
00831                           /*
00832                 painter->drawText( points2.point(0), "p+0");
00833                 painter->drawText( points2.point(1), "p+1");
00834                 painter->drawText( points2.point(2), "p+2");
00835                 painter->drawText( points2.point(3), "p+3");
00836                 painter->drawText( points2.point(4), "p+4");
00837                 painter->drawText( points2.point(5), "p+5");
00838               */
00839               painter->drawPolygon( points2 );
00840              
00841               if ( region ) {
00842                 QPointArray points2cpy( points2 );
00843                 points2cpy.detach();
00844                 points2cpy.translate( _dataRect.x(),
00845                           _dataRect.y() );
00846                 *region += QRegion( points2cpy );
00847               }
00848               if ( cellValue < 0 )
00849                 points2.translate( 0, yArrowGap );  
00850               else 
00851                 points2.translate( 0, -yArrowGap );
00852              
00853               painter->drawPolygon( points2 );
00854               // Don't use points2 for drawing after this!
00855               if ( region ) {
00856                 points2.translate( _dataRect.x(), _dataRect.y() );
00857                 *region += QRegion( points2 );
00858               }
00859             }
00860               }
00861               painter->setClipRect( ourClipRect );
00862             } /*if (tooLow && bNormalMode)*/
00863             else {
00864                       
00865               //
00866               // old code (sometimes not touching the grid):
00867               //QRect rec( xpos, yZero, frontBarWidth, -barHeight );
00868               //painter->drawRect( rec );
00869               //
00870                           
00871               int pt1Y = static_cast < int > ( yZero - barHeight /*- sideBarsHeight*/ );
00872               
00873               /*              
00874                       if ( cellValue != 0 ) {
00875                       pt1Y = static_cast <int> (cellValue * pixelsPerUnit * -2);
00876                       qDebug( "value %s",QString::number(static_cast <int> (cellValue)).latin1());
00877                       qDebug( "pt1Y %s", QString::number(static_cast <int> (cellValue * pixelsPerUnit * -2)).latin1()); 
00878                       }
00879                       else 
00880               
00881                       pt1Y = static_cast < int > ( yZero - barHeight);
00882                       */               
00883               calculateXFront1_2( bNormalMode, bIsVeryFirstBar, bIsFirstDataset, _bThreeDBars,
00884                       xpos, valueBlockGap, datasetGap, frontBarWidth,
00885                       frontX1, frontX2, prevFrontX2 );
00886 
00887               QPoint pt1( frontX1, pt1Y );
00888               QPoint pt2( frontX2,
00889                   static_cast < int > ( yZero + sideBarHeight) );
00890 
00891                                         
00892               if( 0.0 > maxColumnValue ){
00893             pt2.setY(pt2.y() - static_cast < int > (pixelsPerUnit * maxColumnValue));
00894               }
00895               if( pt2.y() < pt1Y ) {
00896             pt1.setY( pt2.y() );
00897             pt2.setY( pt1Y );
00898               }
00899               if( pt2.x() < frontX1 ) {
00900             pt1.setX( frontX2 );
00901             pt2.setX( frontX1 );
00902               }
00903               if( bDrawExtraLines ){
00904             int y = pt2.y();
00905             if( _bThreeDBars )
00906               y -= static_cast < int > ( sideBarHeight );
00907             drawExtraLinesAndMarkers(
00908                          propSet,
00909                          defaultPen,
00910                          defaultMarkerStyle,
00911                          (frontX1+frontX2)/2, y,
00912                          painter,
00913                          ai.abscissaPara,
00914                          ordinatePara,
00915                          areaWidthP1000,
00916                          logHeight/1000.0,
00917                          bDrawExtraLinesInFront );
00918               }else if( bShowThisBar ){
00919 
00920             QSize siz( pt2.x() - pt1.x(),
00921                    pt2.y() - pt1.y() );
00922             QRect rect( pt1, siz );
00923 
00924             if( 1.5 > frontBarWidth ){
00925               QPen oldPen( painter->pen() );
00926               painter->setPen( QPen(painter->brush().color(), 0) );
00927               painter->drawLine(pt1, QPoint(pt1.x(),pt2.y()));
00928               painter->setPen( oldPen );
00929             }else{
00930               // store the front rect negative
00931               if ( tooLow || cellValue < minColumnValue) { 
00932                                                                             
00933                 frontRectNegative.setTopLeft(excessRectNegative.bottomLeft());
00934                 frontRectNegative.setTopRight(excessRectNegative.bottomRight());
00935                 frontRectNegative.setBottomRight(excessRectNegative.topRight());
00936                 frontRectNegative.setBottomLeft(excessRectNegative.topLeft());
00937 
00938               } else {
00939                 frontRectNegative.setTopLeft(rect.topLeft());
00940                 frontRectNegative.setTopRight(rect.topRight());
00941                 frontRectNegative.setBottomRight(rect.bottomRight());
00942                 frontRectNegative.setBottomLeft(rect.bottomLeft());
00943               }
00944               //debug  lines and points
00945               /*
00946                 painter->drawLine( rect.topLeft(), rect.topRight());
00947                 painter->drawLine( rect.topRight(), rect.bottomRight());
00948                 painter->drawLine( rect.bottomRight(), rect.bottomLeft());
00949                 painter->drawLine( rect.bottomLeft(), rect.topLeft()); 
00950                 painter->drawText( frontRectNegative.topLeft(), "0f");
00951                 painter->drawText( frontRectNegative.topRight(), "1f");
00952                 painter->drawText( frontRectNegative.bottomRight(), "2f");
00953                 painter->drawText( frontRectNegative.bottomLeft(), "3f"); 
00954               */
00955 
00956                           //Pending Michel adjust the painting in case we have a user given Width 
00957                           //and it is not larger than the auto calculated width                          
00958               
00959               if ( params()->userWidth() != 0 ) {
00960                 int userwidth = 0;
00961                 if ( params()->userWidth() < 0 )
00962                   userwidth = static_cast <int> (params()->userWidth() * -areaWidthP1000);
00963                 else
00964                   userwidth = static_cast <int> (params()->userWidth() * areaWidthP1000);
00965                 //if ( userwidth < frontBarWidth ) {                            
00966                 rect.setLeft( static_cast <int> (rect.center().x() - (userwidth/2)));
00967                 rect.setRight( static_cast <int> (rect.center().x() + (userwidth/2)));
00968                 rect.setWidth( static_cast <int> (userwidth) );
00969                 frontRectNegative.setLeft( tooLow || cellValue < minColumnValue ? static_cast <int> (excessRectNegative.center().x() - (userwidth/2)):rect.left());
00970                 frontRectNegative.setRight( tooHigh ? static_cast <int> (excessRectNegative.center().x() + (userwidth/2)):rect.right());
00971                 //}
00972               }
00973               
00974               //drawing the front size negative values
00975               painter->drawRect( rect );                                                  
00976             }
00977             // Don't use rect for drawing after this!
00978             if ( region ) {
00979               rect.moveBy( _dataRect.x(), _dataRect.y() );
00980               *region += QRegion( rect );
00981             }
00982               }
00983             }
00984           } else {
00985             //
00986             //  Positive values:
00987             //
00988                     /*Pending Michel: all values under the min value are handled as negative*/
00989                     
00990                     double maxValueYPos = maxColumnValue * pixelsPerUnit;
00991             double minValueYPos = minColumnValue * pixelsPerUnit;
00992                     double minDataValueYPos = maxValueYPos - minValueYPos;
00993             double yZero = yposPositives - zeroXAxisI;
00994             
00995                     //qDebug( "yZero %s", QString::number( yZero ).latin1());
00996             //qDebug( "minDataValueYPos = %s",  QString::number( minDataValueYPos).latin1()); 
00997             //qDebug( "positive value %s",  QString::number( cellValue).latin1());          
00998             
00999             //Pending Michel: draw the default split excess arrows 
01000             //when the top back of the 3d chart reach the max Y value
01001             
01002             if(!_bThreeDBars) {
01003               tooHigh = (barHeight - yZero) > 0;      
01004             } else {
01005               //calculate the Y position for the top back line
01006               //  if it is over the max height pos - tooHigh becomes true
01007               int dataValueYPos = static_cast <int>( (cellValue * pixelsPerUnit) + sideBarHeight );
01008               tooHigh = dataValueYPos - (maxColumnValue * pixelsPerUnit) > 0;            
01009             }
01010                                
01011             if ( tooHigh && bNormalMode ) {                   
01012               double delta   = -0.0125 * logHeight;
01013               double height  = -1.0 * yZero
01014             - 2.0 * delta;
01015               double height1 = height + -3.0 * delta;
01016                       
01017               int yArrowGap = static_cast < int > ( 2.5 * delta );
01018               calculateXFront1_2( bNormalMode, bIsVeryFirstBar, bIsFirstDataset, _bThreeDBars,
01019                       xpos, valueBlockGap, datasetGap, frontBarWidth,
01020                       frontX1, frontX2, prevFrontX2 );
01021 
01022               const int xm = static_cast < int > ( (frontX1 + frontX2) / 2.0 );
01023               QRect rect( ourClipRect );
01024 
01025               rect.setTop( static_cast<int>( rect.top() + 3 * delta ) );
01026               rect.setHeight( static_cast<int>( rect.height() - 3 * delta ) );
01027               painter->setClipRect( rect );
01028                                         
01029               if( bDrawExtraLines ){                      
01030             drawExtraLinesAndMarkers(
01031                          propSet,
01032                          defaultPen,
01033                          defaultMarkerStyle,
01034                          xm, static_cast<int>( yZero + height1 ),
01035                          painter,
01036                          ai.abscissaPara,
01037                          ordinatePara,
01038                          areaWidthP1000,
01039                          logHeight/1000.0,
01040                          bDrawExtraLinesInFront );
01041               }else if( bShowThisBar ){                      
01042             if( params()->drawSolidExcessArrows() ) {
01043 
01044               // Draw solid excess arrows
01045               QPointArray points( 5 );                        
01046                           /*this works for positive config and 0 include config*/  
01047               points.setPoint( 0, frontX1, 
01048                        (minDataValueYPos < static_cast <int> (yZero))? 
01049                        static_cast <int> (minDataValueYPos-1):static_cast <int>(yZero));
01050               points.setPoint( 1, frontX2,
01051                        (minDataValueYPos < static_cast <int> (yZero))? 
01052                        static_cast <int> (minDataValueYPos-1):static_cast <int>(yZero));
01053               points.setPoint( 2, frontX2, static_cast<int>( yZero + height1 - 3.0 * delta ) 
01054                        + 2 * yArrowGap );
01055               points.setPoint( 3, xm,      static_cast<int>( yZero + height1 )               
01056                        + 2 * yArrowGap );
01057               points.setPoint( 4, frontX1, static_cast<int>( yZero + height1 - 3.0 * delta ) 
01058                        + 2 * yArrowGap );
01059              
01060               /*case where start and end value are negatives */
01061               if ( cellValue > maxColumnValue && 0 > maxColumnValue ) {
01062                 //qDebug( "cellValue positive > max =  %s",QString::number(cellValue).latin1()); 
01063                             points.setPoint( 0, frontX1,static_cast<int>( yZero + height1 - 3.0 * delta ) + 2 * yArrowGap);
01064                 points.setPoint( 1, frontX2,static_cast<int>( yZero + height1 - 3.0 * delta ) + 2 * yArrowGap);
01065               }
01066 
01067               //Pending Michel adjust the painting in case we have a user given Width 
01068                           //allow it to be larger than the auto calculated width in case we want 
01069                           //to overlap 
01070               if ( params()->userWidth() != 0 ) {
01071                 int userwidth = 0;                
01072                 if ( params()->userWidth() < 0 )
01073                   userwidth = static_cast <int> (params()->userWidth() * -areaWidthP1000);
01074                 else
01075                   userwidth = static_cast <int> (params()->userWidth() * areaWidthP1000);
01076                 //if ( userwidth < frontBarWidth ) {
01077                 QRect tmpRect ( points.point(0), points.point(2));          
01078                 points.setPoint(0, static_cast <int>(tmpRect.center().x() - userwidth/2), 
01079                         points.point(0).y());
01080                 points.setPoint(1, static_cast <int>(tmpRect.center().x() + userwidth/2),
01081                         points.point(1).y());
01082                 points.setPoint(2, static_cast <int>(tmpRect.center().x() + userwidth/2), 
01083                         points.point(2).y());
01084                 points.setPoint(4, static_cast <int>(tmpRect.center().x() - userwidth/2), 
01085                         points.point(4).y());
01086                 //}
01087               } 
01088 
01089               
01090               painter->drawPolygon( points );
01091                                             
01092               //correct the y position: displaying position for the value label
01093               QPoint tpLeft (points.point(4).x(), points.point(4).y() - 2 * yArrowGap);
01094               QPoint tpRight(points.point(2).x(), points.point(2).y() - 2 * yArrowGap);
01095 
01096               //debugging points
01097               /*
01098                 painter->drawText( points.point(0), "p0");
01099                 painter->drawText( points.point(1), "p1");
01100                 painter->drawText( points.point(2), "p2");
01101                 painter->drawText( points.point(3), "p3");
01102                 painter->drawText( points.point(4), "p4");
01103               */  
01104               
01105               //store the front rectangle
01106               excessRectPositive.setTopLeft(tpLeft);
01107               excessRectPositive.setTopRight(tpRight);
01108               excessRectPositive.setBottomRight(points.point(1));
01109               excessRectPositive.setBottomLeft(points.point(0));
01110 
01111               // Don't use points for drawing afte this!
01112               if( region ) {
01113                 points.translate( _dataRect.x(), _dataRect.y() );
01114                 *region += QRegion( points );
01115               }
01116             } else {
01117 
01118               // Draw split excess arrows (default)           
01119 
01120               /* PENDING Michel:
01121                * Here we have two situations.
01122                * The value is too high because over the Max positive value
01123                            * or it is not within the configured view.
01124                */
01125 
01126               QPointArray points( 5 );          
01127               /*this works for positive config and 0 include config*/  
01128               points.setPoint( 0, frontX1, 
01129                        (minDataValueYPos < static_cast <int> (yZero))? static_cast <int> (minDataValueYPos - 1) : static_cast <int>(yZero));
01130               points.setPoint( 1, frontX2, 
01131                        (minDataValueYPos < static_cast <int> (yZero))? static_cast<int> ( minDataValueYPos - 1) : static_cast <int>(yZero));
01132               points.setPoint( 2, frontX2, static_cast<int>( yZero + height1 - 3.0 * delta ) );
01133               points.setPoint( 3, xm,      static_cast<int>( yZero + height1 ) );
01134               points.setPoint( 4, frontX1, static_cast<int>( yZero + height1 - 3.0 * delta ) );
01135              
01136               /*case where start and end value are negatives */
01137               if ( cellValue > maxColumnValue && 0 > maxColumnValue ) {
01138                             points.setPoint( 0, frontX1, static_cast<int>( yZero + height1 - 3.0 * delta ));
01139                 points.setPoint( 1, frontX2, static_cast<int>( yZero + height1 - 3.0 * delta ));
01140               }
01141 
01142               //Pending Michel adjust the painting in case we have a user given Width 
01143                           //allow it to be larger than the auto calculated width in case we want 
01144                           //to overlap 
01145               if ( params()->userWidth() != 0 ) {
01146                 int userwidth = 0;                
01147                 if ( params()->userWidth() < 0 )
01148                   userwidth = static_cast <int> (params()->userWidth() * -areaWidthP1000);
01149                 else
01150                   userwidth = static_cast <int> (params()->userWidth() * areaWidthP1000);
01151                 //if ( userwidth < frontBarWidth ) {
01152                 QRect tmpRect ( points.point(0), points.point(2));          
01153                 points.setPoint(0, static_cast <int>(tmpRect.center().x() - userwidth/2), 
01154                         points.point(0).y());
01155                 points.setPoint(1, static_cast <int>(tmpRect.center().x() + userwidth/2),
01156                         points.point(1).y());
01157                 points.setPoint(2, static_cast <int>(tmpRect.center().x() + userwidth/2), 
01158                         points.point(2).y());
01159                 points.setPoint(4, static_cast <int>(tmpRect.center().x() - userwidth/2), 
01160                         points.point(4).y());
01161                 //}
01162               } 
01163 
01164 
01165               //drawing a single front in case it is too hight
01166               painter->drawPolygon( points );
01167 
01168               //debugging points
01169               /*
01170                 painter->drawText( points.point(0), "p0");
01171                 painter->drawText( points.point(1), "p1");
01172                 painter->drawText( points.point(2), "p2");
01173                 painter->drawText( points.point(3), "p3");
01174                 painter->drawText( points.point(4), "p4");
01175               */                                       
01176               //store the front rectangle
01177               excessRectPositive.setTopLeft(points.point(4));
01178               excessRectPositive.setTopRight(points.point(2));
01179               excessRectPositive.setBottomRight(points.point(1));
01180               excessRectPositive.setBottomLeft(points.point(0));                       
01181 
01182               // Don't use points for drawing after this!
01183               if ( region ) {
01184                 points.translate( _dataRect.x(), _dataRect.y() );
01185                 *region += QRegion( points );
01186               }
01187 
01188               QPointArray points2( 6 );
01189               points2.setPoint( 0, frontX1, static_cast<int>( yZero + height1 - 3.0 * delta ) );
01190               points2.setPoint( 1, xm,      static_cast<int>( yZero + height1 ) );
01191               points2.setPoint( 2, frontX2, static_cast<int>( yZero + height1 - 3.0 * delta ) );
01192               points2.setPoint( 3, frontX2, static_cast<int>( yZero + height1 - 3.75 * delta ) );
01193               points2.setPoint( 4, xm,      static_cast<int>( yZero + height1 - 0.75 * delta ) );
01194               points2.setPoint( 5, frontX1, static_cast<int>( yZero + height1 - 3.75 * delta ) );
01195               points2.translate( 0, yArrowGap );
01196 
01197               //Pending Michel adjust the painting in case we have a user given Width 
01198                           //allow it to be larger than the auto calculated width in case we want 
01199                           //to overlap 
01200               if ( params()->userWidth() != 0 ) {
01201                 int userwidth = 0;                
01202                 if ( params()->userWidth() < 0 )
01203                   userwidth = static_cast <int> (params()->userWidth() * -areaWidthP1000);
01204                 else
01205                   userwidth = static_cast <int> (params()->userWidth() * areaWidthP1000);
01206                 //if ( userwidth < frontBarWidth ) {                                
01207                 points2.setPoint(0, excessRectPositive.topLeft().x(),points2.point(0).y());
01208                 points2.setPoint(2, excessRectPositive.topRight().x(),points2.point(2).y());
01209                 points2.setPoint(3, excessRectPositive.topRight().x(),points2.point(3).y());
01210                 points2.setPoint(5, excessRectPositive.topLeft().x(),points2.point(5).y()); 
01211                 //}
01212               }
01213 
01214 
01215               painter->drawPolygon( points2 );
01216               //debugging points
01217               /*
01218                 painter->drawText( points2.point(0), "point0");
01219                 painter->drawText( points2.point(1), "point1");
01220                 painter->drawText( points2.point(2), "point2");
01221                 painter->drawText( points2.point(3), "point3");
01222                 painter->drawText( points2.point(4), "point4");
01223               */
01224               if ( region ) {
01225                 QPointArray points2cpy( points2 );
01226                 points2cpy.detach();
01227                 points2cpy.translate( _dataRect.x(),
01228                           _dataRect.y() );
01229                 *region += QRegion( points2cpy );
01230               }
01231               points2.translate( 0, yArrowGap );
01232               painter->drawPolygon( points2 );
01233 
01234               // Don't use points2 for drawing after this!
01235               if ( region ) {
01236                 points2.translate( _dataRect.x(), _dataRect.y() );
01237                 *region += QRegion( points2 );
01238               }
01239             } // draw split excess arrow
01240               } //if( bShowThisBar )
01241                                    
01242               painter->setClipRect( ourClipRect );
01243             } // not tooLow  && bNormalMode )  
01244             else {                      
01245               //bool fromBottom = bNormalMode && !_bThreeDBars;
01246               double y0 = yposPositives - zeroXAxisI;
01247                                         
01248               int pt1Y = static_cast < int > ( y0 - barHeight - sideBarHeight);
01249                                         
01250               calculateXFront1_2( bNormalMode, bIsVeryFirstBar, bIsFirstDataset, _bThreeDBars,
01251                       xpos, valueBlockGap, datasetGap, frontBarWidth,
01252                       frontX1, frontX2, prevFrontX2 );
01253                                        
01254               QPoint pt1( frontX1, pt1Y );
01255               QPoint pt2( frontX2,
01256                   static_cast < int > ( y0 + shiftUpperBars ) );
01257                 
01258               if( 0.0 < minColumnValue )
01259             pt2.setY(pt2.y() - static_cast < int > ( pixelsPerUnit * minColumnValue ));
01260                                         
01261               if( pt2.y() < pt1Y ) {
01262             pt1.setY( pt2.y() );
01263             pt2.setY( pt1Y );
01264               }
01265               if( pt2.x() < frontX1 ) {
01266             pt1.setX( frontX2 );
01267             pt2.setX( frontX1 );
01268               }
01269               if( bDrawExtraLines ){
01270             int y = pt1.y();
01271             if( _bThreeDBars ) 
01272               y -= static_cast < int > ( sideBarHeight );
01273                         
01274             drawExtraLinesAndMarkers(
01275                          propSet,
01276                          defaultPen,
01277                          defaultMarkerStyle,
01278                          (frontX1+frontX2)/2, y,
01279                          painter,
01280                          ai.abscissaPara,
01281                          ordinatePara,
01282                          areaWidthP1000,
01283                          logHeight/1000.0,
01284                          bDrawExtraLinesInFront );
01285               }else if( bShowThisBar ){
01286                                           
01287                                             
01288             QSize siz( pt2.x() - pt1.x(),
01289                    pt2.y() - pt1.y());
01290 
01291             QRect rect(  pt1, siz );
01292             //Pending Michel adjust the bottom of the rect to the XAxis - we need this when the startAxis > yZero
01293             rect.setBottom(static_cast <int> (yZero));
01294 
01295             // store the front rect
01296             if( tooHigh ) {
01297               frontRectPositive.setTopLeft(excessRectPositive.topLeft());
01298               frontRectPositive.setTopRight(excessRectPositive.topRight());
01299               frontRectPositive.setBottomRight(excessRectPositive.bottomRight());
01300               frontRectPositive.setBottomLeft(excessRectPositive.bottomLeft());
01301             } else {
01302               frontRectPositive.setTopLeft(rect.topLeft());
01303               frontRectPositive.setTopRight(rect.topRight());
01304               frontRectPositive.setBottomRight(rect.bottomRight());
01305               frontRectPositive.setBottomLeft(rect.bottomLeft());
01306             }
01307 
01308             if( 1.5 > frontBarWidth ){
01309               //qDebug("1.5 > frontBarWidth ");
01310               QPen oldPen( painter->pen() );
01311               painter->setPen( QPen(painter->brush().color(), 0) );
01312               painter->drawLine(pt1, QPoint(pt1.x(),pt2.y()));
01313               painter->setPen( oldPen );
01314             }else{
01315               //debugging points and lines
01316               /*
01317                 painter->drawText( rect.topLeft(), "0f");
01318                 painter->drawText( rect.topRight(), "1f");
01319                 painter->drawText( rect.bottomRight(), "2f");
01320                 painter->drawText( rect.bottomLeft(), "3f");
01321                 painter->drawLine( rect.topLeft(), rect.topRight());
01322                 painter->drawLine( rect.topRight(), rect.bottomRight());
01323                 painter->drawLine( rect.bottomRight(), rect.bottomLeft());
01324                 painter->drawLine( rect.bottomLeft(), rect.topLeft());
01325               */
01326             
01327                            
01328                           //Pending Michel adjust the painting in case we have a user given Width 
01329                           //allow it to be larger than the auto calculated width in case we want 
01330                           //to overlap                          
01331               if ( params()->userWidth() != 0 ) {
01332                 int userwidth = 0;
01333                 if ( params()->userWidth() < 0 )
01334                   userwidth = static_cast <int> (params()->userWidth() * -areaWidthP1000);
01335                 else
01336                   userwidth = static_cast <int> (params()->userWidth() * areaWidthP1000);
01337                 //if ( userwidth < frontBarWidth ) {
01338                 rect.setLeft( static_cast <int> (rect.center().x() - (userwidth/2)));
01339                 rect.setRight( static_cast <int> (rect.center().x() + (userwidth/2)));
01340                 rect.setWidth( static_cast <int> (userwidth) );
01341                 //adjust the front rect
01342                 frontRectPositive.setLeft( tooHigh ? static_cast <int> (excessRectPositive.center().x() - (userwidth/2)):rect.left());
01343                 frontRectPositive.setRight( tooHigh ? static_cast <int> (excessRectPositive.center().x() + (userwidth/2)):rect.right());
01344                 //}
01345               }
01346                           
01347               //drawing the front side 
01348               //Pending Michel: paint always when percent or stacked
01349               if (!tooHigh && !tooLow || params()->barChartSubType() == KDChartParams::BarPercent
01350                   || params()->barChartSubType() == KDChartParams::BarStacked)
01351                 painter->drawRect( rect );                                                        
01352                   
01353 
01354               // Don't use rect for drawing after this
01355                     
01356               if ( region ) {
01357                 rect.moveBy( _dataRect.x(), _dataRect.y() );
01358                 *region += QRegion( rect );
01359               }
01360                      
01361             }
01362               } // bShowThisBar
01363             } // positive values
01364           }
01365           if ( bShowThisBar && _bThreeDBars &&  !bDrawExtraLines ) {
01366             //Pending Michel: no need to use that anymore 
01367             //const int maxY = 2*devRect.height();
01368             QPointArray points( 4 );
01369                                     
01370             if (cellValue <= 0 || cellValue < minColumnValue) {                                         
01371               if ( tooLow || cellValue < minColumnValue ) {
01372             points.setPoint(0, excessRectNegative.topRight());
01373             points.setPoint(1, excessRectNegative.topRight().x() +  static_cast<int>(sideBarHeight), 
01374                     excessRectNegative.top() - static_cast<int>(sideBarHeight));
01375             points.setPoint(2, excessRectNegative.bottomRight().x() + static_cast<int>(sideBarHeight), 
01376                     excessRectNegative.bottom() - static_cast<int>(sideBarHeight));                     
01377             points.setPoint(3, excessRectNegative.bottomRight());
01378               } else {
01379             points.setPoint( 0, frontRectNegative.bottomRight());
01380             points.setPoint( 1, frontRectNegative.bottomRight().x() +  static_cast<int>(sideBarHeight),
01381                      frontRectNegative.bottom() -  static_cast<int>(sideBarHeight) );
01382             points.setPoint(2,  frontRectNegative.bottomRight().x() +  static_cast<int>(sideBarHeight), 
01383                     frontRectNegative.top() - static_cast<int>(sideBarHeight));
01384             points.setPoint(3, frontRectNegative.topRight() );
01385               }
01386                     
01387                       
01388               rightRectNegative.setTopLeft( points.point(0));
01389               rightRectNegative.setTopRight( points.point(2));
01390               rightRectNegative.setBottomRight(points.point(1));
01391               rightRectNegative.setBottomLeft(points.point(3));
01392                 
01393             } else {  
01394               // Pending Michel
01395               // Make sure to align the right side top and bottom points
01396               // to the front side points                     
01397                     
01398               if ( tooHigh ) {
01399             points.setPoint(0, excessRectPositive.topRight());                                       
01400             points.setPoint(1, excessRectPositive.topRight().x() + static_cast <int> (sideBarHeight), 
01401                     excessRectPositive.top() - static_cast <int> (sideBarHeight) );
01402             points.setPoint(2, excessRectPositive.bottomRight().x() + static_cast <int> (sideBarHeight), 
01403                     excessRectPositive.bottom() - static_cast <int> (sideBarHeight));
01404             points.setPoint(3, excessRectPositive.bottomRight());
01405                       
01406               } else {
01407             points.setPoint(0, frontRectPositive.topRight());
01408             points.setPoint(1, frontRectPositive.topRight().x() + static_cast <int> (sideBarHeight), 
01409                     frontRectPositive.top() - static_cast<int>(sideBarHeight));
01410             points.setPoint(2, frontRectPositive.bottomRight().x() + static_cast <int> (sideBarHeight), 
01411                     frontRectPositive.bottom() - static_cast<int>(sideBarHeight));
01412             points.setPoint(3, frontRectPositive.bottomRight());
01413               }          
01414 
01415               //register the right rect
01416               rightRectPositive.setTopLeft( points.point(0));
01417               rightRectPositive.setTopRight( points.point(1));
01418               rightRectPositive.setBottomLeft( points.point(3));
01419               rightRectPositive.setBottomRight(points.point(2));                                 
01420             }
01421 
01422             if ( myShadow2Color.isValid() )
01423               painter->setBrush( QBrush( myShadow2Color, params()->shadowPattern() ) );
01424             else
01425               painter->setBrush( NoBrush ); 
01426 
01427             //debug points and lines
01428             /*
01429               painter->drawText( points.point(0), "0r");
01430               painter->drawText( points.point(1), "1r");
01431               painter->drawText( points.point(2), "2r");
01432               painter->drawText( points.point(3), "3r");
01433               painter->drawLine( points.point(0), points.point(1));
01434               painter->drawLine( points.point(1), points.point(2));
01435               painter->drawLine( points.point(2), points.point(3));
01436               painter->drawLine( points.point(3), points.point(0));
01437             */              
01438             if( !tooHigh  && !tooLow  || tooHigh && cellValue <= 0 )
01439               painter->drawPolygon( points );
01440               
01441                     
01442             if ( region ) {
01443               QPointArray points2cpy( points.copy() );
01444               //qDebug("g2");
01445               points2cpy.translate( _dataRect.x(), _dataRect.y() );
01446               //qDebug("dataRect XY: %i / %i",_dataRect.x(), _dataRect.y());
01447               //qDebug("g3");
01448               *region += QRegion( points2cpy );
01449               //qDebug("g4");
01450             }
01451                     
01452             // drawing the top, but only for the topmost piece for stacked and percent
01453             if ( bNormalMode || bMultiRows ||
01454              // For stacked and percent bars, there are three ways to determine
01455              // the top:
01456              // 1. all values are negative: the top is the one in the first dataset
01457              ( maxValueInThisColumn <= 0.0 && dataset == firstValidValue ) ||
01458              // 2. all values are positive: the top is the one in the last dataset
01459              ( minValueInThisColumn >= 0.0 && dataset == lastValidPositiveValue ) ||
01460              // 3. some values are positive, some negative:
01461              // the top is the one in the last positive
01462              // dataset value
01463              ( dataset == lastValidPositiveValue ) ) {
01464               if ( /*barHeight < 0.0 */ cellValue <= 0 || cellValue < minColumnValue) {
01465                                           
01466             if ( tooLow ) {    
01467               points.setPoint(0,excessRectNegative.bottomLeft());
01468               points.setPoint(1,excessRectNegative.topLeft().x() + static_cast <int> (sideBarHeight),
01469                       excessRectNegative.bottom() - static_cast <int> (sideBarHeight));
01470               points.setPoint(2,excessRectNegative.bottomRight().x() + static_cast <int> (sideBarHeight), 
01471                       excessRectNegative.bottom() - static_cast <int> (sideBarHeight));
01472               points.setPoint(3,excessRectNegative.bottomRight());
01473             }else {
01474               // Align the top to the front and the right side                  
01475               points.setPoint(0,frontRectNegative.topLeft() );
01476               points.setPoint(1,frontRectNegative.topLeft().x() + static_cast <int> (sideBarHeight),                                        rightRectNegative.top());
01477               points.setPoint(2,rightRectNegative.topRight() );
01478               points.setPoint(3,rightRectNegative.topRight().x() - static_cast <int> (sideBarHeight), 
01479                       frontRectNegative.topRight().y() );
01480             }
01481                         
01482               } else {
01483                                          
01484             if ( tooHigh ) {
01485               points.setPoint(0, excessRectPositive.topLeft());
01486               points.setPoint(1, excessRectPositive.topLeft().x() + static_cast <int> (sideBarHeight),
01487                       excessRectPositive.top() - static_cast <int> (sideBarHeight) );
01488               points.setPoint(2, excessRectPositive.topRight().x() +  static_cast <int> (sideBarHeight),
01489                       excessRectPositive.top() - static_cast <int> (sideBarHeight));
01490               points.setPoint(3, excessRectPositive.topRight());
01491                         
01492             } else {
01493               // Pending Michel
01494               // Align the top to the front and the right side
01495               points.setPoint(0, frontRectPositive.topLeft());
01496               points.setPoint(1, frontRectPositive.topLeft().x() + static_cast <int> (sideBarHeight),
01497                       rightRectPositive.top() );
01498               points.setPoint(2, rightRectPositive.topRight()); 
01499               points.setPoint(3, rightRectPositive.topRight().x() - static_cast <int> (sideBarHeight), 
01500                       frontRectPositive.topRight().y());                      
01501             }
01502               }
01503                                            
01504               if ( /*barHeight*/ cellValue < 0.0 ) {
01505             painter->setBrush( bMultiRows ? myBarColor : black );
01506               }
01507               else
01508             painter->setBrush( QBrush( myShadow1Color, params()->shadowPattern() ) );
01509               if ( !myShadow1Color.isValid() )
01510             painter->setBrush( NoBrush ); // override prev. setting
01511                                         
01512               // debug points and lines
01513               /*
01514             painter->drawText( points.point(0), "0t"); 
01515             painter->drawText( points.point(1), "1t"); 
01516             painter->drawText( points.point(2), "2t");
01517             painter->drawText( points.point(3), "3t");                      
01518             painter->drawLine( points.point(0), points.point(1) );
01519             painter->drawLine( points.point(1),points.point(2) );
01520             painter->drawLine( points.point(2),points.point(3) );
01521             painter->drawLine( points.point(3),points.point(0) );
01522               */
01523                     
01524               // drawing the top side 
01525               if (!tooHigh && !tooLow  || (tooHigh && cellValue <= 0) )                                     
01526             painter->drawPolygon( points );       
01527                 
01528               // Don't use points for drawing after this!
01529               if ( region ) {
01530             points.translate( _dataRect.x(), _dataRect.y() );
01531             *region += QRegion( points );
01532               }
01533                        
01534             }
01535           
01536           }//if ( _bThreeDBars )
01537 
01538           if( regions && region ) {
01539             if( bShowThisBar && !bDrawExtraLines )
01540               regions->append(
01541                       _bThreeDBars
01542                       ? new KDChartDataRegion( *region, dataset, value, chart )
01543                       // just store a rectangle if NOT in 3-D bar mode
01544                       : new KDChartDataRegion( dataset, value, chart, region->boundingRect() ) );
01545             delete region;
01546           }
01547 
01548         }// if( !bDrawExtraLines || bCellPropertiesFound )
01549           }// if( !skipMe )
01550         }else{
01551           // Do not paint a bar, but update the position
01552           // variable: to find the exact x1 position for
01553           // the next bar that will be drawn.
01554           int iDummy1, iDummy2;
01555           calculateXFront1_2( bNormalMode, bIsVeryFirstBar, bIsFirstDataset, _bThreeDBars,
01556                   xpos, valueBlockGap, datasetGap, frontBarWidth,
01557                   iDummy1, iDummy2, prevFrontX2 );
01558         }// if( dataset >= datasetStart && dataset <= datasetEnd )
01559 
01560 
01561         // Vertical advancement in stacked or percent only if there was a value
01562         if ( params()->barChartSubType() == KDChartParams::BarStacked ||
01563          params()->barChartSubType() == KDChartParams::BarPercent )
01564           if ( barHeight < 0.0 )
01565         yposNegatives -= barHeight;
01566           else
01567         yposPositives -= barHeight;
01568       } else {
01569         // Do not paint a bar, but update the position
01570         // variable: to find the exact x1 position for
01571         // the next bar that will be drawn.
01572         int iDummy1, iDummy2;
01573         calculateXFront1_2( bNormalMode, bIsVeryFirstBar, bIsFirstDataset, _bThreeDBars,
01574                 xpos, valueBlockGap, datasetGap, frontBarWidth,
01575                 iDummy1, iDummy2, prevFrontX2 );
01576       }
01577 
01578 
01579       // advance only if the next dataset has DataEntry mode
01580       bool bAdvanceToNextValue =
01581         (    bMultiRows ? (dataset == chartDatasetStart) : (dataset == chartDatasetEnd)
01582          || (    params()->chartSourceMode( bMultiRows ? dataset-1 : dataset+1 )
01583              == KDChartParams::DataEntry ) );
01584       // Advance to next value; only for normal bars
01585       if ( bNormalMode ) {
01586         if( bAdvanceToNextValue )
01587           xpos += barWidth;
01588         // skip gap between datasets, unless last dataset
01589         if ( dataset < myLastDataEntryDataset )
01590           xpos += datasetGap;
01591       }
01592       if( bAdvanceToNextValue || bMultiRows  ){
01593         //qDebug("shiftMyPainter( -nShiftX, nShiftY );");
01594         shiftMyPainter( -nShiftX, nShiftY );
01595       }
01596       bIsVeryFirstBar = false;
01597       bIsFirstDataset = false;
01598     }
01599 
01600 
01601     // Advancement between value blocks
01602     if ( bNormalMode ){
01603       // skip gap between value blocks, don't worry about last one here
01604       xpos += valueBlockGap;
01605       //qDebug("**************************** xpos: %f  +  valueBlockGap: %f  =  %f", xpos, valueBlockGap, xpos+valueBlockGap);
01606     }else{
01607       // skip gap between value blocks
01608       xpos += valueBlockGap + barWidth;
01609       // start at bottom with next value group
01610       yposPositives = yposPositivesStart;
01611       yposNegatives = yposNegativesStart;
01612     }
01613     //qDebug("shiftMyPainterBack");
01614     shiftMyPainterBack();
01615       }
01616       
01617     }
01618 
01619 
01620   if( bMultiRows )
01621     painter->setClipping( bHadClipping );
01622 }
KDE Home | KDE Accessibility Home | Description of Access Keys