Extended slider events. Updated the demo to match.
Actually reduced code size :)
This commit is contained in:
parent
4931f39a0d
commit
5bf2b8678a
4 changed files with 148 additions and 66 deletions
|
@ -56,6 +56,7 @@
|
||||||
#define GWIN_NEED_WINDOWMANAGER TRUE
|
#define GWIN_NEED_WINDOWMANAGER TRUE
|
||||||
#define GWIN_NEED_WIDGET TRUE
|
#define GWIN_NEED_WIDGET TRUE
|
||||||
#define GWIN_NEED_SLIDER TRUE
|
#define GWIN_NEED_SLIDER TRUE
|
||||||
|
#define GWIN_NEED_CONSOLE TRUE
|
||||||
|
|
||||||
/* Features for the GINPUT subsystem. */
|
/* Features for the GINPUT subsystem. */
|
||||||
#define GINPUT_NEED_MOUSE TRUE
|
#define GINPUT_NEED_MOUSE TRUE
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
|
|
||||||
static GListener gl;
|
static GListener gl;
|
||||||
static GHandle ghSlider1, ghSlider2;
|
static GHandle ghSlider1, ghSlider2, ghConsole;
|
||||||
|
|
||||||
static void createWidgets(void) {
|
static void createWidgets(void) {
|
||||||
GWidgetInit wi;
|
GWidgetInit wi;
|
||||||
|
@ -40,16 +40,24 @@ static void createWidgets(void) {
|
||||||
wi.g.show = TRUE;
|
wi.g.show = TRUE;
|
||||||
|
|
||||||
// create Slider1
|
// create Slider1
|
||||||
wi.g.y = 10; wi.g.x = 10; wi.g.width = 200; wi.g.height = 20; wi.text = "S1";
|
wi.g.y = 10; wi.g.x = 10; wi.g.width = gdispGetWidth()-20; wi.g.height = 20; wi.text = "S1";
|
||||||
ghSlider1 = gwinSliderCreate(0, &wi);
|
ghSlider1 = gwinSliderCreate(0, &wi);
|
||||||
|
|
||||||
// create Slider2
|
// create Slider2
|
||||||
wi.g.y = 40; wi.g.x = 10; wi.g.width = 20; wi.g.height = 200; wi.text = "S2";
|
wi.g.y = 40; wi.g.x = 10; wi.g.width = 20; wi.g.height = gdispGetHeight() - 50; wi.text = "S2";
|
||||||
ghSlider2 = gwinSliderCreate(0, &wi);
|
ghSlider2 = gwinSliderCreate(0, &wi);
|
||||||
|
|
||||||
|
// Set slider 2 to return extended events
|
||||||
|
gwinSliderSendExtendedEvents(ghSlider2, TRUE);
|
||||||
|
|
||||||
|
// Console to display slider events
|
||||||
|
wi.g.y = 40; wi.g.x = 40; wi.g.width = gdispGetWidth()-50; wi.g.height = gdispGetHeight()-50;
|
||||||
|
ghConsole = gwinConsoleCreate(0, &wi.g);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
GEvent* pe;
|
GEventGWinSlider * pe;
|
||||||
|
const char * sAction;
|
||||||
|
|
||||||
// Initialize the display
|
// Initialize the display
|
||||||
gfxInit();
|
gfxInit();
|
||||||
|
@ -61,21 +69,32 @@ int main(void) {
|
||||||
|
|
||||||
// create the widget
|
// create the widget
|
||||||
createWidgets();
|
createWidgets();
|
||||||
|
gwinSetColor(ghConsole, Green);
|
||||||
|
gwinSetBgColor(ghConsole, White);
|
||||||
|
gwinClear(ghConsole);
|
||||||
|
|
||||||
// We want to listen for widget events
|
// We want to listen for widget events
|
||||||
geventListenerInit(&gl);
|
geventListenerInit(&gl);
|
||||||
gwinAttachListener(&gl);
|
gwinAttachListener(&gl);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
// Get an Event
|
// Get an Event (assume it is a slider event)
|
||||||
pe = geventEventWait(&gl, TIME_INFINITE);
|
pe = (GEventGWinSlider *)geventEventWait(&gl, TIME_INFINITE);
|
||||||
|
|
||||||
switch(pe->type) {
|
switch(pe->type) {
|
||||||
case GEVENT_GWIN_SLIDER:
|
case GEVENT_GWIN_SLIDER:
|
||||||
//printf("Slider %s = %d\n", gwinGetText(((GEventGWinSlider *)pe)->gwin), ((GEventGWinSlider *)pe)->position);
|
switch(pe->action) {
|
||||||
|
case GSLIDER_EVENT_SET: sAction = "SET"; break;
|
||||||
|
case GSLIDER_EVENT_CANCEL: sAction = "CANCEL"; break;
|
||||||
|
case GSLIDER_EVENT_MOVE: sAction = "MOVE"; break;
|
||||||
|
case GSLIDER_EVENT_START: sAction = "START"; break;
|
||||||
|
default: sAction = "????"; break;
|
||||||
|
}
|
||||||
|
gwinPrintf(ghConsole, "Slider %s = %d%% %s\n", gwinGetText(pe->gwin), pe->position, sAction);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
// Oops - not a slider event.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
#include "gwin_class.h"
|
#include "gwin_class.h"
|
||||||
|
|
||||||
|
#define GSLIDER_FLG_EXTENDED_EVENTS (GWIN_FIRST_CONTROL_FLAG<<0)
|
||||||
|
|
||||||
#ifndef GWIN_SLIDER_DEAD_BAND
|
#ifndef GWIN_SLIDER_DEAD_BAND
|
||||||
#define GWIN_SLIDER_DEAD_BAND 5
|
#define GWIN_SLIDER_DEAD_BAND 5
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,23 +26,58 @@
|
||||||
#define GWIN_SLIDER_TOGGLE_INC 20 // How many toggles to go from minimum to maximum
|
#define GWIN_SLIDER_TOGGLE_INC 20 // How many toggles to go from minimum to maximum
|
||||||
#endif
|
#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
|
// Send the slider event
|
||||||
static void SendSliderEvent(GWidgetObject *gw) {
|
static void SendSliderEvent(GSliderObject *gsw, uint8_t action) {
|
||||||
GSourceListener * psl;
|
GSourceListener * psl;
|
||||||
GEvent * pe;
|
GEvent * pe;
|
||||||
#define pse ((GEventGWinSlider *)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;
|
psl = 0;
|
||||||
while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
|
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)))
|
if (!(pe = geventGetEventBuffer(psl)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Fill in the event
|
||||||
pse->type = GEVENT_GWIN_SLIDER;
|
pse->type = GEVENT_GWIN_SLIDER;
|
||||||
pse->gwin = (GHandle)gw;
|
pse->gwin = (GHandle)gsw;
|
||||||
pse->position = ((GSliderObject *)gw)->pos;
|
pse->action = psl->srcflags;
|
||||||
#if GWIN_WIDGET_TAGS
|
#if GWIN_WIDGET_TAGS
|
||||||
pse->tag = gw->tag;
|
pse->tag = gsw->w.tag;
|
||||||
#endif
|
#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);
|
geventSendEvent(psl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,76 +93,72 @@ static void ResetDisplayPos(GSliderObject *gsw) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GINPUT_NEED_MOUSE
|
#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
|
// A mouse up event
|
||||||
static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
|
static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
|
||||||
#define gsw ((GSliderObject *)gw)
|
#define gsw ((GSliderObject *)gw)
|
||||||
#define gh ((GHandle)gw)
|
|
||||||
|
|
||||||
#if GWIN_BUTTON_LAZY_RELEASE
|
#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
|
|
||||||
// Are we over the slider?
|
// 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
|
// No - restore the slider
|
||||||
ResetDisplayPos(gsw);
|
ResetDisplayPos(gsw);
|
||||||
_gwinUpdate(gh);
|
_gwinUpdate(&gsw->w.g);
|
||||||
|
SendSliderEvent(gsw, GSLIDER_EVENT_CANCEL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set the new position
|
// Set the new position
|
||||||
if (gh->width < gh->height) {
|
SetDisplayPosFromMouse(gsw, x, y);
|
||||||
if (y > gh->height-GWIN_SLIDER_DEAD_BAND)
|
gsw->pos = CalculatePosFromDPos(gsw);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Update the display
|
||||||
ResetDisplayPos(gsw);
|
ResetDisplayPos(gsw);
|
||||||
_gwinUpdate(gh);
|
_gwinUpdate(&gsw->w.g);
|
||||||
|
|
||||||
// Generate the event
|
// Generate the event
|
||||||
SendSliderEvent(gw);
|
SendSliderEvent(gsw, GSLIDER_EVENT_SET);
|
||||||
#undef gh
|
|
||||||
#undef gsw
|
#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) {
|
static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) {
|
||||||
#define gsw ((GSliderObject *)gw)
|
#define gsw ((GSliderObject *)gw)
|
||||||
|
|
||||||
// Determine the temporary display position (with range checking)
|
// Determine the display position
|
||||||
if (gw->g.width < gw->g.height) {
|
SetDisplayPosFromMouse(gsw, x, y);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the display
|
// Update the display
|
||||||
_gwinUpdate(&gw->g);
|
_gwinUpdate(&gsw->w.g);
|
||||||
|
|
||||||
|
// Send the event
|
||||||
|
SendSliderEvent(gsw, GSLIDER_EVENT_MOVE);
|
||||||
|
|
||||||
#undef gsw
|
#undef gsw
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -136,11 +169,11 @@ static void ResetDisplayPos(GSliderObject *gsw) {
|
||||||
#define gsw ((GSliderObject *)gw)
|
#define gsw ((GSliderObject *)gw)
|
||||||
|
|
||||||
if (role) {
|
if (role) {
|
||||||
gwinSliderSetPosition((GHandle)gw, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
|
gwinSliderSetPosition(&gsw->w.g, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
|
||||||
SendSliderEvent(gw);
|
SendSliderEvent(gsw, GSLIDER_EVENT_SET);
|
||||||
} else {
|
} else {
|
||||||
gwinSliderSetPosition((GHandle)gw, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
|
gwinSliderSetPosition(&gsw->w.g, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
|
||||||
SendSliderEvent(gw);
|
SendSliderEvent(gsw, GSLIDER_EVENT_SET);
|
||||||
}
|
}
|
||||||
#undef gsw
|
#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);
|
gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min);
|
||||||
|
|
||||||
ResetDisplayPos(gsw);
|
ResetDisplayPos(gsw);
|
||||||
_gwinUpdate((GHandle)gw);
|
_gwinUpdate(&gsw->w.g);
|
||||||
|
|
||||||
// Generate the event
|
// Generate the event
|
||||||
SendSliderEvent(gw);
|
SendSliderEvent(gsw, GSLIDER_EVENT_SET);
|
||||||
#undef gsw
|
#undef gsw
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +230,7 @@ static const gwidgetVMT sliderVMT = {
|
||||||
gwinSliderDraw_Std, // The default drawing routine
|
gwinSliderDraw_Std, // The default drawing routine
|
||||||
#if GINPUT_NEED_MOUSE
|
#if GINPUT_NEED_MOUSE
|
||||||
{
|
{
|
||||||
0, // Process mouse down events (NOT USED)
|
MouseDown, // Process mouse down events
|
||||||
MouseUp, // Process mouse up events
|
MouseUp, // Process mouse up events
|
||||||
MouseMove, // Process mouse move events
|
MouseMove, // Process mouse move events
|
||||||
},
|
},
|
||||||
|
@ -275,6 +308,16 @@ void gwinSliderSetPosition(GHandle gh, int pos) {
|
||||||
#undef gsw
|
#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
|
* Custom Draw Routines
|
||||||
*----------------------------------------------------------*/
|
*----------------------------------------------------------*/
|
||||||
|
|
|
@ -27,12 +27,18 @@
|
||||||
#define GEVENT_GWIN_SLIDER (GEVENT_GWIN_CTRL_FIRST+1)
|
#define GEVENT_GWIN_SLIDER (GEVENT_GWIN_CTRL_FIRST+1)
|
||||||
|
|
||||||
typedef struct GEventGWinSlider {
|
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
|
GHandle gwin; // The slider that is returning results
|
||||||
#if GWIN_WIDGET_TAGS
|
#if GWIN_WIDGET_TAGS
|
||||||
WidgetTag tag; // The slider tag
|
WidgetTag tag; // The slider tag
|
||||||
#endif
|
#endif
|
||||||
int position;
|
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;
|
} GEventGWinSlider;
|
||||||
|
|
||||||
// There are currently no GEventGWinSlider listening flags - use 0
|
// There are currently no GEventGWinSlider listening flags - use 0
|
||||||
|
@ -123,6 +129,19 @@ void gwinSliderSetPosition(GHandle gh, int pos);
|
||||||
*/
|
*/
|
||||||
#define gwinSliderGetPosition(gh) (((GSliderObject *)(gh))->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
|
* @brief Some custom slider drawing routines
|
||||||
* @details These function may be passed to @p gwinSetCustomDraw() to get different slider drawing styles
|
* @details These function may be passed to @p gwinSetCustomDraw() to get different slider drawing styles
|
||||||
|
|
Loading…
Add table
Reference in a new issue