GWIN button changes

Support a user supplied custom button drawing function.
Add arrow buttons based on the new GDISP polygon support.
This commit is contained in:
Andrew Hannam 2013-03-10 16:15:49 +10:00
parent 40b390908c
commit da37b111e4
2 changed files with 434 additions and 258 deletions

View file

@ -1,194 +1,252 @@
/* /*
ChibiOS/GFX - Copyright (C) 2012, 2013 ChibiOS/GFX - Copyright (C) 2012, 2013
Joel Bodenmann aka Tectu <joel@unormal.org> Joel Bodenmann aka Tectu <joel@unormal.org>
This file is part of ChibiOS/GFX. This file is part of ChibiOS/GFX.
ChibiOS/GFX is free software; you can redistribute it and/or modify ChibiOS/GFX is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
ChibiOS/GFX is distributed in the hope that it will be useful, ChibiOS/GFX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** /**
* @file include/gwin/button.h * @file include/gwin/button.h
* @brief GWIN Graphic window subsystem header file. * @brief GWIN Graphic window subsystem header file.
* *
* @defgroup Button Button * @defgroup Button Button
* @ingroup GWIN * @ingroup GWIN
* *
* @details GWIN allows it to easily create buttons with different styles * @details GWIN allows it to easily create buttons with different styles
* and check for different meta states such as: PRESSED, CLICKED, * and check for different meta states such as: PRESSED, CLICKED,
* RELEASED etc. * RELEASED etc.
* *
* @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h * @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
* @pre GWIN_NEED_BUTTON must be set to TRUE in your gfxconf.h * @pre GWIN_NEED_BUTTON must be set to TRUE in your gfxconf.h
* @{ * @{
*/ */
#ifndef _GWIN_BUTTON_H #ifndef _GWIN_BUTTON_H
#define _GWIN_BUTTON_H #define _GWIN_BUTTON_H
#if GWIN_NEED_BUTTON || defined(__DOXYGEN__) #if GWIN_NEED_BUTTON || defined(__DOXYGEN__)
/*===========================================================================*/ /*===========================================================================*/
/* Driver constants. */ /* Driver constants. */
/*===========================================================================*/ /*===========================================================================*/
#define GW_BUTTON 0x0002 #define GW_BUTTON 0x0002
#define GEVENT_GWIN_BUTTON (GEVENT_GWIN_FIRST+0) #define GEVENT_GWIN_BUTTON (GEVENT_GWIN_FIRST+0)
/*===========================================================================*/ /*===========================================================================*/
/* Type definitions */ /* Type definitions */
/*===========================================================================*/ /*===========================================================================*/
typedef struct GEventGWinButton_t { typedef struct GEventGWinButton_t {
GEventType type; // The type of this event (GEVENT_GWIN_BUTTON) GEventType type; // The type of this event (GEVENT_GWIN_BUTTON)
GHandle button; // The button that has been depressed (actually triggered on release) GHandle button; // The button that has been depressed (actually triggered on release)
} GEventGWinButton; } GEventGWinButton;
// There are currently no GEventGWinButton listening flags - use 0 // There are currently no GEventGWinButton listening flags - use 0
typedef enum GButtonShape_e { typedef enum GButtonShape_e {
GBTN_3D, GBTN_SQUARE, GBTN_ROUNDED, GBTN_ELLIPSE GBTN_3D, GBTN_SQUARE, GBTN_ROUNDED, GBTN_ELLIPSE, GBTN_CUSTOM,
} GButtonShape; GBTN_ARROW_UP, GBTN_ARROW_DOWN, GBTN_ARROW_LEFT, GBTN_ARROW_RIGHT,
} GButtonShape;
typedef struct GButtonStyle_t {
GButtonShape shape; typedef struct GButtonDrawStyle_t {
color_t color_up_edge; color_t color_edge;
color_t color_up_fill; color_t color_fill;
color_t color_up_txt; color_t color_txt;
color_t color_dn_edge; } GButtonDrawStyle;
color_t color_dn_fill;
color_t color_dn_txt; typedef enum GButtonType_e {
} GButtonStyle; GBTN_NORMAL, GBTN_TOGGLE
} GButtonType;
typedef enum GButtonType_e {
GBTN_NORMAL, GBTN_TOGGLE typedef enum GButtonState_e {
} GButtonType; GBTN_UP, GBTN_DOWN
} GButtonState;
typedef enum GButtonState_e {
GBTN_UP, GBTN_DOWN typedef void (*GButtonDrawFunction)(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
} GButtonState;
// A button window
// A button window typedef struct GButtonObject_t {
typedef struct GButtonObject_t { GWindowObject gwin;
GWindowObject gwin;
GButtonDrawStyle up;
GButtonStyle style; GButtonDrawStyle dn;
GButtonState state; GButtonState state;
GButtonType type; GButtonType type;
const char * txt; const char *txt;
GListener listener; GButtonDrawFunction fn;
} GButtonObject; void *param;
GListener listener;
/*===========================================================================*/ } GButtonObject;
/* External declarations. */
/*===========================================================================*/ /*===========================================================================*/
/* External declarations. */
#ifdef __cplusplus /*===========================================================================*/
extern "C" {
#endif #ifdef __cplusplus
extern "C" {
/** #endif
* @brief Create a button window.
* @return NULL if there is no resultant drawing area, otherwise a window handle. /**
* * @brief Create a button window.
* @param[in] gb The GButtonObject structure to initialise. If this is NULL the structure is dynamically allocated. * @return NULL if there is no resultant drawing area, otherwise a window handle.
* @param[in] x,y The screen co-ordinates for the bottom left corner of the window *
* @param[in] width The width of the window * @param[in] gb The GButtonObject structure to initialise. If this is NULL the structure is dynamically allocated.
* @param[in] height The height of the window * @param[in] x,y The screen co-ordinates for the bottom left corner of the window
* @param[in] font The font to use * @param[in] width The width of the window
* @param[in] type The type of button * @param[in] height The height of the window
* @note The drawing color gets set to White and the background drawing color to Black. * @param[in] font The font to use
* @note The dimensions and position may be changed to fit on the real screen. * @param[in] type The type of button
* @note The button is not automatically drawn. Call gwinButtonDraw() after changing the button style or setting the text. * @note The drawing color gets set to White and the background drawing color to Black.
* * @note The dimensions and position may be changed to fit on the real screen.
* @api * @note The button is not automatically drawn. Call gwinButtonDraw() after changing the button style or setting the text.
*/ *
GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type); * @api
*/
/** GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type);
* @brief Set the style of a button.
* @details The button style is defined by its shape and colours. /**
* * @brief Set the style of a button.
* @param[in] gh The window handle (must be a button window) * @details The button style is defined by its shape and colours.
* @param[in] style The button style to set. *
* @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button style * @param[in] gh The window handle (must be a button window)
* * @param[in] shape The shape of the button.
* @api * @param[in] pUp The styling for the button when in the up state.
*/ * @param[in] pDown The styling for the button when in the down state.
void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style); *
* @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
* @brief Set the text of a button. * maintain a static style structures.
* * @note The pUp and pDown parameters can be NULL. If they are then the existing color styles
* @param[in] gh The window handle (must be a button window) * are not changed for that button state.
* @param[in] txt The button text to set. This must be a constant string unless useAlloc is set. *
* @param[in] useAlloc If TRUE the string specified will be copied into dynamically allocated memory. * @api
* @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button text. */
* void gwinSetButtonStyle(GHandle gh, GButtonShape shape, const GButtonDrawStyle *pUp, const GButtonDrawStyle *pDown);
* @api
*/ /**
void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc); * @brief Set the text of a button.
*
/** * @param[in] gh The window handle (must be a button window)
* @brief Redraw the button. * @param[in] txt The button text to set. This must be a constant string unless useAlloc is set.
* * @param[in] useAlloc If TRUE the string specified will be copied into dynamically allocated memory.
* @param[in] gh The window handle (must be a button window) * @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button text.
* *
* @api * @api
*/ */
void gwinButtonDraw(GHandle gh); void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc);
#define gwinGetButtonState(gh) (((GButtonObject *)(gh))->state) /**
* @brief Redraw the button.
/** *
* @brief Get the source handle of a button * @param[in] gh The window handle (must be a button window)
* @details Get the source handle of a button so the application can listen for events *
* * @api
* @param[in] gh The Hanlde */
*/ void gwinButtonDraw(GHandle gh);
#define gwinGetButtonSource(gh) ((GSourceHandle)(gh))
/**
#if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE * @brief Set the callback routine to perform a custom button drawing.
/** *
* @brief Attach a mouse source * @param[in] gh The window handle (must be a button window)
* @details Attach a mouse source to a given button * @param[in] fn The function to use to draw the button
* * @param[in] param A parameter to pass to the button drawing function
* @param[in] gh The button handle *
* @param[in] gsh The source handle * @api
* */
* @return void gwinSetButtonCustom(GHandle gh, GButtonDrawFunction fn, void *param);
*/
bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh); #define gwinGetButtonState(gh) (((GButtonObject *)(gh))->state)
#endif
/**
#if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE * @brief Get the source handle of a button
/** * @details Get the source handle of a button so the application can listen for events
* @brief Attach a toggle source *
* @details Attach a toggle source to this button * @param[in] gh The window handle
* *
* @gh The button handle * @api
* @gsh The source handle */
* #define gwinGetButtonSource(gh) ((GSourceHandle)(gh))
* @return
*/ #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE
bool_t gwinAttachButtonToggleSource(GHandle gh, GSourceHandle gsh); /**
#endif * @brief Attach a mouse source
* @details Attach a mouse source to a given button
#ifdef __cplusplus *
} * @param[in] gh The button handle
#endif * @param[in] gsh The source handle
*
#endif /* GWIN_NEED_BUTTON */ * @api
*/
#endif /* _GWIN_BUTTON_H */ bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh);
/** @} */ #endif
#if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE
/**
* @brief Attach a toggle source
* @details Attach a toggle source to this button
*
* @param[in] gh The button handle
* @param[in] gsh The source handle
*
* @api
*/
bool_t gwinAttachButtonToggleSource(GHandle gh, GSourceHandle gsh);
#endif
/**
* @brief Standard button drawing routines
* @details These routines are called to draw the standard button styles.
*
* @param[in] gh The button handle
* @param[in] isdown Is the button currently down (depressed)
* @param[in] pstyle The current drawing style for the state we are in
* @param[in] param A parameter passed in from the user
*
* @note In your custom button 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. It is there
* only to ensure the functions match the GButtonDrawFunction type.
* @note When called by a button press/release the framework ensure that it is
* a button object and sets up clipping to the button object window. These
* drawing routines then don't have to worry about explicitly doing that.
*
* @api
* @{
*/
void gwinButtonDraw_3D(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_Square(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
#if GDISP_NEED_ARC || defined(__DOXYGEN__)
void gwinButtonDraw_Rounded(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
#endif
#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
void gwinButtonDraw_Ellipse(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
#endif
#if GDISP_NEED_CONVEX_POLYGON || defined(__DOXYGEN__)
void gwinButtonDraw_ArrowUp(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_ArrowDown(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_ArrowLeft(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_ArrowRight(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
#endif
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* GWIN_NEED_BUTTON */
#endif /* _GWIN_BUTTON_H */
/** @} */

View file

@ -33,15 +33,23 @@
#if (GFX_USE_GWIN && GWIN_NEED_BUTTON) || defined(__DOXYGEN__) #if (GFX_USE_GWIN && GWIN_NEED_BUTTON) || defined(__DOXYGEN__)
/* Parameters for various shapes */
#define RND_CNR_SIZE 5 // Rounded corner size for rounded buttons
#define ARROWHEAD_DIVIDER 4 // A quarter of the height for the arrow head
#define ARROWBODY_DIVIDER 4 // A quarter of the width for the arrow body
#include <string.h> #include <string.h>
#include "gwin/internal.h" #include "gwin/internal.h"
static const GButtonStyle GButtonDefaultStyle = { #define GWIN_BUTTON_DEFAULT_SHAPE GBTN_3D
GBTN_3D,
static const GButtonDrawStyle GButtonDefaultStyleUp = {
HTML2COLOR(0x404040), // color_up_edge; HTML2COLOR(0x404040), // color_up_edge;
HTML2COLOR(0xE0E0E0), // color_up_fill; HTML2COLOR(0xE0E0E0), // color_up_fill;
HTML2COLOR(0x000000), // color_up_txt; HTML2COLOR(0x000000), // color_up_txt;
};
static const GButtonDrawStyle GButtonDefaultStyleDown = {
HTML2COLOR(0x404040), // color_dn_edge; HTML2COLOR(0x404040), // color_dn_edge;
HTML2COLOR(0x808080), // color_dn_fill; HTML2COLOR(0x808080), // color_dn_fill;
HTML2COLOR(0x404040), // color_dn_txt; HTML2COLOR(0x404040), // color_dn_txt;
@ -139,8 +147,10 @@ GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width,
if (!(gb = (GButtonObject *)_gwinInit((GWindowObject *)gb, x, y, width, height, sizeof(GButtonObject)))) if (!(gb = (GButtonObject *)_gwinInit((GWindowObject *)gb, x, y, width, height, sizeof(GButtonObject))))
return 0; return 0;
gb->gwin.type = GW_BUTTON; gb->gwin.type = GW_BUTTON;
gb->fn = 0;
gb->param = 0;
gwinSetFont(&gb->gwin, font); gwinSetFont(&gb->gwin, font);
gwinSetButtonStyle(&gb->gwin, &GButtonDefaultStyle); gwinSetButtonStyle(&gb->gwin, GWIN_BUTTON_DEFAULT_SHAPE, &GButtonDefaultStyleUp, &GButtonDefaultStyleDown);
gb->type = type; gb->type = type;
gb->state = GBTN_UP; gb->state = GBTN_UP;
gb->txt = ""; gb->txt = "";
@ -149,18 +159,41 @@ GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width,
return (GHandle)gb; return (GHandle)gb;
} }
void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style) { void gwinSetButtonStyle(GHandle gh, GButtonShape shape, const GButtonDrawStyle *pUp, const GButtonDrawStyle *pDown) {
#define gbw ((GButtonObject *)gh) #define gbw ((GButtonObject *)gh)
if (gh->type != GW_BUTTON) if (gh->type != GW_BUTTON)
return; return;
gbw->style.shape = style->shape; switch(shape) {
gbw->style.color_up_edge = style->color_up_edge; case GBTN_SQUARE: gbw->fn = gwinButtonDraw_Square; break;
gbw->style.color_up_fill = style->color_up_fill; #if GDISP_NEED_ARC
gbw->style.color_dn_edge = style->color_dn_edge; case GBTN_ROUNDED: gbw->fn = gwinButtonDraw_Rounded; break;
gbw->style.color_dn_fill = style->color_dn_fill; #endif
gbw->style.color_up_txt = style->color_up_txt; #if GDISP_NEED_ELLIPSE
gbw->style.color_dn_txt = style->color_dn_txt; case GBTN_ELLIPSE: gbw->fn = gwinButtonDraw_Ellipse; break;
#endif
#if GDISP_NEED_CONVEX_POLYGON
case GBTN_ARROW_UP: gbw->fn = gwinButtonDraw_ArrowUp; break;
case GBTN_ARROW_DOWN: gbw->fn = gwinButtonDraw_ArrowDown; break;
case GBTN_ARROW_LEFT: gbw->fn = gwinButtonDraw_ArrowLeft; break;
case GBTN_ARROW_RIGHT: gbw->fn = gwinButtonDraw_ArrowRight; break;
#endif
case GBTN_CUSTOM: if (gbw->fn) break; /* Fall Through */
case GBTN_3D: /* Fall through */
default: gbw->fn = gwinButtonDraw_3D; break;
}
if (pUp) {
gbw->up.color_edge = pUp->color_edge;
gbw->up.color_fill = pUp->color_fill;
gbw->up.color_txt = pUp->color_txt;
}
if (pDown) {
gbw->dn.color_edge = pDown->color_edge;
gbw->dn.color_fill = pDown->color_fill;
gbw->dn.color_txt = pDown->color_txt;
}
#undef gbw #undef gbw
} }
@ -193,12 +226,7 @@ void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc) {
} }
void gwinButtonDraw(GHandle gh) { void gwinButtonDraw(GHandle gh) {
color_t cedge;
color_t cfill;
color_t ctxt;
const char * txt;
#define gbw ((GButtonObject *)gh) #define gbw ((GButtonObject *)gh)
#define RND_CNR_SIZE 5
if (gh->type != GW_BUTTON) if (gh->type != GW_BUTTON)
return; return;
@ -206,56 +234,146 @@ void gwinButtonDraw(GHandle gh) {
#if GDISP_NEED_CLIP #if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height); gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif #endif
// Get the text (safely) gbw->fn(gh,
txt = gh->font && gbw->txt ? gbw->txt : ""; gbw->state == GBTN_DOWN,
gh->font && gbw->txt ? gbw->txt : "",
// Determine the colors to use gbw->state == GBTN_DOWN ? &gbw->dn : &gbw->up,
switch(gbw->state) { gbw->param);
case GBTN_DOWN:
cedge = gbw->style.color_dn_edge;
cfill = gbw->style.color_dn_fill;
ctxt = gbw->style.color_dn_txt;
break;
case GBTN_UP: default:
cedge = gbw->style.color_up_edge;
cfill = gbw->style.color_up_fill;
ctxt = gbw->style.color_up_txt;
break;
}
// Draw according to the shape specified.
switch(gbw->style.shape) {
#if GDISP_NEED_ARC
case GBTN_ROUNDED:
if (gh->width >= 2*RND_CNR_SIZE+10) {
gdispFillRoundedBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, RND_CNR_SIZE-1, cfill);
gdispDrawStringBox(gh->x+1, gh->y+RND_CNR_SIZE, gh->width-2, gh->height-(2*RND_CNR_SIZE), txt, gh->font, ctxt, justifyCenter);
gdispDrawRoundedBox(gh->x, gh->y, gh->width, gh->height, RND_CNR_SIZE, cedge);
break;
}
/* Fall Through */
#endif
case GBTN_SQUARE:
gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, cfill, justifyCenter);
gdispDrawBox(gh->x, gh->y, gh->width, gh->height, cedge);
break;
#if GDISP_NEED_ELLIPSE
case GBTN_ELLIPSE:
gdispFillEllipse(gh->x+1, gh->y+1, gh->width/2-1, gh->height/2-1, cfill);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, justifyCenter);
gdispDrawEllipse(gh->x, gh->y, gh->width/2, gh->height/2, cedge);
break;
#endif
case GBTN_3D: default:
gdispFillStringBox(gh->x, gh->y, gh->width-1, gh->height-1, txt, gh->font, ctxt, cfill, justifyCenter);
gdispDrawLine(gh->x+gh->width-1, gh->y, gh->x+gh->width-1, gh->y+gh->height-1, cedge);
gdispDrawLine(gh->x, gh->y+gh->height-1, gh->x+gh->width-2, gh->y+gh->height-1, cedge);
break;
}
#undef gbw #undef gbw
} }
void gwinSetButtonCustom(GHandle gh, GButtonDrawFunction fn, void *param) {
#define gbw ((GButtonObject *)gh)
if (gh->type != GW_BUTTON)
return;
gbw->fn = fn ? fn : gwinButtonDraw_3D;
gbw->param = param;
#undef gbw
}
void gwinButtonDraw_3D(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) isdown;
(void) param;
gdispFillStringBox(gh->x, gh->y, gh->width-1, gh->height-1, txt, gh->font, pstyle->color_txt, pstyle->color_fill, justifyCenter);
gdispDrawLine(gh->x+gh->width-1, gh->y, gh->x+gh->width-1, gh->y+gh->height-1, pstyle->color_edge);
gdispDrawLine(gh->x, gh->y+gh->height-1, gh->x+gh->width-2, gh->y+gh->height-1, pstyle->color_edge);
}
void gwinButtonDraw_Square(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) isdown;
(void) param;
gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, pstyle->color_fill, justifyCenter);
gdispDrawBox(gh->x, gh->y, gh->width, gh->height, pstyle->color_edge);
}
#if GDISP_NEED_ARC
void gwinButtonDraw_Rounded(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) isdown;
(void) param;
if (gh->width >= 2*RND_CNR_SIZE+10) {
gdispFillRoundedBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, RND_CNR_SIZE-1, pstyle->color_fill);
gdispDrawStringBox(gh->x+1, gh->y+RND_CNR_SIZE, gh->width-2, gh->height-(2*RND_CNR_SIZE), txt, gh->font, pstyle->color_txt, justifyCenter);
gdispDrawRoundedBox(gh->x, gh->y, gh->width, gh->height, RND_CNR_SIZE, pstyle->color_edge);
} else {
gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, pstyle->color_fill, justifyCenter);
gdispDrawBox(gh->x, gh->y, gh->width, gh->height, pstyle->color_edge);
}
}
#endif
#if GDISP_NEED_ELLIPSE
void gwinButtonDraw_Ellipse(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) isdown;
(void) param;
gdispFillEllipse(gh->x+1, gh->y+1, gh->width/2-1, gh->height/2-1, pstyle->color_fill);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
gdispDrawEllipse(gh->x, gh->y, gh->width/2, gh->height/2, pstyle->color_edge);
}
#endif
#if GDISP_NEED_CONVEX_POLYGON
void gwinButtonDraw_ArrowUp(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) isdown;
(void) param;
point arw[7];
arw[0].x = gh->x+gh->width/2; arw[0].y = gh->y;
arw[1].x = gh->x+gh->width-1; arw[1].y = gh->y+gh->height/ARROWHEAD_DIVIDER;
arw[2].x = gh->x+(gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[2].y = gh->y+gh->height/ARROWHEAD_DIVIDER;
arw[3].x = gh->x+(gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[3].y = gh->y+gh->height-1;
arw[4].x = gh->x+(gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[4].y = gh->y+gh->height-1;
arw[5].x = gh->x+(gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[5].y = gh->y+gh->height/ARROWHEAD_DIVIDER;
arw[6].x = gh->x; arw[6].y = gh->y+gh->height/ARROWHEAD_DIVIDER;
gdispFillConvexPoly(arw, 7, pstyle->color_fill);
gdispDrawPoly(arw, 7, pstyle->color_edge);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
}
void gwinButtonDraw_ArrowDown(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) isdown;
(void) param;
point arw[7];
arw[0].x = gh->x+gh->width/2; arw[0].y = gh->y+gh->height-1;
arw[1].x = gh->x+gh->width-1; arw[1].y = gh->y+gh->height-1-gh->height/ARROWHEAD_DIVIDER;
arw[2].x = gh->x+(gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[2].y = gh->y+gh->height-1-gh->height/ARROWHEAD_DIVIDER;
arw[3].x = gh->x+(gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[3].y = gh->y;
arw[4].x = gh->x+(gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[4].y = gh->y;
arw[5].x = gh->x+(gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[5].y = gh->y+gh->height-1-gh->height/ARROWHEAD_DIVIDER;
arw[6].x = gh->x; arw[6].y = gh->y+gh->height-1-gh->height/ARROWHEAD_DIVIDER;
gdispFillConvexPoly(arw, 7, pstyle->color_fill);
gdispDrawPoly(arw, 7, pstyle->color_edge);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
}
void gwinButtonDraw_ArrowLeft(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) isdown;
(void) param;
point arw[7];
arw[0].x = gh->x; arw[0].y = gh->y+gh->height/2;
arw[1].x = gh->x+gh->width/ARROWHEAD_DIVIDER; arw[1].y = gh->y;
arw[2].x = gh->x+gh->width/ARROWHEAD_DIVIDER; arw[2].y = gh->y+(gh->height - gh->height/ARROWBODY_DIVIDER)/2;
arw[3].x = gh->x+gh->width-1; arw[3].y = gh->y+(gh->height - gh->height/ARROWBODY_DIVIDER)/2;
arw[4].x = gh->x+gh->width-1; arw[4].y = gh->y+(gh->height + gh->height/ARROWBODY_DIVIDER)/2;
arw[5].x = gh->x+gh->width/ARROWHEAD_DIVIDER; arw[5].y = gh->y+(gh->height + gh->height/ARROWBODY_DIVIDER)/2;
arw[6].x = gh->x+gh->width/ARROWHEAD_DIVIDER; arw[6].y = gh->y+gh->height-1;
gdispFillConvexPoly(arw, 7, pstyle->color_fill);
gdispDrawPoly(arw, 7, pstyle->color_edge);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
}
void gwinButtonDraw_ArrowRight(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) isdown;
(void) param;
point arw[7];
arw[0].x = gh->x+gh->width-1; arw[0].y = gh->y+gh->height/2;
arw[1].x = gh->x+gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[1].y = gh->y;
arw[2].x = gh->x+gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[2].y = gh->y+(gh->height - gh->height/ARROWBODY_DIVIDER)/2;
arw[3].x = gh->x; arw[3].y = gh->y+(gh->height - gh->height/ARROWBODY_DIVIDER)/2;
arw[4].x = gh->x; arw[4].y = gh->y+(gh->height + gh->height/ARROWBODY_DIVIDER)/2;
arw[5].x = gh->x+gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[5].y = gh->y+(gh->height + gh->height/ARROWBODY_DIVIDER)/2;
arw[6].x = gh->x+gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[6].y = gh->y+gh->height-1;
gdispFillConvexPoly(arw, 7, pstyle->color_fill);
gdispDrawPoly(arw, 7, pstyle->color_edge);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
}
#endif
#if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE
bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh) { bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh) {
if (gh->type != GW_BUTTON) if (gh->type != GW_BUTTON)