ui code -> extend 'active' system to all left/middle/right mouse buttons, rather than just min/max (left/right)

This commit is contained in:
Ryan Fleury
2024-02-07 14:20:21 -08:00
parent fb9e890653
commit b9cec99cd4
4 changed files with 118 additions and 78 deletions
+3
View File
@@ -170,6 +170,9 @@
#define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end)) #define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end))
#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end)) #define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
#define EachEnumVal(type, it) type it = (type)0; it < type##_COUNT; it = (type)(it+1)
#define EachNonZeroEnumVal(type, it) type it = (type)1; it < type##_COUNT; it = (type)(it+1)
#if LANG_CPP #if LANG_CPP
# define zero_struct {} # define zero_struct {}
#else #else
+4 -1
View File
@@ -7537,7 +7537,10 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scop
internal void internal void
df_set_hover_eval(DF_Window *ws, Vec2F32 pos, DF_CtrlCtx ctrl_ctx, DF_Entity *file, TxtPt pt, U64 vaddr, String8 string) df_set_hover_eval(DF_Window *ws, Vec2F32 pos, DF_CtrlCtx ctrl_ctx, DF_Entity *file, TxtPt pt, U64 vaddr, String8 string)
{ {
if(ws->hover_eval_last_frame_idx+1 < df_frame_index() && ui_key_match(ui_active_key(Side_Min), ui_key_zero()) && ui_key_match(ui_active_key(Side_Max), ui_key_zero())) if(ws->hover_eval_last_frame_idx+1 < df_frame_index() &&
ui_key_match(ui_active_key(UI_MouseButtonKind_Left), ui_key_zero()) &&
ui_key_match(ui_active_key(UI_MouseButtonKind_Middle), ui_key_zero()) &&
ui_key_match(ui_active_key(UI_MouseButtonKind_Right), ui_key_zero()))
{ {
B32 is_new_string = !str8_match(ws->hover_eval_string, string, 0); B32 is_new_string = !str8_match(ws->hover_eval_string, string, 0);
if(is_new_string) if(is_new_string)
+55 -33
View File
@@ -591,9 +591,9 @@ ui_hot_key(void)
} }
internal UI_Key internal UI_Key
ui_active_key(Side side) ui_active_key(UI_MouseButtonKind button_kind)
{ {
return ui_state->active_box_key[side]; return ui_state->active_box_key[button_kind];
} }
//- rjf: controls over interaction //- rjf: controls over interaction
@@ -601,7 +601,10 @@ ui_active_key(Side side)
internal void internal void
ui_kill_action(void) ui_kill_action(void)
{ {
ui_state->active_box_key[Side_Min] = ui_state->active_box_key[Side_Max] = ui_key_zero(); for(EachEnumVal(UI_MouseButtonKind, k))
{
ui_state->active_box_key[k] = ui_key_zero();
}
} }
//- rjf: box cache lookup //- rjf: box cache lookup
@@ -958,32 +961,41 @@ ui_begin_build(OS_EventList *events, OS_Handle window, UI_NavActionList *nav_act
} }
//- rjf: reset hot if we don't have an active widget //- rjf: reset hot if we don't have an active widget
if(ui_key_match(ui_state->active_box_key[Side_Min], ui_key_zero()) && {
ui_key_match(ui_state->active_box_key[Side_Max], ui_key_zero())) B32 has_active = 0;
for(EachEnumVal(UI_MouseButtonKind, k))
{
if(!ui_key_match(ui_state->active_box_key[k], ui_key_zero()))
{
has_active = 1;
}
}
if(!has_active)
{ {
ui_state->hot_box_key = ui_key_zero(); ui_state->hot_box_key = ui_key_zero();
} }
}
//- rjf: reset active if our active box is disabled //- rjf: reset active if our active box is disabled
for(Side side = (Side)0; side < Side_COUNT; side = (Side)(side+1)) for(EachEnumVal(UI_MouseButtonKind, k))
{ {
if(!ui_key_match(ui_state->active_box_key[side], ui_key_zero())) if(!ui_key_match(ui_state->active_box_key[k], ui_key_zero()))
{ {
UI_Box *box = ui_box_from_key(ui_state->active_box_key[side]); UI_Box *box = ui_box_from_key(ui_state->active_box_key[k]);
if(!ui_box_is_nil(box) && box->flags & UI_BoxFlag_Disabled) if(!ui_box_is_nil(box) && box->flags & UI_BoxFlag_Disabled)
{ {
ui_state->active_box_key[side] = ui_key_zero(); ui_state->active_box_key[k] = ui_key_zero();
} }
} }
} }
//- rjf: reset active keys if they have been pruned //- rjf: reset active keys if they have been pruned
for(Side side = Side_Min; side < Side_COUNT; side = (Side)(side + 1)) for(EachEnumVal(UI_MouseButtonKind, k))
{ {
UI_Box *box = ui_box_from_key(ui_state->active_box_key[side]); UI_Box *box = ui_box_from_key(ui_state->active_box_key[k]);
if(ui_box_is_nil(box)) if(ui_box_is_nil(box))
{ {
ui_state->active_box_key[side] = ui_key_zero(); ui_state->active_box_key[k] = ui_key_zero();
} }
} }
@@ -993,9 +1005,9 @@ ui_begin_build(OS_EventList *events, OS_Handle window, UI_NavActionList *nav_act
if((event->kind == OS_EventKind_Press || event->kind == OS_EventKind_Release) && if((event->kind == OS_EventKind_Press || event->kind == OS_EventKind_Release) &&
!os_handle_match(event->window, window)) !os_handle_match(event->window, window))
{ {
for(Side side = Side_Min; side < Side_COUNT; side = (Side)(side + 1)) for(EachEnumVal(UI_MouseButtonKind, k))
{ {
ui_state->active_box_key[side] = ui_key_zero(); ui_state->active_box_key[k] = ui_key_zero();
} }
break; break;
} }
@@ -1154,7 +1166,7 @@ ui_end_build(void)
{ {
// rjf: grab states informing animation // rjf: grab states informing animation
B32 is_hot = ui_key_match(box->key, ui_state->hot_box_key); B32 is_hot = ui_key_match(box->key, ui_state->hot_box_key);
B32 is_active = ui_key_match(box->key, ui_state->active_box_key[Side_Min]); B32 is_active = ui_key_match(box->key, ui_state->active_box_key[UI_MouseButtonKind_Left]);
B32 is_disabled = !!(box->flags & UI_BoxFlag_Disabled) && (box->first_disabled_build_index+10 < ui_state->build_index || B32 is_disabled = !!(box->flags & UI_BoxFlag_Disabled) && (box->first_disabled_build_index+10 < ui_state->build_index ||
box->first_touched_build_index == box->first_disabled_build_index); box->first_touched_build_index == box->first_disabled_build_index);
B32 is_focus_hot = !!(box->flags & UI_BoxFlag_FocusHot) && !(box->flags & UI_BoxFlag_FocusHotDisabled); B32 is_focus_hot = !!(box->flags & UI_BoxFlag_FocusHot) && !(box->flags & UI_BoxFlag_FocusHotDisabled);
@@ -1273,7 +1285,7 @@ ui_end_build(void)
//- rjf: hover cursor //- rjf: hover cursor
{ {
UI_Box *hot = ui_box_from_key(ui_state->hot_box_key); UI_Box *hot = ui_box_from_key(ui_state->hot_box_key);
UI_Box *active = ui_box_from_key(ui_state->active_box_key[Side_Min]); UI_Box *active = ui_box_from_key(ui_state->active_box_key[UI_MouseButtonKind_Left]);
UI_Box *box = ui_box_is_nil(active) ? hot : active; UI_Box *box = ui_box_is_nil(active) ? hot : active;
OS_Cursor cursor = box->hover_cursor; OS_Cursor cursor = box->hover_cursor;
if(box->flags & UI_BoxFlag_Disabled && box->flags & UI_BoxFlag_Clickable) if(box->flags & UI_BoxFlag_Disabled && box->flags & UI_BoxFlag_Clickable)
@@ -1313,8 +1325,17 @@ ui_end_build(void)
} }
//- rjf: hovering possibly-truncated drawn text -> store text //- rjf: hovering possibly-truncated drawn text -> store text
if(ui_key_match(ui_key_zero(), ui_state->active_box_key[Side_Min]) && {
ui_key_match(ui_key_zero(), ui_state->active_box_key[Side_Max])) B32 inactive = 1;
for(EachEnumVal(UI_MouseButtonKind, k))
{
if(!ui_key_match(ui_key_zero(), ui_state->active_box_key[k]))
{
inactive = 0;
break;
}
}
if(inactive)
{ {
B32 found = 0; B32 found = 0;
for(UI_Box *box = ui_state->root, *next = 0; !ui_box_is_nil(box); box = next) for(UI_Box *box = ui_state->root, *next = 0; !ui_box_is_nil(box); box = next)
@@ -1367,6 +1388,7 @@ ui_end_build(void)
ui_state->is_animating = 1; ui_state->is_animating = 1;
} }
} }
}
ui_state->build_index += 1; ui_state->build_index += 1;
arena_clear(ui_build_arena()); arena_clear(ui_build_arena());
@@ -2449,8 +2471,8 @@ ui_signal_from_box(UI_Box *box)
if(box->flags & UI_BoxFlag_MouseClickable && !ui_key_match(ui_key_zero(), box->key)) ProfScope("clickability") if(box->flags & UI_BoxFlag_MouseClickable && !ui_key_match(ui_key_zero(), box->key)) ProfScope("clickability")
{ {
// rjf: hot management // rjf: hot management
if((ui_key_match(ui_key_zero(), ui_state->active_box_key[Side_Min]) && if((ui_key_match(ui_key_zero(), ui_state->active_box_key[UI_MouseButtonKind_Left]) &&
ui_key_match(ui_key_zero(), ui_state->active_box_key[Side_Max])) && ui_key_match(ui_key_zero(), ui_state->active_box_key[UI_MouseButtonKind_Right])) &&
ui_key_match(ui_key_zero(), ui_state->hot_box_key) && ui_key_match(ui_key_zero(), ui_state->hot_box_key) &&
mouse_is_over) mouse_is_over)
{ {
@@ -2458,8 +2480,8 @@ ui_signal_from_box(UI_Box *box)
} }
else if(ui_key_match(ui_state->hot_box_key, box->key) && else if(ui_key_match(ui_state->hot_box_key, box->key) &&
!mouse_is_over && !mouse_is_over &&
!ui_key_match(ui_state->active_box_key[Side_Min], box->key) && !ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], box->key) &&
!ui_key_match(ui_state->active_box_key[Side_Max], box->key)) !ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Right], box->key))
{ {
ui_state->hot_box_key = ui_key_zero(); ui_state->hot_box_key = ui_key_zero();
} }
@@ -2467,48 +2489,48 @@ ui_signal_from_box(UI_Box *box)
// rjf: active management (left click) // rjf: active management (left click)
if(!disabled && if(!disabled &&
ui_key_match(ui_state->hot_box_key, box->key) && ui_key_match(ui_state->hot_box_key, box->key) &&
ui_key_match(ui_state->active_box_key[Side_Min], ui_key_zero()) && ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], ui_key_zero()) &&
left_press != 0) left_press != 0)
{ {
os_eat_event(ui_state->events, left_press); os_eat_event(ui_state->events, left_press);
result.pressed = 1; result.pressed = 1;
ui_state->active_box_key[Side_Min] = box->key; ui_state->active_box_key[UI_MouseButtonKind_Left] = box->key;
} }
else if(!disabled && else if(!disabled &&
ui_key_match(ui_state->active_box_key[Side_Min], box->key) && ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], box->key) &&
left_release != 0) left_release != 0)
{ {
os_eat_event(ui_state->events, left_release); os_eat_event(ui_state->events, left_release);
result.released = 1; result.released = 1;
result.clicked = mouse_is_over; result.clicked = mouse_is_over;
ui_state->hot_box_key = mouse_is_over ? box->key : ui_key_zero(); ui_state->hot_box_key = mouse_is_over ? box->key : ui_key_zero();
ui_state->active_box_key[Side_Min] = ui_key_zero(); ui_state->active_box_key[UI_MouseButtonKind_Left] = ui_key_zero();
} }
// rjf: active management (right click) // rjf: active management (right click)
if(!disabled && if(!disabled &&
ui_key_match(ui_state->hot_box_key, box->key) && ui_key_match(ui_state->hot_box_key, box->key) &&
ui_key_match(ui_state->active_box_key[Side_Max], ui_key_zero()) && ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Right], ui_key_zero()) &&
right_press != 0) right_press != 0)
{ {
os_eat_event(ui_state->events, right_press); os_eat_event(ui_state->events, right_press);
// NOTE(rjf): Add this in if it ever needs to exist: // NOTE(rjf): Add this in if it ever needs to exist:
// result.right_pressed = 1; // result.right_pressed = 1;
ui_state->active_box_key[Side_Max] = box->key; ui_state->active_box_key[UI_MouseButtonKind_Right] = box->key;
} }
else if(!disabled && else if(!disabled &&
ui_key_match(ui_state->active_box_key[Side_Max], box->key) && ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Right], box->key) &&
right_release != 0) right_release != 0)
{ {
os_eat_event(ui_state->events, right_release); os_eat_event(ui_state->events, right_release);
// NOTE(rjf): Add this in if it ever needs to exist: // NOTE(rjf): Add this in if it ever needs to exist:
// result.right_released = 1; // result.right_released = 1;
result.right_clicked = mouse_is_over; result.right_clicked = mouse_is_over;
ui_state->active_box_key[Side_Max] = ui_key_zero(); ui_state->active_box_key[UI_MouseButtonKind_Right] = ui_key_zero();
} }
// rjf: dragging // rjf: dragging
if(ui_key_match(ui_state->active_box_key[Side_Min], box->key)) if(ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], box->key))
{ {
result.dragging = 1; result.dragging = 1;
if(result.pressed) if(result.pressed)
@@ -2700,8 +2722,8 @@ ui_signal_from_box(UI_Box *box)
//- rjf: set hovering status //- rjf: set hovering status
result.hovering = mouse_is_over && ((ui_key_match(ui_state->hot_box_key, ui_key_zero()) || result.hovering = mouse_is_over && ((ui_key_match(ui_state->hot_box_key, ui_key_zero()) ||
ui_key_match(ui_state->hot_box_key, box->key)) && ui_key_match(ui_state->hot_box_key, box->key)) &&
(ui_key_match(ui_state->active_box_key[Side_Min], ui_key_zero()) || (ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], ui_key_zero()) ||
ui_key_match(ui_state->active_box_key[Side_Min], box->key))); ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], box->key)));
result.mouse_over = mouse_is_over; result.mouse_over = mouse_is_over;
//- rjf: clicking in default nav -> set navigation state to this box //- rjf: clicking in default nav -> set navigation state to this box
+16 -4
View File
@@ -31,6 +31,18 @@ struct UI_IconInfo
String8 icon_kind_text_map[UI_IconKind_COUNT]; String8 icon_kind_text_map[UI_IconKind_COUNT];
}; };
////////////////////////////////
//~ rjf: Mouse Button Kinds
typedef enum UI_MouseButtonKind
{
UI_MouseButtonKind_Left,
UI_MouseButtonKind_Middle,
UI_MouseButtonKind_Right,
UI_MouseButtonKind_COUNT
}
UI_MouseButtonKind;
//////////////////////////////// ////////////////////////////////
//~ rjf: Focus Types //~ rjf: Focus Types
@@ -415,10 +427,10 @@ struct UI_State
//- rjf: user interaction state //- rjf: user interaction state
UI_Key hot_box_key; UI_Key hot_box_key;
UI_Key active_box_key[Side_COUNT]; UI_Key active_box_key[UI_MouseButtonKind_COUNT];
UI_Key clipboard_copy_key; UI_Key clipboard_copy_key;
F32 time_since_last_click[Side_COUNT]; F32 time_since_last_click[UI_MouseButtonKind_COUNT];
UI_Key last_click_key[Side_COUNT]; UI_Key last_click_key[UI_MouseButtonKind_COUNT];
Vec2F32 drag_start_mouse; Vec2F32 drag_start_mouse;
Arena *drag_state_arena; Arena *drag_state_arena;
String8 drag_state_data; String8 drag_state_data;
@@ -551,7 +563,7 @@ internal D_FancyRunList ui_string_hover_runs(Arena *arena);
//- rjf: interaction keys //- rjf: interaction keys
internal UI_Key ui_hot_key(void); internal UI_Key ui_hot_key(void);
internal UI_Key ui_active_key(Side side); internal UI_Key ui_active_key(UI_MouseButtonKind button_kind);
//- rjf: controls over interaction //- rjf: controls over interaction
internal void ui_kill_action(void); internal void ui_kill_action(void);