From ecaf8b83f8227724e9f862a0a8f64e6004a63d56 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Wed, 20 Aug 2014 12:18:27 +1000
Subject: Create a generic GWIN event. The frame now sends a GEVENT_GWIN_CLOSE
 event on closing. Unfortunately some gwin events have had a field renamed in
 order to generalise the structure. Demo's updated to match.

---
 src/gwin/button.c     | 26 ++------------------
 src/gwin/button.h     | 10 ++------
 src/gwin/checkbox.c   |  2 +-
 src/gwin/checkbox.h   |  6 ++---
 src/gwin/class_gwin.h | 14 ++++++++++-
 src/gwin/frame.c      |  1 +
 src/gwin/gwidget.c    | 18 ++++++++++++++
 src/gwin/gwidget.h    | 30 +++++++++++++++++++++++
 src/gwin/gwin.c       | 67 ++++++++++++++++++++++++++-------------------------
 src/gwin/list.c       |  2 +-
 src/gwin/list.h       |  6 ++---
 src/gwin/radio.c      |  2 +-
 src/gwin/radio.h      |  6 ++---
 src/gwin/slider.c     |  2 +-
 src/gwin/slider.h     |  6 ++---
 15 files changed, 116 insertions(+), 82 deletions(-)

(limited to 'src')

diff --git a/src/gwin/button.c b/src/gwin/button.c
index fc1cb976..5507a07a 100644
--- a/src/gwin/button.c
+++ b/src/gwin/button.c
@@ -26,28 +26,6 @@
 // Our pressed state
 #define GBUTTON_FLG_PRESSED		(GWIN_FIRST_CONTROL_FLAG<<0)
 
-// Send the button event
-static void SendButtonEvent(GWidgetObject *gw) {
-	GSourceListener	*	psl;
-	GEvent *			pe;
-	#define pbe			((GEventGWinButton *)pe)
-
-	// Trigger a GWIN Button Event
-	psl = 0;
-	while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
-		if (!(pe = geventGetEventBuffer(psl)))
-			continue;
-		pbe->type = GEVENT_GWIN_BUTTON;
-		pbe->button = (GHandle)gw;
-		#if GWIN_WIDGET_TAGS
-			pbe->tag = gw->tag;
-		#endif
-		geventSendEvent(psl);
-	}
-
-	#undef pbe
-}
-
 #if GINPUT_NEED_MOUSE
 	// A mouse down has occurred over the button
 	static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
@@ -68,7 +46,7 @@ static void SendButtonEvent(GWidgetObject *gw) {
 				return;
 		#endif
 
-		SendButtonEvent(gw);
+		_gwinSendEvent(&gw->g, GEVENT_GWIN_BUTTON);
 	}
 #endif
 
@@ -86,7 +64,7 @@ static void SendButtonEvent(GWidgetObject *gw) {
 		gw->g.flags |= GBUTTON_FLG_PRESSED;
 		_gwinUpdate((GHandle)gw);
 		// Trigger the event on button down (different than for mouse/touch)
-		SendButtonEvent(gw);
+		_gwinSendEvent(&gw->g, GEVENT_GWIN_BUTTON);
 	}
 
 	static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
diff --git a/src/gwin/button.h b/src/gwin/button.h
index 077b50f4..5f5d2838 100644
--- a/src/gwin/button.h
+++ b/src/gwin/button.h
@@ -29,19 +29,13 @@
 /**
  * @brief	The Event Type for a Button Event
  */
-#define GEVENT_GWIN_BUTTON		(GEVENT_GWIN_FIRST+0)
+#define GEVENT_GWIN_BUTTON		(GEVENT_GWIN_CTRL_FIRST+0)
 
 /**
  * @brief	A Button Event
  * @note	There are currently no GEventGWinButton listening flags - use 0 as the flags to @p gwinAttachListener()
  */
-typedef struct GEventGWinButton {
-	GEventType		type;				// The type of this event (GEVENT_GWIN_BUTTON)
-	GHandle			button;				// The button that has been depressed (actually triggered on release)
-	#if GWIN_WIDGET_TAGS
-		WidgetTag	tag;				// The button tag
-	#endif
-} GEventGWinButton;
+typedef GEventGWin		GEventGWinButton;
 
 /**
  * @brief	The button widget structure
diff --git a/src/gwin/checkbox.c b/src/gwin/checkbox.c
index 7914ee82..6269acc1 100644
--- a/src/gwin/checkbox.c
+++ b/src/gwin/checkbox.c
@@ -31,7 +31,7 @@ static void SendCheckboxEvent(GWidgetObject *gw) {
 		if (!(pe = geventGetEventBuffer(psl)))
 			continue;
 		pce->type = GEVENT_GWIN_CHECKBOX;
-		pce->checkbox = &gw->g;
+		pce->gwin = &gw->g;
 		pce->isChecked = (gw->g.flags & GCHECKBOX_FLG_CHECKED) ? TRUE : FALSE;
 		#if GWIN_WIDGET_TAGS
 			pce->tag = gw->tag;
diff --git a/src/gwin/checkbox.h b/src/gwin/checkbox.h
index ebd35a0b..3c426242 100644
--- a/src/gwin/checkbox.h
+++ b/src/gwin/checkbox.h
@@ -28,7 +28,7 @@
 /* Driver constants.														 */
 /*===========================================================================*/
 
-#define GEVENT_GWIN_CHECKBOX		(GEVENT_GWIN_FIRST+2)
+#define GEVENT_GWIN_CHECKBOX		(GEVENT_GWIN_CTRL_FIRST+2)
 
 /*===========================================================================*/
 /* Type definitions                                                          */
@@ -36,11 +36,11 @@
 
 typedef struct GEventGWinCheckbox {
 	GEventType		type;			// The type of this event (GEVENT_GWIN_CHECKBOX)
-	GHandle			checkbox;		// The checkbox that has been depressed (actually triggered on release)
-	bool_t			isChecked;		// Is the checkbox currently checked or unchecked?
+	GHandle			gwin;			// The checkbox that has been depressed (actually triggered on release)
 	#if GWIN_WIDGET_TAGS
 		WidgetTag	tag;			// The checkbox tag
 	#endif
+	bool_t			isChecked;		// Is the checkbox currently checked or unchecked?
 } GEventGWinCheckbox;
 
 /* A Checkbox window */
diff --git a/src/gwin/class_gwin.h b/src/gwin/class_gwin.h
index 488f3d68..e45914a6 100644
--- a/src/gwin/class_gwin.h
+++ b/src/gwin/class_gwin.h
@@ -243,7 +243,7 @@ bool_t _gwinDrawStart(GHandle gh);
 void _gwinDrawEnd(GHandle gh);
 
 /**
- * @brief	Flush any pending redraws in the system.
+ * @brief	Destroy a window.
  *
  * @param[in]	gh		The window
  * @param[in]	how		Do we wait for the lock?
@@ -301,6 +301,18 @@ bool_t _gwinWMAdd(GHandle gh, const GWindowInit *pInit);
 	 * @notapi
 	 */
 	void _gwidgetRedraw(GHandle gh);
+
+	/**
+	 * @brief	Send a standard GWIN event.
+	 *
+	 * @param[in]	gh		The window
+	 * @param[in]	type	The event type
+	 *
+	 * @note		No consideration is given to recording EVENT LOST statuses.
+	 *
+	 * @notapi
+	 */
+	void _gwinSendEvent(GHandle gh, GEventType type);
 #endif
 
 #if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__)
diff --git a/src/gwin/frame.c b/src/gwin/frame.c
index f24ad569..fd8fafea 100644
--- a/src/gwin/frame.c
+++ b/src/gwin/frame.c
@@ -95,6 +95,7 @@ static void forceFrameRedraw(GWidgetObject *gw) {
 				// Close is released - destroy the window
 				gw->g.flags &= ~(GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED);
 				forceFrameRedraw(gw);
+				_gwinSendEvent(&gw->g, GEVENT_GWIN_CLOSE);
 				gwinDestroy(&gw->g);
 				return;
 			}
diff --git a/src/gwin/gwidget.c b/src/gwin/gwidget.c
index c9fff50e..e773dc6c 100644
--- a/src/gwin/gwidget.c
+++ b/src/gwin/gwidget.c
@@ -302,6 +302,24 @@ void _gwidgetRedraw(GHandle gh) {
 	gw->fnDraw(gw, gw->fnParam);
 }
 
+void _gwinSendEvent(GHandle gh, GEventType type) {
+	GSourceListener	*	psl;
+	GEventGWin *		pge;
+
+	// Trigger a GWIN Event
+	psl = 0;
+	while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
+		if (!(pge = (GEventGWin *)geventGetEventBuffer(psl)))
+			continue;
+		pge->type = type;
+		pge->gwin = gh;
+		#if GWIN_WIDGET_TAGS
+			pge->tag = (gh->flags & GWIN_FLG_WIDGET) ? ((GWidgetObject *)gh)->tag : 0;
+		#endif
+		geventSendEvent(psl);
+	}
+}
+
 void gwinWidgetClearInit(GWidgetInit *pwi) {
 	char		*p;
 	unsigned	len;
diff --git a/src/gwin/gwidget.h b/src/gwin/gwidget.h
index bd1ea4c8..18b42b79 100644
--- a/src/gwin/gwidget.h
+++ b/src/gwin/gwidget.h
@@ -135,6 +135,36 @@ typedef struct GWidgetObject {
  * won't support it even with special flags.
  */
 
+/**
+ * @brief	A Generic GWIN Event
+ * @note	All gwin windows when sending events will either use this structure or a
+ * 			structure that is 100% compatible except that it may also have extra fields.
+ * @note	There are currently no GEventGWin listening flags - use 0 as the flags to @p gwinAttachListener()
+ *
+ * @{
+ */
+typedef struct GEventGWin {
+	GEventType		type;				// The type of this event
+	GHandle			gwin;				// The gwin window handle
+	#if GWIN_NEED_WIDGET && GWIN_WIDGET_TAGS
+		WidgetTag	tag;				// The tag (if applicable)
+	#endif
+} GEventGWin;
+/** @} */
+
+/**
+ * @brief	The list of predefined GWIN events.
+ * @note	The definition of an event type does not mean it is always sent. For example,
+ * 			close events are sent by Frame windows but by little else. They are normally
+ * 			only sent if there is a specific reason that the event should be sent.
+ * @{
+ */
+#define GEVENT_GWIN_OPEN		(GEVENT_GWIN_FIRST+0x00)
+#define GEVENT_GWIN_CLOSE		(GEVENT_GWIN_FIRST+0x01)
+#define GEVENT_GWIN_RESIZE		(GEVENT_GWIN_FIRST+0x02)
+#define GEVENT_GWIN_CTRL_FIRST	(GEVENT_GWIN_FIRST+0x40)
+/** @} */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index 9b0fb03a..b5b7ad6b 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -101,6 +101,40 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
 	return (GHandle)pgw;
 }
 
+// Internal routine for use by GWIN components only
+void _gwinDestroy(GHandle gh, GRedrawMethod how) {
+	if (!gh)
+		return;
+
+	// Make the window invisible
+	gwinSetVisible(gh, FALSE);
+
+	// Make sure it is flushed first - must be REDRAW_WAIT or REDRAW_INSESSION
+	_gwinFlushRedraws(how);
+
+	#if GWIN_NEED_CONTAINERS
+		// Notify the parent it is about to be deleted
+		if (gh->parent && ((gcontainerVMT *)gh->parent->vmt)->NotifyDelete)
+			((gcontainerVMT *)gh->parent->vmt)->NotifyDelete(gh->parent, gh);
+	#endif
+
+	// Remove from the window manager
+	#if GWIN_NEED_WINDOWMANAGER
+		_GWINwm->vmt->Delete(gh);
+	#endif
+
+	// Class destroy routine
+	if (gh->vmt->Destroy)
+		gh->vmt->Destroy(gh);
+
+	// Clean up the structure
+	if (gh->flags & GWIN_FLG_DYNAMIC) {
+		gh->flags = 0;							// To be sure, to be sure
+		gfxFree((void *)gh);
+	} else
+		gh->flags = 0;							// To be sure, to be sure
+}
+
 /*-----------------------------------------------
  * Routines that affect all windows
  *-----------------------------------------------*/
@@ -152,39 +186,6 @@ GHandle gwinGWindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pI
 	return pgw;
 }
 
-void _gwinDestroy(GHandle gh, GRedrawMethod how) {
-	if (!gh)
-		return;
-
-	// Make the window invisible
-	gwinSetVisible(gh, FALSE);
-
-	// Make sure it is flushed first - must be REDRAW_WAIT or REDRAW_INSESSION
-	_gwinFlushRedraws(how);
-
-	#if GWIN_NEED_CONTAINERS
-		// Notify the parent it is about to be deleted
-		if (gh->parent && ((gcontainerVMT *)gh->parent->vmt)->NotifyDelete)
-			((gcontainerVMT *)gh->parent->vmt)->NotifyDelete(gh->parent, gh);
-	#endif
-
-	// Remove from the window manager
-	#if GWIN_NEED_WINDOWMANAGER
-		_GWINwm->vmt->Delete(gh);
-	#endif
-
-	// Class destroy routine
-	if (gh->vmt->Destroy)
-		gh->vmt->Destroy(gh);
-
-	// Clean up the structure
-	if (gh->flags & GWIN_FLG_DYNAMIC) {
-		gh->flags = 0;							// To be sure, to be sure
-		gfxFree((void *)gh);
-	} else
-		gh->flags = 0;							// To be sure, to be sure
-}
-
 void gwinDestroy(GHandle gh) {
 	_gwinDestroy(gh, REDRAW_WAIT);
 }
diff --git a/src/gwin/list.c b/src/gwin/list.c
index 98ec2ed5..10926238 100644
--- a/src/gwin/list.c
+++ b/src/gwin/list.c
@@ -64,7 +64,7 @@ static void sendListEvent(GWidgetObject *gw, int item) {
 			continue;
 
 		ple->type = GEVENT_GWIN_LIST;
-		ple->list = (GHandle)gw;
+		ple->gwin = (GHandle)gw;
 		ple->item = item;
 		#if GWIN_WIDGET_TAGS
 			ple->tag = gw->tag;
diff --git a/src/gwin/list.h b/src/gwin/list.h
index 1eae3c19..d9979993 100644
--- a/src/gwin/list.h
+++ b/src/gwin/list.h
@@ -31,18 +31,18 @@
 /**
  * @brief	The event type for a list event
  */
-#define GEVENT_GWIN_LIST	(GEVENT_GWIN_FIRST+4)
+#define GEVENT_GWIN_LIST	(GEVENT_GWIN_CTRL_FIRST+4)
 
 /**
  * @brief	A list event
  */
 typedef struct GEventGWinList {
 	GEventType		type;		// The type of this event (GEVENT_GWIN_LIST)
-	GHandle			list;		// The list
-	int				item;		// The item that has been selected (or unselected in a multi-select listbox)
+	GHandle			gwin;		// The list
 	#if GWIN_WIDGET_TAGS
 		WidgetTag	tag;		// The list tag
 	#endif
+	int				item;		// The item that has been selected (or unselected in a multi-select listbox)
 } GEventGWinList;
 
 // A list window
diff --git a/src/gwin/radio.c b/src/gwin/radio.c
index 557061e4..4799c2a4 100644
--- a/src/gwin/radio.c
+++ b/src/gwin/radio.c
@@ -36,7 +36,7 @@ static void SendRadioEvent(GWidgetObject *gw) {
 		if (!(pe = geventGetEventBuffer(psl)))
 			continue;
 		pbe->type = GEVENT_GWIN_RADIO;
-		pbe->radio = (GHandle)gw;
+		pbe->gwin = (GHandle)gw;
 		pbe->group = ((GRadioObject *)gw)->group;
 		#if GWIN_WIDGET_TAGS
 			pbe->tag = gw->tag;
diff --git a/src/gwin/radio.h b/src/gwin/radio.h
index eb7ee719..e13962c7 100644
--- a/src/gwin/radio.h
+++ b/src/gwin/radio.h
@@ -27,7 +27,7 @@
 /**
  * @brief	The Event Type for a Radio Event
  */
-#define GEVENT_GWIN_RADIO		(GEVENT_GWIN_FIRST+3)
+#define GEVENT_GWIN_RADIO		(GEVENT_GWIN_CTRL_FIRST+3)
 
 /**
  * @brief	A Button Event
@@ -35,11 +35,11 @@
  */
 typedef struct GEventGWinRadio {
 	GEventType		type;				// The type of this event (GEVENT_GWIN_RADIO)
-	GHandle			radio;				// The radio button that has been depressed
-	uint16_t		group;				// The group for this radio button
+	GHandle			gwin;				// The radio button that has been depressed
 	#if GWIN_WIDGET_TAGS
 		WidgetTag	tag;				// The radio tag
 	#endif
+	uint16_t		group;				// The group for this radio button
 } GEventGWinRadio;
 
 /**
diff --git a/src/gwin/slider.c b/src/gwin/slider.c
index 7ce7b83f..2329230c 100644
--- a/src/gwin/slider.c
+++ b/src/gwin/slider.c
@@ -36,7 +36,7 @@ static void SendSliderEvent(GWidgetObject *gw) {
 		if (!(pe = geventGetEventBuffer(psl)))
 			continue;
 		pse->type = GEVENT_GWIN_SLIDER;
-		pse->slider = (GHandle)gw;
+		pse->gwin = (GHandle)gw;
 		pse->position = ((GSliderObject *)gw)->pos;
 		#if GWIN_WIDGET_TAGS
 			pse->tag = gw->tag;
diff --git a/src/gwin/slider.h b/src/gwin/slider.h
index 32161d62..6cd8088b 100644
--- a/src/gwin/slider.h
+++ b/src/gwin/slider.h
@@ -24,15 +24,15 @@
 
 /* This file is included within "gwin/gwidget.h" */
 
-#define GEVENT_GWIN_SLIDER		(GEVENT_GWIN_FIRST+1)
+#define GEVENT_GWIN_SLIDER		(GEVENT_GWIN_CTRL_FIRST+1)
 
 typedef struct GEventGWinSlider {
 	GEventType		type;				// The type of this event (GEVENT_GWIN_BUTTON)
-	GHandle			slider;				// The slider that is returning results
-	int				position;
+	GHandle			gwin;				// The slider that is returning results
 	#if GWIN_WIDGET_TAGS
 		WidgetTag	tag;				// The slider tag
 	#endif
+	int				position;
 } GEventGWinSlider;
 
 // There are currently no GEventGWinSlider listening flags - use 0
-- 
cgit v1.2.3