/***************************************************************************
**
**  This file is part of SciFigs.
**
**  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 file 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2008-02-18
**  Copyright: 2008-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#ifndef GRAPHCONTENTOPTIONS_H
#define GRAPHCONTENTOPTIONS_H

#include <QtGui>
#include <QGpCoreMath.h>

#include "SciFigsDLLExport.h"

namespace SciFigs {

class SCIFIGS_EXPORT GraphContentOptions
{
  TRANSLATIONS("GraphContentOptions")
public:
  GraphContentOptions();
  GraphContentOptions(const GraphContentOptions& o);
  ~GraphContentOptions();

  // X and Y scales
  Scale& scaleX() {return _scaleX;}
  Scale& scaleY() {return _scaleY;}
  const Scale& scaleX() const {return _scaleX;}
  const Scale& scaleY() const {return _scaleY;}
  // coordinates conversion for screen
  int xa2s(double x) const {return _scaleX.a2s(x);}
  int ya2s(double y) const {return _scaleY.a2s(y);}
  int xr2s(double x) const {return _scaleX.r2s(x);}
  int yr2s(double y) const {return _scaleY.r2s(y);}
  QPoint r2s(double x, double y) const {return QPoint(xr2s(x), yr2s(y));}
  QPoint r2s(const Point& p) const {return QPoint(xr2s(p.x()), yr2s(p.y()));}
  QPoint r2s(const Point2D& p) const {return QPoint(xr2s(p.x()), yr2s(p.y()));}
  // coordinates conversion for screen in floating point values
  double xr2sF(double x) const {return _scaleX.r2sF(x);}
  double yr2sF(double y) const {return _scaleY.r2sF(y);}
  QPointF r2sF(double x, double y) const {return QPointF(xr2sF(x), yr2sF(y));}
  QPointF r2sF(const Point& p) const {return QPointF(xr2sF(p.x()), yr2sF(p.y()));}
  QPointF r2sF(const Point2D& p) const {return QPointF(xr2sF(p.x()), yr2sF(p.y()));}
  /*
     Returns true if the segment must be drawn
     This tranformation function is used to avoid overflow in super zoomed graphics
  */
  bool r2s(const Point2D& p1, const Point2D& p2, QPoint& ps1, QPoint& ps2) const;
  bool yr2s(const Point2D& p1, const Point2D& p2, QPoint& ps1, QPoint& ps2) const;
  inline bool r2s(const Point& p1, const Point& p2, QPoint& ps1, QPoint& ps2) const;
  /* I noticed that on some linux systems it is forbiden to draw a line
     outside the widget frame especially for negative X and Y greater than
     height(), this is why I'm forced to check this at the end of the
     routine before drawing
  */
  inline void checkOrigin(QPoint& ps1, QPoint& ps2, int h) const;
  double xs2r(int x) const {return _scaleX.s2r(x);}
  double ys2r(int y) const {return _scaleY.s2r(y);}
  Point s2r(const QPoint& p) const {return Point(xs2r( p.x()), ys2r(p.y()) );}
  Point2D s2r2D(const QPoint& p) const {return Point2D(xs2r( p.x()), ys2r(p.y()) );}
  double xVisMin() const {return _scaleX.minimum();}
  double yVisMin() const {return _scaleY.minimum();}
  double xVisMax() const {return _scaleX.maximum();}
  double yVisMax() const {return _scaleY.maximum();}
  Rect visibleRect() const;
  double ax() const {return _scaleX.a();}
  double ay() const {return _scaleY.a();}
  double bx() const {return _scaleX.b();}
  double by() const {return _scaleY.b();}

  bool gridLines() const {return _gridLines;}
  void setGridLines(bool g) {_gridLines=g;}

  const QColor& gridLineColor() const {return _gridLineColor;}
  void setGridLineColor(const QColor& c) {_gridLineColor=c;}

  bool transparentMask() const {return _transparentMask;}
  void setTransparentMask(bool tm) {_transparentMask=tm;}

  double gridLineWeight() const {return _gridLineWeight;}
  void setGridLineWeight(double lw) {_gridLineWeight=lw;}

  double contourWeight() const {return _contourWeight;}
  void setContourWeight(double lw) {_contourWeight=lw;}

  bool printBitmap() const {return _printBitmap;}
  void setPrintBitmap(bool p) {_printBitmap=p;}

  void paintGridLines (QPainter& p, double dotpercm, int w, int h) const;
  void paintContour (QPainter& p, double dotpercm, int w, int h) const;

  void swapAxes();
private:
  inline bool oneInside(const Point2D& p1, const Point2D& p2, QPoint& ps1, QPoint& ps2) const;
  inline bool bothOutside(const Point2D& p1, const Point2D& p2, QPoint& ps1, QPoint& ps2) const;

  bool _gridLines;
  bool _transparentMask;
  QColor _gridLineColor;
  double _gridLineWeight;
  double _contourWeight;
  bool _printBitmap;

  Scale _scaleX;
  Scale _scaleY;
};

inline bool GraphContentOptions::r2s(const Point& p1, const Point& p2, QPoint& ps1, QPoint& ps2) const
{
  TRACE;
  Point2D p2D1=p1;
  Point2D p2D2=p2;
  return r2s(p2D1, p2D2, ps1, ps2);
}

inline void GraphContentOptions::checkOrigin(QPoint& ps1, QPoint& ps2, int h) const
{
  TRACE;
  if(ps1.x() < 0) ps1.setX(0);
  if(ps1.y() >= h) ps1.setY(h - 1);
  if(ps2.x() < 0) ps2.setX(0);
  if(ps2.y() >= h) ps2.setY(h - 1);
}

} // namespace SciFigs

#endif // GRAPHCONTENTOPTIONS_H
