/*
 * Electric(tm) VLSI Design Systems
 *
 * File: graphqt.h
 * Qt Window System interface
 * Written by: Dmitry Nadezhin, Instutute for Design Problems in Microelectronics, Russian Academy of Sciences
 *
 * Copyright (c) 2001 Static Free Software.
 *
 * Electric(tm) is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Electric(tm) 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 Electric(tm); see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, Mass 02111-1307, USA.
 *
 * Static Free Software
 * 4119 Alpine Road
 * Portola Valley, California 94028
 * info@staticfreesoft.com
 */

#ifndef GRAPHQT_H
#define GRAPHQT_H

#include "global.h"
#include "usr.h"

#define QT_CLEAN_NAMESPACE
#include <qapplication.h>
#include <qbitmap.h>
#include <qcursor.h>
#include <qmainwindow.h>
#include <qpainter.h>
#include <qpixmap.h>

#ifndef Q_ASSERT
#define Q_ASSERT(x) ASSERT(x)
#endif
#ifndef Q_CHECK_PTR
#define Q_CHECK_PTR(p) CHECK_PTR(p)
#endif

#define GTRACE          0       /* etrace flag of usual graphics trace */
#define GTRACE_CONT     0       /* etrace flag of usual graphics trace (continue line) */

#ifdef ONUNIX
#define QDRAW      /* use Qt drawing */
#endif

class QHBox;
class QLabel;
class QLineEdit;
class QMultiLineEdit;
class QPaintDevice;

class MessagesMainWindow: public QMainWindow
{
    Q_OBJECT
public:
    MessagesMainWindow();
    void closeEvent( QCloseEvent *e );
    void keyPressEvent( QKeyEvent *e );
public slots:
    void lineEntered();
protected:
    bool eventFilter( QObject *watched, QEvent *e ); 
public:
    QMultiLineEdit *scroll;
    QHBox *input;
    QLabel *prompt;
    QLineEdit *line;
    bool stopped;
};

class EPainter: public QPainter
{
public:
  EPainter();
  static void init( QStringList &facelist );
  static void term();
  bool begin( QPaintDevice *pd );
  void screendrawline(INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2, GRAPHICS *desc, INTBIG texture);
  void screeninvertline(INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2);
  void screendrawbox(INTBIG lowx, INTBIG highx, INTBIG lowy, INTBIG highy, GRAPHICS *desc);
  void screendrawpolygon(INTBIG *x, INTBIG *y, INTBIG count, GRAPHICS *desc);
  void screeninvertbox(INTBIG lowx, INTBIG highx, INTBIG lowy, INTBIG highy);
  void screenmovebox(INTBIG sx, INTBIG sy, INTBIG wid, INTBIG hei, INTBIG dx, INTBIG dy);
  void drawPixmap( QPoint orig, QPixmap pixmap );
  void screendrawtext(INTBIG atx, INTBIG aty, char *s, GRAPHICS *desc);
  void screendrawcircle(INTBIG atx, INTBIG aty, INTBIG radius, GRAPHICS *desc);
  void screendrawthickcircle(INTBIG atx, INTBIG aty, INTBIG radius, GRAPHICS *desc);
  void screendrawdisc(INTBIG atx, INTBIG aty, INTBIG radius, GRAPHICS *desc);
  void screendrawcirclearc(INTBIG centerx, INTBIG centery, INTBIG p1_x, INTBIG p1_y,
			   INTBIG p2_x, INTBIG p2_y, GRAPHICS *desc);
  void screendrawthickcirclearc(INTBIG centerx, INTBIG centery, INTBIG p1_x, INTBIG p1_y,
				INTBIG p2_x, INTBIG p2_y, GRAPHICS *desc);
  void screendrawgrid(int pointWidth, double x0, double y0, double dx, double dy, int nx, int ny);

  QRect copyRect() { return cr;  };
  bool dirty() { return cr.isValid(); };
  void clearDirty() { cr = QRect(); }
  void updateAll();
  UINTBIG startTime() { return starttime; }
private:
  void setPlanes( ulong planes = ~0);
  void setBrushPlanes( ulong planes = ~0);
  void setBrush( GRAPHICS *desc );
  void updateCopyRect( int x, int y, int w, int h );
  QBitmap loadStipple( UINTSML raster[] );
  QRect cr;
  UINTBIG starttime;
};

class GraphicsDraw: public QWidget
{
    Q_OBJECT
public:
    GraphicsDraw( QWidget *parent );
    bool event( QEvent * e );
    void focusInEvent( QFocusEvent *e );
    void focusOutEvent( QFocusEvent *e );
    void paintEvent( QPaintEvent *e );
    void keyPressEvent( QKeyEvent *e );
    void mouseDoubleClickEvent( QMouseEvent *e );
    void mouseMoveEvent( QMouseEvent *e );
    void mousePressEvent( QMouseEvent *e );
    void mouseReleaseEvent( QMouseEvent *e );
    void resizeEvent( QResizeEvent *e );
    void wheelEvent( QWheelEvent * e);
private:
    void keepCursorPos( QPoint pos );
    void buttonPressed( QPoint pos, INTSML but );
    void recalcSize();
public:
    WINDOWFRAME *wf;
    QPixmap pixmap;			/* offscreen data */
    EPainter painter;
    int colorvalue[256];
};

class GraphicsMainWindow: public QMainWindow
{
    Q_OBJECT
public:
    GraphicsMainWindow( QWidget *parent, BOOLEAN floating );
    ~GraphicsMainWindow();
    void closeEvent( QCloseEvent *e );

    QPopupMenu *makepdmenu(POPUPMENU *pm, INTSML value);
    INTSML pulldownindex(POPUPMENU *pm);
    void pulldownmenuload();
    void nativemenurename(POPUPMENU *pm, INTBIG pindex);
private:
    QString describeboundkey(INTSML key, INTBIG special);
public slots:
    void menuAction( int id );
public:
    QLabel *statusItems[100];
    WINDOWFRAME *wf;
    GraphicsDraw *draw;
    QPopupMenu **pulldownmenus;		/* list of Windows pulldown menus */
    POPUPMENU  **pulldowns;			/* list of Electric pulldown menus */
    INTSML       pulldownmenucount;	/* number of pulldown menus */
};

class EApplication: public QApplication
{
    Q_OBJECT
public:
    EApplication( int &argc, char **argv);
    ~EApplication();
    Display* dpy() const;
    int screen() const;
    MessagesMainWindow *messMainWin;
    static char *localize (QString qstr);
    static char *localizeFilePath (QString filePath, bool addSeparator );
    int translatekey(QKeyEvent *e, INTBIG *special);

    QBitmap textbits;
    QFont curfont;
    QStringList facelist;
    QString defface;
    QFont fixedfont;

    QBitmap programicon;
    QCursor realcursor;
    QCursor nomousecursor;
    QCursor drawcursor;
    QCursor nullcursor;
    QCursor menucursor;
    QCursor handcursor;
    QCursor techcursor;
    QCursor ibeamcursor;
    QCursor lrcursor;
    QCursor udcursor;

    /* trackcursor */
    INTSML waitforpush;
    BOOLEAN (*whileup)(INTBIG x, INTBIG y);
    void (*whendown)(void);
    BOOLEAN (*eachdown)(INTBIG x, INTBIG y);
    BOOLEAN (*eachchar)(INTBIG x, INTBIG y, INTSML c);

    /* modalloop */
    BOOLEAN (*charhandler)(INTSML chr, INTBIG special);
    BOOLEAN (*buttonhandler)(INTBIG x, INTBIG y, INTBIG but);

public slots:
    void toolTimeSlice(); 
private:
    Display      *gra_dpy;				/* the main X display */
};

inline Display* EApplication::dpy() const
{
    return qt_xdisplay();
}

extern EApplication *gra;

#endif
