/*
   KDChart - a multi-platform charting engine
   */

/****************************************************************************
 ** Copyright (C) 2001-2003 Klarälvdalens Datakonsult AB.  All rights reserved.
 **
 ** This file is part of the KDChart library.
 **
 ** This file may be distributed and/or modified under the terms of the
 ** GNU General Public License version 2 as published by the Free Software
 ** Foundation and appearing in the file LICENSE.GPL included in the
 ** packaging of this file.
 **
 ** Licensees holding valid commercial KDChart licenses may use this file in
 ** accordance with the KDChart Commercial License Agreement provided with
 ** the Software.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ** See http://www.klaralvdalens-datakonsult.se/?page=products for
 **   information about KDChart Commercial License Agreements.
 **
 ** Contact info@klaralvdalens-datakonsult.se if any conditions of this
 ** licensing are not clear to you.
 **
 **********************************************************************/
#ifndef __KDCHARTPAINTER_H__
#define __KDCHARTPAINTER_H__

#include <tqmap.h>
#include <tqrect.h>
#include <tqdatetime.h>
#include <tqregion.h>
#include <tqstring.h>

#include "KDChartGlobal.h"
#include "KDChartUnknownTypeException.h"
#include "KDChartNotEnoughSpaceException.h"
#include "KDChartTable.h"
#include "KDChartDataRegion.h"
#include "KDChartParams.h"

class KDChartTableDataBase;
class KDChartCustomBox;
class KDChartTextPiece;
class KDChartPropertySet;
class KDChartAxisParams;
class TQPainter;


struct internal__KDChart__CalcValues {
    bool processThisAxis;
    bool bSteadyCalc;
    bool bLogarithmic;
    bool bDecreasing;
    KDChartAxisParams::AxisPos basicPos;
    TQPoint orig;
    TQPoint dest;
    double pXDeltaFactor;
    double pYDeltaFactor;
    double pXDelimDeltaFaktor;
    double pYDelimDeltaFaktor;
    double nSubDelimFactor;
    double pDelimDelta;
    double nTxtHeight;
    double pTextsX;
    double pTextsY;
    double pTextsW;
    double pTextsH;
    int textAlign;
    bool isDateTime;
    bool autoDtLabels;
    TQDateTime dtLow;
    TQDateTime dtHigh;
    KDChartAxisParams::ValueScale dtDeltaScale;
    double nLow;
    double nHigh;
    double nDelta;
    double nDeltaPix;
    double pLastX;
    double pLastY;
};


class KDCHART_EXPORT KDChartPainter
{
    public:
        static KDChartPainter* create( KDChartParams* params,
                                       bool make2nd = false );

        virtual ~KDChartPainter();

        static void registerPainter( const TQString& painterName,
                                     KDChartPainter* painter );
        static void unregisterPainter( const TQString& painterName );

        virtual void setupGeometry ( TQPainter* painter,
                                     KDChartTableDataBase* data,
                                     const TQRect& rect );

        virtual void paint( TQPainter* painter, KDChartTableDataBase* data,
                            bool paintFirst,
                            bool paintLast,
                            KDChartDataRegionList* regions = 0,
                            const TQRect* rect = 0,
                            bool mustCalculateGeometry = true );

        virtual TQRect outermostRect() const { return _outermostRect; }

        static void drawMarker( TQPainter* painter,
                                 int style,
                                 const TQColor& color,
                                 const TQPoint& p,
                                 const TQSize& size,
                                 uint align = TQt::AlignCenter );

    protected:
        KDChartPainter( KDChartParams* );

        // Note: dataRow, dataCol (and data3rd, resp.)
        //       must only be set if area == KDChartEnums::AreaChartDataRegion
        virtual void paintArea( TQPainter* painter,
                                uint area,
                                KDChartDataRegionList* regions = 0,
                                uint dataRow = 0,
                                uint dataCol = 0,
                                uint data3rd = 0 );

        virtual void paintDataRegionAreas( TQPainter* painter,
                                           KDChartDataRegionList* regions );

        virtual void paintAreaWithGap( TQPainter* painter,
                                       TQRect rect,
                                       const KDChartParams::KDChartFrameSettings& settings );
        virtual void paintCustomBoxes( TQPainter* painter,
                                       KDChartDataRegionList* regions );

        virtual void paintData( TQPainter* painter, KDChartTableDataBase* data,
                                bool paint2nd,
                                KDChartDataRegionList* regions = 0 ) = 0;
        virtual void paintDataValues( TQPainter* painter,
                                      KDChartTableDataBase* data,
                                      KDChartDataRegionList* regions );
        virtual void paintAxes( TQPainter* painter,
                                KDChartTableDataBase* data );
        virtual void paintLegend( TQPainter* painter,
                                  KDChartTableDataBase* data );
        virtual void paintHeaderFooter( TQPainter* painter,
                                        KDChartTableDataBase* data );
        virtual bool axesOverlapping( int axis1, int axis2 );

        virtual void findChartDatasets( KDChartTableDataBase* data,
                                        bool paint2nd,
                                        uint chart,
                                        uint& chartDatasetStart,
                                        uint& chartDatasetEnd );

        virtual void calculateAllAxesRects( TQPainter* painter,
                                            bool finalPrecision,
                                            KDChartTableDataBase* data );

        virtual TQPoint calculateAnchor( const KDChartCustomBox & box,
                KDChartDataRegionList* regions = 0 ) const;
        virtual TQRect calculateAreaRect( bool & allCustomBoxes,
                                         uint area,
                                         uint dataRow,
                                         uint dataCol,
                                         uint data3rd,
                                         KDChartDataRegionList* regions ) const;

        virtual TQString fallbackLegendText( uint dataset ) const;
        virtual uint numLegendFallbackTexts( KDChartTableDataBase* data ) const;

        static TQPoint pointOnCircle( const TQRect& rect, double angle );
        static void makeArc( TQPointArray& points,
                             const TQRect& rect,
                             double startAngle, double angles );

        const KDChartParams* params() const
        {
            return _params;
        }

        TQRect _outermostRect; /* The Outermost rect covers the complete
                                 area of the painter. */

        TQRect _innermostRect; /* The Innermost rect covers the area of
                                 the painter MINUS the the global
                                 left/top/right/bottom leading.
                                 ALL following ones are INSIDE the Innermost.
                                 */

        TQRect _dataRect;

        TQRect _axesRect; /* The Axes rect contains the Data rect. Up to 4
                            axes might be at the left and bottom as well
                            as at the right and/or at the to top of the
                            chart.
                            */

        TQRect _legendRect; /* The legend position depends on the parameter
                              settings. If it is not directly to the left or
                              to the right of the data display, it will be
                              below the headers and on top of the footers.
                              */
        int _legendEMSpace; // an em space in the legend font
        int _legendSpacing; // the line spacing in the legend font
        int _legendHeight; // the font height in the legend font
        int _legendLeading; // the font leading in the legend font
        //     int _legendTitleSpacing; // the line spacing in the legend title font
        //     int _legendTitleLeading; // the font leading in the legend title font
        KDChartTextPiece* _legendTitle;

        int _numLegendTexts; // the number of legend items to show

        int _logicalWidth;
        int _logicalHeight;
        double _areaWidthP1000;
        double _areaHeightP1000;

        TQMap < int, TQString > _legendTexts; // precomputed legend texts

        internal__KDChart__CalcValues calcVal[ KDCHART_MAX_AXES ];
        virtual bool calculateAllAxesLabelTextsAndCalcValues(
                        TQPainter* painter,
                        KDChartTableDataBase* data,
                        double areaWidthP1000,
                        double areaHeightP1000,
                        double& delimLen );

        virtual void drawExtraLinesAndMarkers(
                        KDChartPropertySet& propSet,
                        const TQPen& defaultPen,
                        const KDChartParams::LineMarkerStyle& defaultMarkerStyle,
                        int myPointX,
                        int myPointY,
                        TQPainter* painter,
                        const KDChartAxisParams* abscissaPara,
                        const KDChartAxisParams* ordinatePara,
                        const double areaWidthP1000,
                        const double areaHeightP1000,
                        bool bDrawInFront = false );

        static KDChartDataRegion* drawMarker( TQPainter* painter,
                                               const KDChartParams* params,
                                               double areaWidthP1000,
                                               double areaHeightP1000,
                                               int deltaX,
                                               int deltaY,
                                               int style,
                                               const TQColor& color,
                                               const TQPoint& p,
                                               uint dataset, uint value, uint chart,
                                               KDChartDataRegionList* regions = 0,
                                               int* width = 0,
                                               int* height = 0,
                                               uint align = TQt::AlignCenter );

    private:
        // disallow copy-construction and assignment
        KDChartPainter( const KDChartPainter& );
        KDChartPainter& operator=( const KDChartPainter& );


        TQMap < TQString, KDChartPainter* > _customPainters;
        KDChartParams* _params;

        TQRect trueFrameRect( const TQRect& orgRect,
                             const KDChartParams::KDChartFrameSettings* settings ) const;

        int legendTitleVertGap() const;
        TQFont trueLegendTitleFont() const;
        TQFont trueLegendFont() const;
        void calculateHorizontalLegendSize( TQPainter* painter,
                                            TQSize& size,
                                            bool& legendNewLinesStartAtLeft ) const;
        bool mustDrawVerticalLegend() const;
        void findLegendTexts( KDChartTableDataBase* );
        int calculateHdFtRects( TQPainter* painter,
                                double averageValueP1000,
                                int  xposLeft,
                                int  xposRight,
                                bool bHeader,
                                int& yposTop,
                                int& yposBottom );
        bool _legendNewLinesStartAtLeft;
        int _legendTitleHeight;
        int _legendTitleWidth;
        int _legendTitleMetricsHeight; // the font height in the legend title font
        int _hdLeading;
        int _ftLeading;
};

#endif
