pgpl/src/gui/helpers.c
2025-10-08 18:22:43 +02:00

255 lines
8.2 KiB
C

#include <pgpl.h>
void pgpl_gui_theme_configure(PGPL_GuiTheme *theme, PGPL_Color base_color,
double content_font_size, PGPL_Font *font) {
theme->background_color = pgpl_color_divide(base_color, 8);
theme->widget_background_color[PGPL_GUI_STATUS_COLOR_NORMAL] =
pgpl_color_divide(base_color, 5);
theme->widget_background_color[PGPL_GUI_STATUS_COLOR_HOVER] =
pgpl_color_divide(base_color, 4);
theme->widget_background_color[PGPL_GUI_STATUS_COLOR_ACTIVE] =
pgpl_color_divide(base_color, 3);
theme->text_color[PGPL_GUI_STATUS_COLOR_NORMAL] =
pgpl_color_divide(base_color, 1.5);
theme->text_color[PGPL_GUI_STATUS_COLOR_HOVER] =
pgpl_color_divide(base_color, 1.25);
theme->text_color[PGPL_GUI_STATUS_COLOR_ACTIVE] = base_color;
theme->font_size[PGPL_GUI_FONT_SIZE_TITLE] = content_font_size * 4;
theme->font_size[PGPL_GUI_FONT_SIZE_HEADING_LARGE] = content_font_size * 3;
theme->font_size[PGPL_GUI_FONT_SIZE_HEADING_SMALL] = content_font_size * 2;
theme->font_size[PGPL_GUI_FONT_SIZE_CONTENT] = content_font_size;
theme->margin.top = content_font_size / 3;
theme->margin.left = theme->margin.top;
theme->margin.bottom = theme->margin.top;
theme->margin.right = theme->margin.top;
theme->border.top = content_font_size / 6;
theme->border.left = theme->border.top;
theme->border.bottom = theme->border.top;
theme->border.right = theme->border.top;
theme->padding.top = content_font_size / 3;
theme->padding.left = theme->padding.top;
theme->padding.bottom = theme->padding.top;
theme->padding.right = theme->padding.top;
theme->font = font;
}
void pgpl_gui_widget_adjust_event_params(PGPL_GuiWidget *widget,
PGPL_GuiTheme *theme, double *x,
double *y, double *max_width,
double *max_height) {
double width, height;
pgpl_gui_widget_max_content_size(widget, theme, &width, &height, *max_width,
*max_height);
widget->get_content_size(widget, theme, &width, &height, width, height);
if (!widget->expand_x) {
*max_width = width;
if (!widget->ignore_margin) {
*max_width += theme->margin.left + theme->margin.right;
}
if (!widget->ignore_border) {
*max_width += theme->border.left + theme->border.right;
}
if (!widget->ignore_padding) {
*max_width += theme->padding.left + theme->padding.right;
}
}
if (!widget->expand_y) {
*max_height = height;
if (!widget->ignore_margin) {
*max_height += theme->margin.top + theme->margin.bottom;
}
if (!widget->ignore_border) {
*max_height += theme->border.top + theme->border.bottom;
}
if (!widget->ignore_padding) {
*max_height += theme->padding.top + theme->padding.bottom;
}
}
if (!widget->ignore_margin) {
*x += theme->margin.left;
*y += theme->margin.top;
*max_width -= theme->margin.left + theme->margin.right;
*max_height -= theme->margin.top + theme->margin.bottom;
}
if (!widget->ignore_border) {
*x += theme->border.left;
*y += theme->border.top;
*max_width -= theme->border.left + theme->border.right;
*max_height -= theme->border.top + theme->border.bottom;
}
if (!widget->ignore_padding) {
*x += theme->padding.left;
*y += theme->padding.top;
*max_width -= theme->padding.left + theme->padding.right;
*max_height -= theme->padding.top + theme->padding.bottom;
}
*x += (*max_width - width) / 2;
*y += (*max_height - height) / 2;
}
void pgpl_gui_widget_max_content_size(PGPL_GuiWidget *widget,
PGPL_GuiTheme *theme, double *width,
double *height, double max_width,
double max_height) {
*width = max_width;
*height = max_height;
if (!widget->ignore_margin) {
*width -= theme->margin.left + theme->margin.right;
*height -= theme->margin.top + theme->margin.bottom;
}
if (!widget->ignore_border) {
*width -= theme->border.left + theme->border.right;
*height -= theme->border.top + theme->border.bottom;
}
if (!widget->ignore_padding) {
*width -= theme->padding.left + theme->padding.right;
*height -= theme->padding.top + theme->padding.bottom;
}
}
void pgpl_gui_widget_render_full(PGPL_GuiWidget *widget,
PGPL_Renderer *renderer, PGPL_GuiTheme *theme,
double x, double y, double max_width,
double max_height) {
double width, height;
if (widget->theme_override) {
theme = widget->theme_override;
}
x += widget->offset_x;
y += widget->offset_y;
pgpl_gui_widget_max_content_size(widget, theme, &width, &height, max_width,
max_height);
widget->get_content_size(widget, theme, &width, &height, width, height);
if (!widget->expand_x) {
max_width = width;
if (!widget->ignore_margin) {
max_width += theme->margin.left + theme->margin.right;
}
if (!widget->ignore_border) {
max_width += theme->border.left + theme->border.right;
}
if (!widget->ignore_padding) {
max_width += theme->padding.left + theme->padding.right;
}
}
if (!widget->expand_y) {
max_height = height;
if (!widget->ignore_margin) {
max_height += theme->margin.top + theme->margin.bottom;
}
if (!widget->ignore_border) {
max_height += theme->border.top + theme->border.bottom;
}
if (!widget->ignore_padding) {
max_height += theme->padding.top + theme->padding.bottom;
}
}
if (!widget->ignore_margin) {
x += theme->margin.left;
y += theme->margin.top;
max_width -= theme->margin.left + theme->margin.right;
max_height -= theme->margin.top + theme->margin.bottom;
}
if (widget->border) {
pgpl_render_rectangle(renderer, theme->text_color[widget->gui_color], x, y,
max_width, max_height);
}
if (!widget->ignore_border) {
x += theme->border.left;
y += theme->border.top;
max_width -= theme->border.left + theme->border.right;
max_height -= theme->border.top + theme->border.bottom;
}
if (widget->background) {
pgpl_render_rectangle(renderer,
theme->widget_background_color[widget->gui_color], x,
y, max_width, max_height);
} else {
pgpl_render_rectangle(renderer, theme->background_color, x, y, max_width,
max_height);
}
if (!widget->ignore_padding) {
x += theme->padding.left;
y += theme->padding.top;
max_width -= theme->padding.left + theme->padding.right;
max_height -= theme->padding.top + theme->padding.bottom;
}
x += (max_width - width) / 2;
y += (max_height - height) / 2;
widget->render_content(widget, renderer, theme, x, y, max_width, max_height);
}
bool pgpl_gui_widget_within_area(double x, double y, double area_x,
double area_y, double area_width,
double area_height) {
return (x >= area_x && x <= (area_x + area_width)) &&
(y >= area_y && y <= (area_y + area_height));
}
bool pgpl_gui_widget_within_bounds(PGPL_GuiWidget *widget, PGPL_GuiTheme *theme,
double widget_x, double widget_y,
double max_width, double max_height,
double x, double y) {
(void)widget;
widget_x += theme->margin.left;
widget_y += theme->margin.top;
max_width -= theme->margin.left + theme->margin.right;
max_height -= theme->margin.top + theme->margin.bottom;
return pgpl_gui_widget_within_area(x, y, widget_x, widget_y, max_width,
max_height);
}
void pgpl_gui_widget_default_config(PGPL_GuiWidget *widget) {
widget->offset_x = 0;
widget->offset_y = 0;
widget->expand_x = true;
widget->expand_y = true;
widget->border = false;
widget->background = false;
widget->font_size = PGPL_GUI_FONT_SIZE_CONTENT;
widget->expansion_fraction = 1;
widget->theme_override = NULL;
widget->ignore_margin = false;
widget->ignore_border = false;
widget->ignore_padding = false;
}