#ifndef K3DSDK_IMOUSE_EVENT_OBSERVER_H
#define K3DSDK_IMOUSE_EVENT_OBSERVER_H

// K-3D
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// 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.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
		\brief Declares imouse_event_observer, an abstract interface implemented by objects that want to receive notification of mouse events
		\author Tim Shead (tshead@k-3d.com)
*/

#include "axis.h"
#include "iunknown.h"
#include "keyboard.h"
#include "vectors.h"

#include <string>

namespace k3d
{
// Forward declarations
class iviewport;

/** \brief Abstract interface for objects that want to receive interactive user events.
	\note All mouse coordinates are in Normalized Device Coordinates (i.e. they are in the range [0, 1] where 0 = top / left and 1 = bottom / right.
	\note An observer should return true from it event handler iff it "uses" (i.e. performs work in response to) the event.
	\note In the case of drag events, an observer must always return the same value whether the event is type START_DRAG, DRAG, or END_DRAG.
*/
class imouse_event_observer :
	public virtual k3d::iunknown
{
public:
	/// Consolidates (potentially) useful state for observers
	struct event_state
	{
		event_state(iviewport& Viewport, const key_modifiers& Modifiers, const axis ActiveAxis) :
			viewport(Viewport),
			modifiers(Modifiers),
			active_axis(ActiveAxis)
		{
		}
		
		/// The viewport associated with the event
		iviewport& viewport;
		/// The current keyboard modifiers (e.g. shift, control, alt, etc) in effect for the event
		key_modifiers modifiers;
		/// The current "active axis" in effect for the event
		axis active_axis;
	};
	
	typedef enum
	{
		START_DRAG,
		CONTINUE_DRAG,
		END_DRAG
	} drag_type_t;

	/// Called to return a human-readable description of how the observer plans to use the input events
	virtual const std::string Usage() = 0;
	/// Called when the user moves the mouse - return true iff the observer actually "used" the event
	virtual bool OnMouseMove(const event_state& State, const vector2& Current) = 0;
	/// Called when the left mouse button goes down - return true iff the observer actually "used" the event
	virtual bool OnLButtonDown(const event_state& State, const vector2& Current) = 0;
	/// Called when the user clicks the left mouse button - return true iff the observer actually "used" the event
	virtual bool OnLButtonClick(const event_state& State, const vector2& Current) = 0;
	/// Called when the left mouse button goes up - return true iff the observer actually "used" the event
	virtual bool OnLButtonUp(const event_state& State, const vector2& Current) = 0;
	/// Called when the user double-clicks the left mouse button - return true iff the observer actually "used" the event
	virtual bool OnLButtonDoubleClick(const event_state& State, const vector2& Current) = 0;
	/// Called while the user drags the mouse with the left mouse button down - return true iff the observer actually "used" the event
	virtual bool OnLButtonDrag(const event_state& State, const vector2& Current, const vector2& Last, const vector2& Start, const drag_type_t DragType) = 0;
	/// Called when the middle mouse button goes down - return true iff the observer actually "used" the event
	virtual bool OnMButtonDown(const event_state& State, const vector2& Current) = 0;
	/// Called when the user clicks the middle mouse button - return true iff the observer actually "used" the event
	virtual bool OnMButtonClick(const event_state& State, const vector2& Current) = 0;
	/// Called when the middle mouse button goes up - return true iff the observer actually "used" the event
	virtual bool OnMButtonUp(const event_state& State, const vector2& Current) = 0;
	/// Called when the user double-clicks the middle mouse button - return true iff the observer actually "used" the event
	virtual bool OnMButtonDoubleClick(const event_state& State, const vector2& Current) = 0;
	/// Called while the user drags the mouse with the middle mouse button down - return true iff the observer actually "used" the event
	virtual bool OnMButtonDrag(const event_state& State, const vector2& Current, const vector2& Last, const vector2& Start, const drag_type_t DragType) = 0;
	/// Called when the right mouse button goes down - return true iff the observer actually "used" the event
	virtual bool OnRButtonDown(const event_state& State, const vector2& Current) = 0;
	/// Called when the user clicks the right mouse button - return true iff the observer actually "used" the event
	virtual bool OnRButtonClick(const event_state& State, const vector2& Current) = 0;
	/// Called when the right mouse button goes up - return true iff the observer actually "used" the event
	virtual bool OnRButtonUp(const event_state& State, const vector2& Current) = 0;
	/// Called when the user double-clicks the right mouse button - return true iff the observer actually "used" the event
	virtual bool OnRButtonDoubleClick(const event_state& State, const vector2& Current) = 0;
	/// Called while the user drags the mouse with the right mouse button down - return true iff the observer actually "used" the event
	virtual bool OnRButtonDrag(const event_state& State, const vector2& Current, const vector2& Last, const vector2& Start, const drag_type_t DragType) = 0;

protected:
	imouse_event_observer() {}
	imouse_event_observer(const imouse_event_observer& RHS) {}
	imouse_event_observer& operator = (const imouse_event_observer& RHS) { return *this; }
	virtual ~imouse_event_observer() {}
};

} // namespace k3d

#endif // !K3DSDK_IMOUSE_EVENT_OBSERVER_H


