kpmpgsmkii/client/src/gui/button.c
2021-11-07 18:45:50 -06:00

142 lines
4.2 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 buttonDel(WidgetT **widget);
static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
static void buttonPaint(WidgetT *widget, RectT pos);
void buttonClickHandlerSet(ButtonT *button, widgetCallback callback) {
button->clicked = callback;
}
static void buttonDel(WidgetT **widget) {
ButtonT *b = (ButtonT *)*widget;
if (b->title) free(b->title);
free(b);
b = NULL;
}
WidgetT *buttonInit(WidgetT *button, char *title, widgetCallback callback) {
ButtonT *b = (ButtonT *)button;
b->base.delMethod = buttonDel;
b->base.paintMethod = buttonPaint;
b->base.mouseEventMethod = buttonMouseEvent;
b->title = NULL;
buttonClickHandlerSet(b, callback);
// Width is set in buttonSetTitle
buttonTitleSet(b, title);
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;
uint16_t h = fontHeightGet(_guiFont) + (_guiMetric[METRIC_BUTTON_VERTICAL_PADDING] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2);
if (!button) return NULL;
// Width is set in Init.
widget = widgetInit(W(button), MAGIC_BUTTON, x, y, 0, h, 0, 0, 0, 0);
if (!widget) {
free(button);
return NULL;
}
button = (ButtonT *)buttonInit((WidgetT *)button, title, callback);
return button;
}
static void buttonPaint(WidgetT *widget, RectT pos) {
ButtonT *b;
int16_t i;
int8_t active;
ColorT highlight;
ColorT shadow;
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
b = (ButtonT *)widget;
active = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE);
highlight = active ? _guiColor[COLOR_BUTTON_SHADOW] : _guiColor[COLOR_BUTTON_HIGHLIGHT];
shadow = active ? _guiColor[COLOR_BUTTON_HIGHLIGHT] : _guiColor[COLOR_BUTTON_SHADOW];
// Draw bezel.
for (i=0; i<_guiMetric[METRIC_BUTTON_BEZEL_SIZE]; i++) {
surfaceHighlightFrameDraw(pos.x + i, pos.y + i, pos.x + pos.w - i, pos.y + pos.h - i, highlight, shadow);
}
// Draw background (depends on x from above).
surfaceRectangleFilledDraw(pos.x + i, pos.y + i, pos.x + pos.w - i, pos.y + pos.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], pos.x + i + _guiMetric[METRIC_BUTTON_HORIZONTAL_PADDING] + active, pos.y + i + _guiMetric[METRIC_BUTTON_VERTICAL_PADDING] + active);
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
}
}
void buttonTitleSet(ButtonT *button, char *title) {
if (button->title) free(button->title);
button->title = strdup(title);
button->base.pos.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);
}