// render2d.h -- class definition for XDrawChem render widget.

#ifndef RENDER2D_H
#define RENDER2D_H

#include <qwidget.h>
#include <qcursor.h>
#include <qrect.h>
#include <qfont.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qpainter.h>
#include <kprinter.h>
#include <qdragobject.h>
#include "drawable.h"
#include "paintable.h"
#include "dpoint.h"
#include "prefs.h"
#include "clipboard.h"
#include "xdc_event.h"
#include "custom_rings.h"

class ChemData;
class Text;

extern Preferences preferences;

class Render2D : public QWidget {
  Q_OBJECT
    public:
  void setChemData(ChemData *c1) { c = c1; }
  void setCustomRings(CustomRings* rings) { m_rings=rings; }
  // defined in render2d.cpp
  Render2D(QWidget *parent = 0, const char *name = 0);
  void CorrectEndpoint_arrow();
  void CorrectEndpoint_bond();
  void CleanUpAfterTextTool();
  void setClipboard(Clipboard *);
  Clipboard *getClipboard();

  public slots:
    // defined in render2d.cpp
    void ReactionAnalysis(int);
    void setMode_Select();
    void setMode_DrawLine();
    void setMode_DrawDashLine();
    void setMode_DrawUpLine();
    void setMode_DrawDownLine();
    void setMode_DrawArrow(QString);
    void setMode_DrawBracket(QString);
    void setMode_Erase();
    void setMode_DrawText();
    void setMode_DrawSymbol(QString);
    void setMode_DrawRing(QString, QString, int sp = 0);
    void setMode_DrawCurveArrow(QString);
    void Tool(int);
    void SelectAll();
    void EraseSelected();
    void Inserted();
    void SetFont(QFont);
    void SetColor(QColor);
    QFont GetFont();
    QColor GetColor();
    void Cut();
    void Copy();
    void Paste();
    void Undo();
    void Rotate90();
    void Rotate180();
    void Rotate270();
    void AutoLayout();
    void Flip(int);
    bool SaveEPS(QString);
    bool SaveSVG(QString);
    void clearAllGroups();
    // defined in render2d_draw.cpp
    double getAngle(QPoint, QPoint);
    void drawLine(QPoint, QPoint, int, QColor, int = 0);
    void drawPolyline(QPointArray, QColor);
    void drawUpLine(QPoint, QPoint, QColor);
    void drawDownLine(QPoint, QPoint, QColor);
    void drawArrow(QPoint, QPoint, QColor, int);
    void drawBracket(QPoint, QPoint, QColor, int);
    void drawBox(QPoint, QPoint, QColor);
    void drawFillBox(QPoint, QPoint, QColor);
    void drawFillBox(QPoint, QPoint, QColor, bool, QColor, int);
    void drawCircle(QPoint, int, QColor);
    void drawText(QChar, QPoint, QColor, QFont);
    void drawString(QString, QPoint, QColor, QFont);
    void drawTextReverse(QChar, QPoint, QColor, QFont);
    void drawPixmap(QPoint, QPixmap);
    void drawCurveArrow(QPoint, QPoint, QColor, QString);
    QPixmap MakePixmap(bool transp = false);
    QPixmap MakeFullPixmap();
    // defined in render2d_text.cpp
    QString EditText(QPoint, QString, int, bool);
    QRect GetTextDimensions(QString, QFont);
    int GetTextHeight(QFont);
    int GetTextFullHeight(QFont);
    int GetCharWidth(QChar, QFont);
    int GetStringWidth(QString, QFont);
    void DrawText_mousePressEvent(QMouseEvent *);
    void DrawText_mouseReleaseEvent(QMouseEvent *);
    void DrawText_mouseMoveEvent(QMouseEvent *);
    void Superscript(bool flag);
    void Subscript(bool flag);
    void Bold(bool flag);
    void Italic(bool flag);
    void Underline(bool flag);
    // defined in render2d_select.cpp
    void Select_mouseMoveEvent(QMouseEvent *);
    double GetAngle(DPoint *, DPoint *, DPoint *);
    // defined in render2d_print.cpp
    void PrintSetup();
    void Print();
    void UpdatePageGeometry();

    // defined here:
    double DistanceBetween(QPoint a, QPoint b) {
      double dx = (double)a.x() - (double)b.x();
      double dy = (double)a.y() - (double)b.y();
      return sqrt(dx * dx + dy * dy);
    }
    QPoint Midpoint(QPoint a, QPoint b) {
      int ax = (a.x() + b.x()) / 2;
      int ay = (a.y() + b.y()) / 2;
      return QPoint(ax, ay);
    }
    int RoundOff(double x) {
      int x1 = (int)x;
      double x2 = x - (double)x1;
      if (x2 > 0.5)
	return x1 + 1;
      else
	return x1;
    }
    void SetOutputDevice(int x) { outputDevice = x; }
    void SetThick(int t) { thick = t; }
    int getPageSize() { return page_size; }
    int getPageOrientation() { return page_orientation; }
    void setPageSizeAndOrientation(int ps, int po) {
      page_size = ps;
      page_orientation = po;
      UpdatePageGeometry();
    }
    void setBGColor(QColor bc1) {
      bgcolor = bc1;
      setBackgroundColor(bc1);
    }
    QColor getBGColor() { return bgcolor; }
    void setWaitCursor() { setCursor(waitCursor); }
    void setArrowCursor() { setCursor(arrowCursor); }

 signals:
    void SignalSetStatusBar(QString);
    void SignalHelpTopic(QString);
    void XDCEventSignal(XDC_Event *);
    void TextOn(QFont);
    void TextOff();
    /** Does nothing, but is called when Render2D has a modification such as a mouseReleaseEvent */
    void signalModified();
  /** No descriptions */
  void hasBold(bool flag);
  void hasItalic(bool flag);
  void hasUnderline(bool flag);
  void hasSuperscript(bool flag);
  void hasSubscript(bool flag);
  void signalFont(QString font);
  void signalFontSize(int size);
  void signalNewRingsSize(int);

 protected:
  // defined in render2d_event.cpp
  void mousePressEvent(QMouseEvent *);
  void mouseReleaseEvent(QMouseEvent *);
  void mouseMoveEvent(QMouseEvent *);
  void paintEvent(QPaintEvent *);
  void resizeEvent(QResizeEvent *);
  // defined in render2d_text.cpp
  void keyPressEvent(QKeyEvent *);

 //private:
  protected:
  CustomRings* m_rings;
  // Qpixmap of double buffer
  QPixmap dbuffer;
  // height and width of the drawing area
  int renderHeight, renderWidth;
  // cursors
  QCursor skullcursor, rotatecursor;
  // the ChemData object this Render2D is linked with
  ChemData *c;
  // start and end points of object being drawn, or selection box...
  DPoint *startpoint, *endpoint;
  // current drawing font
  QFont currentFont;
  // current drawing color
  QColor currentColor;
  // current background color
  QColor bgcolor;
  // Positions to remember for multiple selection
  QPoint selectOrigin, selectPrev;
  // Rotate and resize handles (used in MODE_SELECT_MULTIPLE_SELECTED)
  QRect selectionBox;
  QPoint rotateHandle, resizeHandle;
  // rotate origin
  QPoint rotateOrigin;
  // previous angle (for rotating)
  double prevangle;
  // previous position (of mouse, usually)
  DPoint *prevpos;
  // highlighted point, if any
  DPoint *highlightpoint;
  // highlighted object, if any
  Drawable *highlightobject;
  // current input/output/drawing mode
  int mode, prev_mode;
  // current button state
  bool mouse1down, mouse3down;
  bool moved;  // to check validity of points, see render2d_event.cpp
  // direct drawing flag
  bool directdraw;
  // fixed length/angle (now controlled by Preferences class, see prefs.h)
  //bool fixed_bond, fixed_arrow;
  //double fixedlength_bond, fixedangle_bond;
  //double fixedlength_arrow, fixedangle_arrow;
  // current line thickness
  int thick;
  // Output device (screen, printer, image)
  int outputDevice;
  // Output file/textstream
  QFile output_file;
  QTextStream output_ts;
  // SVG position correction
  int svg_dx, svg_dy;
  // Output printer
  QList<Paintable> paintqueue;
  KPrinter *printer;
  // Text object, temp string to use when creating/editing text
  Text *localtext;
  QString localstring;
  bool text_exists;  // does this text object exist?
  bool text_drag;
  DPoint *start_drag;
  // Symbol object, which file to use (or ring, if MODE_RING)
  QString symbolfile;
  int smartplace;  // able to attach ring to a point (e.g., benzene, Fmoc)
  // Bracket object, which bracket
  int bracket_type;
  // page setup options
  int page_size;
  int page_orientation;
  // drag object
  QDragObject *drag1;
  bool dragging;
};

#endif
