mirror of
https://git.planet-casio.com/Lephenixnoir/JustUI.git
synced 2025-06-06 05:25:10 +02:00
jbutton: add new bare-bones button widget for touch
This commit is contained in:
parent
bd89221d33
commit
b75c8979ba
3 changed files with 199 additions and 0 deletions
|
@ -34,6 +34,7 @@ add_library(${NAME} STATIC
|
||||||
src/jframe.c
|
src/jframe.c
|
||||||
src/jlist.c
|
src/jlist.c
|
||||||
src/jscrolledlist.c
|
src/jscrolledlist.c
|
||||||
|
src/jbutton.c
|
||||||
src/vec.c
|
src/vec.c
|
||||||
src/keymap.c
|
src/keymap.c
|
||||||
${ASSETS_${FXSDK_PLATFORM}}
|
${ASSETS_${FXSDK_PLATFORM}}
|
||||||
|
|
59
include/justui/jbutton.h
Normal file
59
include/justui/jbutton.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
//---
|
||||||
|
// JustUI.jbutton: Touchable multi-state click button
|
||||||
|
//---
|
||||||
|
|
||||||
|
#ifndef _J_JBUTTON
|
||||||
|
#define _J_JBUTTON
|
||||||
|
|
||||||
|
#include <justui/defs.h>
|
||||||
|
#include <justui/jwidget.h>
|
||||||
|
|
||||||
|
#include <gint/display.h>
|
||||||
|
|
||||||
|
/* jbutton: Button with multiple states
|
||||||
|
|
||||||
|
This widget is your everyday interactible button. It responds to touch by
|
||||||
|
changing its background color for idle, focused and active states. It also
|
||||||
|
has a disabled states which can be used to make a "selected" visual.
|
||||||
|
|
||||||
|
TODO: Allow jbutton it to hold any widget inside.
|
||||||
|
TODO: jbutton's focus state is untested since I only tested touch.
|
||||||
|
|
||||||
|
Events:
|
||||||
|
* JBUTTON_TRIGGERED when activated. */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
JBUTTON_IDLE,
|
||||||
|
JBUTTON_ACTIVE,
|
||||||
|
JBUTTON_DISABLED,
|
||||||
|
|
||||||
|
JBUTTON_STATE_NUM,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
jwidget widget;
|
||||||
|
|
||||||
|
/* Text shown on the button; not owned by the button */
|
||||||
|
char const *text;
|
||||||
|
/* Rendering font */
|
||||||
|
font_t const *font;
|
||||||
|
/* Colors for all states */
|
||||||
|
color_t fg_colors[JBUTTON_STATE_NUM];
|
||||||
|
color_t bg_colors[JBUTTON_STATE_NUM];
|
||||||
|
/* Current state */
|
||||||
|
int state;
|
||||||
|
|
||||||
|
} jbutton;
|
||||||
|
|
||||||
|
/* Event IDs */
|
||||||
|
extern uint16_t JBUTTON_TRIGGERED;
|
||||||
|
|
||||||
|
/* jbutton_create(): Create a button */
|
||||||
|
jbutton *jbutton_create(char const *text, void *parent);
|
||||||
|
|
||||||
|
/* Trivial properties */
|
||||||
|
void jbutton_set_text(jbutton *b, char const *text);
|
||||||
|
void jbutton_set_font(jbutton *b, font_t const *font);
|
||||||
|
void jbutton_set_disabled(jbutton *b, bool disabled);
|
||||||
|
|
||||||
|
#endif /* _J_JBUTTON */
|
139
src/jbutton.c
Normal file
139
src/jbutton.c
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
#include <justui/jwidget.h>
|
||||||
|
#include <justui/jwidget-api.h>
|
||||||
|
#include <justui/jbutton.h>
|
||||||
|
#include <justui/config.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
J_DEFINE_WIDGET(jbutton, csize, render, event)
|
||||||
|
J_DEFINE_EVENTS(JBUTTON_TRIGGERED)
|
||||||
|
|
||||||
|
static void jbutton_set_state(jbutton *b, int state)
|
||||||
|
{
|
||||||
|
if((uint)state >= JBUTTON_STATE_NUM || b->state == state)
|
||||||
|
return;
|
||||||
|
b->state = state;
|
||||||
|
jwidget_set_background(b, b->bg_colors[state]);
|
||||||
|
b->widget.update = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
jbutton *jbutton_create(char const *text, void *parent)
|
||||||
|
{
|
||||||
|
if(jbutton_type_id < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
jbutton *b = malloc(sizeof *b);
|
||||||
|
if(!b)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
jwidget_init(&b->widget, jbutton_type_id, parent);
|
||||||
|
jwidget_set_focus_policy(b, J_FOCUS_POLICY_ACCEPT);
|
||||||
|
|
||||||
|
b->text = text ? text : "";
|
||||||
|
b->font = dfont_default();
|
||||||
|
|
||||||
|
#if GINT_RENDER_MONO
|
||||||
|
b->fg_colors[JBUTTON_IDLE] = C_WHITE;
|
||||||
|
b->fg_colors[JBUTTON_ACTIVE] = C_WHITE;
|
||||||
|
b->fg_colors[JBUTTON_DISABLED] = C_BLACK;
|
||||||
|
b->bg_colors[JBUTTON_IDLE] = C_BLACK;
|
||||||
|
b->bg_colors[JBUTTON_ACTIVE] = C_BLACK;
|
||||||
|
b->bg_colors[JBUTTON_DISABLED] = C_WHITE;
|
||||||
|
jwidget_set_padding(b, 1, 2, 1, 2);
|
||||||
|
#endif
|
||||||
|
#if GINT_RENDER_RGB
|
||||||
|
b->fg_colors[JBUTTON_IDLE] = C_WHITE;
|
||||||
|
b->fg_colors[JBUTTON_ACTIVE] = C_WHITE;
|
||||||
|
b->fg_colors[JBUTTON_DISABLED] = C_RGB(8, 8, 8);
|
||||||
|
b->bg_colors[JBUTTON_IDLE] = C_BLACK;
|
||||||
|
b->bg_colors[JBUTTON_ACTIVE] = C_RGB(8, 8, 8);
|
||||||
|
b->bg_colors[JBUTTON_DISABLED] = C_RGB(24, 24, 24);
|
||||||
|
jwidget_set_padding(b, 2, 4, 2, 4);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
jbutton_set_state(b, JBUTTON_IDLE);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jbutton_set_text(jbutton *b, char const *text)
|
||||||
|
{
|
||||||
|
b->text = text ? text : "";
|
||||||
|
b->widget.dirty = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jbutton_set_font(jbutton *b, font_t const *font)
|
||||||
|
{
|
||||||
|
b->font = font ? font : dfont_default();
|
||||||
|
b->widget.dirty = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jbutton_set_disabled(jbutton *b, bool disabled)
|
||||||
|
{
|
||||||
|
if(disabled)
|
||||||
|
jbutton_set_state(b, JBUTTON_DISABLED);
|
||||||
|
else if(b->state == JBUTTON_DISABLED)
|
||||||
|
jbutton_set_state(b, JBUTTON_IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Polymorphic widget operations
|
||||||
|
//---
|
||||||
|
|
||||||
|
void jbutton_poly_csize(void *b0)
|
||||||
|
{
|
||||||
|
jbutton *b = b0;
|
||||||
|
int w, h;
|
||||||
|
dsize(b->text, b->font ? b->font : dfont_default(), &w, &h);
|
||||||
|
b->widget.w = w;
|
||||||
|
b->widget.h = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jbutton_poly_render(void *b0, int x, int y)
|
||||||
|
{
|
||||||
|
jbutton *b = b0;
|
||||||
|
int cw = jwidget_content_width(b);
|
||||||
|
int ch = jwidget_content_height(b);
|
||||||
|
|
||||||
|
int fg = b->fg_colors[b->state];
|
||||||
|
font_t const *old_font = dfont(b->font);
|
||||||
|
dtext_opt(x + cw / 2, y + ch / 2, fg, C_NONE, DTEXT_CENTER, DTEXT_MIDDLE,
|
||||||
|
b->text, -1);
|
||||||
|
dfont(old_font);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool jbutton_poly_event(void *b0, jevent e)
|
||||||
|
{
|
||||||
|
jbutton *b = b0;
|
||||||
|
key_event_t ev = { .type = KEYEV_NONE };
|
||||||
|
if(e.type == JWIDGET_KEY)
|
||||||
|
ev = e.key;
|
||||||
|
|
||||||
|
#if J_CONFIG_TOUCH
|
||||||
|
bool accepts_touch = b->state != JBUTTON_DISABLED;
|
||||||
|
if((ev.type == KEYEV_TOUCH_DOWN || ev.type == KEYEV_TOUCH_DRAG ||
|
||||||
|
ev.type == KEYEV_TOUCH_UP) && accepts_touch) {
|
||||||
|
int lx = ev.x - jwidget_absolute_padding_x(b);
|
||||||
|
int ly = ev.y - jwidget_absolute_padding_y(b);
|
||||||
|
uint cw = jwidget_padding_width(b);
|
||||||
|
uint ch = jwidget_padding_height(b);
|
||||||
|
bool inside = (uint)lx < cw && (uint)ly < ch;
|
||||||
|
|
||||||
|
if(ev.type == KEYEV_TOUCH_DOWN)
|
||||||
|
jbutton_set_state(b, JBUTTON_ACTIVE);
|
||||||
|
if(ev.type == KEYEV_TOUCH_DRAG)
|
||||||
|
jbutton_set_state(b, inside ? JBUTTON_ACTIVE : JBUTTON_IDLE);
|
||||||
|
if(ev.type == KEYEV_TOUCH_UP && b->state == JBUTTON_ACTIVE) {
|
||||||
|
jbutton_set_state(b, JBUTTON_IDLE);
|
||||||
|
jwidget_emit(b, (jevent){ .type = JBUTTON_TRIGGERED });
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(ev.type == KEYEV_DOWN && (ev.key == KEY_EXE || ev.key == KEY_OK)) {
|
||||||
|
jwidget_emit(b, (jevent){ .type = JBUTTON_TRIGGERED });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return jwidget_poly_event(b, e);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue