src/widget/window_event_base.h
author KUDr
Tue, 27 Feb 2007 22:47:59 +0000
branchcpp_gui
changeset 6264 9fc3b5467396
child 6271 0ad100a98853
permissions -rw-r--r--
(svn r8931) [cpp_gui] -Add: first OO widget type (TextButton) added only with basic functionality
-Add: new gui events (C++)
-Add: dynamic event handlers introduced (see Widget::AddReflectHandlerT)
-Add: test window using the new features (intro_gui.cpp)
/* $Id$ */

#ifndef WINDOW_EVENT_BASE_H
#define WINDOW_EVENT_BASE_H

struct BaseWindow;

namespace gui {

enum EventCode {
	EVT_CREATE,
	EVT_DESTROY,
	EVT_PAINT,
	EVT_KEYPRESS,
	EVT_CLICK,
	EVT_RCLICK,
	EVT_MOUSEOVER,
	EVT_MOUSELOOP,
	EVT_MOUSEWHEEL,
	EVT_TICK,
	EVT_4,
	EVT_TIMEOUT,
	EVT_PLACE_OBJ,
	EVT_ABORT_PLACE_OBJ,
	EVT_ON_EDIT_TEXT,
	EVT_ON_EDIT_TEXT_CANCEL,
	EVT_POPUPMENU_SELECT,
	EVT_POPUPMENU_OVER,
	EVT_DRAGDROP,
	EVT_PLACE_DRAG,
	EVT_PLACE_MOUSEUP,
	EVT_PLACE_PRESIZE,
	EVT_DROPDOWN_SELECT,
	EVT_RESIZE,
	EVT_MESSAGE,
	EVT_SCROLL,
	EVT_INVALIDATE_DATA,
};

template <EventCode Tcode> struct EventT;

typedef EventT<EVT_CREATE             > EvtCreate;
typedef EventT<EVT_DESTROY            > EvtDestroy;
typedef EventT<EVT_PAINT              > EvtPaint;
typedef EventT<EVT_KEYPRESS           > EvtKeyPress;
typedef EventT<EVT_CLICK              > EvtClick;
typedef EventT<EVT_RCLICK             > EvtRightClick;
typedef EventT<EVT_MOUSEOVER          > EvtMouseOver;
typedef EventT<EVT_MOUSELOOP          > EvtMouseLoop;
typedef EventT<EVT_MOUSEWHEEL         > EvtMouseWheel;
typedef EventT<EVT_TICK               > EvtTick;
typedef EventT<EVT_4                  > Evt4;
typedef EventT<EVT_TIMEOUT            > EvtTimeout;
typedef EventT<EVT_PLACE_OBJ          > EvtPlaceObj;
typedef EventT<EVT_ABORT_PLACE_OBJ    > EvtAbortPlaceObj;
typedef EventT<EVT_ON_EDIT_TEXT       > EvtOnEditText;
typedef EventT<EVT_ON_EDIT_TEXT_CANCEL> EvtOnEditTextCancel;
typedef EventT<EVT_POPUPMENU_SELECT   > EvtPopupMenuSelect;
typedef EventT<EVT_POPUPMENU_OVER     > EvtPopupMenuOver;
typedef EventT<EVT_DRAGDROP           > EvtDragDrop;
typedef EventT<EVT_PLACE_DRAG         > EvtPlaceDrag;
typedef EventT<EVT_PLACE_MOUSEUP      > EvtPlaceMouseUp;
typedef EventT<EVT_PLACE_PRESIZE      > EvtPlacePresize;
typedef EventT<EVT_DROPDOWN_SELECT    > EvtDropdownSelect;
typedef EventT<EVT_RESIZE             > EvtResize;
typedef EventT<EVT_MESSAGE            > EvtMessage;
typedef EventT<EVT_SCROLL             > EvtScroll;
typedef EventT<EVT_INVALIDATE_DATA    > EvtInvalidateData;

struct Widget;
typedef CCountedPtr<Widget> WidgetPtr;

/** Base of all gui events. Never constructed directly. Used as base class
 *  of event types */
struct EventBase {
protected:
	EventCode m_code;
	bool      m_handled;

public:
	WidgetPtr m_widget;

protected:
	/** protected constructor (called from subclasses only) */
	EventBase(EventCode code)
		: m_code(code)
		, m_handled(false)
	{}

public:
	virtual ~EventBase() {}

	/** @return event code */
	EventCode GetCode() const
	{
		return m_code;
	}

	/** @return true if event was already handled */
	bool IsHandled() const
	{
		return m_handled;
	}

	void SetHandled(bool handled = true)
	{
		m_handled = handled;
	}

	/** type-safe conversion operator */
	//template <EventCode Tcode> operator EventT<Tcode>& ()
	//{
	//	assert(m_code == Tcode);
	//	return *(EventT<Tcode>*)this;
	//}

	virtual void Dispatch() = 0;
};

/** Intermediate event base that calls EventBase constructor with the proper event type as parameter.
 *  Used only by event subclasses */
template <EventCode Tcode, void (Widget::*Tevt_method)(EventT<Tcode> &)> struct EventBaseT : public EventBase {
	static const EventCode ID = Tcode; ///< allow access to event codes by class name (i.e. EvtCreate::ID)
protected:
	EventBaseT()
		: EventBase(Tcode)
	{}

	/*virtual*/ void Dispatch()
	{
		assert(!m_widget.IsNull());
		assert(m_code == Tcode);
		(m_widget->*Tevt_method)(*(EventT<Tcode>*)this);
	}
};

/**
 * Base of all Event Handler Delegates - class that represents Event Handler object/method
 * pair that can be called by widget when particular event is handled by a widget. Object
 * of any type can register itself and its method as gui event callback handler by adding
 * the appropriate delegate object into widget handler list.
 */
struct EventHandlerDelegate : public SimpleCountedObject {
	EventCode m_code;     ///< event code this handler is registered for

	EventHandlerDelegate(EventCode code)
		: m_code(code)
	{}

	/**
	 * The only method that delegate must provide. Called by widget if the appropriate event
	 * is reflected.
	 */
	virtual void HandleEvent(BaseWindow *w, EventBase &e) = 0;
};

/** Reference counting pointer to the event handler delegate. */
typedef CCountedPtr<EventHandlerDelegate> EventHandlerDelegatePtr;

/**
 * Delegate for handlers of events reflected back from widget to window.
 */
template <class Twnd_cls, EventCode Tevt_code> struct ReflectHandlerDelegateT : public EventHandlerDelegate {
	void (Twnd_cls::*m_handler)(EventT<Tevt_code>&);

	ReflectHandlerDelegateT(void (Twnd_cls::*handler)(EventT<Tevt_code>&))
		: EventHandlerDelegate(Tevt_code)
		, m_handler(handler)
	{}

	virtual void HandleEvent(BaseWindow *w, EventBase &e)
	{
		assert(e.GetCode() == Tevt_code);
		Twnd_cls &wnd = *(Twnd_cls*)w;
		EventT<Tevt_code> &ev = *(EventT<Tevt_code>*)&e;
		(wnd.*m_handler)(ev);
	}
};

}; // namespace gui

#endif /* WINDOW_EVENT_BASE_H */