slider widget, tons of fixes and improvements for win32, reworked font loading.
This commit is contained in:
parent
54a0f5eb4e
commit
69f8a273f3
18 changed files with 452 additions and 90 deletions
|
|
@ -34,6 +34,71 @@ void pgpl_gui_theme_configure(PGPL_GuiTheme *theme, PGPL_Color base_color,
|
|||
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,
|
||||
|
|
@ -67,11 +132,13 @@ void pgpl_gui_widget_render_full(PGPL_GuiWidget *widget,
|
|||
theme = &widget->theme_override;
|
||||
}
|
||||
|
||||
x += +widget->offset_x;
|
||||
y += +widget->offset_y;
|
||||
x += widget->offset_x;
|
||||
y += widget->offset_y;
|
||||
|
||||
widget->get_content_size(widget, theme, &width, &height, max_width,
|
||||
max_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;
|
||||
|
|
@ -143,6 +210,13 @@ void pgpl_gui_widget_render_full(PGPL_GuiWidget *widget,
|
|||
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,
|
||||
|
|
@ -155,12 +229,8 @@ bool pgpl_gui_widget_within_bounds(PGPL_GuiWidget *widget, PGPL_GuiTheme *theme,
|
|||
max_width -= theme->margin.left + theme->margin.right;
|
||||
max_height -= theme->margin.top + theme->margin.bottom;
|
||||
|
||||
if ((x >= widget_x && x <= (widget_x + max_width)) &&
|
||||
(y >= widget_y && y <= (widget_y + max_height))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return pgpl_gui_widget_within_area(x, y, widget_x, widget_y, max_width,
|
||||
max_height);
|
||||
}
|
||||
|
||||
void pgpl_gui_widget_configure(PGPL_GuiWidget *widget, double offset_x,
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ static void get_content_size(PGPL_GuiWidget *widget, PGPL_GuiTheme *theme,
|
|||
double *width, double *height, double max_width,
|
||||
double max_height) {
|
||||
(void)widget;
|
||||
pgpl_gui_widget_max_content_size(widget, theme, width, height, max_width,
|
||||
max_height);
|
||||
(void)theme;
|
||||
|
||||
*width = max_width;
|
||||
*height = max_height;
|
||||
}
|
||||
|
||||
static void render_content(PGPL_GuiWidget *widget, PGPL_Renderer *renderer,
|
||||
|
|
@ -79,12 +81,15 @@ static void event(PGPL_GuiWidget *widget, PGPL_GuiTheme *theme, PGPL_Gui *gui,
|
|||
for (uint32_t i = 0; i < length; i++) {
|
||||
PGPL_GuiWidget *child_widget =
|
||||
*(PGPL_GuiWidget **)pgpl_vector_get_index(container_layout->widgets, i);
|
||||
PGPL_GuiTheme *child_theme;
|
||||
|
||||
if (child_widget->use_theme_override) {
|
||||
theme = &child_widget->theme_override;
|
||||
child_theme = &child_widget->theme_override;
|
||||
} else {
|
||||
child_theme = theme;
|
||||
}
|
||||
|
||||
child_widget->event(child_widget, theme, gui, event_type, event_data,
|
||||
child_widget->event(child_widget, child_theme, gui, event_type, event_data,
|
||||
x + child_widget->offset_x, y + child_widget->offset_y,
|
||||
max_width, max_height);
|
||||
|
||||
|
|
|
|||
201
src/gui/widgets/slider.c
Normal file
201
src/gui/widgets/slider.c
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue