slider widget, tons of fixes and improvements for win32, reworked font loading.

This commit is contained in:
Patrick 2025-10-07 21:45:48 +02:00
commit 69f8a273f3
18 changed files with 452 additions and 90 deletions

201
src/gui/widgets/slider.c Normal file
View file

@ -0,0 +1,201 @@
#include <pgpl.h>
#include <stdlib.h>
static void get_slider_size(PGPL_GuiSliderWidget *slider_widget,
double *slider_x, double *slider_y, double x,
double y, double max_width, double max_height) {
double offset;
if (slider_widget->inversed) {
offset = 1.0 - slider_widget->current_value;
} else {
offset = slider_widget->current_value;
}
if (slider_widget->vertical) {
*slider_x = x - slider_widget->bar_height / 2.0;
*slider_y = y + offset * (max_height - slider_widget->bar_height) -
slider_widget->bar_height / 2.0;
} else {
*slider_x = x + offset * (max_width - slider_widget->bar_height) -
slider_widget->bar_height / 2.0;
*slider_y = y - slider_widget->bar_height / 2.0;
}
}
static void get_content_size(PGPL_GuiWidget *widget, PGPL_GuiTheme *theme,
double *width, double *height, double max_width,
double max_height) {
PGPL_GuiSliderWidget *slider_widget = (PGPL_GuiSliderWidget *)widget;
(void)theme;
if (slider_widget->vertical) {
*width = slider_widget->bar_height;
*height = max_height;
} else {
*width = max_width;
*height = slider_widget->bar_height;
}
}
static void render_content(PGPL_GuiWidget *widget, PGPL_Renderer *renderer,
PGPL_GuiTheme *theme, double x, double y,
double max_width, double max_height) {
PGPL_GuiSliderWidget *slider_widget = (PGPL_GuiSliderWidget *)widget;
double slider_x;
double slider_y;
double completion_x;
double completion_y;
double completion_width;
double completion_height;
get_slider_size(slider_widget, &slider_x, &slider_y, x, y, max_width,
max_height);
if (slider_widget->vertical) {
max_width = slider_widget->bar_height;
} else {
max_height = slider_widget->bar_height;
}
pgpl_render_rectangle(renderer, theme->text_color[widget->gui_color], x, y,
max_width, max_height);
pgpl_render_rectangle(renderer, theme->background_color,
x + slider_widget->bar_height / 4.0,
y + slider_widget->bar_height / 4.0,
max_width - slider_widget->bar_height / 2.0,
max_height - slider_widget->bar_height / 2.0);
max_width -= slider_widget->bar_height / 2.0;
max_height -= slider_widget->bar_height / 2.0;
if (slider_widget->inversed) {
if (slider_widget->vertical) {
completion_x = x + slider_widget->bar_height / 4.0;
completion_y = y + slider_widget->bar_height / 4.0 +
max_height * (1.0 - slider_widget->current_value);
completion_width = max_width;
completion_height = max_height * slider_widget->current_value;
} else {
completion_x = x + slider_widget->bar_height / 4.0 +
max_width * (1.0 - slider_widget->current_value);
completion_y = y + slider_widget->bar_height / 4.0;
completion_width = max_width * slider_widget->current_value;
completion_height = max_height;
}
} else {
completion_x = x + slider_widget->bar_height / 4.0;
completion_y = y + slider_widget->bar_height / 4.0;
if (slider_widget->vertical) {
completion_width = max_width;
completion_height = max_height * slider_widget->current_value;
} else {
completion_width = max_width * slider_widget->current_value;
completion_height = max_height;
}
}
pgpl_render_rectangle(
renderer, theme->widget_background_color[widget->gui_color], completion_x,
completion_y, completion_width, completion_height);
pgpl_render_circle(renderer, theme->text_color[widget->gui_color], slider_x,
slider_y, slider_widget->bar_height, 32);
}
static void event(PGPL_GuiWidget *widget, PGPL_GuiTheme *theme, PGPL_Gui *gui,
PGPL_WindowEventType event_type,
PGPL_WindowEventData *event_data, double x, double y,
double max_width, double max_height) {
if (event_type == PGPL_WINDOW_EVENT_MOUSE_PRESS ||
event_type == PGPL_WINDOW_EVENT_MOUSE_RELEASE ||
event_type == PGPL_WINDOW_EVENT_MOUSE_MOVE) {
PGPL_GuiSliderWidget *slider_widget = (PGPL_GuiSliderWidget *)widget;
double slider_x;
double slider_y;
pgpl_gui_widget_adjust_event_params(widget, theme, &x, &y, &max_width,
&max_height);
get_slider_size(slider_widget, &slider_x, &slider_y, x, y, max_width,
max_height);
if (event_type == PGPL_WINDOW_EVENT_MOUSE_PRESS) {
if (pgpl_gui_widget_within_area(event_data->input_event.x,
event_data->input_event.y, slider_x,
slider_y, slider_widget->bar_height * 2,
slider_widget->bar_height * 2)) {
slider_widget->sliding = true;
if (slider_widget->vertical) {
slider_widget->last_pos = event_data->input_event.y;
} else {
slider_widget->last_pos = event_data->input_event.x;
}
}
} else if (event_type == PGPL_WINDOW_EVENT_MOUSE_RELEASE) {
slider_widget->sliding = false;
} else if (slider_widget->sliding) {
double new_pos;
double axis_length;
if (slider_widget->vertical) {
new_pos = event_data->input_event.y;
axis_length = max_height;
} else {
new_pos = event_data->input_event.x;
axis_length = max_width;
}
axis_length -= slider_widget->bar_height;
if (slider_widget->inversed) {
slider_widget->current_value -=
(new_pos - slider_widget->last_pos) / axis_length;
} else {
slider_widget->current_value +=
(new_pos - slider_widget->last_pos) / axis_length;
}
if (slider_widget->current_value > 1.0) {
slider_widget->current_value = 1.0;
} else if (slider_widget->current_value < 0.0) {
slider_widget->current_value = 0.0;
}
slider_widget->slide_callback(gui->app_data,
slider_widget->current_value);
slider_widget->last_pos = new_pos;
}
}
}
static void destroy(PGPL_GuiWidget *widget) {
pgpl_gui_slider_widget_destroy((PGPL_GuiSliderWidget *)widget);
}
PGPL_GuiSliderWidget *pgpl_gui_slider_widget_create(
uint32_t bar_height, bool inversed, bool vertical, double value,
void (*slide_callback)(void *app_data, double value)) {
PGPL_GuiSliderWidget *slider_widget = calloc(1, sizeof(*slider_widget));
slider_widget->parent.id = "PGPL_GuiSliderWidget";
slider_widget->parent.get_content_size = get_content_size;
slider_widget->parent.render_content = render_content;
slider_widget->parent.event = event;
slider_widget->parent.destroy = destroy;
slider_widget->bar_height = bar_height;
slider_widget->inversed = inversed;
slider_widget->vertical = vertical;
slider_widget->current_value = value;
slider_widget->slide_callback = slide_callback;
return slider_widget;
}
void pgpl_gui_slider_widget_destroy(PGPL_GuiSliderWidget *slider_widget) {
free(slider_widget);
}