diff options
| author | inmarket <andrewh@inmarket.com.au> | 2014-12-06 15:48:47 +1000 | 
|---|---|---|
| committer | inmarket <andrewh@inmarket.com.au> | 2014-12-06 15:48:47 +1000 | 
| commit | 5bf2b8678a5a58059baffe780d00cd570781cea7 (patch) | |
| tree | 001a4d387ecfb39b79c1863a643e36966fd39638 /src | |
| parent | 4931f39a0d26f53a03834cfdc65d5e365a928652 (diff) | |
| download | uGFX-5bf2b8678a5a58059baffe780d00cd570781cea7.tar.gz uGFX-5bf2b8678a5a58059baffe780d00cd570781cea7.tar.bz2 uGFX-5bf2b8678a5a58059baffe780d00cd570781cea7.zip | |
Extended slider events. Updated the demo to match.
Actually reduced code size :)
Diffstat (limited to 'src')
| -rw-r--r-- | src/gwin/gwin_slider.c | 161 | ||||
| -rw-r--r-- | src/gwin/gwin_slider.h | 21 | 
2 files changed, 122 insertions, 60 deletions
| diff --git a/src/gwin/gwin_slider.c b/src/gwin/gwin_slider.c index f1230d5a..9652e6df 100644 --- a/src/gwin/gwin_slider.c +++ b/src/gwin/gwin_slider.c @@ -16,6 +16,8 @@  #include "gwin_class.h" +#define GSLIDER_FLG_EXTENDED_EVENTS		(GWIN_FIRST_CONTROL_FLAG<<0) +  #ifndef GWIN_SLIDER_DEAD_BAND  	#define GWIN_SLIDER_DEAD_BAND	5  #endif @@ -24,23 +26,58 @@  	#define GWIN_SLIDER_TOGGLE_INC	20			// How many toggles to go from minimum to maximum  #endif +// Calculate the slider position from the display position +static int CalculatePosFromDPos(GSliderObject *gsw) { +	// Set the new position +	if (gsw->w.g.width < gsw->w.g.height) { +		if (gsw->dpos > gsw->w.g.height-GWIN_SLIDER_DEAD_BAND) +			return gsw->min; +		if (gsw->dpos < GWIN_SLIDER_DEAD_BAND) +			return gsw->max; +		return ((int)(gsw->w.g.height-1-gsw->dpos-GWIN_SLIDER_DEAD_BAND))*(gsw->max-gsw->min)/(gsw->w.g.height-2*GWIN_SLIDER_DEAD_BAND) + gsw->min; +	} +	if (gsw->dpos > gsw->w.g.width-GWIN_SLIDER_DEAD_BAND) +		return gsw->max; +	if (gsw->dpos < GWIN_SLIDER_DEAD_BAND) +		return gsw->min; +	return ((int)(gsw->dpos-GWIN_SLIDER_DEAD_BAND))*(gsw->max-gsw->min)/(gsw->w.g.width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min; +} +  // Send the slider event -static void SendSliderEvent(GWidgetObject *gw) { +static void SendSliderEvent(GSliderObject *gsw, uint8_t action) {  	GSourceListener	*	psl;  	GEvent *			pe;  	#define pse			((GEventGWinSlider *)pe) -	// Trigger a GWIN Button Event +	// Does this slider want more than just SET events? +	if (action != GSLIDER_EVENT_SET && !(gsw->w.g.flags & GSLIDER_FLG_EXTENDED_EVENTS)) +		return; +  	psl = 0;  	while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) { +		// Work out which action to send. +		// This precedence order helps provide some protection against missed events. +		// Saving it into srcflags works regardless of if a buffer is available. +		if (psl->srcflags < action) +			psl->srcflags = action; + +		// Skip sending if no buffer is available  		if (!(pe = geventGetEventBuffer(psl)))  			continue; + +		// Fill in the event  		pse->type = GEVENT_GWIN_SLIDER; -		pse->gwin = (GHandle)gw; -		pse->position = ((GSliderObject *)gw)->pos; +		pse->gwin = (GHandle)gsw; +		pse->action = psl->srcflags;  		#if GWIN_WIDGET_TAGS -			pse->tag = gw->tag; +			pse->tag = gsw->w.tag;  		#endif + +		// If it is a cancel or set use the defined position else use the calculated position. +		pse->position = pse->action >= GSLIDER_EVENT_CANCEL ? gsw->pos : CalculatePosFromDPos(gsw); + +		// Cleanup and send. +		psl->srcflags = 0;  		geventSendEvent(psl);  	} @@ -56,76 +93,72 @@ static void ResetDisplayPos(GSliderObject *gsw) {  }  #if GINPUT_NEED_MOUSE +	// Set the display position from the mouse position +	static void SetDisplayPosFromMouse(GSliderObject *gsw, coord_t x, coord_t y) { +		if (gsw->w.g.width < gsw->w.g.height) +			gsw->dpos = y < 0 ? 0 : (y >= gsw->w.g.height ? gsw->w.g.height-1 : y); +		else +			gsw->dpos = x < 0 ? 0 : (x >= gsw->w.g.width ? gsw->w.g.width-1 : x); +	} +  	// A mouse up event  	static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {  		#define gsw		((GSliderObject *)gw) -		#define gh		((GHandle)gw) - -		#if GWIN_BUTTON_LAZY_RELEASE -			// Clip to the slider -			if (x < 0) x = 0; -			else if (x >= gh->width) x = gh->width-1; -			if (y < 0) y = 0; -			else if (y >= gh->height) x = gh->height-1; -		#else + +		#if !GWIN_BUTTON_LAZY_RELEASE  			// Are we over the slider? -			if (x < 0 || x >= gh->width || y < 0 || y >= gh->height) { +			if (x < 0 || x >= gsw->w.g.width || y < 0 || y >= gsw->w.g.height) {  				// No - restore the slider  				ResetDisplayPos(gsw); -				_gwinUpdate(gh); +				_gwinUpdate(&gsw->w.g); +				SendSliderEvent(gsw, GSLIDER_EVENT_CANCEL);  				return;  			}  		#endif  		// Set the new position -		if (gh->width < gh->height) { -			if (y > gh->height-GWIN_SLIDER_DEAD_BAND) -				gsw->pos = gsw->min; -			else if (y < GWIN_SLIDER_DEAD_BAND) -				gsw->pos = gsw->max; -			else -				gsw->pos = (uint16_t)((int32_t)(gh->height-1-y-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->height-2*GWIN_SLIDER_DEAD_BAND) + gsw->min); -		} else { -			if (x > gh->width-GWIN_SLIDER_DEAD_BAND) -				gsw->pos = gsw->max; -			else if (x < GWIN_SLIDER_DEAD_BAND) -				gsw->pos = gsw->min; -			else -				gsw->pos = (uint16_t)((int32_t)(x-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min); -		} +		SetDisplayPosFromMouse(gsw, x, y); +		gsw->pos = CalculatePosFromDPos(gsw); +		// Update the display  		ResetDisplayPos(gsw); -		_gwinUpdate(gh); +		_gwinUpdate(&gsw->w.g);  		// Generate the event -		SendSliderEvent(gw); -		#undef gh +		SendSliderEvent(gsw, GSLIDER_EVENT_SET); +  		#undef gsw  	} -	// A mouse move (or mouse down) event +	// A mouse down event +	static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) { +		#define gsw		((GSliderObject *)gw) + +		// Determine the display position +		SetDisplayPosFromMouse(gsw, x, y); + +		// Update the display +		_gwinUpdate(&gsw->w.g); + +		// Send the event +		SendSliderEvent(gsw, GSLIDER_EVENT_START); + +		#undef gsw +	} + +	// A mouse move event  	static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) {  		#define gsw		((GSliderObject *)gw) -		// Determine the temporary display position (with range checking) -		if (gw->g.width < gw->g.height) { -			if (y < 0) -				gsw->dpos = 0; -			else if (y >= gw->g.height) -				gsw->dpos = gw->g.height-1; -			else -				gsw->dpos = y; -		} else { -			if (x < 0) -				gsw->dpos = 0; -			else if (x >= gw->g.width) -				gsw->dpos = gw->g.width-1; -			else -				gsw->dpos = x; -		} +		// Determine the display position +		SetDisplayPosFromMouse(gsw, x, y);  		// Update the display -		_gwinUpdate(&gw->g); +		_gwinUpdate(&gsw->w.g); + +		// Send the event +		SendSliderEvent(gsw, GSLIDER_EVENT_MOVE); +  		#undef gsw  	}  #endif @@ -136,11 +169,11 @@ static void ResetDisplayPos(GSliderObject *gsw) {  		#define gsw		((GSliderObject *)gw)  		if (role) { -			gwinSliderSetPosition((GHandle)gw, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC); -			SendSliderEvent(gw); +			gwinSliderSetPosition(&gsw->w.g, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC); +			SendSliderEvent(gsw, GSLIDER_EVENT_SET);  		} else { -			gwinSliderSetPosition((GHandle)gw, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC); -			SendSliderEvent(gw); +			gwinSliderSetPosition(&gsw->w.g, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC); +			SendSliderEvent(gsw, GSLIDER_EVENT_SET);  		}  		#undef gsw  	} @@ -167,10 +200,10 @@ static void ResetDisplayPos(GSliderObject *gsw) {  		gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min);  		ResetDisplayPos(gsw); -		_gwinUpdate((GHandle)gw); +		_gwinUpdate(&gsw->w.g);  		// Generate the event -		SendSliderEvent(gw); +		SendSliderEvent(gsw, GSLIDER_EVENT_SET);  		#undef gsw  	} @@ -197,7 +230,7 @@ static const gwidgetVMT sliderVMT = {  	gwinSliderDraw_Std,			// The default drawing routine  	#if GINPUT_NEED_MOUSE  		{ -			0,						// Process mouse down events (NOT USED) +			MouseDown,				// Process mouse down events  			MouseUp,				// Process mouse up events  			MouseMove,				// Process mouse move events  		}, @@ -275,6 +308,16 @@ void gwinSliderSetPosition(GHandle gh, int pos) {  	#undef gsw  } +void gwinSliderSendExtendedEvents(GHandle gh, bool_t enabled) { +	if (gh->vmt != (gwinVMT *)&sliderVMT) +		return; + +	if (enabled) +		gh->flags |= GSLIDER_FLG_EXTENDED_EVENTS; +	else +		gh->flags &= ~GSLIDER_FLG_EXTENDED_EVENTS; +} +  /*----------------------------------------------------------   * Custom Draw Routines   *----------------------------------------------------------*/ diff --git a/src/gwin/gwin_slider.h b/src/gwin/gwin_slider.h index b88d6dfd..91a381a5 100644 --- a/src/gwin/gwin_slider.h +++ b/src/gwin/gwin_slider.h @@ -27,12 +27,18 @@  #define GEVENT_GWIN_SLIDER		(GEVENT_GWIN_CTRL_FIRST+1)  typedef struct GEventGWinSlider { -	GEventType		type;				// The type of this event (GEVENT_GWIN_BUTTON) +	GEventType		type;				// The type of this event (GEVENT_GWIN_SLIDER)  	GHandle			gwin;				// The slider that is returning results  	#if GWIN_WIDGET_TAGS  		WidgetTag	tag;				// The slider tag  	#endif  	int				position; + +	uint8_t			action; +		#define GSLIDER_EVENT_SET		4		/* Slider position is set. This is the only event returned by default   */ +		#define GSLIDER_EVENT_CANCEL	3		/* Slider position changing has been cancelled */ +		#define GSLIDER_EVENT_START		2		/* Slider position has started changing */ +		#define GSLIDER_EVENT_MOVE		1		/* Slider position has been moved */  } GEventGWinSlider;  // There are currently no GEventGWinSlider listening flags - use 0 @@ -124,6 +130,19 @@ void gwinSliderSetPosition(GHandle gh, int pos);  #define gwinSliderGetPosition(gh)		(((GSliderObject *)(gh))->pos)  /** + * @brief   Should the slider send extended events. + * + * @param[in] gh		The window handle (must be a slider window) + * @param[in] enabled	TRUE to enable extended events, FALSE to disable them + * + * @note	The slider by default will only send slider events with an action of GSLIDER_EVENT_SET. + * 			This call can be used to enable other slider action's to be sent as events + * + * @api + */ +void gwinSliderSendExtendedEvents(GHandle gh, bool_t enabled); + +/**   * @brief	Some custom slider drawing routines   * @details	These function may be passed to @p gwinSetCustomDraw() to get different slider drawing styles   * | 
