/*-*- 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_PLOT_H
#define QWT_PLOT_H

#include <qframe.h>
#include "qwt_grid.h"
#include "qwt_autoscl.h"
#include "qwt_scldraw.h"
#include <qprinter.h>
#include "qwt_symbol.h"
#include "qwt_curve.h"
#include "qwt_marker.h"
#include "qwt_clrfltr.h"
#include "qwt_plot_classes.h"

class QwtPlotPixFrame;
class QLabel;
class QwtScale;
class QwtLegend;
class QwtCurveDict;
class QwtMarkerDict;

/*!
  \brief A 2-D plotting widget

  QwtPlot is a widget for plotting two-dimensional graphs.
  An unlimited number of data pairs can be displayed as
  curves in different styles and colors. A plot can have
  up to four axes, with each curve attached to an x- and
  a y axis. The scales at the axes are dimensioned automatically
  using an algorithm which can be configured separately for each
  axis. Linear and logarithmic scaling is supported. Markers of
  different styles can be added to the plot. 
  
  Curves and markers are identified by unique keys which are generated
  automatically when a curve or a marker is created. These keys are used to
  access the properties of the corresponding curves and markers.
  
  A QwtPlot widget can have up to four axes which are indexed by
  the constants QwtPlot::yLeft, QwtPlot::yRight, QwtPlot::xTop,
  and QwtPlot::xBottom. Curves, markers, and the grid must be
  attached to an x axis and a y axis (Default: yLeft and xBottom). 

  \par Example
  The following example shows (schematically) the most simple
  way to use QwtPlot. By default, only the left and bottom axes are
  visible and their scales are computed automatically.
  \verbatim
#include "../include/qwt_plot.h>

QwtPlot *myPlot;
long curve1, curve2;                    // keys
double x[100], y1[100], y2[100];        // x and y values

myPlot = new QwtPlot("Two Graphs", parent, name);

// add curves
curve1 = myPlot->insertCurve("Graph 1");
curve2 = myPlot->insertCurve("Graph 2");

getSomeValues(x, y1, y2);

// copy the data into the curves
myPlot->setCurveData(curve1, x, y1, 100);
myPlot->setCurveData(curve2, x, y2, 100);

// finally, refresh the plot
myPlot->replot();
\endverbatim
*/

/*

//
//
//.U PUBLIC MEMBERS
//.u General
//.R
//
QwtPlot::QwtPlot (1) -- Constructor
QwtPlot::QwtPlot (2) -- Constructor
QwtPlot::~QwtPlot -- Destructor
QwtPlot::setTitle -- Change the title
QwtPlot::setTitleFont -- Specify the title font
QwtPlot::enableOutline -- Enable/disable outline drawing
QwtPlot::setPlotBackground -- Set a background color for the plotting region
QwtPlot::setPlotBorder -- Set border width for the plotting region
QwtPlot::setOutlineStyle -- Specify the outline style
QwtPlot::setOutlinePen -- Assign a pen for outline drawing
QwtPlot::setAutoReplot -- Enable automatic replot
QwtPlot::outlineEnabled -- Enable outline drawing
QwtPlot::autoReplot -- Return TRUE if automatic replot enabled
QwtPlot::plotBackground -- Return background color of the plotting region
QwtPlot::plotBorder -- Return border width of the plotting region 
QwtPlot::outlinePen -- Return pen for outline drawing
QwtPlot::outlineStyle -- Return outline style
QwtPlot::print -- Print to file or printer
QwtPlot::title -- Return the title
QwtPlot::titleFont -- Return the title font
QwtPlot::axisValid -- Return TRUE if a number is a valid axis key
QwtPlot::clear -- Remove all curves and markers
//
//.u Curves
//.R
QwtPlot::insertCurve -- Insert a new curve
QwtPlot::removeCurve -- Remove a curve
QwtPlot::removeCurves -- Remove all curves
QwtPlot::setCurveData -- Assign data to a curve
QwtPlot::setCurveOptions -- Specify curve
QwtPlot::setCurvePen -- Set Style options
QwtPlot::setCurveRawData -- Attach data
QwtPlot::setCurveSplineSize -- Set spline size
QwtPlot::setCurveStyle -- Set curve style
QwtPlot::setCurveSymbol -- Assign a symbol
QwtPlot::setCurveTitle -- Assign a title
QwtPlot::setCurveXAxis -- Attach an x axis
QwtPlot::setCurveYAxis -- Attach a y axis
QwtPlot::setCurveBaseline -- Set baseline value
QwtPlot::curveKeys -- Return all valid curve keys
QwtPlot::curveOptions -- Return style options
QwtPlot::curvePen -- Return pen
QwtPlot::curveSplineSize -- Return spline size
QwtPlot::curveStyle -- Return style
QwtPlot::curveSymbol -- Return symbol
QwtPlot::curveTitle -- Return title
QwtPlot::curveXAxis -- Return attached x axis
QwtPlot::curveYAxis -- Return attached y axis
QwtPlot::curveBaseline -- Return baseline value
QwtPlot::closestCurve (1) -- Find closest curve to a given location
QwtPlot::closestCurve (2) -- Find closest data point to a given location
//
//.u Grid
//.R
QwtPlot::enableGridX -- Enable or disable vertical gridlines
QwtPlot::enableGridXMin -- Enable or disable minor vertical gridlines
QwtPlot::enableGridY -- Enable or disable horizontal gridlines
QwtPlot::enableGridYMin -- Enable or disable minor horizontal gridlines
QwtPlot::setGridXAxis -- Attach an x axis
QwtPlot::setGridYAxis -- Attach a y axis
QwtPlot::setGridPen -- Specify pen for all gridlines
QwtPlot::setGridMajPen -- Specify pen for major gridlines
QwtPlot::setGridMinPen -- Specify pen for minor gridlines
QwtPlot::gridXAxis -- Return attached x axis
QwtPlot::gridYAxis -- Return attached y axis
QwtPlot::gridMinPen -- Return pen for minor gridlines
QwtPlot::gridMajPen -- Return pen for major gridlines
//
//.u Axes
//.R
QwtPlot::changeAxisOptions -- Change options
QwtPlot::enableAxis -- Enable/disable axis
QwtPlot::setAxisFont -- Specify font for tick labels
QwtPlot::setAxisMargins -- Specify margins
QwtPlot::setAxisOptions -- Specify options
QwtPlot::setAxisAutoScale -- Enable autoscaling
QwtPlot::setAxisScale -- Set fixed scale
QwtPlot::setAxisLabelFormat -- Set number format
QwtPlot::setAxisTitleFont -- Set Title font
QwtPlot::setAxisMaxMinor -- Set max. number of major tickmarks
QwtPlot::setAxisMaxMajor -- Set max. number of minor tickmarks
QwtPlot::setAxisReference -- Set a reference value
QwtPlot::setAxisTitle -- Assign a title
QwtPlot::invTransform -- Transform position to value
QwtPlot::transform -- Transform value to position
QwtPlot::axisAutoScale -- Return TRUE if autoscaling enabled
QwtPlot::axisEnabled -- Return TRUE if axis enabled
QwtPlot::axisFont -- Return font
QwtPlot::axisMargins -- Return margins
QwtPlot::axisMaxMajor -- Return max. number of major tickmarks
QwtPlot::axisMaxMinor -- Return max. number of minor tickmarks
QwtPlot::axisOptions -- Return options
QwtPlot::axisReference -- Return reference value
QwtPlot::axisScale -- Return scale division
QwtPlot::axisLabelFormat -- Return number format
QwtPlot::axisTitle -- Return title
QwtPlot::axisTitleFont -- Return the title's font
//
//.u Markers
//.R
QwtPlot::insertMarker -- Insert a new marker
QwtPlot::insertLineMarker -- Insert horizontal or vertical line
QwtPlot::removeMarker -- Remove a marker
QwtPlot::removeMarkers -- Remove all markers
QwtPlot::setMarkerFont -- Specify font for the label
QwtPlot::setMarkerLinePen -- Specify pen for line drawing
QwtPlot::setMarkerLineStyle -- Specify line style
QwtPlot::setMarkerPos -- Set (x,y) position
QwtPlot::setMarkerSymbol -- Assign a symbol
QwtPlot::setMarkerLabel -- Assign a label
QwtPlot::setMarkerLabelAlign -- Specify label alignment
QwtPlot::setMarkerLabelPen -- Specify pen for label 
QwtPlot::setMarkerXPos -- Change x position
QwtPlot::setMarkerYPos -- Change y position
QwtPlot::setMarkerPen -- Specify a pen for label and lines
QwtPlot::setMarkerXAxis -- Attach an x axis
QwtPlot::setMarkerYAxis -- Attach a y axis
QwtPlot::markerKeys -- Return all valid marker keys
QwtPlot::markerFont -- Return font
QwtPlot::markerLinePen -- Return line pen
QwtPlot::markerLineStyle -- Return [line style
QwtPlot::markerPos -- Return (x,y) position
QwtPlot::markerSymbol -- Return symbol
QwtPlot::markerLabel -- Return label text
QwtPlot::markerLabelAlign -- Return label alignment
QwtPlot::markerLabelPen -- Return label pen
QwtPlot::markerXAxis -- Return attached x axis
QwtPlot::markerYAxis -- Return attached y axis
QwtPlot::closestMarker -- Find closest marker to a given position
//
//.u Legend
//.R
QwtPlot::enableLegend -- Enable legend
QwtPlot::setLegendPos -- Set relative position of the legend
QwtPlot::setLegendFont -- Specify font for the legend items
QwtPlot::setLegendFrameStyle -- Specify frame style of the legend
QwtPlot::legendEnabled -- Return TRUE if legend enabled
QwtPlot::legendPos -- Return legend position
QwtPlot::legendFrameStyle -- Return frame style
QwtPlot::legendFont -- Return font
//

//
//.U SIGNALS
//.R
QwtPlot::plotMousePressed -- Mouse pressed in plotting region
QwtPlot::plotMouseReleased -- Mouse released in plotting region
QwtPlot::plotMouseMoved -- Mouse moved in plotting region
QwtPlot::legendClicked -- Legend item clicked
//
//.U SLOTS
//.R
QwtPlot::replot -- Update the plot
//
//.U EXAMPLES
see examples/simple_plot, examples/rate_plot and examples/bode
//.-
//.U COPYING
//
Copyright (C) 1997  Josef Wilgen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2,
as published by	the Free Software Foundation.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// 	 
//------------------------------------------------------------

*/
class QwtPlot: public QFrame
{
friend class QwtPlotItem;
friend class QwtPlotPixFrame;

    Q_OBJECT

    
public:
    
    enum {yLeft, yRight, xBottom, xTop, axisCnt};
    
protected:

    QLabel *d_lblTitle;
    QwtPlotPixFrame *d_frmPlot;
    QwtScale *d_scale[axisCnt];
    QwtLegend *d_legend;
    
    bool d_titleEnabled;

    QwtAutoScale d_as[axisCnt];
    QwtDiMap d_map[axisCnt];
    QwtScaleDiv d_sdiv[axisCnt];
    QwtPlotGrid d_grid;

    int d_axisEnabled[axisCnt];
    int d_legendEnabled;
    int d_legendPos;
    
    int d_plotBorder;

    QwtCurveDict *d_curves;
    QwtMarkerDict *d_markers;

    int d_axisDist;
    int d_borderDist;
    int d_hScaleDist;
    int d_vScaleDist;
    
    int d_titleDist;
    int d_margin;
    int d_autoReplot;

private:

    // STATIC DATA
    static QFont& DummyFont();
    static QPen& DummyPen();
    static QwtSymbol& DummySymbol();
    static QwtScaleDiv& DummyScale();
    static QString& DummyString();
    static const int DefaultXAxis;
    static const int DefaultYAxis;

    
    // PRIVATE MEMBER FUNCTIONS
    void initAxes();
    long newCurveKey();
    long newMarkerKey();
    void initPlot(const char *title = 0);
    void plotPressed(QMouseEvent *e);
    void plotReleased(QMouseEvent *e);
    void plotMoved(QMouseEvent *e);

    bool insertCurve(long key, const char *title, int xAxis = xBottom, int yAxis = yLeft);
    bool insertMarker(long key, const char *label = "", int xAxis = xBottom, int yAxis = yLeft);
    bool insertLineMarker(long key, const char *label, int axis);
    
protected:

    // PROTECTED MEMBERS
    void redrawPixmap();
    void updateAxes();
    int verifyXAxis(int axis) const;
    int verifyYAxis(int axis) const;

public:

    //
    //	Constructors
    //
    QwtPlot(QWidget *p = 0, const char *name = 0);
    QwtPlot(const char *title, QWidget *p = 0, const char *name = 0);
    virtual ~QwtPlot();


    //
    // Set General Properties
    //
    void enableOutline(bool tf);
    void setAutoReplot(bool tf = TRUE);
    void setPlotBackground (const QColor &c);
    void setPlotBorder(int bw);
    void setOutlineStyle(Qwt::Shape os);
    void setOutlinePen(const QPen &pn);
    void setTitle(const char *t);
    void setTitleFont (const QFont &f);


    //
    // Retrieve General Properties
    //
    /*! 
      \return TRUE if the autoReplot option is set.
    */
    bool autoReplot() const { return d_autoReplot; }
    bool outlineEnabled() const;
    const QPen& outlinePen() const;
    Qwt::Shape outlineStyle() const;
    const QColor& plotBackground() const;
    /*!
      \return the border width of the plotting area
    */
    int plotBorder() const { return d_plotBorder; }
    QString title() const;
    QFont titleFont() const;


    //
    //	Miscellaneous
    //
    static bool axisValid(int axis);
    void clear();
    void print(QPrinter &p, const QwtColorFilter &cfilter = NoColorFilter);
    
    //
    // Insert/Remove Curves
    //
    long insertCurve(const char *title, int xAxis = xBottom, int yAxis = yLeft);
    bool removeCurve(long key);
    void removeCurves();

    //
    // Modify Curves
    //
    bool setCurveBaseline(long key, double ref);
    bool setCurveData(long key, double *x, double *y, int size);
    bool setCurveData(long key, double *x, double *y, double *e, int size);
    bool setCurveOptions(long key, int t);
    bool setCurvePen(long key, const QPen &pen);
    bool setCurveRawData(long key, double *x, double *y, int size);
    bool setCurveRawData(long key, double *x, double *y, double *e, int size);
    bool setCurveSplineSize(long key, int s);
    bool setCurveStyle(long key, QwtCurve::CurveStyle s, int options = 0);
    bool setCurveSymbol(long key, const QwtSymbol &s);
    bool setCurveTitle(long key, const char *s);
    bool setCurveXAxis(long key, int axis);
    bool setCurveYAxis(long key, int axis);

    //
    // Get Curve Properties
    //
    long closestCurve(int xpos, int ypos, int &dist) const;
    long closestCurve(int xpos, int ypos, int &dist, double &xval, double &yval, int &index) const;
    double curveBaseline(long key) const;
    QArray<long> curveKeys() const;
    int curveOptions(long key) const;
    const QPen &curvePen(long key) const;
    int curveSplineSize(long key) const;
    QwtCurve::CurveStyle curveStyle(long key) const;
    const QwtSymbol &curveSymbol(long key) const;
    QString curveTitle(long key) const;
    int curveXAxis(long key) const;
    int curveYAxis(long key) const;


    //
    //	Modify Grid
    //
    void enableGridX(bool tf = TRUE);
    void enableGridXMin(bool tf = TRUE);
    void enableGridY(bool tf = TRUE);
    void enableGridYMin(bool tf = TRUE);
    void setGridXAxis(int axis);
    void setGridYAxis(int axis);
    void setGridPen(const QPen &p);
    void setGridMajPen(const QPen &p);
    void setGridMinPen(const QPen &p);

    int gridXAxis() const { return d_grid.xAxis(); }
    int gridYAxis() const { return d_grid.yAxis(); }
    const QPen& gridMinPen() { return d_grid.minPen(); }
    const QPen& gridMajPen() { return d_grid.majPen(); }



    //
    //   Modify Axes
    //
    void changeAxisOptions(int axis, int opt, bool value);
    void enableAxis(int axis, bool tf = TRUE);
    void setAxisFont(int axis, const QFont &f);
    void setAxisMargins(int axis, double mlo, double mhi);
    void setAxisOptions(int axis, int opt);
    void setAxisAutoScale(int axis);
    void setAxisScale(int axis, double min, double max, double step = 0);
    void setAxisLabelFormat(int axis, char f, int prec);
    void setAxisTitleFont(int axis, const QFont &f);
    void setAxisMaxMinor(int axis, int maxMinor);
    void setAxisMaxMajor(int axis, int maxMajor);
    void setAxisReference(int axis, double value);
    void setAxisTitle(int axis, const char *t);

    //
    //  Retrieve Axis Properties
    //
    bool axisAutoScale(int axis) const;
    bool axisEnabled(int axis) const;
    const QFont axisFont(int axis);
    bool axisMargins(int axis, double &mlo, double &mhi) const;
    int axisMaxMajor(int axis) const;
    int axisMaxMinor(int axis) const;
    int axisOptions(int axis) const;
    double axisReference(int axis) const;
    const QwtScaleDiv& axisScale(int axis) const;
	void axisLabelFormat(int axis, char &f, int &prec) const;
    const QString& axisTitle(int axis) const;
    const QFont& axisTitleFont(int axis) const;
    double invTransform(int axis, int pos) const;
    int transform(int axis, double value) const;

    //
    //  Insert/Remove Markers
    //
    long insertMarker(const char *label = 0, int xAxis = xBottom, int yAxis = yLeft);
    long insertLineMarker(const char *label, int axis);
    bool removeMarker(long key);
    void removeMarkers();

    //
    // Set Marker Properties
    //
    long closestMarker(int xpos, int ypos, int &dist) const;
    bool setMarkerFont(long key, const QFont &f);
    bool setMarkerLinePen(long key, const QPen &p);
    bool setMarkerLineStyle(long key, QwtMarker::LineStyle st);
    bool setMarkerPos(long key, double xval, double yVal);
    bool setMarkerSymbol(long key, const QwtSymbol &s);
    bool setMarkerLabel(long key, const char *txt);
    bool setMarkerLabelAlign(long key, int align);
    bool setMarkerLabelPen(long key, const QPen &p);
    bool setMarkerXPos(long key, double val);
    bool setMarkerYPos(long key, double val);
    bool setMarkerPen(long key, const QPen &p);
    bool setMarkerXAxis(long key, int axis);
    bool setMarkerYAxis(long key, int axis);

    //
    // Get Marker Properties
    //
    const QFont& markerFont(long key) const;
    QArray<long> markerKeys() const;
    const QString& markerLabel(long key) const;
    int markerLabelAlign(long key) const;
    const QPen& markerLabelPen(long key) const;
    const QPen& markerLinePen(long key) const;
    QwtMarker::LineStyle markerLineStyle(long key) const;
    void markerPos(long key, double &mx, double &my) const;
    const QwtSymbol& markerSymbol(long key) const;
    int markerXAxis(long key) const;
    int markerYAxis(long key) const;

    //
    // Set Legend Properties
    void enableLegend(bool tf);
    void setLegendPos(int pos);
    void setLegendFont(const QFont &f);
    void setLegendFrameStyle(int st);
    
    // Get Legend Properties
    bool legendEnabled() const { return d_legendEnabled; }
    int legendPos() const { return d_legendPos; }
    int legendFrameStyle() const;
    const QFont legendFont() const;
    
protected:
    
    void resizeEvent(QResizeEvent *e);
    void autoRefresh();
    
public slots:
    
    void replot();
    void updatePlot();

private slots:
    void lgdClicked(int index);
    void updatePixmap();
    
signals:
    /*!
      A signal which is emitted when the mouse is pressed in the
      plotting area.
      \param e Mouse event object, event coordinates referring
               to the plotting area
     */
    void plotMousePressed(const QMouseEvent &e);
    /*!
      A signal which is emitted when a mouse button has been
      released in the plotting area.
      \param e Mouse event object, event coordinates referring
               to the plotting area
     */
    void plotMouseReleased(const QMouseEvent &e);
    /*!
      A signal which is emitted when the mouse is moved in the
      plotting area.
      \param e Mouse event object, event coordinates referring
               to the plotting area
     */
    void plotMouseMoved(const QMouseEvent &e);
    /*!
      A signal which is emitted when the user has clicked
      on a legend item.
      \param key Key of the curve corresponding to the
                 selected legend item
     */
    void legendClicked(long key);

};


#endif





