/* -*- mia-c++ -*-
 *
 * This file is part of viewitgui - a library and program for the
 * visualization of 3D data sets. 
 *
 * Copyright (c) Leipzig, Madrid 1999-2013 Mirco Hellmann, Gert Wollny
 *
 * viewitgui 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 3 of the License, or
 * (at your option) any later version.
 *
 * viewitgui 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 viewitgui; if not, see <http://www.gnu.org/licenses/>.
 */


#ifndef __event_hh
#define __event_hh

#include <queue>
#include <iosfwd>
#include <sigc++/sigc++.h>
#include <glibmm/refptr.h>
#include <glibmm/objectbase.h>
#include <mia.hh>
#include <viewit/4DVector.hh>

using namespace mia; 

/**
   Flags for key and mouse events.
   \begin{itemize}
   \item EV\_MOUSE1\_DOWN flag for left mouse button pressed
   \item EV\_MOUSE2\_DOWN flag for middle mouse button pressed
   \item EV\_MOUSE3\_DOWN flag for right mouse button pressed
   \item EV\_MOUSEDOWN\_MASK mask  to check whether any mouse button is pressed
   \item EV\_MOUSE1\_UP flag for left mouse button released
   \item EV\_MOUSE2\_UP flag for middle mouse button pressed
   \item EV\_MOUSE3\_UP flag for right mouse button pressed
   \item EV\_MOUSEUP\_MASK mask  to check whether any mouse button was released
   \item EV\_MOUSE\_MOVE flag if mouse was moved
   \item EV\_KEY\_MODIFIER\_CTRL flag if Ctrl-Key is pressed
   \item EV\_KEY\_MODIFIER\_ALT flag if Alt-Key is pressed
   \item EV\_KEY\_MODIFIER\_SHIFT flag Shift-Key is pressed
   \end{itemize}
*/
enum event_flags {
	EV_MOUSE1_DOWN=1,
	EV_MOUSE2_DOWN=2,
	EV_MOUSE3_DOWN=4,
	EV_MOUSEDOWN_MASK=7,
	EV_MOUSE1_UP=0x10,
	EV_MOUSE2_UP=0x20,
	EV_MOUSE3_UP=0x30,	
	EV_MOUSEUP_MASK=0x70,
	EV_MOUSE_MOVE=0x80,
	EV_KEY_MODIFIER_CTRL=0x100,
	EV_KEY_MODIFIER_ALT=0x200,
	EV_KEY_MODIFIER_SHIFT=0x400
};

/// typedef to get a rgba color vector r=x, b=y, c=z, a=a
typedef C4DFVector TColor;


#if 0
#define EV_MOUSE1_DOWN           1
#define EV_MOUSE2_DOWN           2
#define EV_MOUSE3_DOWN           4
#define EV_MOUSEDOWN_MASK        7
#define EV_MOUSE1_UP          0x10
#define EV_MOUSE2_UP          0x20
#define EV_MOUSE3_UP          0x40
#define EV_MOUSEUP_MASK       0x70
#define EV_MOUSE_MOVE         0x80
#define EV_KEY_MODIFIER_CTRL  0x100
#define EV_KEY_MODIFIER_ALT   0x200
#define EV_KEY_MODIFIER_SHIFT 0x400
#endif

/// empty base class for all event-infos
class CEventInfo : public Glib::ObjectBase {
	int __command; 
public:
	CEventInfo(int command):__command(command){}
	int get_command() const {return __command;}; 
	void set_command(int command) {__command = command;}; 
	virtual void read(std::istream& is);
	virtual void write(std::ostream& os);
};

typedef std::shared_ptr<CEventInfo> PEventInfo; 

/** Drawable commands
   \begin{itemize}
   \item EV\_DRAWABLE\_GET\_STATE to obtain the state of the drawable by the given EventInfo structure
   \item EV\_DRAWABLE\_SHOW to show the drawable
   \item EV\_DRAWABLE\_HIDE to hide the drawable
   \item EV\_DRAWABLE\_SET\_TRANSPARENCY to update the transparency value
   \item EV\_DRAWABLE\_XYCLIP\_ON to activate the xy-clipplane
   \item EV\_DRAWABLE\_XYCLIP\_OFF to deactivate the xy-clipplane
   \item EV\_DRAWABLE\_XZCLIP\_ON to activate the xz-clipplane
   \item EV\_DRAWABLE\_XZCLIP\_OFF  to deactivate the xz-clipplane
   \item EV\_DRAWABLE\_YZCLIP\_ON to activate the yz-clipplane
   \item EV\_DRAWABLE\_YZCLIP\_OFF to deactivate the yz-clipplane
   \item EV\_DRAWABLE\_FREECLIP\_ON to activate the free-clipplane
   \item EV\_DRAWABLE\_FREECLIP\_OFF to deactivate the free-clipplane
   \item EV\_DRAWABLE\_RESET\_STATE to reset the state of this drawable to its initial state
   \end{itemize}
*/
#define EV_DRAWABLE_GET_STATE		0x2000
#define EV_DRAWABLE_SHOW		0x2001
#define EV_DRAWABLE_HIDE		0x2002 
#define EV_DRAWABLE_SET_TRANSPARENCY    0x2003
#define EV_DRAWABLE_XYCLIP_ON		0x2004
#define EV_DRAWABLE_XYCLIP_OFF		0x2005
#define EV_DRAWABLE_XZCLIP_ON		0x2006
#define EV_DRAWABLE_XZCLIP_OFF		0x2007
#define EV_DRAWABLE_YZCLIP_ON		0x2008
#define EV_DRAWABLE_YZCLIP_OFF		0x2009
#define EV_DRAWABLE_FREECLIP_ON		0x200A
#define EV_DRAWABLE_FREECLIP_OFF	0x200B
#define EV_DRAWABLE_RESET_STATE		0x200C


class TDrawableEventInfo : public CEventInfo {
	bool __clipxy;
	bool __clipxz;
	bool __clipyz;
	bool __clipfree;
	bool __visible;
	float __transparency;
	
public:
	TDrawableEventInfo(int command, bool clipxy, bool clipxz, bool clipyz, bool clipfree, bool visible, float transparency)
		: CEventInfo(command), __clipxy(clipxy), __clipxz(clipxz), __clipyz(clipyz), __clipfree(clipfree),
		  __visible(visible), __transparency(transparency < 0.0 ? 0.0 : (transparency > 1.0 ? 1.0 : transparency))
	{;}
	
	TDrawableEventInfo(int command)
		: CEventInfo(command), __clipxy(false), __clipxz(false), __clipyz(false), __clipfree(false), __visible(false), __transparency(1.0) 
	{;}
	
	bool get_clipxy() const { return __clipxy; }
	bool get_clipxz() const { return __clipxz; }
	bool get_clipyz() const { return __clipyz; }
	bool get_clipfree() const { return __clipfree; }
	bool get_visibility() const { return __visible; }
	float get_transparency() const { return __transparency; }
	void set_clipxy(bool clipxy) { __clipxy = clipxy; }
	void set_clipxz(bool clipxz) { __clipxz = clipxz; }	
	void set_clipyz(bool clipyz) { __clipyz = clipyz; }
	void set_clipfree(bool clipfree) { __clipfree = clipfree; }
	void set_visibility(bool visible) { __visible = visible; }
	float set_transparency(float transparency) { return __transparency = (transparency < 0.0 ? 0.0 : (transparency > 1.0 ? 1.0 : transparency)); }
};

typedef std::shared_ptr<TDrawableEventInfo> PDrawableEventInfo; 

/** Coordaxes commands
   \begin{itemize}
   \item EV\_COORDAXES\_GET\_STATE to obtain the state of a TCoordAxes object by the given EventInfo structure
   \item EV\_COORDAXES\_SHOW_DECORATION toggle the drawing of the legend
   \end{itemize}
   \remark EV\_COORDAXES\_GET\_STATE will be ignored at present (only for the sake of completeness)
*/
#define EV_COORDAXES_GET_STATE		0x2050
#define EV_COORDAXES_SHOW_DECORATION	0x2051


/** slice command
   \begin{itemize}
   \item EV\_SLICE\_GET\_STATE to obtain the state of a TSlice object by the given EventInfo structure
   \item EV\_SLICE\_UP to increment the index of the slice slice to be displayed
   \item EV\_SLICE\_DOWN to decrement the index of the slice slice to be displayed
   \item EV\_SLICE\_SET\_SLICE to set index of the slice to be displayed with the value given by the EventInfo
   \end{itemize}
*/
#define EV_SLICE_GET_STATE	0x2100
#define EV_SLICE_UP		0x2101
#define EV_SLICE_DOWN		0x2102
#define EV_SLICE_SET_SLICE	0x2103

class TSliceEventInfo : public CEventInfo {
	float __slice;
	float __range_from;
	float __range_to;
public:
	TSliceEventInfo(int command, float slice, float from, float to)
		: CEventInfo(command), __slice(slice), __range_from(from), __range_to(to)
	{;}
	TSliceEventInfo(int command)
		: CEventInfo(command),__slice(0.0), __range_from(0.0), __range_to(0.0)
	{;}
	void get_slice_range(float& from, float& to)const{from=__range_from; to=__range_to;}
	void set_slice_range(float from, float to){__range_from= from; __range_to=to;}
	float get_slice_nr()const{return __slice;}
	void set_slice_nr(float slice){__slice = slice;}
};



/** clipplane commands
    \begin{itemize}
    \item EV\_CLIPPLANE\_GET\_STATE to obtain the state of a TClipPlane object by the given EventInfo structure
    \item EV\_CLIPPLANE\_INVERT to flip the side to be clipped
    \end{itemize}
    \remark EV\_CLIPPLANE\_GET\_STATE will be ignored at present (only for the sake of completeness)
*/
#define EV_CLIPPLANE_GET_STATE			0x2200
#define EV_CLIPPLANE_INVERT			0x2201

class TClipPlaneEventInfo : public CEventInfo {
public:
	TClipPlaneEventInfo(int command)
		: CEventInfo(command)
	{;}
};



/** freeclipplane commands
    \begin{itemize}
    \item EV\_FREECLIPPLANE\_GET\_STATE to obtain the state of a TFreeClipPlane object by the given EventInfo structure
    \item EV\_FREECLIPPLANE\_SET\_ROTATION to rotate the clipplane around the x,y,z-axis (in that order applied)
    \item EV\_FREECLIPPLANE\_ACTIVATE\_TRIPOD to activate the selection of three points to reposition the clipplane
    \end{itemize}
*/
#define EV_FREECLIPPLANE_GET_STATE		0x2210
#define EV_FREECLIPPLANE_SET_ROTATION		0x221A
#define EV_FREECLIPPLANE_ACTIVATE_TRIPOD	0x221B

class TFreeClipPlaneEventInfo : public CEventInfo {
	float __alpha;
	float __beta;
	float __gamma;
public:
	TFreeClipPlaneEventInfo(int command)
		: CEventInfo(command), __alpha(0.0), __beta(0.0), __gamma(0.0)
	{;}

	TFreeClipPlaneEventInfo(int command, float alpha, float beta, float gamma)
		: CEventInfo(command), __alpha(alpha), __beta(beta), __gamma(gamma)
	{;}

	float get_alpha() const { return __alpha; }
	float get_beta()  const { return __beta; }
	float get_gamma() const { return __gamma; }

	void set_alpha(float alpha) { __alpha = alpha; }
	void set_beta(float beta)  { __beta = beta; }
	void set_gamma(float gamma) { __gamma = gamma; }
};




/** glslice commands
    \begin{itemize}
    \item EV\_GLSLICE\_GET\_STATE to obtain the state of a TGLSlice object by the given EventInfo structure
    \item EV\_GLSLICE\_SET\_TRANSLUCENCY to set the translucency
    \end{itemize}
*/
#define EV_GLSLICE_GET_STATE			0x2300
#define EV_GLSLICE_SET_TRANSLUCENCY		0x2301

class TGLSliceEventInfo : public CEventInfo {
	float __translucency;
public:
	TGLSliceEventInfo(int command, float translucency)
		: CEventInfo(command), __translucency(translucency)
	{;}

	TGLSliceEventInfo(int command)
		: CEventInfo(command), __translucency(0.2f)
	{;}

	float set_translucency(float translucency) { return __translucency = (translucency < 0.0 ? 0.0 : (translucency > 1.0 ? 1.0 : translucency)); }
	float get_translucency()const { return __translucency; }
};


/** voxelcloud commands
    \begin{itemize}
    \item EV\_VOXELCLOUD\_GET\_STATE to obtain the state of a TVoxelCloud object by the given EventInfo structure
    \item EV\_VOXELCLOUD\_SET\_LIFETIME to set the lifetime of a voxel
    \item EV\_VOXELCLOUD\_TOGGLE\_DIFFUSION to start or stop the diffusion algorithm
    \end{itemize}
*/
#define EV_VOXELCLOUD_GET_STATE			0x2400
#define EV_VOXELCLOUD_SET_LIFETIME		0x2401
#define EV_VOXELCLOUD_TOGGLE_DIFFUSION		0x2402

class TVoxelCloudEventInfo : public CEventInfo {
	float __lifetime;
public:
	TVoxelCloudEventInfo(int command, float lifetime)
		: CEventInfo(command), __lifetime(lifetime)
	{;}
	TVoxelCloudEventInfo(int command)
		: CEventInfo(command), __lifetime(2000.0f)
	{;}
	
	float get_lifetime()const { return __lifetime; }
	void set_lifetime(float lifetime) { __lifetime = lifetime; }
};

/** arrowlist commands
    \begin{itemize}
    \item EV\_ARROWLIST\_GET\_STATE to obtain the state of a TArrowList object by the given EventInfo structure
    \item EV\_ARROWLIST\_INCREASE\_ARROW\_NUMBER to increase the number of arrows to be displayed
    \item EV\_ARROWLIST\_DECREASE\_ARROW\_NUMBER to decrease the number of arrows to be displayed
    \item EV\_ARROWLIST\_INCREASE\_ARROW\_LENGTH to increase the arrow length
    \item EV\_ARROWLIST\_DECREASE\_ARROW\_LENGTH to decrease the arrow length
    \end{itemize}
    \remark EV\_ARROWLIST\_GET\_STATE will be ignored at present (only for the sake of completeness)    
*/
#define EV_ARROWLIST_GET_STATE			0x2500
#define EV_ARROWLIST_INCREASE_ARROW_NUMBER	0x2501
#define EV_ARROWLIST_DECREASE_ARROW_NUMBER	0x2502
#define EV_ARROWLIST_INCREASE_ARROW_LENGTH	0x2503
#define EV_ARROWLIST_DECREASE_ARROW_LENGTH	0x2504
#define EV_ARROWLIST_FLIP_ARROWS                0x2505

/** arrowlistgrow commands
    \begin{itemize}
    \item EV\_ARROWLISTGROW\_GET\_STATE to obtain the state of a TArrowListGrow object by the given EventInfo structure
    \item EV\_ARROWLISTGROW\_ADD\_ARROW to add an arrow to the list
    \end{itemize}
    \remark EV\_ARROWLISTGROW\_GET\_STATE will be ignored at present (just for the sake of completeness)    
*/
#define EV_ARROWLISTGROW_GET_STATE		0x2600
#define EV_ARROWLISTGROW_ADD_ARROW		0x2601

/** glmesh commands
    \begin{itemize}
    \item EV\_GLMESH\_GET\_STATE to obtain the state of a TGLMesh object by the given EventInfo structure
    \item EV\_GLMESH\_TOGGLE\_SHINY to toggle shiny drawing
    \item EV\_GLMESH\_TOGGLE\_LIGHTMODEL to toggle between the lightmodels
    \item EV\_GLMESH\_TOGGLE\_CULLING to enable or disable culling
    \item EV\_GLMESH\_TOGGLE\_FRONTFACECULLING to toggle between front- or backface culling
    \item EV\_GLMESH\_SET\_COLOR1 to set the first color
    \item EV\_GLMESH\_SET\_COLOR2 to set the second color
    \item EV\_GLMESH\_SET\_COLOR3 to set the third color
    \item EV\_GLMESH\_TOGGLE\_COLORSCALE to toggle between the scale types
    \end{itemize}
*/
#define EV_GLMESH_GET_STATE				0x2700
#define EV_GLMESH_TOGGLE_SHINY				0x2701
#define EV_GLMESH_TOGGLE_LIGHTMODEL			0x2702
#define EV_GLMESH_TOGGLE_CULLING			0x2703
#define EV_GLMESH_TOGGLE_FRONTFACECULLING		0x2704
#define EV_GLMESH_SET_COLOR1				0x2705
#define EV_GLMESH_SET_COLOR2				0x2706
#define EV_GLMESH_SET_COLOR3				0x2707
#define EV_GLMESH_TOGGLE_COLORSCALE			0x2708
#define EV_GLMESH_SHOW_DECORATION			0x2709

class TGLMeshEventInfo : public CEventInfo {
	bool __draw_shiny;
	bool __light_model;
	bool __culling;
	bool __front_face_culling;
	bool __has_color;
	TColor __color1;
	TColor __color2;
	TColor __color3;

public:
	TGLMeshEventInfo(int command, bool draw_shiny, bool light_model, bool culling, bool front_face_culling,
		     bool has_color, const TColor & color1, const TColor & color2, const TColor & color3)
		: CEventInfo(command), __draw_shiny(draw_shiny), __light_model(light_model),
		  __culling(culling), __front_face_culling(front_face_culling),
		  __has_color(has_color), __color1(color1), __color2(color2), __color3(color3)
	{;}

	TGLMeshEventInfo(int command)
		: CEventInfo(command), __draw_shiny(false), __light_model(true),
		  __culling(true), __front_face_culling(false), __has_color(false), 
		  __color1(0.7,0.7,0.7,0.7), __color2(0.3,0.3,1.0,0.7), __color3(1.0,0.3,0.2,0.7)
	{;}

	bool get_draw_shiny()const  { return __draw_shiny; }
	bool get_light_model() const {return __light_model; }
	bool get_culling() const { return __culling; }
	bool get_front_face_culling() const { return __front_face_culling; }
	bool get_has_color()const  { return __has_color; }
	TColor get_color1()const  { return __color1; }
	TColor get_color2()const  { return __color2; }
	TColor get_color3()const  { return __color3; }

	void set_draw_shiny(bool draw_shiny) { __draw_shiny = draw_shiny; }
	void set_light_model(bool light_model) { __light_model = light_model; }
	void set_culling(bool culling) { __culling = culling; }
	void set_front_face_culling(bool front_face_culling) { __front_face_culling = front_face_culling; }
	void set_has_color(bool hc) { __has_color=hc; }
	void set_color1(const TColor & color) { __color1 = color; }
	void set_color2(const TColor & color) { __color2 = color; }
	void set_color3(const TColor & color) { __color3 = color; }
};

/** wireframe commands
   \begin{itemize}
   \item EV\_WIREFRAME\_GET\_STATE to obtain the state of a TWireFrame object by the given EventInfo structure
   \item EV\_WIREFRAME\_TOGGLE\_VIEW to select the components to be displayed (lines, unconnected points, all)
   \end{itemize}
   \remark EV\_WIREFRAME\_GET\_STATE will be ignored at present (just for the sake of completeness)
*/
#define EV_WIREFRAME_GET_STATE			0x2850
#define EV_WIREFRAME_TOGGLE_VIEW		0x2851


/** smarties commands
   \begin{itemize}
   \item EV\_SMARTIES\_GET\_STATE to obtain the state of a TSmarties object by the given EventInfo structure
   \item EV\_SMARTIES\_INCREASE\_SMARTY\_NUMBER to increase the number of smarties to be displayed
   \item EV\_SMARTIES\_DECREASE\_SMARTY\_NUMBER to decrease the number of smarties to be displayed
   \end{itemize}
   \remark EV\_SMARTIES\_GET\_STATE will be ignored at present (just for the sake of completeness)
*/
#define EV_SMARTIES_GET_STATE			0x2900
#define EV_SMARTIES_INCREASE_SMARTY_NUMBER	0x2901
#define EV_SMARTIES_DECREASE_SMARTY_NUMBER	0x2902

/** glviewer commands
   \begin{itemize}
   \item EV\_GLVIEWER\_GET\_STATE to obtain the state of a TGLViewer object by the given EventInfo structure
   \item EV\_GLVIEWER\_SNAP\_THIS to make a single snapshot
   \item EV\_GLVIEWER\_SNAP\_ALL to make a series of snapshots using the standard views
   \item EV\_GLVIEWER\_VIEW\_NEXT to select the next view
   \item EV\_GLVIEWER\_VIEW\_SAVE\_THIS to add this view to the standard views
   \item EV\_GLVIEWER\_VIEW\_SAVE\_ALL to save all views
   \item EV\_GLVIEWER\_SET\_ROTATION\_SPEED to set the rotation speed
   \item EV\_GLVIEWER\_SET\_ROTATION\_ENABLED to enable or disable rotation
   \item EV\_GLVIEWER\_SET\_BG\_BRIGHTNESS to set the background brightness
   \item EV\_GLVIEWER\_TOGGLE\_MOVIEMODE to enable or disable the moviemode
   \end{itemize}
*/
#define EV_GLVIEWER_GET_STATE			0x2950
#define EV_GLVIEWER_SNAP_THIS			0x2951
#define EV_GLVIEWER_SNAP_ALL			0x2952
#define EV_GLVIEWER_VIEW_NEXT			0x2953
#define EV_GLVIEWER_VIEW_SAVE_THIS		0x2954
#define EV_GLVIEWER_VIEW_SAVE_ALL		0x2955
#define EV_GLVIEWER_SET_ROTATION_SPEED		0x2956
#define EV_GLVIEWER_SET_ROTATION_ENABLED	0x2957
#define EV_GLVIEWER_SET_BG_BRIGHTNESS		0x2958
#define EV_GLVIEWER_TOGGLE_MOVIEMODE		0x2959

class TGLViewerEventInfo: public CEventInfo {
	float background_brightness;
	float rotation_speed;
	bool  rotation_enabled;
	bool  snapper_available;
	bool  moviemode_enabled;
	
public:
	TGLViewerEventInfo(int command, float bg_brightness, float rot_speed, bool rot_enabled, bool snapper, bool movie_enabled)
		: CEventInfo(command), background_brightness(bg_brightness), 
		  rotation_speed(rot_speed), rotation_enabled(rot_enabled),
		  snapper_available(snapper), moviemode_enabled(movie_enabled)
	{;}
	TGLViewerEventInfo(int command)
		: CEventInfo(command), background_brightness(0.0), 
		  rotation_speed(0.0), rotation_enabled(false), 
		  snapper_available(false), moviemode_enabled(false)
	{;}
	
	float get_background_brightness() const { return background_brightness; }
	float get_rotation_speed() const { return rotation_speed; }
	bool  get_rotation_enabled() const { return rotation_enabled; }
	float set_background_brightness(float brightness) { return ( background_brightness = brightness < 0.0 ? 0.0 : (brightness > 1.0 ? 1.0 : brightness)); }
	float set_rotation_speed(float speed) { return ( rotation_speed = speed < 0.0 ? 0.0 : (speed > 1.0 ? 1.0 : speed)); }
	bool  set_rotation_enabled(bool enabled) { return (rotation_enabled = enabled); }
	bool  get_snapper_available() const { return snapper_available; }
	bool  set_snapper_available(bool snapper) { return (snapper_available = snapper); }
	bool  get_moviemode_enabled()const  { return moviemode_enabled; }
	bool  set_moviemode_enabled(bool enabled) { return (moviemode_enabled = enabled); }
};


/** attribute commands
   \begin{itemize}
   \item EV\_SET\_ATTRIBUTE to set the given attribute
   \end{itemize}
*/
#define EV_SET_ATTRIBUTE 0x3001
class TSetAttributeEvent: public CEventInfo {
	const std::string& m_name;
	const std::string& m_value; 
public:
	TSetAttributeEvent(const std::string& name, const std::string& value):
		CEventInfo(EV_SET_ATTRIBUTE),
		m_name(name),m_value(value) 
	{;}
	const std::string& get_name()const {return m_name;}
	const std::string& get_value()const {return m_value;}
};
	


/**  This structure containes information about a key, mouse or command event. 
*/
struct event_t {
	/** 
	    Enumeration of event types. 
	    \begin{itemize}
	    \item ev\_nothing #...# no event is stored
	    \item ev\_key #...# a regular key was pressed - {\em action.key} contains the key-code
	    \item ev\_mouse #...# the mouse was moved, or a mouse button was pressed/released 
	    {\em action.button} contains flags with more description and {\em where} stored the mouse
	    location, where the event occured
	    \item ev\_command #...# a command was send. {\em action.command} contains the command code and {\em info}
	    may contain additional information
	    \end{itemize}
	*/
	enum type_t {ev_nothing, ev_key, ev_mouse, ev_command};
	
	/// Here is stored, what type of command the structure holds.
	type_t what; 
	
	/// Union to hold specific information of the event
	union action_u {
		
		/// keycode if a key was pressed + flags for modifier keys
		int key; 
		
		/// mouse and modifier flags if a mouse event occured
		int button; 
	};

	/// Dependend on the value of {\em what}. See description of  {\em type\_t} for more information.
	action_u action;
	
			
	/// a command code with additional information (used if what==ev_command)
	PEventInfo info;


	struct where_s{ int x,y; }; 
	
	///   location of a mouse event
	where_s where; 
};


///   This operator takes an {\em event\_t} structure and writes it out to {\em os}.
std::ostream& operator << (std::ostream& os, const event_t& event);


/// This is a class to store pending events
class CEventQueue {
public:
	bool handle_events();
	void push(event_t &ev);

	typedef sigc::signal1<bool, event_t*>			type_signal_handle_event;
	type_signal_handle_event				signal_handle_event();

	typedef sigc::signal1<bool, char>			type_signal_handle_key;
	type_signal_handle_key					signal_handle_key();

	typedef sigc::signal3<bool, int, int, int>		type_signal_handle_mouse;
	type_signal_handle_mouse				signal_handle_mouse();

	typedef sigc::signal1<bool, PEventInfo >	type_signal_handle_command;
	type_signal_handle_command				signal_handle_command();
	
	bool							get_handled() const;
	void							reset_handled();

protected:
	std::queue<event_t>			__ev_queue;
	bool					__sth_handled;

private:
	type_signal_handle_event		__signal_handle_event;
	type_signal_handle_key			__signal_handle_key;
	type_signal_handle_mouse		__signal_handle_mouse;
	type_signal_handle_command		__signal_handle_command;
};
	

/// The base class to handle events. Every class that wants to handle events has to be derived from this class.
class TEventHandler {
public:	
	/** This function takes an event, checks its type and calls the apropriated handler.
	    If the specialized handler returns true, then the event is cleared, i.e. {\em event->what} is 
	    set to {\em ev\_nothing}
	    @param event the event to be handled
	    @return true if event was handled, false otherwise
	*/
	virtual bool handle_event(event_t *event);
	
	/// This destructor is only here to make clear that we need a virtual one. 
	virtual ~TEventHandler();
protected:
	/** This function handles all key events. 
	    @param key ascii code of the pressed key and modifier key flags 
	    @return {\em bool}: {\bf true} if the key was handled, {\bf false} if not
	    
	    In {\bf TEventHandler} it only returns {\bf false}. 
	 */
	virtual bool do_handle_key_event(int key);

	/** This function handles all mouse events. 
	    @param button flag of the mouse event and modifier key flags 
	    @param x x-ccordinte where the event occured
	    @param y y-ccordinte where the event occured	    
	    @return {\em bool}: {\bf true} if the event was handled, {\bf false} if not
	    In {\bf TEventHandler} it only returns {\bf false}. 
	 */
	virtual bool do_handle_mouse_event(int button, int x, int y);

	/** This function handles all mouse events. 
	    @param button flag of the mouse event and modifier key flags 
	    @param x x-ccordinte where the event occured
	    @param y y-ccordinte where the event occured	    
	    @return {\em bool}: {\bf true} if the event was handled, {\bf false} if not
	    In {\bf TEventHandler} it only returns {\bf false}. 
	*/
	virtual bool do_handle_command_event(PEventInfo info);	
	
	/** This function translates an incoming events to another event
	    \param event the incoming event - will be overwritten with the new event
	    \retval event
	*/
};

#endif

