/***************************************************************************
                          geowidget.h  -  description
                             -------------------
    begin                : Mon Feb 14 2000
    copyright            : (C) 2000 by Marc Bartsch
    email                : marc.bartsch@topmail.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program 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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef GEOWIDGET_H
#define GEOWIDGET_H

#include <iostream.h>

#include <qpoint.h>
#include <qptrlist.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <qdragobject.h>

#include "coordinates.h"
#include "geoobjects.h"


/**	
		This class represents the widget that shows the grid and all geometrical objects.
*/
class GeoWidget : public QWidget
{
		Q_OBJECT

	public:

  	/** Constructor */
  	GeoWidget( QWidget *parent=0, const char *name=0 );

  	/** Destructor */
  	~GeoWidget();

  	/** Is the widget used in kiosk mode? */
		bool getIsKiosk(){ return isKiosk; };

  	/** Set flag that widget is used in kiosk mode. */
		void setIsKiosk( bool pIsKiosk ){ isKiosk = pIsKiosk; };

  	/** Sets the background color of the widget. Widget will not be drawn! */
		void setBackgroundColor( QColor color ){ backgroundColor = color; };

  	/** Sets the grid color of the widget. Widget will not be drawn! */
		void setGridColor( QColor & color ){ gridColor = color; };

  	/** Sets the maximum numbers of the grid. Widget will not be drawn! */
		void setNumberRange( int x, int y ){ maxX = x; maxY = y; };

  	/** This number determines how much percent of the current screen height is taken
				for one unit. */
		void setUnit( int punit ){ unitInPercent = punit; unitInPixel = (int)( punit * intCanvasHeight / 100 ); };

  	/** Whether numbers will be drawn. */
		void showNumbers( bool pnumbers ){ numbers = pnumbers; };

  	/** Whether grid will be drawn. */
		void showGridLines( bool pgridLines ){ gridLines = pgridLines; };

  	/** Whether axes will be drawn. */
		void showAxes( bool paxes ){ axes = paxes; };

  	/** This method is only for internal reasons. The objects you see on screen are only copies
				from an internal pixmap. Now, to update the screen, not only one single rectangle will
				copied that contains all objects, or one rectangle per object. Instead, for perfomrance
				reasons, every object is broken into a set of rectangle whose overall area is much smaller
				than of just one rectangle. Calling this method with true will show you the boundaries of
				all the little rectangles. */
		void showBoundingRects( bool pboundingRects ){ boundingRects = pboundingRects; };

  	/** Center canvas. Canvas will not be painted! */
    void setCentered( bool pcenter ){ center = pcenter; };

  	/** Turns on move mode. Means, the next mouse movements will move the underlying
				grid. */
    void startMoveMode( bool pmove ){ move = pmove; };

  	/** Paints the whole canvas and not only rect */
    void paintWholeWidget();

  	/**	This method draws the objects contained in the list on the internal
  			canvas and updates the widget on screen.	*/
    void drawObjects( QList <GeoObjects> & objectList );

  	/**	This method draws the objects contained in the list on the internal
  			canvas and updates the widget on screen.	*/
		void drawMovedObjects( QList <GeoObjects> & objectList );

		/** This method does everything needed before moving. It creates a tempCanvas
				that contains the background and all objects that don't move. This is the
				background our moved objects will drawn upon. */
		void prepareMoving( 	QList <GeoObjects> & staticObjectList,
													QList <GeoObjects> & moveObjectList   );

  	/**	Draws coordinates and everything on any paintDevice. Used for printing. */
  	void drawGrid( QPainter & p );

  	/**	Draws coordinates and everything on internal canvasses. */
		void drawGrid();

  	/**	Clears all objects and fills widget with background. */
		void clear();

	private:

  	/** This is where painting actually takes place (of rect). */
    void 	paint( QRect *rect );

  	/** This is where painting actually takes place (of rect). */
    void 	paint( QList <QRect> list );

  	/**	This method draws the objects contained in the list on the canvas. */
    void drawObjects( QList <GeoObjects> & objectList, QPixmap *canvas );

  	/**	This method moves the underlying grid around. */
		void moveGrid ( Coordinates coords );

		/** Maps intCanvas coordinates to widget coordinates. */
		QPoint mapCanvasToWidget( QPoint pt );

		/** Maps widget coordinates to intCanvas coordinates. */
		void mapWidgetToCanvas( Coordinates & coords );

  	/** Is true if widget is used in kiosk mode, false otherwise. */
  	bool isKiosk;

  	/** Internal Pixmap that contains coord grid and objects. This pixmap
  			is copied into the actual widget on the screen. */
    QPixmap	*intCanvas;

  	/** Internal Pixmap that contains only coord grid and NO objects. */
  	QPixmap	*gridOnlyCanvas;

  	/** Internal Pixmap for temporary reasons. */
  	QPixmap	*tempMoveCanvas;

  	/** Width of canvas. Is as big as screen resolution (for the kiosk mode) */
  	int intCanvasWidth;

  	/** Height of canvas. Is as big as screen resolution (for the kiosk mode) */
  	int intCanvasHeight;

  	/** Since the widget that shows the canvas on the screen is smaller than intCanvas,
        this is where the TopLeftX of the widget is positioned.	*/
    int intCanvasLeftTopX;

  	/**	Since the widget that shows the canvas on the screen is smaller than intCanvas,
        this is where the TopLeftY of the widget is positioned.	*/
  	int intCanvasLeftTopY;

  	/**	If you press the mouse button on the widget, the pos is stored in here. Used when
				moving the underlying grid. */
  	int 		extCanvasPosX;

  	/**	If you press the mouse button on the widget, the pos is stored in here. Used when
				moving the underlying grid. */
  	int 		extCanvasPosY;

  	/**	Stores the highest x coordinate you see on screen. */
		int 		maxX;

  	/**	Stores the highest y coordinate you see on screen. */
		int 		maxY;

  	/**	Stores how much percent of the screen height is taken for one unit. */
		int			unitInPercent;

  	/**	Stores how many pixel of the screen height is taken for one unit. */
		int			unitInPixel;

  	/**	Stores whether left mouse button has been pressed. */
    bool 		leftPressed;

  	/**	Stores whether gridLines should be drawn the next time drawGrid is called. */
  	bool  	gridLines;

  	/**	Stores whether numbers should be drawn the next time drawGrid is called. */
  	bool  	numbers;

  	/**	Stores whether axes should be drawn the next time drawGrid is called. */
  	bool  	axes;

  	/**	Stores whether grid should be centered the next time paintWholeWidget is called. */		
  	bool 		center;

  	/**	Stores whether grid will be moved next time the mouse is moved with a pressed button. */		
  	bool 		move;

  	/**	Stores whether boundingRects will be drawn. */		
		bool		boundingRects;

  	/**	Stores background color. */		
		QColor 	backgroundColor;

  	/**	Stores grid color. */		
		QColor 	gridColor;

  	/**	Stores list of rects of those objects that will not move when another object is moved. */		
		QList <QRect> staticOverlayList;

  	/**	Stores list of rects of those objects that will move when another object is moved. */		
		QList <QRect> moveOverlayList;

	protected:

    void	paintEvent( QPaintEvent * );
    void 	mouseMoveEvent( QMouseEvent *ev );
    void 	mousePressEvent( QMouseEvent *ev );
    void 	mouseReleaseEvent( QMouseEvent *ev );
  	void 	focusOutEvent( QFocusEvent * );
    void 	resizeEvent ( QResizeEvent * );
  	void	dragEnterEvent( QDragEnterEvent* event );
  	void	dropEvent( QDropEvent* event );

	signals:

    void mouseMoveLeftButton( Coordinates coords );
    void mouseMove( Coordinates coords );
    void mouseRelease( Coordinates coords );

  	void mouseRightPressEvent( Coordinates coords );
    void mouseLeftPressEvent( Coordinates coords );
    void mouseLeftClickEvent( Coordinates coords );

  	void loadDropFile( QString fileName );
  	void focusOut();
};

#endif
