#include #include 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); }