/*-*- c++ -*-******************************************************************
 * Qwt Widget Library 
 * Copyright (C) 1997   Josef Wilgen
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *****************************************************************************/

#ifndef QWT_CURVE_H
#define QWT_CURVE_H

#include <qglobal.h>
#include <qpen.h>
#include <qstring.h>
#include <qrect.h>
#include <qcolor.h>
#include <qpntarry.h>
#include <qarray.h>
#include "qwt_dimap.h"
#include "qwt_spline.h"
#include "qwt_symbol.h"
#include "qwt.h"

class QPainter;

/*!
  \brief A class which draws curves

  This class can be used to display data as a curve in the  x-y plane.
  It supports different display styles, spline interpolation and symbols.

  \par Usage
  <dl><dt>A. Assign y and y data.</dt>
  <dd>Data can be assigned in two ways:<ul>
  <li>setData() copies the x and y data from the specified
  arrays into its internal buffer.
  <li>setRawData() does not make a copy of the data, but
  only stores the pointers and size information instead. This
  function is less safe (you must not delete the data while they are attached),
  but more efficient, and more
  convenient if the data change dynamically.</ul></dd>
  <dt>B. Assign Properties</dt>
  <dd>When a curve is created, it is configured to draw black solid lines
  with no symbols. You can change this by calling the setPen()
  and setSymbolY() members.</dd>
  <dt>C. Assign y and y maps</dt>
  <dd>Before a curve can be drawn, it has be mapped into a rectangle.
  This can either be done implicitly with the
  draw() member, or explicitly using setMap(const QRect &r, double x1,
  double x2, bool xlog, double y1, double y2, bool ylog)
  or setMap(const QwtDiMap &mx, const QwtDiMap& my) before drawing.
  The map can also be changed with the
  setRect() and setRange() members.</dd>
  <dt>D. Draw</dt>
  <dd>The draw(QPainter *p, const QwtDiMap &xMap, const QwtDiMap &yMap) member
  assumes that a curve has already been mapped.
  The draw(QPainter *p, const QRect &r) member draws the curve with
  specified y and y maps. The draw(QPainter *p) member draws the curve into
  a rectangle, thereby adjusting the curve's mapping.</dd></dl>

  \par Example:
  see examples/curvdemo

  \sa QwtSymbol, QwtDiMap
*/
class QwtCurve 
{
    
public:


    enum { Auto = 0, Yfx = 1, Xfy = 2, Parametric = 4,
	   Periodic = 8, Inverted = 16};
    enum CurveStyle{ NoCurve, Lines, Sticks, Steps, Dots, Spline };

private:

    int *refcnt;
    double d_ref;
    
    QwtDiMap d_xMap;
    QwtDiMap d_yMap;
    QwtSymbol d_sym;
    QwtSpline d_spx;
    QwtSpline d_spy;
    
protected:
    
    QPen d_pen;
    QString d_title;
    QPointArray d_pa;
    
    QArray<double> d_x;
    QArray<double> d_y;
    QArray<double> d_e;
    
    int d_options;
    int d_splineSize;
    
    
private:

    // DATA MEMBERS
    CurveStyle d_style;

    bool d_xraw;
    bool d_yraw;
    bool d_eraw;
    bool hasErrors;    
    
    void init(const char *title);
    void copy(const QwtCurve &c);

    // PRIVATE DRAWING FUNCTIONS
    void drawLines(QPainter &p, int i1 = -1, int i2 = -1);
    void drawSticks(QPainter &p, int i1 = -1, int i2 = -1);
    void drawDots(QPainter &p, int i1 = -1, int i2 = -1);
    void drawSteps(QPainter &p, int i1 = -1, int i2 = -1);
    void drawSymbols(QPainter &p, int i1 = -1, int i2 = -1);
    void drawSpline(QPainter &p);
    void drawErrors(QPainter &p, int i1 = -1, int i2 = -1);
    void transform(double x, double y, int &u, int &v);
    
public:

    // CREATORS
    QwtCurve(const char *title = 0);
    QwtCurve(const QwtCurve &c);
    virtual ~QwtCurve();

    // OPERATORS
    const QwtCurve& operator= (const QwtCurve &c);
    
    // MANIPULATORS
    void draw(QPainter *p, const QwtDiMap &xMap, const QwtDiMap &yMap);
    void draw(QPainter *p, const QRect &r);
    void draw(QPainter *p);
    void drawIntv(QPainter *p, int i1, int i2);
    void setData(double *x, double *y, int size);
    void setData(double *x, double *y, double *e, int size);
    void setMap(const QRect &r, double x1, double x2, bool xlog,
		double y1, double y2, bool ylog);
    void setMap(const QwtDiMap &mx, const QwtDiMap& my);
    void setOptions(int t);
    void setPen(const QPen &p);
    void setRange(double x1, double x2, bool xlog,
		double y1, double y2, bool ylog);
    void setRawData(double *x, double *y, int size);
    void setRawData(double *x, double *y, double *e, int size);
    void setRect(const QRect &r);
    void setBaseline(double ref);
    void setStyle(CurveStyle cs, int options = 0);
    void setSymbol(const QwtSymbol &s);
    void setSplineSize(int s);
    void setTitle(const char *title);
    

    // ACCESSORS
  /*!
    \brief Return the value of the baseline
    \sa QwtCurve::setBaseline
  */
    double baseline() const { return d_ref; }
    int dataSize() const;
    double minXValue() const;
    double maxXValue() const;
    double minYValue() const;
    double maxYValue() const;

  /*!
    \brief Return the current style options
    \sa QwtCurve::setOptions
  */
  int options() const { return d_options; }
  /*!
    \brief Return the pen used to draw the lines
    \sa QwtCurve::setPen
  */
  const QPen& pen() const { return d_pen; }
  // double reference() const { return d_ref; } // for compatibility with older
					       // versions; renamed to baseline
  /*!
    \fn int QwtCurve::splineSize() const
    \brief Return the spline size
    \sa QwtCurve::setSplineSize
  */
    int splineSize() const { return d_splineSize; }
  /*!
    \fn CurveStyle QwtCurve::style() const
    \brief Return the current style
    \sa QwtCurve::setStyle
  */
  CurveStyle style() const { return d_style; }
    const QwtSymbol& symbol() const { return d_sym; }
    const QString &title() const { return d_title; } 

    double x(int i) const { return d_x[i]; }
    double y(int i) const { return d_y[i]; }
    double e(int i) const { return d_e[i]; }
    

protected:
    virtual void curveChanged() {}
    int verifyRange(int &i1, int &i2);
    
};


#endif




