Clean up GWIN Event assignment. Optimise event efficiency.

This commit is contained in:
inmarket 2013-06-10 17:18:01 +10:00
parent 777ec6af7c
commit 2cb35d6815
25 changed files with 561 additions and 242 deletions

View File

@ -47,7 +47,7 @@
GHandle gwinCreateScope(GScopeObject *gs, coord_t x, coord_t y, coord_t cx, coord_t cy, uint32_t physdev, uint32_t frequency) {
/* Initialise the base class GWIN */
if (!(gs = (GScopeObject *)_gwindowInit((GWindowObject *)gs, x, y, cx, cy, sizeof(GScopeObject))))
if (!(gs = (GScopeObject *)_gwindowCreate((GWindowObject *)gs, x, y, cx, cy, sizeof(GScopeObject))))
return 0;
/* Initialise the scope object members and allocate memory for buffers */

View File

@ -54,7 +54,7 @@
GHandle gwinCreateScope(GScopeObject *gs, coord_t x, coord_t y, coord_t cx, coord_t cy, uint16_t channel, uint32_t frequency) {
/* Initialise the base class GWIN */
if (!(gs = (GScopeObject *)_gwindowInit((GWindowObject *)gs, x, y, cx, cy, sizeof(GScopeObject))))
if (!(gs = (GScopeObject *)_gwindowCreate((GWindowObject *)gs, x, y, cx, cy, sizeof(GScopeObject))))
return 0;
/* Initialise the scope object members and allocate memory for buffers */

View File

@ -51,15 +51,17 @@
#define GDISP_NEED_IMAGE_PNG FALSE
/* Features for the GWIN sub-system. */
#define GWIN_NEED_WINDOWMANAGER TRUE
#define GWIN_NEED_CONSOLE TRUE
#define GWIN_NEED_GRAPH FALSE
#define GWIN_NEED_WIDGET TRUE
#define GWIN_NEED_BUTTON TRUE
#define GWIN_NEED_SLIDER TRUE
#define GWIN_NEED_CHECKBOX TRUE
/* Features for the GINPUT sub-system. */
#define GINPUT_NEED_MOUSE TRUE
#define GINPUT_NEED_TOGGLE FALSE
#define GINPUT_NEED_TOGGLE TRUE
#define GINPUT_NEED_DIAL FALSE
#endif /* _GFXCONF_H */

View File

@ -49,11 +49,20 @@ int main(void) {
gfxInit();
gdispClear(White);
// Set the font and defalt colors
// Set the widget defaults
gwinSetDefaultFont(gdispOpenFont("UI2"));
gwinSetDefaultColor(Black);
gwinSetDefaultBgColor(White);
// We want to listen for widget events
geventListenerInit(&gl);
gwinAttachListener(&gl);
// Connect the mouse
#if GINPUT_NEED_MOUSE
gwinAttachMouse(0);
#endif
// Create out gwin windows/widgets
ghConsole = gwinCreateConsole(NULL, ScrWidth/2+1, ScrHeight/2+1, ScrWidth/2-1, ScrHeight/2-1);
ghButton1 = gwinCreateButton(NULL, 0+0*(BUTTON_WIDTH+1), 0, BUTTON_WIDTH, BUTTON_HEIGHT);
@ -84,49 +93,28 @@ int main(void) {
gwinSetText(ghCheckbox1, "C1", FALSE);
gwinSetText(ghCheckbox2, "C2", FALSE);
// Assign the mouse and dials to the buttons & sliders etc.
#if GINPUT_NEED_MOUSE
gwinAttachMouse(ghButton1, 0);
gwinAttachMouse(ghButton2, 0);
gwinAttachMouse(ghButton3, 0);
gwinAttachMouse(ghButton4, 0);
gwinAttachMouse(ghSlider1, 0);
gwinAttachMouse(ghSlider2, 0);
gwinAttachMouse(ghSlider3, 0);
gwinAttachMouse(ghSlider4, 0);
gwinAttachMouse(ghCheckbox1, 0);
gwinAttachMouse(ghCheckbox2, 0);
#endif
#if GINPUT_NEED_DIAL
gwinAttachSliderDial(ghSlider1, 0);
gwinAttachSliderDial(ghSlider3, 1);
#endif
// We want to listen for widget events
geventListenerInit(&gl);
gwinAttachListener(ghButton1, &gl, 0);
gwinAttachListener(ghButton2, &gl, 0);
gwinAttachListener(ghButton3, &gl, 0);
gwinAttachListener(ghButton4, &gl, 0);
gwinAttachListener(ghSlider1, &gl, 0);
gwinAttachListener(ghSlider2, &gl, 0);
gwinAttachListener(ghSlider3, &gl, 0);
gwinAttachListener(ghSlider4, &gl, 0);
gwinAttachListener(ghCheckbox1, &gl, 0);
gwinAttachListener(ghCheckbox2, &gl, 0);
// Assign toggles and dials to the buttons & sliders etc.
#if GINPUT_NEED_TOGGLE
gwinAttachToggle(ghButton1, 0, 0);
gwinAttachToggle(ghButton2, 0, 1);
#endif
#if GINPUT_NEED_DIAL
gwinAttachDial(ghSlider1, 0, 0);
gwinAttachDial(ghSlider3, 0, 1);
#endif
// Draw everything on the screen
gwinClear(ghConsole);
gwinDraw(ghButton1);
gwinDraw(ghButton2);
gwinDraw(ghButton3);
gwinDraw(ghButton4);
gwinDraw(ghSlider1);
gwinDraw(ghSlider2);
gwinDraw(ghSlider3);
gwinDraw(ghSlider4);
gwinDraw(ghCheckbox1);
gwinDraw(ghCheckbox2);
gwinSetVisible(ghButton1, TRUE);
gwinSetVisible(ghButton2, TRUE);
gwinSetVisible(ghButton3, TRUE);
gwinSetVisible(ghButton4, TRUE);
gwinSetVisible(ghSlider1, TRUE);
gwinSetVisible(ghSlider2, TRUE);
gwinSetVisible(ghSlider3, TRUE);
gwinSetVisible(ghSlider4, TRUE);
gwinSetVisible(ghCheckbox1, TRUE);
gwinSetVisible(ghCheckbox2, TRUE);
while(1) {
// Get an Event

View File

@ -119,8 +119,8 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
break;
case WM_LBUTTONUP:
#if GINPUT_NEED_TOGGLE
if ((toggles & 0xF0)) {
toggles &= 0x0F;
if ((toggles & 0x0F)) {
toggles &= ~0x0F;
rect.left = 0;
rect.right = wWidth;
rect.top = wHeight;

View File

@ -1,9 +1,9 @@
/*
* This file is subject to the terms of the GFX License, v1.0. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/*
* This file is subject to the terms of the GFX License, v1.0. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file drivers/multiple/Win32/ginput_lld_toggle_config.h
@ -20,19 +20,19 @@
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
#define GINPUT_TOGGLE_POLL_PERIOD TIME_INFINITE // We are interrupt driven (or polled - ether works here)
#define GINPUT_TOGGLE_POLL_PERIOD TIME_INFINITE // We are interrupt driven (or polled - either works here)
#define GINPUT_TOGGLE_NUM_PORTS 8 // The total number of toggle inputs
#define GINPUT_TOGGLE_CONFIG_ENTRIES 1 // The total number of GToggleConfig entries
#define GINPUT_TOGGLE_SW1 0 // Switch 1 - Toggle
#define GINPUT_TOGGLE_SW2 1 // Switch 2 - Toggle
#define GINPUT_TOGGLE_SW3 2 // Switch 3 - Toggle
#define GINPUT_TOGGLE_SW4 3 // Switch 4 - Toggle
#define GINPUT_TOGGLE_MOMENTARY1 0 // Switch 5 - Momentary
#define GINPUT_TOGGLE_MOMENTARY2 1 // Switch 6 - Momentary
#define GINPUT_TOGGLE_MOMENTARY3 2 // Switch 7 - Momentary
#define GINPUT_TOGGLE_MOMENTARY4 3 // Switch 8 - Momentary
#define GINPUT_TOGGLE_MOMENTARY1 4 // Switch 5 - Momentary
#define GINPUT_TOGGLE_MOMENTARY2 5 // Switch 6 - Momentary
#define GINPUT_TOGGLE_MOMENTARY3 6 // Switch 7 - Momentary
#define GINPUT_TOGGLE_MOMENTARY4 7 // Switch 8 - Momentary
#define GINPUT_TOGGLE_SW1 4 // Switch 1 - Toggle
#define GINPUT_TOGGLE_SW2 5 // Switch 2 - Toggle
#define GINPUT_TOGGLE_SW3 6 // Switch 3 - Toggle
#define GINPUT_TOGGLE_SW4 7 // Switch 4 - Toggle
#endif /* GFX_USE_GDISP && GINPUT_NEED_TOGGLE */

View File

@ -46,24 +46,6 @@
#warning "GWIN: Drawing can occur outside the defined windows as GDISP_NEED_CLIP is FALSE"
#endif
#endif
#if GWIN_NEED_WINDOWMANAGER
#if !GFX_USE_GQUEUE || !GQUEUE_NEED_ASYNC
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: GFX_USE_GQUEUE and GQUEUE_NEED_ASYNC is required if GWIN_NEED_WINDOWMANAGER is TRUE. It has been turned on for you."
#endif
#undef GFX_USE_GQUEUE
#undef GQUEUE_NEED_ASYNC
#define GFX_USE_GQUEUE TRUE
#define GQUEUE_NEED_ASYNC TRUE
#endif
#endif
#if GWIN_NEED_CONSOLE
#if !GDISP_NEED_TEXT
#error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."
#endif
#endif
#if GWIN_NEED_GRAPH
#endif
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX
#if !GWIN_NEED_WIDGET
#if GFX_DISPLAY_RULE_WARNINGS
@ -81,6 +63,13 @@
// This test also ensures that GFX_USE_GEVENT is set
#error "GWIN: GFX_USE_GINPUT (and one or more input sources) is required if GWIN_NEED_WIDGET is TRUE"
#endif
#if !GWIN_NEED_WINDOWMANAGER
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: GWIN_NEED_WINDOWMANAGER is required if GWIN_NEED_WIDGET is TRUE. It has been turned on for you."
#endif
#undef GWIN_NEED_WINDOWMANAGER
#define GWIN_NEED_WINDOWMANAGER TRUE
#endif
#if !GDISP_NEED_MULTITHREAD && !GDISP_NEED_ASYNC
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: Either GDISP_NEED_MULTITHREAD or GDISP_NEED_ASYNC is required if GWIN_NEED_WIDGET is TRUE."
@ -90,6 +79,24 @@
#define GDISP_NEED_MULTITHREAD TRUE
#endif
#endif
#if GWIN_NEED_WINDOWMANAGER
#if !GFX_USE_GQUEUE || !GQUEUE_NEED_ASYNC
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: GFX_USE_GQUEUE and GQUEUE_NEED_ASYNC is required if GWIN_NEED_WINDOWMANAGER is TRUE. It has been turned on for you."
#endif
#undef GFX_USE_GQUEUE
#undef GQUEUE_NEED_ASYNC
#define GFX_USE_GQUEUE TRUE
#define GQUEUE_NEED_ASYNC TRUE
#endif
#endif
#if GWIN_NEED_CONSOLE
#if !GDISP_NEED_TEXT
#error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."
#endif
#endif
#if GWIN_NEED_GRAPH
#endif
#endif
#if GFX_USE_GINPUT

View File

@ -36,6 +36,7 @@ typedef struct GEventDial_t {
GEventType type; // The type of this event (GEVENT_DIAL)
uint16_t instance; // The dial instance
uint16_t value; // The dial value
uint16_t maxvalue; // The maximum dial value
} GEventDial;
/*===========================================================================*/

View File

@ -103,7 +103,7 @@ void gfxQueueFSyncInit(gfxQueueFSync *pqueue);
/* @} */
/**
* @brief Get an item from the head of the queue.
* @brief Get an item from the head of the queue (and remove it from the queue).
* @return NULL if the timeout expires before an item is available
*
* @param[in] pqueue A pointer to the queue
@ -139,7 +139,7 @@ bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delayti
/* @} */
/**
* @brief Pop an item from the head of the queue.
* @brief Pop an item from the head of the queue (and remove it from the queue).
* @detail This is exactly the same as the Get operation above.
*
* @api
@ -220,6 +220,46 @@ bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem);
/* @} */
/**
* @brief Get the first item from the head of the queue but do not remove it from the queue.
* @return NULL if no item is available.
*
* @param[in] pqueue A pointer to the queue
*
* @note This call does not block.
* @note This can be used as the first call to iterate all the elements in the queue.
* @note As that item is still on the queue, it should be treated as read-only. It could
* also be removed from the queue at any time by another thread (thereby altering the
* queue item).
*
* @api
* @{
*/
#define gfxQueueASyncPeek(pqueue) ((const gfxQueueASyncItem *)((pqueue)->head))
#define gfxQueueGSyncPeek(pqueue) ((const gfxQueueGSyncItem *)((pqueue)->head))
#define gfxQueueFSyncPeek(pqueue) ((const gfxQueueFSyncItem *)((pqueue)->head))
/* @} */
/**
* @brief Get the next item in the queue (but do not remove it from the queue).
* @return NULL if no item is available.
*
* @param[in] pitem The previous item in the queue
*
* @note This call does not block.
* @note This can be used as subsequent calls to iterate all the elements in the queue.
* @note As that item is still on the queue, it should be treated as read-only. It could
* also be removed from the queue at any time by another thread (thereby altering the
* queue item).
*
* @api
* @{
*/
#define gfxQueueASyncNext(pitem) ((const gfxQueueASyncItem *)((pitem)->next))
#define gfxQueueGSyncNext(pitem) ((const gfxQueueGSyncItem *)((pitem)->next))
#define gfxQueueFSyncNext(pitem) ((const gfxQueueFSyncItem *)((pitem)->next))
/* @} */
#ifdef __cplusplus
}
#endif

View File

@ -55,6 +55,7 @@ typedef struct GButtonColors {
*/
typedef struct GButtonObject_t {
GWidgetObject w;
uint16_t toggle;
GButtonColors c_up;
GButtonColors c_dn;
GButtonColors c_dis;
@ -78,10 +79,13 @@ extern "C" {
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
* is no default font and text drawing operations will no nothing.
* @note The dimensions and position may be changed to fit on the real screen.
* @note A button remembers its normal button state. If there is a window manager then it is automatically
* @note A button remembers its normal drawing state. If there is a window manager then it is automatically
* redrawn if the window is moved or its visibility state is changed.
* @note The button is initially marked as invisible so that more properties can be set before display.
* Call @p gwinSetVisible() to display it when ready.
* @note A button supports mouse and a toggle input.
* @note When assigning a toggle, only one toggle is supported. If you try to assign more than one toggle it will
* forget the previous toggle. When assigning a toggle the role parameter must be 0.
*
* @api
*/

View File

@ -50,6 +50,7 @@ typedef struct GCheckboxColors {
/* A Checkbox window */
typedef struct GCheckboxObject_t {
GWidgetObject w;
uint16_t toggle;
GCheckboxColors c;
} GCheckboxObject;
@ -62,10 +63,18 @@ typedef struct GCheckboxObject_t {
* @param[in] width The width of the window
* @param[in] height The height of the window
*
* @note The drawing color gets set to White and the background drawing color to Black.
* @note Don't forget to set the font using @p gwinSetFont() or @p gwinSetDefaultFont()
* @note The drawing color and the background color get set to the current defaults. If you haven't called
* @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
* is no default font and text drawing operations will no nothing.
* @note The dimensions and position may be changed to fit on the real screen.
* @note The checkbox is not automatically drawn. Call gwinDraw() to draw it.
* @note A checkbox remembers its normal drawing state. If there is a window manager then it is automatically
* redrawn if the window is moved or its visibility state is changed.
* @note The checkbox is initially marked as invisible so that more properties can be set before display.
* Call @p gwinSetVisible() to display it when ready.
* @note A checkbox supports mouse and a toggle input.
* @note When assigning a toggle, only one toggle is supported. If you try to assign more than one toggle it will
* forget the previous toggle. When assigning a toggle the role parameter must be 0.
*
* @api
*/

View File

@ -52,37 +52,58 @@ typedef struct gwinVMT {
/* @} */
#if GWIN_NEED_WIDGET || defined(__DOXYGEN__)
/**
* @brief An toggle/dial instance is not being used
*/
#define GWIDGET_NO_INSTANCE ((uint16_t)-1)
/**
* @brief The source handle that widgets use when sending events
*/
#define GWIDGET_SOURCE ((GSourceHandle)(void *)_gwidgetCreate)
/**
* @brief The Virtual Method Table for a widget
* @note A widget must have a destroy function. Either use @p _gwidgetDestroy() or use your own function
* which internally calls @p _gwidgetDestroy().
* @note A widget must have a redraw function. Use @p _gwidgetRedraw().
* @note If no MouseDown(), MouseUp() or MouseMove() function is provided, the widget will not accept being attached to a mouse input source.
* @note If no ToggleOn() or ToggleOff() function is provided, the widget will not accept being attached to a toggle input source.
* @note If no DialMove() function is provided, the widget will not accept being attached to a dial input source.
* @note AssignToggle() and AssignDial() enable a widget to handle more than one toggle/dial device attached to the widget.
* For example, a slider might accept two toggles, one for slider-down and one for slider-up.
* The function enables the widget to record that a particular device instance performs each particular role.
* (eg toggle0 = slider-down, toggle1 = slider-up).
* @note If toggleroles != 0, ToggleAssign(), ToggleGet() and one or both of ToggleOff() and ToggleOn() must be specified.
* @note If dialroles != 0, DialAssign(), DialGet() and DialMove() must be specified.
* @{
*/
typedef struct gwidgetVMT {
struct gwinVMT g; // @< This is still a GWIN
void (*DefaultDraw) (GWidgetObject *gw, void *param); // @< The default drawing routine (mandatory)
void (*MouseDown) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse down events (optional)
void (*MouseUp) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse up events (optional)
void (*MouseMove) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse move events (optional)
void (*ToggleOff) (GWidgetObject *gw, uint16_t instance); // @< Process toggle off events (optional)
void (*ToggleOn) (GWidgetObject *gw, uint16_t instance); // @< Process toggle on events (optional)
void (*DialMove) (GWidgetObject *gw, uint16_t instance, uint16_t value); // @< Process dial move events (optional)
void (*AllEvents) (GWidgetObject *gw, GEvent *pe); // @< Process all events (optional)
bool_t (*AssignToggle) (GWidgetObject *gw, uint16_t role, uint16_t instance); // @< Test the role and save the toggle instance handle (optional)
bool_t (*AssignDial) (GWidgetObject *gw, uint16_t role, uint16_t instance); // @< Test the role and save the dial instance handle (optional)
struct gwinVMT g; // @< This is still a GWIN
void (*DefaultDraw) (GWidgetObject *gw, void *param); // @< The default drawing routine (mandatory)
struct {
void (*MouseDown) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse down events (optional)
void (*MouseUp) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse up events (optional)
void (*MouseMove) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse move events (optional)
};
struct {
uint16_t toggleroles; // @< The roles supported for toggles (0->toggleroles-1)
void (*ToggleAssign) (GWidgetObject *gw, uint16_t role, uint16_t instance); // @< Assign a toggle to a role (optional)
uint16_t (*ToggleGet) (GWidgetObject *gw, uint16_t role); // @< Return the instance for a particular role (optional)
void (*ToggleOff) (GWidgetObject *gw, uint16_t role); // @< Process toggle off events (optional)
void (*ToggleOn) (GWidgetObject *gw, uint16_t role); // @< Process toggle on events (optional)
};
struct {
uint16_t dialroles; // @< The roles supported for dials (0->dialroles-1)
void (*DialAssign) (GWidgetObject *gw, uint16_t role, uint16_t instance); // @< Test the role and save the dial instance handle (optional)
uint16_t (*DialGet) (GWidgetObject *gw, uint16_t role); // @< Return the instance for a particular role (optional)
void (*DialMove) (GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max); // @< Process dial move events (optional)
};
} gwidgetVMT;
/* @} */
#endif
#if GWIN_NEED_WINDOWMANAGER || defined(__DOXYGEN__)
#if 1 // When we know that wmq is the first element of the GWindowObject structure
#define QItem2GWindow(qi) ((GHandle)qi)
#else
#define QItem2GWindow(qi) ((GHandle)(((char *)(qi)) - (size_t)(&(((GWindowObject *)0)->wmq))))
#endif
// @note There is only ever one instance of each GWindowManager type
typedef struct GWindowManager {
const struct gwmVMT *vmt;
@ -126,7 +147,7 @@ extern "C" {
*
* @notapi
*/
GHandle _gwindowInit(GWindowObject *pgw, coord_t x, coord_t y, coord_t w, coord_t h, size_t size, const gwinVMT *vmt, uint16_t flags);
GHandle _gwindowCreate(GWindowObject *pgw, coord_t x, coord_t y, coord_t w, coord_t h, size_t size, const gwinVMT *vmt, uint16_t flags);
#if GWIN_NEED_WIDGET || defined(__DOXYGEN__)
/**
@ -140,7 +161,7 @@ GHandle _gwindowInit(GWindowObject *pgw, coord_t x, coord_t y, coord_t w, coord_
*
* @notapi
*/
GHandle _gwidgetInit(GWidgetObject *pgw, coord_t x, coord_t y, coord_t w, coord_t h, size_t size, const gwidgetVMT *vmt);
GHandle _gwidgetCreate(GWidgetObject *pgw, coord_t x, coord_t y, coord_t w, coord_t h, size_t size, const gwidgetVMT *vmt);
/**
* @brief Destroy the Widget object

View File

@ -46,7 +46,6 @@ typedef void (*CustomWidgetDrawFunction)(struct GWidgetObject *gw, void *param);
*/
typedef struct GWidgetObject {
GWindowObject g; // @< This is still a GWIN
GListener listener; // @< The widget listener
const char * txt; // @< The widget text
CustomWidgetDrawFunction fnDraw; // @< The current draw function
void * fnParam; // @< A parameter for the current draw function
@ -120,28 +119,27 @@ const char *gwinGetText(GHandle gh);
void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param);
/**
* @brief Attach a Listener to this widget
* @brief Attach a Listener to listen for widget events
* @return TRUE on success
*
* @param[in] gh The widget handle
* @param[in] pl The listener
* @param[in] flags Flags to use for listening. For most widgets this should be 0.
*
* @api
*/
bool_t gwinAttachListener(GHandle gh, GListener *pl, unsigned flags);
bool_t gwinAttachListener(GListener *pl);
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
/**
* @brief Attach a mouse to a widget
* @brief Set the mouse to be used to control the widgets
* @return TRUE on success
*
* @param[in] gh The widget handle
* @param[in] instance The mouse instance
*
* @note Every widget uses the same mouse.
*
* @api
*/
bool_t gwinAttachMouse(GHandle gh, uint16_t instance);
bool_t gwinAttachMouse(uint16_t instance);
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE

View File

@ -35,6 +35,7 @@
*/
typedef struct GWindowObject {
#if GWIN_NEED_WINDOWMANAGER
// This MUST be the first member of the struct
gfxQueueASyncItem wmq; // @< The next window (for the window manager)
#endif
const struct gwinVMT *vmt; // @< The VMT for this GWIN

View File

@ -21,11 +21,11 @@
* @{
*/
/**
* @brief Should a window manager be used.
* @brief Should window manager support be included
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_WINDOWMANAGER
#define GWIN_NEED_WINDOWMANAGER FALSE
#define GWIN_NEED_WIDGET FALSE
#endif
/**
* @brief Should widget functions be included. Needed for any widget (eg Buttons, Sliders etc)

View File

@ -45,11 +45,14 @@ typedef struct GSliderColors {
// A slider window
typedef struct GSliderObject_t {
GWidgetObject w;
GSliderColors c;
uint16_t t_dn;
uint16_t t_up;
uint16_t dial;
coord_t dpos;
int min;
int max;
int pos;
GSliderColors c;
} GSliderObject;
#ifdef __cplusplus
@ -65,11 +68,22 @@ extern "C" {
* @param[in] width The width of the window
* @param[in] height The height of the window
*
* @note The drawing color gets set to White and the background drawing color to Black.
* @note Don't forget to set the font using @p gwinSetFont() or @p gwinSetDefaultFont()
* @note The drawing color and the background color get set to the current defaults. If you haven't called
* @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
* is no default font and text drawing operations will no nothing.
* @note The dimensions and position may be changed to fit on the real screen.
* @note The slider is not automatically drawn. Call gwinDraw() to draw it.
* @note Sets the slider range from 0 to 100 with an initial position of 0
* @note A slider remembers its normal drawing state. If there is a window manager then it is automatically
* redrawn if the window is moved or its visibility state is changed.
* @note The slider is initially marked as invisible so that more properties can be set before display.
* Call @p gwinSetVisible() to display it when ready.
* @note The initial slider range is from 0 to 100 with an initial position of 0.
* @note A slider supports mouse, toggle and dial input.
* @note When assigning a toggle, only one toggle is supported per role. If you try to assign more than
* one toggle to a role it will forget the previous toggle. Two roles are supported:
* Role 0 = toggle for down, Role 1 = toggle for up.
* @note When assigning a dial, only one dial is supported. If you try to assign more than one dial
* it will forget the previous dial. Only dial role 0 is supported.
*
* @api
*/

View File

@ -57,6 +57,7 @@ static void DialCallback(uint16_t instance, uint16_t rawvalue) {
pe->type = GEVENT_DIAL;
pe->instance = instance;
pe->value = pds->lastvalue;
pe->maxvalue = pds->max;
geventSendEvent(psl);
}
}
@ -144,6 +145,7 @@ bool_t ginputGetDialStatus(uint16_t instance, GEventDial *pdial) {
pdial->type = GEVENT_DIAL;
pdial->instance = instance;
pdial->value = DialStatus[instance].lastvalue;
pdial->maxvalue = DialStatus[instance].max;
return TRUE;
}

View File

@ -37,6 +37,7 @@
gfxSystemLock();
if ((pi = pqueue->head))
pqueue->head = pi->next;
pi->next = 0;
gfxSystemUnlock();
return pi;
}
@ -68,12 +69,14 @@
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
pitem->next = 0;
} else {
for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
pitem->next = 0;
break;
}
}
@ -111,6 +114,7 @@
gfxSystemLock();
pi = pqueue->head;
pqueue->head = pi->next;
pi->next = 0;
gfxSytemUnlock();
return pi;
}
@ -146,12 +150,14 @@
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
pitem->next = 0;
} else {
for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
pitem->next = 0;
break;
}
}
@ -189,6 +195,7 @@
gfxSystemLock();
pi = pqueue->head;
pqueue->head = pi->next;
pi->next = 0;
gfxSytemUnlock();
gfxSemSignalI(&pi->sem);
@ -233,6 +240,7 @@
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
found:
pitem->next = 0;
gfxSystemUnlock();
gfxSemSignal(&pitem->sem);
gfxSemDestroy(&pitem->sem);

View File

@ -32,8 +32,10 @@
// Prototypes for button VMT functions
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y);
static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y);
static void ToggleOff(GWidgetObject *gw, uint16_t instance);
static void ToggleOn(GWidgetObject *gw, uint16_t instance);
static void ToggleOff(GWidgetObject *gw, uint16_t role);
static void ToggleOn(GWidgetObject *gw, uint16_t role);
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role);
// The button VMT table
static const gwidgetVMT buttonVMT = {
@ -43,16 +45,25 @@ static const gwidgetVMT buttonVMT = {
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
gwinButtonDraw_3D, // The default drawing routine
MouseDown, // Process mouse down events
MouseUp, // Process mouse up events
0, // Process mouse move events (NOT USED)
ToggleOff, // Process toggle off events
ToggleOn, // Process toggle on events
0, // Process dial move events (NOT USED)
0, // Process all events (NOT USED)
0, // AssignToggle (NOT USED)
0, // AssignDial (NOT USED)
gwinButtonDraw_3D, // The default drawing routine
{
MouseDown, // Process mouse down events
MouseUp, // Process mouse up events
0, // Process mouse move events (NOT USED)
},
{
1, // 1 toggle role
ToggleAssign, // Assign Toggles
ToggleGet, // Get Toggles
ToggleOff, // Process toggle off events
ToggleOn, // Process toggle on events
},
{
0, // No dial roles
0, // Assign Dials (NOT USED)
0, // Get Dials (NOT USED)
0, // Process dial move events (NOT USED)
}
};
// Default color scheme
@ -80,7 +91,7 @@ static void SendButtonEvent(GWidgetObject *gw) {
// Trigger a GWIN Button Event
psl = 0;
while ((psl = geventGetSourceListener((GSourceHandle)gw, psl))) {
while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pbe->type = GEVENT_GWIN_BUTTON;
@ -114,25 +125,36 @@ static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
}
// A toggle off has occurred
static void ToggleOff(GWidgetObject *gw, uint16_t instance) {
(void) instance;
static void ToggleOff(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags &= ~GBUTTON_FLG_PRESSED;
_gwidgetRedraw((GHandle)gw);
}
// A toggle on has occurred
static void ToggleOn(GWidgetObject *gw, uint16_t instance) {
(void) instance;
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags |= GBUTTON_FLG_PRESSED;
_gwidgetRedraw((GHandle)gw);
// Trigger the event on button down (different than for mouse/touch)
SendButtonEvent(gw);
}
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
(void) role;
((GButtonObject *)gw)->toggle = instance;
}
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
(void) role;
return ((GButtonObject *)gw)->toggle;
}
GHandle gwinCreateButton(GButtonObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) {
if (!(gw = (GButtonObject *)_gwidgetInit((GWidgetObject *)gw, x, y, width, height, sizeof(GButtonObject), &buttonVMT)))
if (!(gw = (GButtonObject *)_gwidgetCreate((GWidgetObject *)gw, x, y, width, height, sizeof(GButtonObject), &buttonVMT)))
return 0;
gw->toggle = GWIDGET_NO_INSTANCE;
gw->c_up = GButtonDefaultColorsUp;
gw->c_dn = GButtonDefaultColorsDown;
gw->c_dis = GButtonDefaultColorsDisabled;

View File

@ -26,7 +26,9 @@
// Prototypes for button VMT functions
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y);
static void ToggleOn(GWidgetObject *gw, uint16_t instance);
static void ToggleOn(GWidgetObject *gw, uint16_t role);
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role);
// The button VMT table
static const gwidgetVMT checkboxVMT = {
@ -37,15 +39,24 @@ static const gwidgetVMT checkboxVMT = {
0, // The after-clear routine
},
gwinCheckboxDraw_CheckOnLeft, // The default drawing routine
MouseDown, // Process mouse down events
0, // Process mouse up events (NOT USED)
0, // Process mouse move events (NOT USED)
0, // Process toggle off events (NOT USED)
ToggleOn, // Process toggle on events
0, // Process dial move events (NOT USED)
0, // Process all events (NOT USED)
0, // AssignToggle (NOT USED)
0, // AssignDial (NOT USED)
{
MouseDown, // Process mouse down events
0, // Process mouse up events (NOT USED)
0, // Process mouse move events (NOT USED)
},
{
1, // 1 toggle role
ToggleAssign, // Assign Toggles
ToggleGet, // Get Toggles
0, // Process toggle off events (NOT USED)
ToggleOn, // Process toggle on events
},
{
0, // No dial roles
0, // Assign Dials (NOT USED)
0, // Get Dials (NOT USED)
0, // Process dial move events (NOT USED)
}
};
static const GCheckboxColors defaultColors = {
@ -63,7 +74,7 @@ static void SendCheckboxEvent(GWidgetObject *gw) {
// Trigger a GWIN Checkbox Event
psl = 0;
while ((psl = geventGetSourceListener((GSourceHandle)gw, psl))) {
while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pce->type = GEVENT_GWIN_CHECKBOX;
@ -84,17 +95,28 @@ static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
}
// A toggle on has occurred
static void ToggleOn(GWidgetObject *gw, uint16_t instance) {
(void) instance;
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
_gwidgetRedraw((GHandle)gw);
SendCheckboxEvent(gw);
}
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
(void) role;
((GCheckboxObject *)gw)->toggle = instance;
}
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
(void) role;
return ((GCheckboxObject *)gw)->toggle;
}
GHandle gwinCreateCheckbox(GCheckboxObject *gb, coord_t x, coord_t y, coord_t width, coord_t height) {
if (!(gb = (GCheckboxObject *)_gwidgetInit((GWidgetObject *)gb, x, y, width, height, sizeof(GCheckboxObject), &checkboxVMT)))
if (!(gb = (GCheckboxObject *)_gwidgetCreate((GWidgetObject *)gb, x, y, width, height, sizeof(GCheckboxObject), &checkboxVMT)))
return 0;
gb->toggle = (uint16_t) -1;
gb->c = defaultColors; // assign the default colors
return (GHandle)gb;
}

View File

@ -66,7 +66,7 @@ static const gwinVMT consoleVMT = {
};
GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height) {
if (!(gc = (GConsoleObject *)_gwindowInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject), &consoleVMT, GWIN_FLG_VISIBLE)))
if (!(gc = (GConsoleObject *)_gwindowCreate((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject), &consoleVMT, GWIN_FLG_VISIBLE)))
return 0;
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
gc->stream.vmt = &GWindowConsoleVMT;

View File

@ -165,7 +165,7 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t
}
GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height) {
if (!(gg = (GGraphObject *)_gwindowInit((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject), &graphVMT, GWIN_FLG_VISIBLE)))
if (!(gg = (GGraphObject *)_gwindowCreate((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject), &graphVMT, GWIN_FLG_VISIBLE)))
return 0;
gg->xorigin = gg->yorigin = 0;
gg->lastx = gg->lasty = 0;

View File

@ -13,23 +13,25 @@
#include "gwin/class_gwin.h"
/* Our listener for events for widgets */
static GListener gl;
/* We use these everywhere in this file */
#define gw ((GWidgetObject *)gh)
#define wvmt ((gwidgetVMT *)gh->vmt)
static void gwidgetCallback(void *param, GEvent *pe) {
#define gh ((GWindowObject *)param)
/* Process an event */
static void gwidgetEvent(void *param, GEvent *pe) {
#define gh QItem2GWindow(qi)
#define pme ((GEventMouse *)pe)
#define pte ((GEventToggle *)pe)
#define pde ((GEventDial *)pe)
// check if widget is disabled
if ((gw->g.flags & (GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
return;
// Process via AllEvents() if it is defined
if (wvmt->AllEvents)
wvmt->AllEvents(gw, pe);
const gfxQueueASyncItem * qi;
#if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
uint16_t role;
#endif
(void) param;
// Process various events
switch (pe->type) {
@ -37,76 +39,179 @@ static void gwidgetCallback(void *param, GEvent *pe) {
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
case GEVENT_MOUSE:
case GEVENT_TOUCH:
// Are we captured?
if ((gw->g.flags & GWIN_FLG_MOUSECAPTURE)) {
if ((pme->last_buttons & ~pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
gw->g.flags &= ~GWIN_FLG_MOUSECAPTURE;
if (wvmt->MouseUp)
wvmt->MouseUp(gw, pme->x - gw->g.x, pme->y - gw->g.y);
return;
} else if (wvmt->MouseMove)
wvmt->MouseMove(gw, pme->x - gw->g.x, pme->y - gw->g.y);
// Cycle through all windows
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
// We are not captured - look for mouse downs over the widget
} else if ((~pme->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
&& pme->x >= gw->g.x && pme->x < gw->g.x + gw->g.width
&& pme->y >= gw->g.y && pme->y < gw->g.y + gw->g.height) {
gw->g.flags |= GWIN_FLG_MOUSECAPTURE;
if (wvmt->MouseDown)
wvmt->MouseDown(gw, pme->x - gw->g.x, pme->y - gw->g.y);
// check if it a widget that is enabled and visible
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
continue;
// Are we captured?
if ((gw->g.flags & GWIN_FLG_MOUSECAPTURE)) {
if ((pme->last_buttons & ~pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
gw->g.flags &= ~GWIN_FLG_MOUSECAPTURE;
if (wvmt->MouseUp)
wvmt->MouseUp(gw, pme->x - gw->g.x, pme->y - gw->g.y);
} else if (wvmt->MouseMove)
wvmt->MouseMove(gw, pme->x - gw->g.x, pme->y - gw->g.y);
// We are not captured - look for mouse downs over the widget
} else if ((~pme->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
&& pme->x >= gw->g.x && pme->x < gw->g.x + gw->g.width
&& pme->y >= gw->g.y && pme->y < gw->g.y + gw->g.height) {
gw->g.flags |= GWIN_FLG_MOUSECAPTURE;
if (wvmt->MouseDown)
wvmt->MouseDown(gw, pme->x - gw->g.x, pme->y - gw->g.y);
}
}
break;
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
case GEVENT_TOGGLE:
if (pte->on) {
if (wvmt->ToggleOn)
wvmt->ToggleOn(gw, pte->instance);
} else {
if (wvmt->ToggleOff)
wvmt->ToggleOff(gw, pte->instance);
// Cycle through all windows
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
// check if it a widget that is enabled and visible
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
continue;
for(role = 0; role < wvmt->toggleroles; role++) {
if (wvmt->ToggleGet(gw, role) == pte->instance) {
if (pte->on) {
if (wvmt->ToggleOn)
wvmt->ToggleOn(gw, role);
} else {
if (wvmt->ToggleOff)
wvmt->ToggleOff(gw, role);
}
}
}
}
break;
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
case GEVENT_DIAL:
if (wvmt->DialMove)
wvmt->DialMove(gw, pde->instance, pde->value);
// Cycle through all windows
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
// check if it a widget that is enabled and visible
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
continue;
for(role = 0; role < wvmt->dialroles; role++) {
if (wvmt->DialGet(gw, role) == pte->instance) {
if (wvmt->DialMove)
wvmt->DialMove(gw, role, pde->value, pde->maxvalue);
}
}
}
break;
#endif
default:
break;
}
#undef gh
#undef pme
#undef pte
#undef pde
}
GHandle _gwidgetInit(GWidgetObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwidgetVMT *vmt) {
if (!(pgw = (GWidgetObject *)_gwindowInit((GWindowObject *)pgw, x, y, width, height, size, (const gwinVMT *)vmt, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED)))
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
static GHandle FindToggleUser(uint16_t instance) {
#define gh QItem2GWindow(qi)
const gfxQueueASyncItem * qi;
uint16_t role;
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
continue;
for(role = 0; role < wvmt->toggleroles; role++) {
if (wvmt->ToggleGet(gw, role) == instance)
return gh;
}
}
return 0;
#undef gh
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
static GHandle FindDialUser(uint16_t instance) {
#define gh QItem2GWindow(qi)
const gfxQueueASyncItem * qi;
uint16_t role;
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
continue;
for(role = 0; role < wvmt->dialroles; role++) {
if (wvmt->DialGet(gw, role) == instance)
return gh;
}
}
return 0;
#undef gh
}
#endif
void _gwidgetInit(void) {
geventListenerInit(&gl);
geventRegisterCallback(&gl, gwidgetEvent, 0);
}
GHandle _gwidgetCreate(GWidgetObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwidgetVMT *vmt) {
if (!(pgw = (GWidgetObject *)_gwindowCreate((GWindowObject *)pgw, x, y, width, height, size, (const gwinVMT *)vmt, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED)))
return 0;
pgw->txt = "";
pgw->fnDraw = vmt->DefaultDraw;
pgw->fnParam = 0;
geventListenerInit(&pgw->listener);
geventRegisterCallback(&pgw->listener, gwidgetCallback, pgw);
return (GHandle)pgw;
}
void _gwidgetDestroy(GHandle gh) {
#if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
uint16_t role, instance;
#endif
// Deallocate the text (if necessary)
if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
gh->flags &= ~GWIN_FLG_ALLOCTXT;
gfxFree((void *)gw->txt);
}
// Untangle the listeners (both on us and to us).
geventDetachSource(&gw->listener, 0);
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
// Detach any toggles from this object
for(role = 0; role < wvmt->toggleroles; role++) {
instance = wvmt->ToggleGet(gw, role);
if (instance != GWIDGET_NO_INSTANCE) {
wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
if (!FindToggleUser(instance))
geventDetachSource(&gl, ginputGetToggle(instance));
}
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
// Detach any dials from this object
for(role = 0; role < wvmt->dialroles; role++) {
instance = wvmt->DialGet(gw, role);
if (instance != GWIDGET_NO_INSTANCE) {
wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
if (!FindDialUser(instance))
geventDetachSource(&gl, ginputGetDial(instance));
}
}
#endif
// Remove any listeners on this object.
geventDetachSourceListeners((GSourceHandle)gh);
}
@ -183,76 +288,89 @@ void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) {
_gwidgetRedraw(gh);
}
bool_t gwinAttachListener(GHandle gh, GListener *pl, unsigned flags) {
if (!(gh->flags & GWIN_FLG_WIDGET))
return FALSE;
return geventAttachSource(pl, (GSourceHandle)gh, flags);
bool_t gwinAttachListener(GListener *pl) {
return geventAttachSource(pl, GWIDGET_SOURCE, 0);
}
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
bool_t gwinAttachMouse(GHandle gh, uint16_t instance) {
bool_t gwinAttachMouse(uint16_t instance) {
GSourceHandle gsh;
unsigned flags;
if (!(gh->flags & GWIN_FLG_WIDGET))
return FALSE;
if (!wvmt->MouseDown && !wvmt->MouseMove && !wvmt->MouseUp)
return FALSE;
if (!(gsh = ginputGetMouse(instance)))
return FALSE;
flags = wvmt->MouseMove ? (GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES) : GLISTEN_MOUSEMETA;
return geventAttachSource(&gw->listener, gsh, flags);
return geventAttachSource(&gl, gsh, GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance) {
GSourceHandle gsh;
unsigned flags;
uint16_t oi;
// Is this a widget
if (!(gh->flags & GWIN_FLG_WIDGET))
return FALSE;
flags = 0;
if (wvmt->ToggleOff) flags |= GLISTEN_TOGGLE_OFF;
if (wvmt->ToggleOn) flags |= GLISTEN_TOGGLE_ON;
if (!flags)
// Is the role valid
if (role >= wvmt->toggleroles)
return FALSE;
// Is this a valid device
if (!(gsh = ginputGetToggle(instance)))
return FALSE;
if (wvmt->AssignToggle && !wvmt->AssignToggle(gw, role, instance))
return FALSE;
// Is this already done?
oi = wvmt->ToggleGet(gw, role);
if (instance == oi)
return TRUE;
return geventAttachSource(&gw->listener, gsh, flags);
// Remove the old instance
if (oi != GWIDGET_NO_INSTANCE) {
wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
if (!FindToggleUser(oi))
geventDetachSource(&gl, ginputGetToggle(oi));
}
// Assign the new
wvmt->ToggleAssign(gw, role, instance);
return geventAttachSource(&gl, gsh, GLISTEN_TOGGLE_ON|GLISTEN_TOGGLE_OFF);
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance) {
GSourceHandle gsh;
uint16_t oi;
if (!(gh->flags & GWIN_FLG_WIDGET))
return FALSE;
if (!wvmt->DialMove)
// Is the role valid
if (role >= wvmt->dialroles)
return FALSE;
// Is this a valid device
if (!(gsh = ginputGetDial(instance)))
return FALSE;
if (wvmt->AssignDial && !wvmt->AssignDial(gw, role, instance))
return FALSE;
// Is this already done?
oi = wvmt->DialGet(gw, role);
if (instance == oi)
return TRUE;
return geventAttachSource(&gw->listener, gsh, 0);
// Remove the old instance
if (oi != GWIDGET_NO_INSTANCE) {
wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
if (!FindDialUser(oi))
geventDetachSource(&gl, ginputGetDial(oi));
}
// Assign the new
wvmt->DialAssign(gw, role, instance);
return geventAttachSource(&gl, gsh, 0);
}
#endif
#endif /* GFX_USE_GWIN && GWIN_NEED_WIDGET */
/** @} */

View File

@ -70,6 +70,11 @@ static color_t defaultBgColor = Black;
*-----------------------------------------------*/
void _gwinInit(void) {
#if GWIN_NEED_WIDGET
extern void _gwidgetInit(void);
_gwidgetInit();
#endif
#if GWIN_NEED_WINDOWMANAGER
gfxQueueASyncInit(&_GWINList);
cwm = &GNullWindowManager;
@ -79,7 +84,7 @@ void _gwinInit(void) {
// Internal routine for use by GWIN components only
// Initialise a window creating it dynamically if required.
GHandle _gwindowInit(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwinVMT *vmt, uint16_t flags) {
GHandle _gwindowCreate(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwinVMT *vmt, uint16_t flags) {
// Allocate the structure if necessary
if (!pgw) {
if (!(pgw = (GWindowObject *)gfxAlloc(size)))
@ -146,7 +151,7 @@ void gwinSetDefaultBgColor(color_t bgclr) {
*-----------------------------------------------*/
GHandle gwinCreateWindow(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height) {
return _gwindowInit(pgw, x, y, width, height, sizeof(GWindowObject), &basegwinVMT, GWIN_FLG_VISIBLE);
return _gwindowCreate(pgw, x, y, width, height, sizeof(GWindowObject), &basegwinVMT, GWIN_FLG_VISIBLE);
}
void gwinDestroy(GHandle gh) {

View File

@ -25,10 +25,19 @@
#define GWIN_SLIDER_DEAD_BAND 5
#endif
#ifndef GWIN_SLIDER_TOGGLE_INC
#define GWIN_SLIDER_TOGGLE_INC 20 // How many toggles to go from minimum to maximum
#endif
// Prototypes for slider VMT functions
static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y);
static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y);
static void DialMove(GWidgetObject *gw, uint16_t instance, uint16_t value);
static void ToggleOn(GWidgetObject *gw, uint16_t role);
static void DialMove(GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max);
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
static void DialAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role);
static uint16_t DialGet(GWidgetObject *gw, uint16_t role);
// The button VMT table
static const gwidgetVMT sliderVMT = {
@ -38,16 +47,25 @@ static const gwidgetVMT sliderVMT = {
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
gwinSliderDraw_Std, // The default drawing routine
MouseMove, // Process mouse down events (AS MOUSEMOVE)
MouseUp, // Process mouse up events
MouseMove, // Process mouse move events
0, // Process toggle off events (NOT USED)
0, // Process toggle on events (NOT USED)
DialMove, // Process dial move events
0, // Process all events (NOT USED)
0, // AssignToggle (NOT USED)
0, // AssignDial (NOT USED)
gwinSliderDraw_Std, // The default drawing routine
{
0, // Process mouse down events (NOT USED)
MouseUp, // Process mouse up events
MouseMove, // Process mouse move events
},
{
2, // 1 toggle role
ToggleAssign, // Assign Toggles
ToggleGet, // Get Toggles
0, // Process toggle off events (NOT USED)
ToggleOn, // Process toggle on events
},
{
1, // 1 dial roles
DialAssign, // Assign Dials
DialGet, // Get Dials
DialMove, // Process dial move events
}
};
static const GSliderColors GSliderDefaultColors = {
@ -66,7 +84,7 @@ static void SendSliderEvent(GWidgetObject *gw) {
// Trigger a GWIN Button Event
psl = 0;
while ((psl = geventGetSourceListener((GSourceHandle)gw, psl))) {
while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pse->type = GEVENT_GWIN_SLIDER;
@ -75,7 +93,7 @@ static void SendSliderEvent(GWidgetObject *gw) {
geventSendEvent(psl);
}
#undef pbe
#undef pse
}
// Reset the display position back to the value predicted by the saved slider position
@ -159,13 +177,28 @@ static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) {
#undef gsw
}
// A dial move event
static void DialMove(GWidgetObject *gw, uint16_t instance, uint16_t value) {
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
// A toggle on has occurred
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
#define gsw ((GSliderObject *)gw)
if (role) {
gwinSetSliderPosition((GHandle)gw, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
SendSliderEvent(gw);
} else {
gwinSetSliderPosition((GHandle)gw, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
SendSliderEvent(gw);
}
#undef gsw
}
// A dial move event
static void DialMove(GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max) {
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
#define gsw ((GSliderObject *)gw)
(void) role;
// Set the new position
gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/ginputGetDialRange(instance) + gsw->min);
gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min);
ResetDisplayPos(gsw);
gwinDraw(&gw->g);
@ -174,13 +207,37 @@ static void DialMove(GWidgetObject *gw, uint16_t instance, uint16_t value) {
SendSliderEvent(gw);
#undef gsw
#else
(void)gw; (void)instance; (void)value;
(void)gw; (void)role; (void)value; (void)max;
#endif
}
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
if (role)
((GSliderObject *)gw)->t_up = instance;
else
((GSliderObject *)gw)->t_dn = instance;
}
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
return role ? ((GSliderObject *)gw)->t_up : ((GSliderObject *)gw)->t_dn;
}
static void DialAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
(void) role;
((GSliderObject *)gw)->dial = instance;
}
static uint16_t DialGet(GWidgetObject *gw, uint16_t role) {
(void) role;
return ((GSliderObject *)gw)->dial;
}
GHandle gwinCreateSlider(GSliderObject *gs, coord_t x, coord_t y, coord_t width, coord_t height) {
if (!(gs = (GSliderObject *)_gwidgetInit((GWidgetObject *)gs, x, y, width, height, sizeof(GSliderObject), &sliderVMT)))
if (!(gs = (GSliderObject *)_gwidgetCreate((GWidgetObject *)gs, x, y, width, height, sizeof(GSliderObject), &sliderVMT)))
return 0;
gs->t_dn = (uint16_t) -1;
gs->t_up = (uint16_t) -1;
gs->dial = (uint16_t) -1;
gs->c = GSliderDefaultColors;
gs->min = 0;
gs->max = 100;