ui truncated string hovering -> display full string as a tooltip

This commit is contained in:
Ryan Fleury
2024-01-26 09:04:29 -08:00
parent 33f5d4f5b1
commit 89af8124c7
8 changed files with 139 additions and 4 deletions
+13
View File
@@ -2886,6 +2886,19 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
Rng2F32 bottom_bar_rect = r2f32p(window_rect.x0, window_rect_dim.y - ui_top_pref_height().value, window_rect.x0+window_rect_dim.x, window_rect.y0+window_rect_dim.y);
Rng2F32 content_rect = r2f32p(window_rect.x0, top_bar_rect.y1, window_rect.x0+window_rect_dim.x, bottom_bar_rect.y0);
////////////////////////////
//- rjf: truncated string hover
//
if(ui_string_hover_active()) UI_Tooltip
{
Temp scratch = scratch_begin(&arena, 1);
String8 string = ui_string_hover_string(scratch.arena);
D_FancyRunList runs = ui_string_hover_runs(scratch.arena);
UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero());
ui_box_equip_display_string_fancy_runs(box, string, &runs);
scratch_end(scratch);
}
////////////////////////////
//- rjf: drag/drop visualization tooltips
//
+16
View File
@@ -90,6 +90,22 @@ d_fancy_run_list_from_fancy_string_list(Arena *arena, D_FancyStringList *strs)
return run_list;
}
internal D_FancyRunList
d_fancy_run_list_copy(Arena *arena, D_FancyRunList *src)
{
D_FancyRunList dst = {0};
for(D_FancyRunNode *src_n = src->first; src_n != 0; src_n = src_n->next)
{
D_FancyRunNode *dst_n = push_array(arena, D_FancyRunNode, 1);
SLLQueuePush(dst.first, dst.last, dst_n);
MemoryCopyStruct(&dst_n->v, &src_n->v);
dst_n->v.run.pieces = f_piece_array_copy(arena, &src_n->v.run.pieces);
dst.node_count += 1;
}
dst.dim = src->dim;
return dst;
}
////////////////////////////////
//~ rjf: Top-Level API
//
+1
View File
@@ -111,6 +111,7 @@ internal U64 d_hash_from_string(String8 string);
internal void d_fancy_string_list_push(Arena *arena, D_FancyStringList *list, D_FancyString *str);
internal String8 d_string_from_fancy_string_list(Arena *arena, D_FancyStringList *list);
internal D_FancyRunList d_fancy_run_list_from_fancy_string_list(Arena *arena, D_FancyStringList *strs);
internal D_FancyRunList d_fancy_run_list_copy(Arena *arena, D_FancyRunList *src);
////////////////////////////////
//~ rjf: Top-Level API
+10
View File
@@ -502,6 +502,16 @@ f_piece_array_from_chunk_list(Arena *arena, F_PieceChunkList *list)
return array;
}
internal F_PieceArray
f_piece_array_copy(Arena *arena, F_PieceArray *src)
{
F_PieceArray dst = {0};
dst.count = src->count;
dst.v = push_array_no_zero(arena, F_Piece, dst.count);
MemoryCopy(dst.v, src->v, sizeof(F_Piece)*dst.count);
return dst;
}
////////////////////////////////
//~ rjf: Rasterization Cache
+1
View File
@@ -241,6 +241,7 @@ internal void f_atlas_region_release(F_Atlas *atlas, Rng2S16 region);
internal F_Piece *f_piece_chunk_list_push_new(Arena *arena, F_PieceChunkList *list, U64 cap);
internal void f_piece_chunk_list_push(Arena *arena, F_PieceChunkList *list, U64 cap, F_Piece *piece);
internal F_PieceArray f_piece_array_from_chunk_list(Arena *arena, F_PieceChunkList *list);
internal F_PieceArray f_piece_array_copy(Arena *arena, F_PieceArray *src);
////////////////////////////////
//~ rjf: Rasterization Cache
-4
View File
@@ -7,13 +7,9 @@
// [ ] source view -> floating margin/line-nums
// [ ] theme colors -> more explicit about e.g. opaque backgrounds vs. floating
// & scrollbars etc.
// [ ] need bilinear interpolation on color picker - fine for most UI to not do
// do it but it needs to be correct for the color picker, so maybe that
// should be a heavier path
// [ ] drag/drop tab cleanup
// [ ] target/breakpoint/watch-pin reordering
// [ ] watch window reordering
// [x] query views, cleanup & floating - maybe merge "applies to view" vs. not
// [ ] standard way to filter
// [ ] visualize remapped files (via path map)
// [ ] hovering truncated string for a short time -> tooltip with full wrapped
+88
View File
@@ -428,6 +428,7 @@ ui_state_alloc(void)
ui->build_arenas[0] = arena_alloc();
ui->build_arenas[1] = arena_alloc();
ui->drag_state_arena = arena_alloc();
ui->string_hover_arena = arena_alloc();
ui->box_table_size = 4096;
ui->box_table = push_array(arena, UI_BoxHashSlot, ui->box_table_size);
UI_InitStackNils(ui);
@@ -437,6 +438,7 @@ ui_state_alloc(void)
internal void
ui_state_release(UI_State *state)
{
arena_release(state->string_hover_arena);
arena_release(state->drag_state_arena);
for(int i = 0; i < ArrayCount(state->build_arenas); i += 1)
{
@@ -551,6 +553,35 @@ ui_get_drag_data(U64 min_required_size)
return ui_state->drag_state_data;
}
//- rjf: hovered string info
internal B32
ui_string_hover_active(void)
{
return (ui_state->build_index > 0 && ui_state->string_hover_build_index >= ui_state->build_index-1 &&
os_now_microseconds() >= ui_state->string_hover_begin_us + 500000);
}
internal U64
ui_string_hover_begin_time_us(void)
{
return ui_state->string_hover_begin_us;
}
internal String8
ui_string_hover_string(Arena *arena)
{
String8 result = push_str8_copy(arena, ui_state->string_hover_string);
return result;
}
internal D_FancyRunList
ui_string_hover_runs(Arena *arena)
{
D_FancyRunList result = d_fancy_run_list_copy(arena, &ui_state->string_hover_fancy_runs);
return result;
}
//- rjf: interaction keys
internal UI_Key
@@ -1270,6 +1301,55 @@ ui_end_build(void)
scratch_end(scratch);
}
//- rjf: hovering possibly-truncated drawn text -> store text
{
B32 found = 0;
for(UI_Box *box = ui_state->root, *next = 0; !ui_box_is_nil(box); box = next)
{
UI_BoxRec rec = ui_box_rec_df_pre(box, ui_state->root);
next = rec.next;
S32 pop_idx = 0;
for(UI_Box *b = box; !ui_box_is_nil(b) && pop_idx <= rec.pop_count; b = b->parent, pop_idx += 1)
{
if(b->flags & UI_BoxFlag_DrawText && !(b->flags & UI_BoxFlag_DisableTextTrunc))
{
String8 box_display_string = ui_box_display_string(b);
Vec2F32 text_pos = ui_box_text_position(b);
Vec2F32 drawn_text_dim = b->display_string_runs.dim;
if(drawn_text_dim.x > dim_2f32(b->rect).x &&
contains_2f32(r2f32p(text_pos.x,
b->rect.y0,
Min(text_pos.x+drawn_text_dim.x, b->rect.x1),
b->rect.y1),
ui_state->mouse))
{
if(!str8_match(box_display_string, ui_state->string_hover_string, 0))
{
arena_clear(ui_state->string_hover_arena);
ui_state->string_hover_string = push_str8_copy(ui_state->string_hover_arena, box_display_string);
ui_state->string_hover_fancy_runs = d_fancy_run_list_copy(ui_state->string_hover_arena, &b->display_string_runs);
ui_state->string_hover_begin_us = os_now_microseconds();
}
ui_state->string_hover_build_index = ui_state->build_index;
found = 1;
goto break_all_hover_string;
}
}
}
}
break_all_hover_string:;
if(!found)
{
arena_clear(ui_state->string_hover_arena);
ui_state->string_hover_build_index = 0;
MemoryZeroStruct(&ui_state->string_hover_string);
}
if(found && !ui_string_hover_active())
{
ui_state->is_animating = 1;
}
}
ui_state->build_index += 1;
arena_clear(ui_build_arena());
ProfEnd();
@@ -2103,6 +2183,14 @@ ui_box_equip_display_fancy_strings(UI_Box *box, D_FancyStringList *strings)
box->display_string_runs = d_fancy_run_list_from_fancy_string_list(ui_build_arena(), strings);
}
internal inline void
ui_box_equip_display_string_fancy_runs(UI_Box *box, String8 string, D_FancyRunList *runs)
{
box->flags |= UI_BoxFlag_HasDisplayString;
box->string = push_str8_copy(ui_build_arena(), string);
box->display_string_runs = d_fancy_run_list_copy(ui_build_arena(), runs);
}
internal void
ui_box_equip_draw_bucket(UI_Box *box, D_Bucket *bucket)
{
+10
View File
@@ -416,6 +416,11 @@ struct UI_State
Vec2F32 drag_start_mouse;
Arena *drag_state_arena;
String8 drag_state_data;
Arena *string_hover_arena;
String8 string_hover_string;
D_FancyRunList string_hover_fancy_runs;
U64 string_hover_begin_us;
U64 string_hover_build_index;
//- rjf: tooltip state
F32 tooltip_open_t;
@@ -533,6 +538,10 @@ internal String8 ui_get_drag_data(U64 min_required_size);
#define ui_store_drag_struct(ptr) ui_store_drag_data(str8_struct(ptr))
#define ui_get_drag_struct(type) ((type *)ui_get_drag_data(sizeof(type)).str)
//- rjf: hovered string info
internal B32 ui_string_hover_active(void);
internal D_FancyRunList ui_string_hover_runs(Arena *arena);
//- rjf: interaction keys
internal UI_Key ui_hot_key(void);
internal UI_Key ui_active_key(Side side);
@@ -591,6 +600,7 @@ internal UI_Box * ui_build_box_from_stringf(UI_BoxFlags flags, char *fm
//- rjf: box node equipment
internal inline void ui_box_equip_display_string(UI_Box *box, String8 string);
internal inline void ui_box_equip_display_fancy_strings(UI_Box *box, D_FancyStringList *strings);
internal inline void ui_box_equip_display_string_fancy_runs(UI_Box *box, String8 string, D_FancyRunList *runs);
internal inline void ui_box_equip_draw_bucket(UI_Box *box, D_Bucket *bucket);
internal inline void ui_box_equip_custom_draw(UI_Box *box, UI_BoxCustomDrawFunctionType *custom_draw, void *user_data);