mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-13 00:24:12 +00:00
[ui] Implement dragable collapsible windows
And of course, closable.
This commit is contained in:
parent
300badc96a
commit
df40a50b91
3 changed files with 148 additions and 23 deletions
|
@ -68,6 +68,16 @@ typedef struct imui_style_s {
|
||||||
imui_color_t text;
|
imui_color_t text;
|
||||||
} imui_style_t;
|
} imui_style_t;
|
||||||
|
|
||||||
|
typedef struct imui_window_s {
|
||||||
|
const char *name;
|
||||||
|
int xpos;
|
||||||
|
int ypos;
|
||||||
|
int xlen;
|
||||||
|
int ylen;
|
||||||
|
bool is_open;
|
||||||
|
bool is_collapsed;
|
||||||
|
} imui_window_t;
|
||||||
|
|
||||||
imui_ctx_t *IMUI_NewContext (struct canvas_system_s canvas_sys,
|
imui_ctx_t *IMUI_NewContext (struct canvas_system_s canvas_sys,
|
||||||
const char *font, float fontsize);
|
const char *font, float fontsize);
|
||||||
void IMUI_DestroyContext (imui_ctx_t *ctx);
|
void IMUI_DestroyContext (imui_ctx_t *ctx);
|
||||||
|
@ -80,6 +90,8 @@ void IMUI_Draw (imui_ctx_t *ctx);
|
||||||
|
|
||||||
void IMUI_PushLayout (imui_ctx_t *ctx, bool vertical);
|
void IMUI_PushLayout (imui_ctx_t *ctx, bool vertical);
|
||||||
void IMUI_PopLayout (imui_ctx_t *ctx);
|
void IMUI_PopLayout (imui_ctx_t *ctx);
|
||||||
|
void IMUI_StartWindow (imui_ctx_t *ctx, imui_window_t *window);
|
||||||
|
void IMUI_EndWindow (imui_ctx_t *ctx);
|
||||||
|
|
||||||
bool IMUI_Button (imui_ctx_t *ctx, const char *label);
|
bool IMUI_Button (imui_ctx_t *ctx, const char *label);
|
||||||
bool IMUI_Checkbox (imui_ctx_t *ctx, bool *flag, const char *label);
|
bool IMUI_Checkbox (imui_ctx_t *ctx, bool *flag, const char *label);
|
||||||
|
@ -112,6 +124,10 @@ void IMUI_FlexibleSpace (imui_ctx_t *ctx);
|
||||||
IMUI_DeferLoop (IMUI_PushLayout (IMUI_context, vertical), \
|
IMUI_DeferLoop (IMUI_PushLayout (IMUI_context, vertical), \
|
||||||
IMUI_PopLayout (IMUI_context ))
|
IMUI_PopLayout (IMUI_context ))
|
||||||
|
|
||||||
|
#define UI_Window(window) \
|
||||||
|
IMUI_DeferLoop (IMUI_StartWindow (IMUI_context, window), \
|
||||||
|
IMUI_EndWindow (IMUI_context))
|
||||||
|
|
||||||
#define UI_Horizontal UI_Layout(false)
|
#define UI_Horizontal UI_Layout(false)
|
||||||
#define UI_Vertical UI_Layout(true)
|
#define UI_Vertical UI_Layout(true)
|
||||||
|
|
||||||
|
|
|
@ -156,21 +156,33 @@ Con_Debug_Draw (void)
|
||||||
IMUI_BeginFrame (debug_imui);
|
IMUI_BeginFrame (debug_imui);
|
||||||
static int state;
|
static int state;
|
||||||
static bool flag = true;
|
static bool flag = true;
|
||||||
|
static imui_window_t window = {
|
||||||
|
.name = "Test Window",
|
||||||
|
.xpos = 50,
|
||||||
|
.ypos = 50,
|
||||||
|
.xlen = 400,
|
||||||
|
.ylen = 250,
|
||||||
|
.is_open = true,
|
||||||
|
};
|
||||||
|
UI_Window (&window) {
|
||||||
|
if (!window.is_open || window.is_collapsed) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
UI_Vertical {
|
UI_Vertical {
|
||||||
UI_Horizontal {
|
UI_Horizontal {
|
||||||
if (UI_Button ("Close Debug")) {
|
if (UI_Button ("Close Debug")) {
|
||||||
close_debug ();
|
close_debug ();
|
||||||
}
|
}
|
||||||
if (flag) {
|
|
||||||
UI_FlexibleSpace ();
|
UI_FlexibleSpace ();
|
||||||
UI_Button ("abcdefghijklmnopqrstuvwxyza##1");
|
if (flag) {
|
||||||
|
UI_Button ("abcde##1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UI_Horizontal {
|
UI_Horizontal {
|
||||||
UI_Checkbox (&flag, "hi there");
|
UI_Checkbox (&flag, "hi there");
|
||||||
if (flag) {
|
|
||||||
UI_FlexibleSpace ();
|
UI_FlexibleSpace ();
|
||||||
UI_Button ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst##2");
|
if (flag) {
|
||||||
|
UI_Button ("abcdefg##2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UI_Horizontal {
|
UI_Horizontal {
|
||||||
|
@ -185,6 +197,7 @@ static bool flag = true;
|
||||||
}
|
}
|
||||||
UI_FlexibleSpace ();
|
UI_FlexibleSpace ();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IMUI_Draw (debug_imui);
|
IMUI_Draw (debug_imui);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "QF/mathlib.h"
|
#include "QF/mathlib.h"
|
||||||
#include "QF/progs.h"
|
#include "QF/progs.h"
|
||||||
#include "QF/quakeio.h"
|
#include "QF/quakeio.h"
|
||||||
|
#include "QF/va.h"
|
||||||
|
|
||||||
#include "QF/input/event.h"
|
#include "QF/input/event.h"
|
||||||
|
|
||||||
|
@ -90,6 +91,7 @@ struct imui_ctx_s {
|
||||||
|
|
||||||
uint32_t hot;
|
uint32_t hot;
|
||||||
uint32_t active;
|
uint32_t active;
|
||||||
|
view_pos_t mouse_active;
|
||||||
bool mouse_pressed;
|
bool mouse_pressed;
|
||||||
bool mouse_released;
|
bool mouse_released;
|
||||||
unsigned mouse_buttons;
|
unsigned mouse_buttons;
|
||||||
|
@ -632,6 +634,26 @@ check_button_state (imui_ctx_t *ctx, uint32_t entity)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static view_pos_t
|
||||||
|
check_drag_delta (imui_ctx_t *ctx, uint32_t entity)
|
||||||
|
{
|
||||||
|
view_pos_t delta = {};
|
||||||
|
if (ctx->active == entity) {
|
||||||
|
delta.x = ctx->mouse_position.x - ctx->mouse_active.x;
|
||||||
|
delta.y = ctx->mouse_position.y - ctx->mouse_active.y;
|
||||||
|
ctx->mouse_active = ctx->mouse_position;
|
||||||
|
if (ctx->mouse_released) {
|
||||||
|
ctx->active = nullent;
|
||||||
|
}
|
||||||
|
} else if (ctx->hot == entity) {
|
||||||
|
if (ctx->mouse_pressed) {
|
||||||
|
ctx->mouse_active = ctx->mouse_position;
|
||||||
|
ctx->active = entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
static view_t
|
static view_t
|
||||||
add_text (imui_ctx_t *ctx, view_t view, imui_state_t *state, int mode)
|
add_text (imui_ctx_t *ctx, view_t view, imui_state_t *state, int mode)
|
||||||
{
|
{
|
||||||
|
@ -703,6 +725,14 @@ set_control (imui_ctx_t *ctx, view_t view, bool active)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_expand_x (imui_ctx_t *ctx, view_t view, int weight)
|
||||||
|
{
|
||||||
|
View_Control (view)->semantic_x = imui_size_expand;
|
||||||
|
uint32_t c_percent_x = ctx->csys.imui_base + imui_percent_x;
|
||||||
|
*(int *) Ent_AddComponent(view.id, c_percent_x, ctx->csys.reg) = weight;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IMUI_Button (imui_ctx_t *ctx, const char *label)
|
IMUI_Button (imui_ctx_t *ctx, const char *label)
|
||||||
{
|
{
|
||||||
|
@ -817,3 +847,69 @@ IMUI_FlexibleSpace (imui_ctx_t *ctx)
|
||||||
|
|
||||||
set_fill (ctx, view, ctx->style.background.normal);
|
set_fill (ctx, view, ctx->style.background.normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMUI_StartWindow (imui_ctx_t *ctx, imui_window_t *window)
|
||||||
|
{
|
||||||
|
if (!window->is_open) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto state = imui_get_state (ctx, window->name);
|
||||||
|
uint32_t old_entity = state->entity;
|
||||||
|
|
||||||
|
DARRAY_APPEND (&ctx->parent_stack, ctx->current_parent);
|
||||||
|
|
||||||
|
auto window_view = View_New (ctx->vsys, ctx->current_parent);
|
||||||
|
state->entity = window_view.id;
|
||||||
|
int mode = update_hot_active (ctx, old_entity, state->entity);
|
||||||
|
|
||||||
|
ctx->current_parent = window_view;
|
||||||
|
*View_Control (window_view) = (viewcont_t) {
|
||||||
|
.gravity = grav_northwest,
|
||||||
|
.visible = 1,
|
||||||
|
.semantic_x = imui_size_none,
|
||||||
|
.semantic_y = imui_size_none,
|
||||||
|
.vertical = true,
|
||||||
|
.active = 1,
|
||||||
|
};
|
||||||
|
View_SetPos (window_view, window->xpos, window->ypos);
|
||||||
|
View_SetLen (window_view, window->xlen, window->ylen);
|
||||||
|
|
||||||
|
#define IMUI_context ctx
|
||||||
|
UI_Horizontal {
|
||||||
|
if (UI_Button (va (0, "%c##collapse_%s",
|
||||||
|
window->is_collapsed ? '>' : 'v', window->name))) {
|
||||||
|
window->is_collapsed = !window->is_collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto tb_state = imui_get_state (ctx, va (0, "%s##title_bar",
|
||||||
|
window->name));
|
||||||
|
uint32_t tb_old_entity = tb_state->entity;
|
||||||
|
auto title_bar = View_New (ctx->vsys, ctx->current_parent);
|
||||||
|
tb_state->entity = title_bar.id;
|
||||||
|
int tb_mode = update_hot_active (ctx, tb_old_entity, tb_state->entity);
|
||||||
|
auto delta = check_drag_delta (ctx, tb_state->entity);
|
||||||
|
if (ctx->active == tb_state->entity) {
|
||||||
|
window->xpos += delta.x;
|
||||||
|
window->ypos += delta.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_control (ctx, title_bar, true);
|
||||||
|
set_expand_x (ctx, title_bar, 100);
|
||||||
|
set_fill (ctx, title_bar, ctx->style.foreground.color[tb_mode]);
|
||||||
|
|
||||||
|
auto title = add_text (ctx, title_bar, state, mode);
|
||||||
|
View_Control (title)->gravity = grav_center;
|
||||||
|
|
||||||
|
if (UI_Button (va (0, "X##close_%s", window->name))) {
|
||||||
|
window->is_open = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef IMUI_context
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMUI_EndWindow (imui_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
IMUI_PopLayout (ctx);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue