Add Radio buttons (can also be used as a Tab group)

ugfx_release_2.6
inmarket 2013-07-06 01:46:34 +10:00
parent ab44f32859
commit 5191c278e7
8 changed files with 532 additions and 20 deletions

View File

@ -80,6 +80,7 @@
#define GWIN_NEED_CHECKBOX TRUE #define GWIN_NEED_CHECKBOX TRUE
#define GWIN_NEED_LABEL TRUE #define GWIN_NEED_LABEL TRUE
#define GWIN_NEED_IMAGE TRUE #define GWIN_NEED_IMAGE TRUE
#define GWIN_NEED_RADIO TRUE
/* Features for the GINPUT sub-system. */ /* Features for the GINPUT sub-system. */
#define GINPUT_NEED_MOUSE TRUE #define GINPUT_NEED_MOUSE TRUE

View File

@ -30,19 +30,36 @@
static GListener gl; static GListener gl;
static GHandle ghConsole; static GHandle ghConsole;
static GHandle ghTabButtons, ghTabSliders, ghTabCheckboxes, ghTabLabels, ghTabRadios, ghTabImages;
static GHandle ghButton1, ghButton2, ghButton3, ghButton4; static GHandle ghButton1, ghButton2, ghButton3, ghButton4;
static GHandle ghSlider1, ghSlider2, ghSlider3, ghSlider4; static GHandle ghSlider1, ghSlider2, ghSlider3, ghSlider4;
static GHandle ghCheckbox1, ghCheckbox2; static GHandle ghCheckbox1, ghCheckbox2;
static GHandle ghLabel1; static GHandle ghLabel1;
static GHandle ghRadio1, ghRadio2;
//static GHandle ghImage1;
#define ScrWidth gdispGetWidth() #define ScrWidth gdispGetWidth()
#define ScrHeight gdispGetHeight() #define ScrHeight gdispGetHeight()
#define TAB_HEIGHT 30
#define BUTTON_WIDTH 50 #define BUTTON_WIDTH 50
#define BUTTON_HEIGHT 30 #define BUTTON_HEIGHT 30
#define SLIDER_WIDTH 20 #define SLIDER_WIDTH 20
#define CHECKBOX_WIDTH 80 #define CHECKBOX_WIDTH 80
#define CHECKBOX_HEIGHT 20 #define CHECKBOX_HEIGHT 20
#define RADIO_WIDTH 50
#define RADIO_HEIGHT 20
#define GROUP_TABS 0
#define GROUP_R1R2 1
static GHandle createTab(GWidgetInit *pwi) {
GHandle gh;
gh = gwinCreateRadio(NULL, pwi, GROUP_TABS);
gwinSetCustomDraw(gh, gwinRadioDraw_Tab, 0);
gwinSetVisible(gh, TRUE);
return gh;
}
int main(void) { int main(void) {
GEvent * pe; GEvent * pe;
@ -69,10 +86,17 @@ int main(void) {
{ {
GWidgetInit wi; GWidgetInit wi;
wi.g.show = TRUE; // Create the Tabs
wi.g.show = FALSE; wi.g.width = ScrWidth/6; wi.g.height = TAB_HEIGHT; wi.g.y = 0;
wi.g.x = 0*wi.g.width; wi.text = "Buttons"; ghTabButtons = createTab(&wi);
wi.g.x = 1*wi.g.width; wi.text = "Sliders"; ghTabSliders = createTab(&wi);
wi.g.x = 2*wi.g.width; wi.text = "Checkbox"; ghTabCheckboxes = createTab(&wi);
wi.g.x = 3*wi.g.width; wi.text = "Labels"; ghTabLabels = createTab(&wi);
wi.g.x = 4*wi.g.width; wi.text = "Radios"; ghTabRadios = createTab(&wi);
wi.g.x = 5*wi.g.width; wi.text = "Images"; ghTabImages = createTab(&wi);
// Buttons // Buttons
wi.g.width = BUTTON_WIDTH; wi.g.height = BUTTON_HEIGHT; wi.g.y = 0; wi.g.width = BUTTON_WIDTH; wi.g.height = BUTTON_HEIGHT; wi.g.y = TAB_HEIGHT+5;
wi.g.x = 0+0*(BUTTON_WIDTH+1); wi.text = "B1"; ghButton1 = gwinCreateButton(NULL, &wi); wi.g.x = 0+0*(BUTTON_WIDTH+1); wi.text = "B1"; ghButton1 = gwinCreateButton(NULL, &wi);
wi.g.x = 0+1*(BUTTON_WIDTH+1); wi.text = "B2"; ghButton2 = gwinCreateButton(NULL, &wi); wi.g.x = 0+1*(BUTTON_WIDTH+1); wi.text = "B2"; ghButton2 = gwinCreateButton(NULL, &wi);
wi.g.x = 0+2*(BUTTON_WIDTH+1); wi.text = "B3"; ghButton3 = gwinCreateButton(NULL, &wi); wi.g.x = 0+2*(BUTTON_WIDTH+1); wi.text = "B3"; ghButton3 = gwinCreateButton(NULL, &wi);
@ -90,24 +114,25 @@ int main(void) {
// Checkboxes - for the 2nd checkbox we apply special drawing before making it visible // Checkboxes - for the 2nd checkbox we apply special drawing before making it visible
wi.g.width = CHECKBOX_WIDTH; wi.g.height = CHECKBOX_HEIGHT; wi.g.x = 0; wi.g.width = CHECKBOX_WIDTH; wi.g.height = CHECKBOX_HEIGHT; wi.g.x = 0;
wi.g.y = BUTTON_HEIGHT+1+0*(CHECKBOX_HEIGHT+1); wi.text = "C1"; ghCheckbox1 = gwinCreateCheckbox(NULL, &wi); wi.g.y = TAB_HEIGHT+5+0*(CHECKBOX_HEIGHT+1); wi.text = "C1"; ghCheckbox1 = gwinCreateCheckbox(NULL, &wi);
wi.g.show = FALSE; wi.g.y = TAB_HEIGHT+5+1*(CHECKBOX_HEIGHT+1); wi.text = "C2"; ghCheckbox2 = gwinCreateCheckbox(NULL, &wi);
wi.g.y = BUTTON_HEIGHT+1+1*(CHECKBOX_HEIGHT+1); wi.text = "C2"; ghCheckbox2 = gwinCreateCheckbox(NULL, &wi);
gwinSetCustomDraw(ghCheckbox2, gwinCheckboxDraw_CheckOnRight, 0); gwinSetCustomDraw(ghCheckbox2, gwinCheckboxDraw_CheckOnRight, 0);
gwinSetVisible(ghCheckbox2, TRUE);
wi.g.show = TRUE; wi.g.width = 0; // Labels
wi.g.y = BUTTON_HEIGHT+1+2*(CHECKBOX_HEIGHT+1); wi.text = "L1"; ghLabel1 = gwinLabelCreate(NULL, &wi); wi.g.width = 0; // dynamic width
wi.g.y = TAB_HEIGHT+5+2*(CHECKBOX_HEIGHT+1); wi.text = "L1"; ghLabel1 = gwinLabelCreate(NULL, &wi);
// Radio Buttons
wi.g.width = RADIO_WIDTH; wi.g.height = RADIO_HEIGHT; wi.g.y = TAB_HEIGHT+5;
wi.g.x = 0*wi.g.width; wi.text = "Yes"; ghRadio1 = gwinCreateRadio(NULL, &wi, GROUP_R1R2);
wi.g.x = 1*wi.g.width; wi.text = "No"; ghRadio2 = gwinCreateRadio(NULL, &wi, GROUP_R1R2);
// Console - we apply some special colors before making it visible // Console - we apply some special colors before making it visible
wi.g.show = FALSE;
wi.g.width = ScrWidth/2-1; wi.g.height = ScrHeight/2-1; wi.g.width = ScrWidth/2-1; wi.g.height = ScrHeight/2-1;
wi.g.x = ScrWidth/2+1; wi.g.y = ScrHeight/2+1; wi.g.x = ScrWidth/2+1; wi.g.y = ScrHeight/2+1;
ghConsole = gwinCreateConsole(NULL, &wi.g); ghConsole = gwinCreateConsole(NULL, &wi.g);
gwinSetColor(ghConsole, Yellow); gwinSetColor(ghConsole, Yellow);
gwinSetBgColor(ghConsole, Black); gwinSetBgColor(ghConsole, Black);
gwinSetVisible(ghConsole, TRUE);
gwinClear(ghConsole);
} }
// Assign toggles and dials to the buttons & sliders etc. // Assign toggles and dials to the buttons & sliders etc.
@ -120,15 +145,12 @@ int main(void) {
gwinAttachDial(ghSlider3, 0, 1); gwinAttachDial(ghSlider3, 0, 1);
#endif #endif
gfxSleepMilliseconds(5000); // Make the console visible
gwinSetBgColor(ghLabel1, Blue); gwinSetVisible(ghConsole, TRUE);
gwinSetColor(ghLabel1, Yellow); gwinClear(ghConsole);
gwinSetText(ghLabel1, "Very Big Label", FALSE);
gfxSleepMilliseconds(5000); // Press the Buttons Tab
gwinSetBgColor(ghLabel1, Yellow); gwinPressRadio(ghTabButtons);
gwinSetColor(ghLabel1, Red);
gwinSetText(ghLabel1, "L1", FALSE);
while(1) { while(1) {
// Get an Event // Get an Event
@ -144,6 +166,48 @@ int main(void) {
case GEVENT_GWIN_CHECKBOX: case GEVENT_GWIN_CHECKBOX:
gwinPrintf(ghConsole, "Checkbox %s=%s\n", gwinGetText(((GEventGWinCheckbox *)pe)->checkbox), ((GEventGWinCheckbox *)pe)->isChecked ? "Checked" : "UnChecked"); gwinPrintf(ghConsole, "Checkbox %s=%s\n", gwinGetText(((GEventGWinCheckbox *)pe)->checkbox), ((GEventGWinCheckbox *)pe)->isChecked ? "Checked" : "UnChecked");
break; break;
case GEVENT_GWIN_RADIO:
gwinPrintf(ghConsole, "Radio Group %u=%s\n", ((GEventGWinRadio *)pe)->group, gwinGetText(((GEventGWinRadio *)pe)->radio));
// Is this the tab radio's
if (((GEventGWinRadio *)pe)->group == GROUP_TABS) {
// Do some special animation for Label1
if (((GEventGWinRadio *)pe)->radio == ghTabLabels) {
gwinSetBgColor(ghLabel1, gwinGetDefaultBgColor());
gwinSetColor(ghLabel1, gwinGetDefaultColor());
}
// Set control visibility depending on the tab selected
gwinSetVisible(ghButton1, ((GEventGWinRadio *)pe)->radio == ghTabButtons);
gwinSetVisible(ghButton2, ((GEventGWinRadio *)pe)->radio == ghTabButtons);
gwinSetVisible(ghButton3, ((GEventGWinRadio *)pe)->radio == ghTabButtons);
gwinSetVisible(ghButton4, ((GEventGWinRadio *)pe)->radio == ghTabButtons);
gwinSetVisible(ghSlider1, ((GEventGWinRadio *)pe)->radio == ghTabSliders);
gwinSetVisible(ghSlider2, ((GEventGWinRadio *)pe)->radio == ghTabSliders);
gwinSetVisible(ghSlider3, ((GEventGWinRadio *)pe)->radio == ghTabSliders);
gwinSetVisible(ghSlider4, ((GEventGWinRadio *)pe)->radio == ghTabSliders);
gwinSetVisible(ghCheckbox1, ((GEventGWinRadio *)pe)->radio == ghTabCheckboxes);
gwinSetVisible(ghCheckbox2, ((GEventGWinRadio *)pe)->radio == ghTabCheckboxes);
gwinSetVisible(ghLabel1, ((GEventGWinRadio *)pe)->radio == ghTabLabels);
gwinSetVisible(ghRadio1, ((GEventGWinRadio *)pe)->radio == ghTabRadios);
gwinSetVisible(ghRadio2, ((GEventGWinRadio *)pe)->radio == ghTabRadios);
//gwinSetVisible(ghImage1, ((GEventGWinRadio *)pe)->radio == ghTabImages);
// Do some special animation for Label1
if (((GEventGWinRadio *)pe)->radio == ghTabLabels) {
gfxSleepMilliseconds(1000);
gwinSetBgColor(ghLabel1, Blue);
gwinSetColor(ghLabel1, Yellow);
gwinSetText(ghLabel1, "Very Big Label", FALSE);
gfxSleepMilliseconds(1000);
gwinSetBgColor(ghLabel1, Yellow);
gwinSetColor(ghLabel1, Red);
gwinSetText(ghLabel1, "L1", FALSE);
}
}
break;
default: default:
gwinPrintf(ghConsole, "Unknown %d\n", pe->type); gwinPrintf(ghConsole, "Unknown %d\n", pe->type);
break; break;

View File

@ -51,7 +51,14 @@
#error "GWIN: GDISP_NEED_IMAGE is required when GWIN_NEED_IMAGE is TRUE." #error "GWIN: GDISP_NEED_IMAGE is required when GWIN_NEED_IMAGE is TRUE."
#endif #endif
#endif #endif
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX || GWIN_NEED_LABEL #if GWIN_NEED_RADIO
#if !GDISP_NEED_CIRCLE
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: GDISP_NEED_CIRCLE should be set to TRUE for much nicer radio button widgets."
#endif
#endif
#endif
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX || GWIN_NEED_LABEL || GWIN_NEED_RADIO
#if !GWIN_NEED_WIDGET #if !GWIN_NEED_WIDGET
#if GFX_DISPLAY_RULE_WARNINGS #if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: GWIN_NEED_WIDGET is required when a Widget is used. It has been turned on for you." #warning "GWIN: GWIN_NEED_WIDGET is required when a Widget is used. It has been turned on for you."

View File

@ -195,6 +195,9 @@ bool_t gwinAttachListener(GListener *pl);
#if GWIN_NEED_CHECKBOX || defined(__DOXYGEN__) #if GWIN_NEED_CHECKBOX || defined(__DOXYGEN__)
#include "gwin/checkbox.h" #include "gwin/checkbox.h"
#endif #endif
#if GWIN_NEED_RADIO || defined(__DOXYGEN__)
#include "gwin/radio.h"
#endif
#endif /* _GWIDGET_H */ #endif /* _GWIDGET_H */
/** @} */ /** @} */

View File

@ -83,6 +83,13 @@
#ifndef GWIN_NEED_LABEL #ifndef GWIN_NEED_LABEL
#define GWIN_NEED_LABEL FALSE #define GWIN_NEED_LABEL FALSE
#endif #endif
/**
* @brief Should radio button functions be included.
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_RADIO
#define GWIN_NEED_RADIO FALSE
#endif
/** /**
* @} * @}
* *

View File

@ -0,0 +1,169 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file include/gwin/radio.h
* @brief GWIN Graphic window subsystem header file.
*
* @defgroup RadioButton RadioButton
* @ingroup GWIN
*
* @details GWIN allows it to easily create radio buttons with different styles.
*
* @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
* @pre GWIN_NEED_RADIO must be set to TRUE in your gfxconf.h
* @{
*/
#ifndef _GWIN_RADIO_H
#define _GWIN_RADIO_H
/* This file is included within "gwin/gwidget.h" */
/**
* @brief The Event Type for a Radio Event
*/
#define GEVENT_GWIN_RADIO (GEVENT_GWIN_FIRST+3)
/**
* @brief A Button Event
* @note There are currently no GEventGWinRadio listening flags - use 0 as the flags to @p gwinAttachListener()
*/
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
} GEventGWinRadio;
/**
* @brief Button colors
*/
typedef struct GRadioColors {
color_t color_edge;
color_t color_fill;
color_t color_txt;
} GRadioColors;
/**
* @brief The radio button widget structure
* @note Do not use the members directly - treat it as a black-box.
*/
typedef struct GRadioObject_t {
GWidgetObject w;
#if GINPUT_NEED_TOGGLE
uint16_t toggle;
#endif
uint16_t group;
GRadioColors c_up;
GRadioColors c_dn;
GRadioColors c_dis;
} GRadioObject;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Create a radio widget.
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gb The GRadioObject structure to initialise. If this is NULL the structure is dynamically allocated.
* @param[in] pInit The initialisation parameters
* @param[in] group The group of radio buttons this radio button belongs to.
*
* @note Only one radio button in any group is ever pressed at one time. Pressing one radio button will
* release all others in the group.
* @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 A radio 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 A radio 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
*/
GHandle gwinCreateRadio(GRadioObject *gb, const GWidgetInit *pInit, uint16_t group);
/**
* @brief Set the colors of a button.
*
* @param[in] gh The window handle (must be a radio widget)
* @param[in] pUp The colors for the button when in the up state.
* @param[in] pDown The colors for the button when in the down state.
* @param[in] pDisabled The colors for the button when it is disabled.
*
* @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button style
* @note The button style is copied into the internal button structure - there is no need to
* maintain static style structures (they can be temporary structures on the stack).
* @note The pUp, pDown and pDisabled parameters can be NULL. If they are then the existing color styles
* are not changed for that button state.
* @note Some custom drawn buttons will ignore he specified colors
*
* @api
*/
void gwinSetRadioColors(GHandle gh, const GRadioColors *pUp, const GRadioColors *pDown, const GRadioColors *pDisabled);
/**
* @brief Press this radio button (and by definition unset any others in the group)
*
* @param[in] gh The window handle (must be a radio widget)
*
* @api
*/
void gwinPressRadio(GHandle gh);
/**
* @brief Is the radio button currently pressed
* @return TRUE if the button is pressed
*
* @param[in] gh The window handle (must be a radio widget)
*
* @api
*/
bool_t gwinIsRadioPressed(GHandle gh);
/**
* @brief Find the currently pressed radio button in the specified group
* @return The handle of the pressed radio button or NULL if none are pressed
*
* @param[in] gh The window handle (must be a radio widget)
*
* @api
*/
GHandle gwinActiveRadio(uint16_t group);
/**
* @brief Some custom radio button drawing routines
* @details These function may be passed to @p gwinSetCustomDraw() to get different radio button drawing styles
*
* @param[in] gw The widget object (in this case a radio button)
* @param[in] param A parameter passed in from the user
*
* @note In your custom radio drawing function you may optionally call these
* standard functions and then draw your extra details on top.
* @note The standard functions below ignore the param parameter.
* @note These custom drawing routines don't have to worry about setting clipping as the framework
* sets clipping to the object window prior to calling these routines.
*
* @api
* @{
*/
void gwinRadioDraw_Radio(GWidgetObject *gw, void *param); // @< A standard radio button
void gwinRadioDraw_Button(GWidgetObject *gw, void *param); // @< Draw as a button
void gwinRadioDraw_Tab(GWidgetObject *gw, void *param); // @< Draw as a tab
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _GWIN_RADIO_H */
/** @} */

View File

@ -8,4 +8,5 @@ GFXSRC += $(GFXLIB)/src/gwin/gwin.c \
$(GFXLIB)/src/gwin/checkbox.c \ $(GFXLIB)/src/gwin/checkbox.c \
$(GFXLIB)/src/gwin/gimage.c \ $(GFXLIB)/src/gwin/gimage.c \
$(GFXLIB)/src/gwin/label.c \ $(GFXLIB)/src/gwin/label.c \
$(GFXLIB)/src/gwin/radio.c \

260
src/gwin/radio.c 100644
View File

@ -0,0 +1,260 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file src/gwin/radio.c
* @brief GWIN sub-system radio button code.
*
* @defgroup RadioButton RadioButton
* @ingroup GWIN
*
* @{
*/
#include "gfx.h"
#if GFX_USE_GWIN && GWIN_NEED_RADIO
#include "gwin/class_gwin.h"
// Our pressed state
#define GRADIO_FLG_PRESSED (GWIN_FIRST_CONTROL_FLAG<<0)
// Default color scheme
static const GRadioColors GRadioDefaultColorsUp = {
HTML2COLOR(0x404040), // color_up_edge;
HTML2COLOR(0xE0E0E0), // color_up_fill;
HTML2COLOR(0x000000), // color_up_txt;
};
static const GRadioColors GRadioDefaultColorsDown = {
HTML2COLOR(0x404040), // color_dn_edge;
HTML2COLOR(0x808080), // color_dn_fill;
HTML2COLOR(0x404040), // color_dn_txt;
};
static const GRadioColors GRadioDefaultColorsDisabled = {
HTML2COLOR(0x808080), // color_dis_edge;
HTML2COLOR(0xE0E0E0), // color_dis_fill;
HTML2COLOR(0xC0C0C0), // color_dis_txt;
};
// Send the button event
static void SendButtonEvent(GWidgetObject *gw) {
GSourceListener * psl;
GEvent * pe;
#define pbe ((GEventGWinRadio *)pe)
// Trigger a GWIN Button Event
psl = 0;
while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pbe->type = GEVENT_GWIN_RADIO;
pbe->radio = (GHandle)gw;
pbe->group = ((GRadioObject *)gw)->group;
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) {
(void) x; (void) y;
gwinPressRadio((GHandle)gw);
}
#endif
#if GINPUT_NEED_TOGGLE
// A toggle on has occurred
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
(void) role;
gwinPressRadio((GHandle)gw);
}
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
(void) role;
((GRadioObject *)gw)->toggle = instance;
}
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
(void) role;
return ((GRadioObject *)gw)->toggle;
}
#endif
// The radio button VMT table
static const gwidgetVMT radioVMT = {
{
"Radio", // The classname
sizeof(GRadioObject), // The object size
_gwidgetDestroy, // The destroy routine
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
gwinRadioDraw_Radio, // The default drawing routine
#if GINPUT_NEED_MOUSE
{
MouseDown, // Process mouse down events
0, // Process mouse up events (NOT USED)
0, // Process mouse move events (NOT USED)
},
#endif
#if GINPUT_NEED_TOGGLE
{
1, // 1 toggle role
ToggleAssign, // Assign Toggles
ToggleGet, // Get Toggles
0, // Process toggle off events (NOT USED)
ToggleOn, // Process toggle on events
},
#endif
#if GINPUT_NEED_DIAL
{
0, // No dial roles
0, // Assign Dials (NOT USED)
0, // Get Dials (NOT USED)
0, // Process dial move events (NOT USED)
},
#endif
};
GHandle gwinCreateRadio(GRadioObject *gw, const GWidgetInit *pInit, uint16_t group) {
if (!(gw = (GRadioObject *)_gwidgetCreate(&gw->w, pInit, &radioVMT)))
return 0;
#if GINPUT_NEED_TOGGLE
gw->toggle = GWIDGET_NO_INSTANCE;
#endif
gw->group = group;
gw->c_up = GRadioDefaultColorsUp;
gw->c_dn = GRadioDefaultColorsDown;
gw->c_dis = GRadioDefaultColorsDisabled;
gwinSetVisible((GHandle)gw, pInit->g.show);
return (GHandle)gw;
}
void gwinSetRadioColors(GHandle gh, const GRadioColors *pUp, const GRadioColors *pDown, const GRadioColors *pDisabled) {
if (gh->vmt != (gwinVMT *)&radioVMT)
return;
if (pUp) ((GRadioObject *)gh)->c_up = *pUp;
if (pDown) ((GRadioObject *)gh)->c_dn = *pDown;
if (pDisabled) ((GRadioObject *)gh)->c_dis = *pDisabled;
}
void gwinPressRadio(GHandle gh) {
GHandle gx;
if (gh->vmt != (gwinVMT *)&radioVMT || (gh->flags & GRADIO_FLG_PRESSED))
return;
if ((gx = gwinActiveRadio(((GRadioObject *)gh)->group))) {
gx->flags &= ~GRADIO_FLG_PRESSED;
_gwidgetRedraw(gx);
}
gh->flags |= GRADIO_FLG_PRESSED;
_gwidgetRedraw(gh);
SendButtonEvent((GWidgetObject *)gh);
}
bool_t gwinIsRadioPressed(GHandle gh) {
if (gh->vmt != (gwinVMT *)&radioVMT)
return FALSE;
return (gh->flags & GRADIO_FLG_PRESSED) ? TRUE : FALSE;
}
/**
* @brief Find the currently pressed radio button in the specified group
* @return The handle of the pressed radio button or NULL if none are pressed
*
* @param[in] gh The window handle (must be a radio widget)
*
* @api
*/
GHandle gwinActiveRadio(uint16_t group) {
const gfxQueueASyncItem * qi;
GHandle gh;
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
gh = QItem2GWindow(qi);
if (gh->vmt == (gwinVMT *)&radioVMT && ((GRadioObject *)gh)->group == group && (gh->flags & GRADIO_FLG_PRESSED))
return gh;
}
return 0;
}
/*----------------------------------------------------------
* Custom Draw Routines
*----------------------------------------------------------*/
static GRadioColors *getDrawColors(GWidgetObject *gw) {
if (!(gw->g.flags & GWIN_FLG_ENABLED)) return &((GRadioObject *)gw)->c_dis;
if ((gw->g.flags & GRADIO_FLG_PRESSED)) return &((GRadioObject *)gw)->c_dn;
return &((GRadioObject *)gw)->c_up;
}
void gwinRadioDraw_Radio(GWidgetObject *gw, void *param) {
#define gcw ((GRadioObject *)gw)
coord_t ld, df;
GRadioColors * pcol;
(void) param;
if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
pcol = getDrawColors(gw);
ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;
#if GDISP_NEED_CIRCLE
df = ld/2;
gdispFillArea(gw->g.x, gw->g.y, ld, ld, gw->g.bgcolor);
gdispDrawCircle(gw->g.x+df, gw->g.y+df, df, pcol->color_edge);
if (gw->g.flags & GRADIO_FLG_PRESSED)
gdispFillCircle(gw->g.x+df, gw->g.y+df, df <= 2 ? 1 : (df-2), pcol->color_fill);
#else
gdispFillArea(gw->g.x+1, gw->g.y+1, ld, ld-2, gw->g.bgcolor);
gdispDrawBox(gw->g.x, gw->g.y, ld, ld, pcol->color_edge);
df = ld < 4 ? 1 : 2;
if (gw->g.flags & GRADIO_FLG_PRESSED)
gdispFillArea(gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->color_fill);
#endif
gdispFillStringBox(gw->g.x+ld+1, gw->g.y, gw->g.width-ld-1, gw->g.height, gw->txt, gw->g.font, pcol->color_txt, gw->g.bgcolor, justifyLeft);
#undef gcw
}
void gwinRadioDraw_Button(GWidgetObject *gw, void *param) {
(void) param;
GRadioColors * pcol;
if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
pcol = getDrawColors(gw);
gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->txt, gw->g.font, pcol->color_txt, pcol->color_fill, justifyCenter);
gdispDrawLine(gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->color_edge);
gdispDrawLine(gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->color_edge);
}
void gwinRadioDraw_Tab(GWidgetObject *gw, void *param) {
(void) param;
GRadioColors * pcol;
if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
pcol = getDrawColors(gw);
gdispFillStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, pcol->color_txt, pcol->color_fill, justifyCenter);
gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->color_edge);
}
#endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */
/** @} */