2025-10-03 20:16:11 +02:00
|
|
|
#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[0] = pgpl_color_divide(base_color, 5);
|
|
|
|
|
theme->widget_background_color[1] = pgpl_color_divide(base_color, 4);
|
|
|
|
|
theme->widget_background_color[2] = pgpl_color_divide(base_color, 3);
|
|
|
|
|
|
|
|
|
|
theme->text_color[0] = pgpl_color_divide(base_color, 1.5);
|
|
|
|
|
theme->text_color[1] = pgpl_color_divide(base_color, 1.25);
|
|
|
|
|
theme->text_color[2] = base_color;
|
|
|
|
|
|
|
|
|
|
theme->font_size[0] = content_font_size * 3;
|
|
|
|
|
theme->font_size[1] = content_font_size * 2;
|
|
|
|
|
theme->font_size[2] = content_font_size;
|
|
|
|
|
|
|
|
|
|
theme->margin.top = content_font_size / 6;
|
|
|
|
|
theme->margin.left = theme->margin.top;
|
|
|
|
|
theme->margin.bottom = theme->margin.top;
|
|
|
|
|
theme->margin.right = theme->margin.top;
|
|
|
|
|
|
|
|
|
|
theme->border.top = content_font_size / 12;
|
|
|
|
|
theme->border.left = theme->border.top;
|
|
|
|
|
theme->border.bottom = theme->border.top;
|
|
|
|
|
theme->border.right = theme->border.top;
|
|
|
|
|
|
|
|
|
|
theme->padding.top = content_font_size / 6;
|
|
|
|
|
theme->padding.left = theme->padding.top;
|
|
|
|
|
theme->padding.bottom = theme->padding.top;
|
|
|
|
|
theme->padding.right = theme->padding.top;
|
|
|
|
|
|
|
|
|
|
theme->font = font;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-07 21:45:48 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-03 20:16:11 +02:00
|
|
|
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;
|
|
|
|
|
|
2025-10-07 23:39:22 +02:00
|
|
|
if (widget->theme_override) {
|
|
|
|
|
theme = widget->theme_override;
|
2025-10-03 20:16:11 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-07 21:45:48 +02:00
|
|
|
x += widget->offset_x;
|
|
|
|
|
y += widget->offset_y;
|
2025-10-03 20:16:11 +02:00
|
|
|
|
2025-10-07 21:45:48 +02:00
|
|
|
pgpl_gui_widget_max_content_size(widget, theme, &width, &height, max_width,
|
|
|
|
|
max_height);
|
|
|
|
|
|
|
|
|
|
widget->get_content_size(widget, theme, &width, &height, width, height);
|
2025-10-03 20:16:11 +02:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-07 21:45:48 +02:00
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-03 20:16:11 +02:00
|
|
|
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;
|
|
|
|
|
|
2025-10-07 21:45:48 +02:00
|
|
|
return pgpl_gui_widget_within_area(x, y, widget_x, widget_y, max_width,
|
|
|
|
|
max_height);
|
2025-10-03 20:16:11 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-07 23:39:22 +02:00
|
|
|
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;
|
2025-10-03 20:16:11 +02:00
|
|
|
}
|