kpmpgsmkii/client/src/gui/button.c

139 lines
4.3 KiB
C

/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "button.h"
static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
static void buttonPaint(WidgetT *widget);
void buttonDel(WidgetT **widget) {
ButtonT *b = (ButtonT *)*widget;
if (b->title) free(b->title);
free(b);
b = NULL;
}
WidgetT *buttonInit(WidgetT *button, uint16_t x, uint16_t y, char *title, widgetCallback callback) {
ButtonT *b = (ButtonT *)button;
b->base.magic = MAGIC_BUTTON;
b->base.x = x;
b->base.y = y;
b->base.delMethod = buttonDel;
b->base.paintMethod = buttonPaint;
b->base.mouseEventMethod = buttonMouseEvent;
b->title = NULL;
buttonSetClickHandler(b, callback);
buttonSetTitle(b, title);
// Width is set in buttonSetTitle
b->base.h = fontHeightGet(_guiFont) + (_guiMetric[METRIC_BUTTON_VERTICAL_PADDING] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2);
return button;
}
static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event) {
ButtonT *b = (ButtonT *)widget;
(void)x;
(void)y;
(void)mouse;
// Button pressed?
if (event == MOUSE_EVENT_LEFT_HOLD) {
if (!GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE)) {
GUI_SET_FLAG(widget, WIDGET_FLAG_ACTIVE);
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
}
} else {
if (GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE)) {
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_ACTIVE);
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
}
}
// Fire callback on mouse up.
if (event == MOUSE_EVENT_LEFT_UP) {
if (b->clicked) b->clicked(widget);
}
}
ButtonT *buttonNew(uint16_t x, uint16_t y, char *title, widgetCallback callback) {
ButtonT *button = (ButtonT *)malloc(sizeof(ButtonT));
WidgetT *widget = NULL;
if (!button) return NULL;
widget = widgetInit((WidgetT *)button);
if (!widget) {
free(button);
return NULL;
}
button = (ButtonT *)buttonInit((WidgetT *)button, x, y, title, callback);
return button;
}
static void buttonPaint(WidgetT *widget) {
ButtonT *b = (ButtonT *)widget;
int16_t i;
int8_t active = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE);
ColorT highlight = active ? _guiColor[COLOR_BUTTON_SHADOW] : _guiColor[COLOR_BUTTON_HIGHLIGHT];
ColorT shadow = active ? _guiColor[COLOR_BUTTON_HIGHLIGHT] : _guiColor[COLOR_BUTTON_SHADOW] ;
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
vbeSurfaceSet(b->base.surface);
// Draw bezel.
for (i=0; i<_guiMetric[METRIC_BUTTON_BEZEL_SIZE]; i++) {
guiDrawHighlightFrame(b->base.x + i, b->base.y + i, b->base.x + b->base.w - i, b->base.y + b->base.h - i, highlight, shadow);
}
// Draw background (depends on x from above).
guiDrawRectangleFilled(b->base.x + i, b->base.y + i, b->base.x + b->base.w - i, b->base.y + b->base.h - i, _guiColor[COLOR_BUTTON_BACKGROUND]);
// Draw title (depends on x from above).
fontRender(_guiFont, b->title, _guiColor[COLOR_BUTTON_TEXT], _guiColor[COLOR_BUTTON_BACKGROUND], b->base.x + i + _guiMetric[METRIC_BUTTON_HORIZONTAL_PADDING] + active, b->base.y + i + _guiMetric[METRIC_BUTTON_VERTICAL_PADDING] + active);
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
}
}
void buttonSetClickHandler(ButtonT *button, widgetCallback callback) {
button->clicked = callback;
}
void buttonSetTitle(ButtonT *button, char *title) {
if (button->title) free(button->title);
button->title = strdup(title);
button->base.w = (strlen(title) * fontWidthGet(_guiFont)) + (_guiMetric[METRIC_BUTTON_HORIZONTAL_PADDING] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2);
GUI_SET_FLAG((WidgetT *)button, WIDGET_FLAG_DIRTY);
}