Files
wschod/game/src/ui/widget_core.h
T
2025-07-20 18:47:42 +02:00

207 lines
4.5 KiB
C

#pragma once
#include <glib-2.0/glib.h>
#include <cglm/cglm.h>
#include "widget_fw.h"
#include "widget_render.h"
#include "widget_layout.h"
#include "widget_style.h"
#include "widget_boilerplate.h"
#include "../util.h"
#include "../resources.h"
#include "../flags.h"
#include "../gl/mesh.h"
#include "../gl/program.h"
#define WFOREACH(widget, child) \
for (unsigned int _i = 0; _i < (widget)->children->len; ++_i) \
for (Widget *child = g_array_index ((widget)->children, Widget *, _i); child; child = NULL)
#define SCROLL_UP (ivec2) { 0, -1 }
#define SCROLL_DOWN (ivec2) { 0, 1 }
typedef enum WidgetKind
{
WIDGET_PLAIN,
WIDGET_LABEL,
WIDGET_SCROLLBAR,
WIDGET_PROGRESS,
WIDGET_ENTRY,
WIDGET_MULTILINE_TEXT,
WIDGET_CONTAINER,
WIDGET_SCROLLABLE,
WIDGET_FLOWBOX,
WIDGET_WINDOW
} WidgetKind;
typedef enum WidgetIcon
{
ICON_NONE,
ICON_CHECKBOX_UNCHECKED,
ICON_CHECKBOX_CHECKED,
ICON_MINUS,
ICON_PLUS,
ICON_ARROW_LEFT,
ICON_ARROW_RIGHT,
ICON_ARROW_UP,
ICON_ARROW_DOWN
} WidgetIcon;
typedef enum WidgetEvent
{
EVENT_TICK,
EVENT_LEFT_DOWN,
EVENT_LEFT_UP,
EVENT_RIGHT_DOWN,
EVENT_RIGHT_UP,
EVENT_MOUSE_ENTER,
EVENT_MOUSE_LEAVE,
EVENT_MOUSE_MOVE,
EVENT_SCROLL_UP,
EVENT_SCROLL_DOWN,
EVENT_FOCUS_GAINED,
EVENT_FOCUS_LOST,
EVENT_TEXT_INPUT,
EVENT_COUNT
} WidgetEvent;
typedef enum TextAlignment
{
TEXT_ALIGN_LEFT,
TEXT_ALIGN_CENTER,
TEXT_ALIGN_RIGHT
} TextAlignment;
typedef struct LabelWidget
{
GString *text;
TextAlignment text_alignment;
} LabelWidget;
typedef struct ScrollbarWidget
{
struct Widget *target;
gboolean horizontal;
/* Used for input. */
gboolean dragging;
int drag_offset;
} ScrollbarWidget;
typedef struct ProgressWidget
{
gboolean horizontal;
float min, max, *ptr;
} ProgressWidget;
typedef struct EntryWidget
{
GString *ghost_text;
GString *content;
/* cursor_position is in UTF-8 characters. */
int cursor_position;
} EntryWidget;
typedef struct MultilineTextWidget
{
GString *text;
GArray *lines;
int line_height;
TextAlignment text_alignment;
} MultilineTextWidget;
typedef struct ContainerWidget
{
gboolean horizontal;
} ContainerWidget;
typedef struct ScrollableWidget
{
gboolean layout_horizontal;
gboolean layout_vertical;
int scroll_amount;
ivec2 scroll_position;
ivec2 content_size;
} ScrollableWidget;
typedef struct FlowBoxWidget
{
gboolean horizontal;
} FlowBoxWidget;
typedef struct WindowWidget
{
GString *title;
int titlebar_height;
gboolean moving, resizing;
ivec2 drag_offset;
gboolean resizable_h, resizable_v;
} WindowWidget;
typedef struct Widget
{
struct Widget *parent;
GArray *children;
WidgetKind kind;
union
{
LabelWidget label;
ScrollbarWidget scrollbar;
ProgressWidget progress;
MultilineTextWidget multiline_text;
EntryWidget entry;
ContainerWidget container;
ScrollableWidget scrollable;
FlowBoxWidget flowbox;
WindowWidget window;
};
gboolean visible;
gboolean layout_dirty; /* Unused. */
gboolean hovered, clicked, focused;
ivec2 position;
ivec2 size;
int layout_padding, layout_spacing;
float layout_weight, aspect_ratio;
const WidgetStyle *style;
WidgetIcon icon;
GString *tooltip;
void (*do_layout) (struct Widget *);
void (*do_render) (struct Widget *, mat4, int);
void (*on_event[EVENT_COUNT]) (struct Widget *, SDL_Event *sdl_event, void *);
void *event_data[EVENT_COUNT];
void (*on_key[SDL_SCANCODE_COUNT]) (struct Widget *, SDL_Event *null, void *);
void *key_data[SDL_SCANCODE_COUNT];
} Widget;
Widget *Widget_new ();
void Widget_add_child (Widget *parent, Widget *child);
void Widget_entry_input_text (Widget *widget, const char *text);
void Widget_scrollable_scroll (Widget *widget, ivec2 direction);
static inline gboolean wcond_tooltip (Widget *widget, void *userdata) { UNUSED (userdata); return widget->tooltip->len > 0; }
static inline gboolean wcond_event (Widget *widget, void *event) { WidgetEvent e = GPOINTER_TO_INT (event); return widget->on_event[e] != NULL; }
static inline gboolean wcond_any (Widget *widget, void *userdata) { UNUSED (widget, userdata); return TRUE; }
Widget *Widget_find_xy_cond (Widget *widget, ivec2 point, gboolean (*cond_func) (Widget *, void *), void *userdata);
void Widget_tick (Widget *widget);
void Widget_render (Widget *widget, mat4 projection, int window_height);
void Widget_free (Widget *widget);