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
|
|
@ -7,6 +7,13 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* This function adjusts the values of the parameters that are passed to the
|
||||||
|
* event method to match the values that are passed to the render function. */
|
||||||
|
void pgpl_gui_widget_adjust_event_params(PGPL_GuiWidget *widget,
|
||||||
|
PGPL_GuiTheme *theme, double *x,
|
||||||
|
double *y, double *max_width,
|
||||||
|
double *max_height);
|
||||||
|
|
||||||
/* This function basically subtracts margin, border and padding from the
|
/* This function basically subtracts margin, border and padding from the
|
||||||
* max_width and max_height, and then return that through the width and height
|
* max_width and max_height, and then return that through the width and height
|
||||||
* pointers. */
|
* pointers. */
|
||||||
|
|
@ -31,6 +38,11 @@ void pgpl_gui_widget_render_full(PGPL_GuiWidget *widget,
|
||||||
double x, double y, double max_width,
|
double x, double y, double max_width,
|
||||||
double max_height);
|
double max_height);
|
||||||
|
|
||||||
|
/* Checks if a point is within the bounds of the area. */
|
||||||
|
bool pgpl_gui_widget_within_area(double x, double y, double area_x,
|
||||||
|
double area_y, double area_width,
|
||||||
|
double area_height);
|
||||||
|
|
||||||
/* Checks if x and y lie within the visible bounds of a widget, accounting for
|
/* Checks if x and y lie within the visible bounds of a widget, accounting for
|
||||||
* margin, border and padding and returns true or false. */
|
* margin, border and padding and returns true or false. */
|
||||||
bool pgpl_gui_widget_within_bounds(PGPL_GuiWidget *widget, PGPL_GuiTheme *theme,
|
bool pgpl_gui_widget_within_bounds(PGPL_GuiWidget *widget, PGPL_GuiTheme *theme,
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,30 @@ PGPL_GuiWidget *pgpl_gui_empty_widget_create(void);
|
||||||
/* Destroys a empty widget. */
|
/* Destroys a empty widget. */
|
||||||
void pgpl_gui_empty_widget_destroy(PGPL_GuiWidget *empty_widget);
|
void pgpl_gui_empty_widget_destroy(PGPL_GuiWidget *empty_widget);
|
||||||
|
|
||||||
|
/* This is the struct for a slider widget. The inversed option inverses its
|
||||||
|
* slide direction, vertical determines if it's vertical or horizontal. The
|
||||||
|
* bar_height is the height of the slider bar. The slide_callback gets called
|
||||||
|
* whenever there is sliding activity. */
|
||||||
|
typedef struct PGPL_GuiSliderWidget {
|
||||||
|
PGPL_GuiWidget parent;
|
||||||
|
uint32_t bar_height;
|
||||||
|
bool inversed;
|
||||||
|
bool vertical;
|
||||||
|
double current_value;
|
||||||
|
void (*slide_callback)(void *app_data, double value);
|
||||||
|
/* Do not modify the following two attributes manually. */
|
||||||
|
bool sliding;
|
||||||
|
double last_pos;
|
||||||
|
} PGPL_GuiSliderWidget;
|
||||||
|
|
||||||
|
/* This creates a new slider with the given properties. */
|
||||||
|
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));
|
||||||
|
|
||||||
|
/* This destorys a slider widget. */
|
||||||
|
void pgpl_gui_slider_widget_destroy(PGPL_GuiSliderWidget *slider_widget);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,24 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* These are the different supported logging levels. */
|
||||||
typedef enum PGPL_LogLevel {
|
typedef enum PGPL_LogLevel {
|
||||||
PGPL_LOG_LEVEL_DEBUG,
|
PGPL_LOG_LEVEL_DEBUG, /* For frequent debug prints, use this. */
|
||||||
PGPL_LOG_LEVEL_INFO,
|
PGPL_LOG_LEVEL_INFO, /* For general info, that isn't spammed. */
|
||||||
PGPL_LOG_LEVEL_WARN,
|
PGPL_LOG_LEVEL_WARN, /* For non-critical problems. */
|
||||||
PGPL_LOG_LEVEL_ERROR,
|
PGPL_LOG_LEVEL_ERROR, /* For critical problems that could halt the program */
|
||||||
} PGPL_LogLevel;
|
} PGPL_LogLevel;
|
||||||
|
|
||||||
|
/* This sets the minimum level required for a message to be displayed. */
|
||||||
void pgpl_log_set_minimum_level(PGPL_LogLevel level);
|
void pgpl_log_set_minimum_level(PGPL_LogLevel level);
|
||||||
|
|
||||||
|
/* This selects the file that things should be outputted to. By default this is
|
||||||
|
* goes to stderr. */
|
||||||
void pgpl_log_output_file(FILE *file);
|
void pgpl_log_output_file(FILE *file);
|
||||||
|
|
||||||
|
/* This logs a message. This function can be used like printf. The output
|
||||||
|
* follows the following scheme: [ERROR] <message>
|
||||||
|
* It is also terminated by a newline. */
|
||||||
void pgpl_log_message(PGPL_LogLevel level, const char *message, ...);
|
void pgpl_log_message(PGPL_LogLevel level, const char *message, ...);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,9 @@ extern "C" {
|
||||||
* can be any custom pointer to anything that might be needed inside of the
|
* can be any custom pointer to anything that might be needed inside of the
|
||||||
* event_loop. If the user_data is not needed it can also be NULL.
|
* event_loop. If the user_data is not needed it can also be NULL.
|
||||||
*
|
*
|
||||||
* Returning false from the event_loop will close the window.
|
* Returning false from the event_loop will close the window. Do not call any of
|
||||||
*/
|
* the window_thread functions from within the event loop, as this will cause
|
||||||
|
* the thread to lock up. Use the window functions directly. */
|
||||||
PGPL_WindowThread *pgpl_window_thread_create(
|
PGPL_WindowThread *pgpl_window_thread_create(
|
||||||
const char *title, uint32_t width, uint32_t height, int32_t x, int32_t y,
|
const char *title, uint32_t width, uint32_t height, int32_t x, int32_t y,
|
||||||
bool (*event_loop)(PGPL_Window *window, PGPL_WindowEventType event,
|
bool (*event_loop)(PGPL_Window *window, PGPL_WindowEventType event,
|
||||||
|
|
@ -93,8 +94,7 @@ void pgpl_window_thread_reparent_to(PGPL_WindowThread *window_thread,
|
||||||
* pgpl_window_get_raw_window for more information. */
|
* pgpl_window_get_raw_window for more information. */
|
||||||
void *pgpl_window_thread_get_raw_window(PGPL_WindowThread *window_thread);
|
void *pgpl_window_thread_get_raw_window(PGPL_WindowThread *window_thread);
|
||||||
|
|
||||||
/* This function halts until the window_thread is destroyed. This function only
|
/* This function halts until the window_thread is destroyed. */
|
||||||
* works once per window_thread. */
|
|
||||||
void pgpl_window_thread_await_destruction(PGPL_WindowThread *window_thread);
|
void pgpl_window_thread_await_destruction(PGPL_WindowThread *window_thread);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,13 @@ lib = both_libraries(
|
||||||
'src/render/shapes.c',
|
'src/render/shapes.c',
|
||||||
'src/render/texture.c',
|
'src/render/texture.c',
|
||||||
'src/render/font.c',
|
'src/render/font.c',
|
||||||
|
'src/render/render.c',
|
||||||
'src/gui/gui.c',
|
'src/gui/gui.c',
|
||||||
'src/gui/helpers.c',
|
'src/gui/helpers.c',
|
||||||
'src/gui/widgets/text.c',
|
'src/gui/widgets/text.c',
|
||||||
'src/gui/widgets/button.c',
|
'src/gui/widgets/button.c',
|
||||||
'src/gui/widgets/container.c',
|
'src/gui/widgets/container.c',
|
||||||
|
'src/gui/widgets/slider.c',
|
||||||
include_directories: include,
|
include_directories: include,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
dependency('gl'),
|
dependency('gl'),
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,71 @@ void pgpl_gui_theme_configure(PGPL_GuiTheme *theme, PGPL_Color base_color,
|
||||||
theme->font = font;
|
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,
|
void pgpl_gui_widget_max_content_size(PGPL_GuiWidget *widget,
|
||||||
PGPL_GuiTheme *theme, double *width,
|
PGPL_GuiTheme *theme, double *width,
|
||||||
double *height, double max_width,
|
double *height, double max_width,
|
||||||
|
|
@ -67,12 +132,14 @@ void pgpl_gui_widget_render_full(PGPL_GuiWidget *widget,
|
||||||
theme = &widget->theme_override;
|
theme = &widget->theme_override;
|
||||||
}
|
}
|
||||||
|
|
||||||
x += +widget->offset_x;
|
x += widget->offset_x;
|
||||||
y += +widget->offset_y;
|
y += widget->offset_y;
|
||||||
|
|
||||||
widget->get_content_size(widget, theme, &width, &height, max_width,
|
pgpl_gui_widget_max_content_size(widget, theme, &width, &height, max_width,
|
||||||
max_height);
|
max_height);
|
||||||
|
|
||||||
|
widget->get_content_size(widget, theme, &width, &height, width, height);
|
||||||
|
|
||||||
if (!widget->expand_x) {
|
if (!widget->expand_x) {
|
||||||
max_width = width;
|
max_width = width;
|
||||||
if (!widget->ignore_margin) {
|
if (!widget->ignore_margin) {
|
||||||
|
|
@ -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);
|
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,
|
bool pgpl_gui_widget_within_bounds(PGPL_GuiWidget *widget, PGPL_GuiTheme *theme,
|
||||||
double widget_x, double widget_y,
|
double widget_x, double widget_y,
|
||||||
double max_width, double max_height,
|
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_width -= theme->margin.left + theme->margin.right;
|
||||||
max_height -= theme->margin.top + theme->margin.bottom;
|
max_height -= theme->margin.top + theme->margin.bottom;
|
||||||
|
|
||||||
if ((x >= widget_x && x <= (widget_x + max_width)) &&
|
return pgpl_gui_widget_within_area(x, y, widget_x, widget_y, max_width,
|
||||||
(y >= widget_y && y <= (widget_y + max_height))) {
|
max_height);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pgpl_gui_widget_configure(PGPL_GuiWidget *widget, double offset_x,
|
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 *width, double *height, double max_width,
|
||||||
double max_height) {
|
double max_height) {
|
||||||
(void)widget;
|
(void)widget;
|
||||||
pgpl_gui_widget_max_content_size(widget, theme, width, height, max_width,
|
(void)theme;
|
||||||
max_height);
|
|
||||||
|
*width = max_width;
|
||||||
|
*height = max_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_content(PGPL_GuiWidget *widget, PGPL_Renderer *renderer,
|
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++) {
|
for (uint32_t i = 0; i < length; i++) {
|
||||||
PGPL_GuiWidget *child_widget =
|
PGPL_GuiWidget *child_widget =
|
||||||
*(PGPL_GuiWidget **)pgpl_vector_get_index(container_layout->widgets, i);
|
*(PGPL_GuiWidget **)pgpl_vector_get_index(container_layout->widgets, i);
|
||||||
|
PGPL_GuiTheme *child_theme;
|
||||||
|
|
||||||
if (child_widget->use_theme_override) {
|
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,
|
x + child_widget->offset_x, y + child_widget->offset_y,
|
||||||
max_width, max_height);
|
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);
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <locale.h>
|
||||||
#include <pgpl.h>
|
#include <pgpl.h>
|
||||||
|
|
||||||
PGPL_Mutex *pgpl_internal_render_lock;
|
PGPL_Mutex *pgpl_internal_render_lock;
|
||||||
|
|
@ -5,6 +6,7 @@ PGPL_Mutex *pgpl_internal_log_lock;
|
||||||
FILE *pgpl_internal_log_file;
|
FILE *pgpl_internal_log_file;
|
||||||
|
|
||||||
void pgpl_init(void) {
|
void pgpl_init(void) {
|
||||||
|
setlocale(LC_ALL, "C.UTF-8");
|
||||||
pgpl_internal_render_lock = pgpl_mutex_create();
|
pgpl_internal_render_lock = pgpl_mutex_create();
|
||||||
pgpl_internal_log_lock = pgpl_mutex_create();
|
pgpl_internal_log_lock = pgpl_mutex_create();
|
||||||
pgpl_internal_log_file = stderr;
|
pgpl_internal_log_file = stderr;
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
#define STBTT_STATIC
|
#define STBTT_STATIC
|
||||||
#include <stb/stb_truetype.h>
|
#include <stb/stb_truetype.h>
|
||||||
|
|
||||||
#define CHAR_AMOUNT 256
|
#define CHAR_AMOUNT 8
|
||||||
#define BANK_AMOUNT 256
|
#define BANK_AMOUNT (65536 / CHAR_AMOUNT)
|
||||||
|
|
||||||
typedef struct PGPL_FontBank {
|
typedef struct PGPL_FontBank {
|
||||||
stbtt_bakedchar baked[CHAR_AMOUNT];
|
stbtt_bakedchar baked[CHAR_AMOUNT];
|
||||||
|
|
@ -93,8 +93,8 @@ void pgpl_font_render_glyph(PGPL_Renderer *renderer, PGPL_Font *font, wchar_t c,
|
||||||
PGPL_Color color, double x, double y, double size,
|
PGPL_Color color, double x, double y, double size,
|
||||||
double *xoff, double *yoff) {
|
double *xoff, double *yoff) {
|
||||||
stbtt_aligned_quad q;
|
stbtt_aligned_quad q;
|
||||||
uint32_t bank_index = c / 256;
|
uint32_t bank_index = c / CHAR_AMOUNT;
|
||||||
uint32_t bank_offset = c % 256;
|
uint32_t bank_offset = c % CHAR_AMOUNT;
|
||||||
double factor = size / font->glyph_size;
|
double factor = size / font->glyph_size;
|
||||||
float xoff_stb = *xoff;
|
float xoff_stb = *xoff;
|
||||||
float yoff_stb = *yoff;
|
float yoff_stb = *yoff;
|
||||||
|
|
@ -121,7 +121,7 @@ void pgpl_font_render_glyph(PGPL_Renderer *renderer, PGPL_Font *font, wchar_t c,
|
||||||
|
|
||||||
pgpl_render_texture_extended(
|
pgpl_render_texture_extended(
|
||||||
renderer, font->banks[bank_index]->texture, (x + q.x0 * factor),
|
renderer, font->banks[bank_index]->texture, (x + q.x0 * factor),
|
||||||
(y + q.y0 * factor + size / 1.75), (q.x1 - q.x0) * factor,
|
(y + q.y0 * factor + size / 1.6), (q.x1 - q.x0) * factor,
|
||||||
(q.y1 - q.y0) * factor, color, q.s0, q.t0, q.s1, q.t1);
|
(q.y1 - q.y0) * factor, color, q.s0, q.t0, q.s1, q.t1);
|
||||||
|
|
||||||
*xoff = xoff_stb;
|
*xoff = xoff_stb;
|
||||||
|
|
@ -164,8 +164,8 @@ void pgpl_font_glyph_dimensions(PGPL_Font *font, wchar_t c, double size,
|
||||||
double *xoff, double *yoff,
|
double *xoff, double *yoff,
|
||||||
PGPL_Rectangle *rectangle) {
|
PGPL_Rectangle *rectangle) {
|
||||||
stbtt_aligned_quad q;
|
stbtt_aligned_quad q;
|
||||||
uint32_t bank_index = c / 256;
|
uint32_t bank_index = c / CHAR_AMOUNT;
|
||||||
uint32_t bank_offset = c % 256;
|
uint32_t bank_offset = c % CHAR_AMOUNT;
|
||||||
double factor = size / font->glyph_size;
|
double factor = size / font->glyph_size;
|
||||||
float xoff_stb = *xoff;
|
float xoff_stb = *xoff;
|
||||||
float yoff_stb = *yoff;
|
float yoff_stb = *yoff;
|
||||||
|
|
@ -179,9 +179,9 @@ void pgpl_font_glyph_dimensions(PGPL_Font *font, wchar_t c, double size,
|
||||||
font->glyph_size * font->chars_vertical, bank_offset,
|
font->glyph_size * font->chars_vertical, bank_offset,
|
||||||
&xoff_stb, &yoff_stb, &q, 0);
|
&xoff_stb, &yoff_stb, &q, 0);
|
||||||
|
|
||||||
rectangle->top = q.y0 * factor + size / 1.5;
|
rectangle->top = q.y0 * factor + size / 1.6;
|
||||||
rectangle->left = q.x0 * factor;
|
rectangle->left = q.x0 * factor;
|
||||||
rectangle->bottom = q.y1 * factor + size / 1.5;
|
rectangle->bottom = q.y1 * factor + size / 1.6;
|
||||||
rectangle->right = q.x1 * factor;
|
rectangle->right = q.x1 * factor;
|
||||||
|
|
||||||
*xoff = xoff_stb;
|
*xoff = xoff_stb;
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,5 @@
|
||||||
struct PGPL_Texture {
|
struct PGPL_Texture {
|
||||||
GLuint id;
|
GLuint id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void pgpl_render_internal_handle_opengl_error(int line, const char *file);
|
||||||
|
|
|
||||||
42
src/render/render.c
Normal file
42
src/render/render.c
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
void pgpl_render_internal_handle_opengl_error(int line, const char *file) {
|
||||||
|
GLenum error = glGetError();
|
||||||
|
|
||||||
|
if (error != GL_NO_ERROR) {
|
||||||
|
switch (error) {
|
||||||
|
case GL_INVALID_ENUM:
|
||||||
|
pgpl_log_message(PGPL_LOG_LEVEL_WARN,
|
||||||
|
"OpenGL invalid enum at line %d in file %s", line, file);
|
||||||
|
break;
|
||||||
|
case GL_INVALID_VALUE:
|
||||||
|
pgpl_log_message(PGPL_LOG_LEVEL_WARN,
|
||||||
|
"OpenGL invalid value at line %d in file %s", line,
|
||||||
|
file);
|
||||||
|
break;
|
||||||
|
case GL_INVALID_OPERATION:
|
||||||
|
pgpl_log_message(PGPL_LOG_LEVEL_WARN,
|
||||||
|
"OpenGL invalid operation at line %d", line);
|
||||||
|
break;
|
||||||
|
case GL_STACK_OVERFLOW:
|
||||||
|
pgpl_log_message(PGPL_LOG_LEVEL_WARN,
|
||||||
|
"OpenGL stack overflow at line %d in file %s", line,
|
||||||
|
file);
|
||||||
|
break;
|
||||||
|
case GL_STACK_UNDERFLOW:
|
||||||
|
pgpl_log_message(PGPL_LOG_LEVEL_WARN,
|
||||||
|
"OpenGL stack underflow at line %d in file %s", line,
|
||||||
|
file);
|
||||||
|
break;
|
||||||
|
case GL_OUT_OF_MEMORY:
|
||||||
|
pgpl_log_message(PGPL_LOG_LEVEL_ERROR,
|
||||||
|
"OpenGL out of memory at line %d in file %s", line,
|
||||||
|
file);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pgpl_log_message(PGPL_LOG_LEVEL_ERROR,
|
||||||
|
"Unknown OpenGL error at line %d in file %s", line,
|
||||||
|
file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#define STB_IMAGE_STATIC
|
#define STB_IMAGE_STATIC
|
||||||
|
|
@ -94,6 +92,8 @@ PGPL_Texture *pgpl_render_create_texture(PGPL_Renderer *renderer,
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_format, width, height, 0, gl_format,
|
glTexImage2D(GL_TEXTURE_2D, 0, gl_format, width, height, 0, gl_format,
|
||||||
GL_UNSIGNED_BYTE, data);
|
GL_UNSIGNED_BYTE, data);
|
||||||
|
|
||||||
|
pgpl_render_internal_handle_opengl_error(__LINE__, __FILE__);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#include <locale.h>
|
|
||||||
#include <pgpl.h>
|
#include <pgpl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -11,13 +10,11 @@ wchar_t *pgpl_string_to_wide_string(const char *str) {
|
||||||
size_t length = strlen(str);
|
size_t length = strlen(str);
|
||||||
wchar_t *wstr = malloc((length + 1) * sizeof(*wstr));
|
wchar_t *wstr = malloc((length + 1) * sizeof(*wstr));
|
||||||
|
|
||||||
setlocale(LC_ALL, "en_US.UTF-8");
|
|
||||||
|
|
||||||
/* mbstowcs works just fine with UTF-8 strings on most platforms, except on
|
/* mbstowcs works just fine with UTF-8 strings on most platforms, except on
|
||||||
* Windows, where we have to use MultiByteToWideChar to do the exact same
|
* Windows, where we have to use MultiByteToWideChar to do the exact same
|
||||||
* thing. */
|
* thing. */
|
||||||
#if defined(__WIN32__)
|
#if defined(__WIN32__)
|
||||||
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, str, -1, wstr, length + 1);
|
MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, length + 1);
|
||||||
#else
|
#else
|
||||||
mbstowcs(wstr, str, length + 1);
|
mbstowcs(wstr, str, length + 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ struct PGPL_Window {
|
||||||
PGPL_Vector *window_proc_event_type;
|
PGPL_Vector *window_proc_event_type;
|
||||||
PGPL_Vector *window_proc_event_data;
|
PGPL_Vector *window_proc_event_data;
|
||||||
int32_t last_mouse_x, last_mouse_y;
|
int32_t last_mouse_x, last_mouse_y;
|
||||||
|
int32_t scroll_accumulator;
|
||||||
char title[128];
|
char title[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -44,18 +45,30 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
||||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN: {
|
||||||
|
wchar_t buffer[16];
|
||||||
|
BYTE keyboard_state[256];
|
||||||
|
GetKeyboardState(keyboard_state);
|
||||||
|
buffer[ToUnicode(wParam, (lParam >> 16) & 0x00ff, keyboard_state, buffer,
|
||||||
|
15, 0)] = 0;
|
||||||
event_type = PGPL_WINDOW_EVENT_KEY_PRESS;
|
event_type = PGPL_WINDOW_EVENT_KEY_PRESS;
|
||||||
event_data.input_event.key = wParam;
|
event_data.input_event.key = buffer[0];
|
||||||
event_data.input_event.x = window->last_mouse_x;
|
event_data.input_event.x = window->last_mouse_x;
|
||||||
event_data.input_event.y = window->last_mouse_y;
|
event_data.input_event.y = window->last_mouse_y;
|
||||||
break;
|
break;
|
||||||
case WM_KEYUP:
|
}
|
||||||
|
case WM_KEYUP: {
|
||||||
|
wchar_t buffer[16];
|
||||||
|
BYTE keyboard_state[256];
|
||||||
|
GetKeyboardState(keyboard_state);
|
||||||
|
buffer[ToUnicode(wParam, (lParam >> 16) & 0x00ff, keyboard_state, buffer,
|
||||||
|
15, 0)] = 0;
|
||||||
event_type = PGPL_WINDOW_EVENT_KEY_RELEASE;
|
event_type = PGPL_WINDOW_EVENT_KEY_RELEASE;
|
||||||
event_data.input_event.key = wParam;
|
event_data.input_event.key = buffer[0];
|
||||||
event_data.input_event.x = window->last_mouse_x;
|
event_data.input_event.x = window->last_mouse_x;
|
||||||
event_data.input_event.y = window->last_mouse_y;
|
event_data.input_event.y = window->last_mouse_y;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case WM_LBUTTONDOWN: {
|
case WM_LBUTTONDOWN: {
|
||||||
POINTS points = MAKEPOINTS(lParam);
|
POINTS points = MAKEPOINTS(lParam);
|
||||||
event_type = PGPL_WINDOW_EVENT_MOUSE_PRESS;
|
event_type = PGPL_WINDOW_EVENT_MOUSE_PRESS;
|
||||||
|
|
@ -105,15 +118,18 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_MOUSEWHEEL: {
|
case WM_MOUSEWHEEL: {
|
||||||
/* TODO: This code probably doesn't work that well. Unlike X11, this only
|
|
||||||
* returns a MOUSE_PRESS event, and if the scrolls are more granular, this
|
|
||||||
* will scroll really fast.
|
|
||||||
*/
|
|
||||||
POINTS points = MAKEPOINTS(lParam);
|
POINTS points = MAKEPOINTS(lParam);
|
||||||
|
window->scroll_accumulator += GET_WHEEL_DELTA_WPARAM(wParam);
|
||||||
event_type = PGPL_WINDOW_EVENT_MOUSE_PRESS;
|
event_type = PGPL_WINDOW_EVENT_MOUSE_PRESS;
|
||||||
event_data.input_event.x = points.x;
|
event_data.input_event.x = points.x;
|
||||||
event_data.input_event.y = points.y;
|
event_data.input_event.y = points.y;
|
||||||
event_data.input_event.key = GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? 4 : 5;
|
if (window->scroll_accumulator >= 120) {
|
||||||
|
event_data.input_event.key = 4;
|
||||||
|
window->scroll_accumulator -= 120;
|
||||||
|
} else if (window->scroll_accumulator <= -120) {
|
||||||
|
event_data.input_event.key = 5;
|
||||||
|
window->scroll_accumulator += 120;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_MOUSEMOVE: {
|
case WM_MOUSEMOVE: {
|
||||||
|
|
@ -121,7 +137,7 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
||||||
event_type = PGPL_WINDOW_EVENT_MOUSE_MOVE;
|
event_type = PGPL_WINDOW_EVENT_MOUSE_MOVE;
|
||||||
window->last_mouse_x = points.x;
|
window->last_mouse_x = points.x;
|
||||||
window->last_mouse_y = points.y;
|
window->last_mouse_y = points.y;
|
||||||
event_data.input_event.key = -1;
|
event_data.input_event.key = 0;
|
||||||
event_data.input_event.x = points.x;
|
event_data.input_event.x = points.x;
|
||||||
event_data.input_event.y = points.y;
|
event_data.input_event.y = points.y;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/* Platform agnostic functions for our PGPL_Window "class" */
|
/* Platform agnostic functions for our PGPL_Window "class" */
|
||||||
|
|
|
||||||
|
|
@ -1,60 +1,48 @@
|
||||||
#include <pgpl.h>
|
#include <pgpl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
struct AppData {
|
struct AppData {
|
||||||
int counter;
|
|
||||||
char counter_buffer[128];
|
|
||||||
PGPL_Gui *gui;
|
PGPL_Gui *gui;
|
||||||
|
char buffer[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
static void on_counter_button_click(void *data) {
|
static void slide_callback(void *data, double value) {
|
||||||
struct AppData *app = data;
|
struct AppData *app_data = data;
|
||||||
app->counter++;
|
snprintf(app_data->buffer, 127, "%d", (int)(value * 100));
|
||||||
snprintf(app->counter_buffer, sizeof(app->counter_buffer), "%d",
|
|
||||||
app->counter);
|
|
||||||
|
|
||||||
if (app->counter % 10 == 0) {
|
|
||||||
pgpl_gui_theme_configure(
|
|
||||||
&app->gui->theme,
|
|
||||||
pgpl_color_create(rand() % 256, rand() % 256, rand() % 256, 255), 48,
|
|
||||||
app->gui->theme.font);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void configure_widget_default(PGPL_GuiWidget *widget) {
|
static void configure_widget_default(PGPL_GuiWidget *widget) {
|
||||||
pgpl_gui_widget_configure(widget, 0, 0, true, true, true, true,
|
pgpl_gui_widget_configure(widget, 0, 0, true, true, false, false,
|
||||||
PGPL_GUI_FONT_SIZE_CONTENT, NULL, false, false,
|
PGPL_GUI_FONT_SIZE_CONTENT, NULL, false, false,
|
||||||
false, false);
|
false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPL_GuiWidget *create_main_view(struct AppData *app) {
|
PGPL_GuiWidget *create_main_view(struct AppData *app) {
|
||||||
PGPL_GuiContainerLayout *column_layout;
|
PGPL_GuiContainerLayout *layout;
|
||||||
PGPL_GuiButtonWidget *counter_button;
|
PGPL_GuiSliderWidget *slider;
|
||||||
PGPL_GuiTextWidget *counter;
|
PGPL_GuiTextWidget *text;
|
||||||
|
|
||||||
column_layout = pgpl_gui_container_layout_create(
|
layout = pgpl_gui_container_layout_create(
|
||||||
PGPL_GUI_CONTAINER_LAYOUT_DIRECTION_VERTICAL);
|
PGPL_GUI_CONTAINER_LAYOUT_DIRECTION_HORIZONTAL);
|
||||||
pgpl_gui_widget_configure(&column_layout->parent, 0, 0, true, true, false,
|
pgpl_gui_widget_configure(&layout->parent, 0, 0, true, true, false, false,
|
||||||
false, PGPL_GUI_FONT_SIZE_CONTENT, NULL, false,
|
PGPL_GUI_FONT_SIZE_CONTENT, NULL, false, true, true,
|
||||||
true, true, false);
|
false);
|
||||||
|
|
||||||
counter_button =
|
slider = pgpl_gui_slider_widget_create(16, true, true, 0.0, slide_callback);
|
||||||
pgpl_gui_button_widget_create("Click me!", on_counter_button_click);
|
configure_widget_default(&slider->parent);
|
||||||
configure_widget_default(&counter_button->parent);
|
|
||||||
|
|
||||||
counter = pgpl_gui_text_widget_create(app->counter_buffer);
|
text = pgpl_gui_text_widget_create(app->buffer);
|
||||||
configure_widget_default(&counter->parent);
|
configure_widget_default(&text->parent);
|
||||||
counter->parent.font_size = PGPL_GUI_FONT_SIZE_TITLE;
|
text->parent.font_size = PGPL_GUI_FONT_SIZE_TITLE;
|
||||||
counter->parent.background = false;
|
|
||||||
counter->parent.border = false;
|
|
||||||
|
|
||||||
pgpl_gui_container_layout_widget_add(column_layout, &counter->parent);
|
pgpl_gui_container_layout_widget_add(layout, &text->parent);
|
||||||
pgpl_gui_container_layout_widget_add(column_layout, &counter_button->parent);
|
pgpl_gui_container_layout_widget_add(layout, &slider->parent);
|
||||||
|
|
||||||
return (PGPL_GuiWidget *)column_layout;
|
return (PGPL_GuiWidget *)layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t main(void) {
|
int32_t main(void) {
|
||||||
|
|
@ -67,15 +55,14 @@ int32_t main(void) {
|
||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
strcpy(app.counter_buffer, "0");
|
strcpy(app.buffer, "0");
|
||||||
app.counter = 0;
|
|
||||||
|
|
||||||
font = pgpl_font_create_from_file("../roboto.ttf", 256);
|
font = pgpl_font_create_from_file("../roboto.ttf", 128);
|
||||||
|
|
||||||
pgpl_gui_theme_configure(&theme, pgpl_color_create(255, 255, 255, 255), 48,
|
pgpl_gui_theme_configure(&theme, pgpl_color_create(255, 255, 255, 255), 48,
|
||||||
font);
|
font);
|
||||||
|
|
||||||
gui = pgpl_gui_create("PGPL Test", 320, 320, 0, 0, &theme, &app);
|
gui = pgpl_gui_create("PGPL Test", 480, 240, 0, 0, &theme, &app);
|
||||||
|
|
||||||
app.gui = gui;
|
app.gui = gui;
|
||||||
|
|
||||||
|
|
|
||||||
4
todo.md
4
todo.md
|
|
@ -1,9 +1,5 @@
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
Win32 Blockers:
|
|
||||||
Translate keymaps on windows.
|
|
||||||
Fix the windows scrolling
|
|
||||||
|
|
||||||
Fun Features:
|
Fun Features:
|
||||||
|
|
||||||
- Further error handling on X11, Win32 API and more.
|
- Further error handling on X11, Win32 API and more.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue