mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-17 17:42:22 -07:00
further work on autocompletion system; more carefully preserve information about cursor / what is being replaced, do not apply autocompletion lister enabling setting to required listers (e.g. for settings/themes), and adjust navigation controls such that arrowkeys are consumed by the autocompletion lister (in principle this is 'stealing' functionality from the source ui, e.g. the watch window using up/down to go to different rows, but in practice when an autocompletion lister pops up, it feels way more natural to use arrowkeys)
This commit is contained in:
@@ -931,7 +931,7 @@ RD_CmdTable: // | | | |
|
||||
{Paste 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Clipboard "paste" "Paste" "Pastes the current contents of the clipboard." "" "" }
|
||||
{InsertText 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "insert_text" "Insert Text" "Inserts the text that was used to cause this command." "" "" }
|
||||
|
||||
//- rjf: secondary navigation
|
||||
//- rjf: directionless navigation
|
||||
{MoveNext 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_next" "Move Next" "Moves the cursor or selection to the next element." "" "" }
|
||||
{MovePrev 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_prev" "Move Previous" "Moves the cursor or selection to the previous element." "" "" }
|
||||
|
||||
|
||||
+141
-128
@@ -3585,12 +3585,14 @@ rd_view_ui(Rng2F32 rect)
|
||||
if(!(evt->flags & UI_EventFlag_Delete) && autocomplete_hint_string.size != 0)
|
||||
{
|
||||
take_autocomplete = 1;
|
||||
RD_AutocompCursorInfo autocomp_cursor_info = rd_autocomp_cursor_info_from_input_string_off(scratch.arena, string, edit_state->cursor.column-1);
|
||||
String8 new_string = ui_push_string_replace_range(scratch.arena, string, r1s64(autocomp_cursor_info.replaced_range.min+1, autocomp_cursor_info.replaced_range.max+1), autocomplete_hint_string);
|
||||
RD_Cfg *window = rd_cfg_from_id(rd_regs()->window);
|
||||
RD_WindowState *ws = rd_window_state_from_cfg(window);
|
||||
RD_AutocompCursorInfo *autocomp_cursor_info = &ws->autocomp_cursor_info;
|
||||
String8 new_string = ui_push_string_replace_range(scratch.arena, string, r1s64(autocomp_cursor_info->replaced_range.min+1, autocomp_cursor_info->replaced_range.max+1), autocomplete_hint_string);
|
||||
new_string.size = Min(sizeof(edit_state->input_buffer), new_string.size);
|
||||
MemoryCopy(edit_state->input_buffer, new_string.str, new_string.size);
|
||||
edit_state->input_size = new_string.size;
|
||||
edit_state->cursor = edit_state->mark = txt_pt(1, 1+autocomp_cursor_info.replaced_range.min+autocomplete_hint_string.size);
|
||||
edit_state->cursor = edit_state->mark = txt_pt(1, 1+autocomp_cursor_info->replaced_range.min+autocomplete_hint_string.size);
|
||||
string = str8(edit_state->input_buffer, edit_state->input_size);
|
||||
op = ui_single_line_txt_op_from_event(scratch.arena, evt, string, edit_state->cursor, edit_state->mark);
|
||||
}
|
||||
@@ -4964,15 +4966,7 @@ rd_view_ui(Rng2F32 rect)
|
||||
txt_pt_match(cell_edit_state->cursor, cell_edit_state->mark))
|
||||
{
|
||||
String8 input = str8(cell_edit_state->input_buffer, cell_edit_state->input_size);
|
||||
String8 list_expr = rd_autocomp_primary_list_expr_from_dst_eval(scratch.arena, cell->eval);
|
||||
RD_AutocompCursorInfo cursor_info = rd_autocomp_cursor_info_from_input_string_off(scratch.arena, input, cell_edit_state->cursor.column-1);
|
||||
if(cursor_info.list_expr.size != 0)
|
||||
{
|
||||
list_expr = cursor_info.list_expr;
|
||||
}
|
||||
rd_set_autocomp_regs(.ui_key = line_edit_key,
|
||||
.string = cursor_info.filter,
|
||||
.expr = list_expr);
|
||||
rd_set_autocomp_regs(cell->eval, .ui_key = line_edit_key, .string = input);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6668,7 +6662,7 @@ rd_window_frame(void)
|
||||
RD_Font(RD_FontSlot_Code)
|
||||
{
|
||||
//- rjf: add autocompletion view task
|
||||
if(rd_setting_b32_from_name(str8_lit("autocompletion_lister")) && ws->autocomp_regs != 0 && ws->autocomp_last_frame_index+1 >= rd_state->frame_index)
|
||||
if(ws->autocomp_regs != 0 && ws->autocomp_last_frame_index+1 >= rd_state->frame_index)
|
||||
{
|
||||
// rjf: build view
|
||||
RD_Cfg *root = rd_immediate_cfg_from_keyf("autocomp_view_%I64x", window->id);
|
||||
@@ -6678,7 +6672,7 @@ rd_window_frame(void)
|
||||
RD_Cfg *input = rd_cfg_child_from_string_or_alloc(query, str8_lit("input"));
|
||||
rd_cfg_new_replace(input, ws->autocomp_regs->string);
|
||||
RD_Cfg *expr = rd_cfg_child_from_string_or_alloc(view, str8_lit("expression"));
|
||||
rd_cfg_new_replace(expr, ws->autocomp_regs->expr);
|
||||
rd_cfg_new_replace(expr, ws->autocomp_cursor_info.list_expr);
|
||||
|
||||
// rjf: determine container size
|
||||
EV_BlockTree predicted_block_tree = {0};
|
||||
@@ -9621,123 +9615,142 @@ rd_set_hover_eval(Vec2F32 pos, String8 string)
|
||||
////////////////////////////////
|
||||
//~ rjf: Autocompletion Lister
|
||||
|
||||
internal String8
|
||||
rd_autocomp_primary_list_expr_from_dst_eval(Arena *arena, E_Eval dst_eval)
|
||||
{
|
||||
String8 result = str8_lit("query:locals, query:globals, query:thread_locals, query:procedures, query:types");
|
||||
{
|
||||
E_TypeKey maybe_enum_type = e_type_key_unwrap(dst_eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative & ~E_TypeUnwrapFlag_Enums);
|
||||
if(dst_eval.space.kind == RD_EvalSpaceKind_MetaCfg && str8_match(e_string_from_id(dst_eval.space.u64s[1]), str8_lit("theme"), 0))
|
||||
{
|
||||
result = str8_lit("query:themes");
|
||||
}
|
||||
#if 0
|
||||
else if(e_type_kind_from_key(maybe_enum_type) == E_TypeKind_Enum)
|
||||
{
|
||||
result = e_type_string_from_key(arena, maybe_enum_type);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal RD_AutocompCursorInfo
|
||||
rd_autocomp_cursor_info_from_input_string_off(Arena *arena, String8 input, U64 cursor_off)
|
||||
{
|
||||
RD_AutocompCursorInfo result = {0};
|
||||
{
|
||||
result.filter = input;
|
||||
result.replaced_range = r1u64(0, input.size);
|
||||
}
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_Parse parse = e_parse_from_string(input);
|
||||
|
||||
//- rjf: cursor offset -> cursor containing node
|
||||
E_Expr *cursor_expr = &e_expr_nil;
|
||||
E_Expr *cursor_expr_parent = &e_expr_nil;
|
||||
{
|
||||
typedef struct ExprWalkTask ExprWalkTask;
|
||||
struct ExprWalkTask
|
||||
{
|
||||
ExprWalkTask *next;
|
||||
E_Expr *parent;
|
||||
E_Expr *expr;
|
||||
};
|
||||
ExprWalkTask start_task = {0, &e_expr_nil, parse.expr};
|
||||
ExprWalkTask *first_task = &start_task;
|
||||
ExprWalkTask *last_task = first_task;
|
||||
for(E_Expr *chain = parse.expr->next; chain != &e_expr_nil; chain = chain->next)
|
||||
{
|
||||
ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1);
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
task->parent = &e_expr_nil;
|
||||
task->expr = chain;
|
||||
}
|
||||
for(ExprWalkTask *t = first_task; t != 0; t = t->next)
|
||||
{
|
||||
E_Expr *e = t->expr;
|
||||
if(contains_1u64(e->range, cursor_off) || cursor_off == e->range.max)
|
||||
{
|
||||
cursor_expr_parent = t->parent;
|
||||
cursor_expr = e;
|
||||
break;
|
||||
}
|
||||
for(E_Expr *child = e->first; child != &e_expr_nil; child = child->next)
|
||||
{
|
||||
ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1);
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
task->parent = e;
|
||||
task->expr = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: cursor is on right-hand-side of dot? -> show members of left-hand-side
|
||||
B32 did_special_cursor_case = 0;
|
||||
if(!did_special_cursor_case)
|
||||
{
|
||||
E_Expr *dot_expr = &e_expr_nil;
|
||||
if(cursor_expr->kind == E_ExprKind_MemberAccess && cursor_off == cursor_expr->range.max)
|
||||
{
|
||||
dot_expr = cursor_expr;
|
||||
}
|
||||
else if(cursor_expr_parent->kind == E_ExprKind_MemberAccess && cursor_expr == cursor_expr_parent->first->next)
|
||||
{
|
||||
dot_expr = cursor_expr_parent;
|
||||
}
|
||||
if(dot_expr != &e_expr_nil)
|
||||
{
|
||||
did_special_cursor_case = 1;
|
||||
E_Eval lhs_eval = e_eval_from_expr(dot_expr->first);
|
||||
E_Eval type_of_lhs_eval = e_eval_wrapf(lhs_eval, "typeof($)");
|
||||
result.list_expr = e_full_expr_string_from_key(arena, type_of_lhs_eval.key);
|
||||
result.filter = cursor_expr->string;
|
||||
result.replaced_range = union_1u64(dot_expr->range, cursor_expr->range);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: cursor is on a leaf-identifier? -> replace just that identifier, keep the original list expression
|
||||
if(!did_special_cursor_case && cursor_expr->kind == E_ExprKind_LeafIdentifier)
|
||||
{
|
||||
did_special_cursor_case = 1;
|
||||
result.filter = str8_prefix(cursor_expr->string, cursor_off - cursor_expr->range.min);
|
||||
result.replaced_range = cursor_expr->range;
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
rd_set_autocomp_regs_(RD_Regs *regs)
|
||||
rd_set_autocomp_regs_(E_Eval dst_eval, RD_Regs *regs)
|
||||
{
|
||||
RD_Cfg *window_cfg = rd_cfg_from_id(rd_regs()->window);
|
||||
RD_WindowState *ws = rd_window_state_from_cfg(window_cfg);
|
||||
if(ws->autocomp_last_frame_index < rd_state->frame_index)
|
||||
{
|
||||
ws->autocomp_last_frame_index = rd_state->frame_index;
|
||||
arena_clear(ws->autocomp_arena);
|
||||
ws->autocomp_regs = rd_regs_copy(ws->autocomp_arena, regs);
|
||||
//- rjf: calculate information about the cursor:
|
||||
// * what list should we generate?
|
||||
// * what string in the input should we replace?
|
||||
// etc.
|
||||
B32 is_allowed = 0;
|
||||
RD_AutocompCursorInfo cursor_info = {0};
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
// rjf: calculate most general list expression, given the dst_eval space
|
||||
B32 force_allow = 0;
|
||||
B32 expr_based_replace = 1;
|
||||
String8 list_expr = str8_lit("query:locals, query:globals, query:thread_locals, query:procedures, query:types");
|
||||
{
|
||||
E_TypeKey maybe_enum_type = e_type_key_unwrap(dst_eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative & ~E_TypeUnwrapFlag_Enums);
|
||||
if(dst_eval.space.kind == RD_EvalSpaceKind_MetaCfg && str8_match(e_string_from_id(dst_eval.space.u64s[1]), str8_lit("theme"), 0))
|
||||
{
|
||||
list_expr = str8_lit("query:themes");
|
||||
expr_based_replace = 0;
|
||||
force_allow = 1;
|
||||
}
|
||||
#if 0
|
||||
else if(e_type_kind_from_key(maybe_enum_type) == E_TypeKind_Enum)
|
||||
{
|
||||
list_expr = e_type_string_from_key(arena, maybe_enum_type);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// rjf: determine if autocompletion lister is allowed
|
||||
is_allowed = (force_allow || rd_setting_b32_from_name(str8_lit("autocompletion_lister")));
|
||||
|
||||
// rjf: tighten list_expr, and filter / replaced-range, if needed
|
||||
String8 filter = regs->string;
|
||||
Rng1U64 replaced_range = r1u64(0, filter.size);
|
||||
if(expr_based_replace)
|
||||
{
|
||||
U64 cursor_off = (U64)(regs->cursor.column-1);
|
||||
E_Parse parse = e_parse_from_string(regs->string);
|
||||
|
||||
//- rjf: cursor offset -> cursor containing node
|
||||
E_Expr *cursor_expr = &e_expr_nil;
|
||||
E_Expr *cursor_expr_parent = &e_expr_nil;
|
||||
{
|
||||
typedef struct ExprWalkTask ExprWalkTask;
|
||||
struct ExprWalkTask
|
||||
{
|
||||
ExprWalkTask *next;
|
||||
E_Expr *parent;
|
||||
E_Expr *expr;
|
||||
};
|
||||
ExprWalkTask start_task = {0, &e_expr_nil, parse.expr};
|
||||
ExprWalkTask *first_task = &start_task;
|
||||
ExprWalkTask *last_task = first_task;
|
||||
for(E_Expr *chain = parse.expr->next; chain != &e_expr_nil; chain = chain->next)
|
||||
{
|
||||
ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1);
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
task->parent = &e_expr_nil;
|
||||
task->expr = chain;
|
||||
}
|
||||
for(ExprWalkTask *t = first_task; t != 0; t = t->next)
|
||||
{
|
||||
E_Expr *e = t->expr;
|
||||
if(contains_1u64(e->range, cursor_off) || cursor_off == e->range.max)
|
||||
{
|
||||
cursor_expr_parent = t->parent;
|
||||
cursor_expr = e;
|
||||
break;
|
||||
}
|
||||
for(E_Expr *child = e->first; child != &e_expr_nil; child = child->next)
|
||||
{
|
||||
ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1);
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
task->parent = e;
|
||||
task->expr = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: cursor is on right-hand-side of dot? -> show members of left-hand-side
|
||||
B32 did_special_cursor_case = 0;
|
||||
if(!did_special_cursor_case)
|
||||
{
|
||||
E_Expr *dot_expr = &e_expr_nil;
|
||||
if(cursor_expr->kind == E_ExprKind_MemberAccess && cursor_off == cursor_expr->range.max)
|
||||
{
|
||||
dot_expr = cursor_expr;
|
||||
}
|
||||
else if(cursor_expr_parent->kind == E_ExprKind_MemberAccess && cursor_expr == cursor_expr_parent->first->next)
|
||||
{
|
||||
dot_expr = cursor_expr_parent;
|
||||
}
|
||||
if(dot_expr != &e_expr_nil)
|
||||
{
|
||||
did_special_cursor_case = 1;
|
||||
E_Eval lhs_eval = e_eval_from_expr(dot_expr->first);
|
||||
E_Eval type_of_lhs_eval = e_eval_wrapf(lhs_eval, "typeof($)");
|
||||
list_expr = e_full_expr_string_from_key(scratch.arena, type_of_lhs_eval.key);
|
||||
filter = cursor_expr->string;
|
||||
replaced_range = union_1u64(dot_expr->range, cursor_expr->range);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: cursor is on a leaf-identifier? -> replace just that identifier, keep the original list expression
|
||||
if(!did_special_cursor_case && cursor_expr->kind == E_ExprKind_LeafIdentifier)
|
||||
{
|
||||
did_special_cursor_case = 1;
|
||||
filter = str8_prefix(cursor_expr->string, cursor_off - cursor_expr->range.min);
|
||||
replaced_range = cursor_expr->range;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: fill bundle
|
||||
cursor_info.list_expr = push_str8_copy(ws->autocomp_arena, list_expr);
|
||||
cursor_info.filter = push_str8_copy(ws->autocomp_arena, filter);
|
||||
cursor_info.replaced_range = replaced_range;
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
//- rjf: commit autocompletion info
|
||||
if(is_allowed)
|
||||
{
|
||||
ws->autocomp_last_frame_index = rd_state->frame_index;
|
||||
arena_clear(ws->autocomp_arena);
|
||||
ws->autocomp_regs = rd_regs_copy(ws->autocomp_arena, regs);
|
||||
ws->autocomp_cursor_info = cursor_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15181,7 +15194,7 @@ rd_frame(void)
|
||||
RD_WindowState *ws = rd_window_state_from_cfg(window);
|
||||
UI_Event evt = zero_struct;
|
||||
evt.kind = UI_EventKind_Navigate;
|
||||
evt.flags = UI_EventFlag_ExplicitDirectional;
|
||||
evt.flags = UI_EventFlag_ExplicitDirectional|UI_EventFlag_Secondary;
|
||||
evt.delta_unit = UI_EventDeltaUnit_Char;
|
||||
evt.delta_2s32 = v2s32(+0, -1);
|
||||
ui_event_list_push(scratch.arena, &ws->ui_events, &evt);
|
||||
@@ -15192,7 +15205,7 @@ rd_frame(void)
|
||||
RD_WindowState *ws = rd_window_state_from_cfg(window);
|
||||
UI_Event evt = zero_struct;
|
||||
evt.kind = UI_EventKind_Navigate;
|
||||
evt.flags = UI_EventFlag_ExplicitDirectional;
|
||||
evt.flags = UI_EventFlag_ExplicitDirectional|UI_EventFlag_Secondary;
|
||||
evt.delta_unit = UI_EventDeltaUnit_Char;
|
||||
evt.delta_2s32 = v2s32(+0, +1);
|
||||
ui_event_list_push(scratch.arena, &ws->ui_events, &evt);
|
||||
@@ -15574,7 +15587,7 @@ rd_frame(void)
|
||||
ui_event_list_push(scratch.arena, &ws->ui_events, &evt);
|
||||
}break;
|
||||
|
||||
//- rjf: secondary navigation
|
||||
//- rjf: directionless navigation
|
||||
case RD_CmdKind_MoveNext:
|
||||
{
|
||||
RD_Cfg *window = rd_cfg_from_id(rd_regs()->window);
|
||||
|
||||
@@ -483,6 +483,7 @@ struct RD_WindowState
|
||||
U64 autocomp_last_frame_index;
|
||||
Arena *autocomp_arena;
|
||||
RD_Regs *autocomp_regs;
|
||||
RD_AutocompCursorInfo autocomp_cursor_info;
|
||||
|
||||
// rjf: error state
|
||||
U8 error_buffer[512];
|
||||
@@ -959,10 +960,8 @@ internal void rd_set_hover_eval(Vec2F32 pos, String8 string);
|
||||
////////////////////////////////
|
||||
//~ rjf: Autocompletion Lister
|
||||
|
||||
internal String8 rd_autocomp_primary_list_expr_from_dst_eval(Arena *arena, E_Eval dst_eval);
|
||||
internal RD_AutocompCursorInfo rd_autocomp_cursor_info_from_input_string_off(Arena *arena, String8 input, U64 cursor_off);
|
||||
internal void rd_set_autocomp_regs_(RD_Regs *regs);
|
||||
#define rd_set_autocomp_regs(...) rd_set_autocomp_regs_(&(RD_Regs){rd_regs_lit_init_top __VA_ARGS__})
|
||||
internal void rd_set_autocomp_regs_(E_Eval dst_eval, RD_Regs *regs);
|
||||
#define rd_set_autocomp_regs(dst_eval, ...) rd_set_autocomp_regs_((dst_eval), &(RD_Regs){rd_regs_lit_init_top __VA_ARGS__})
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Colors, Fonts, Config
|
||||
|
||||
@@ -1244,7 +1244,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
|
||||
{
|
||||
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(row->eval, "enabled"),
|
||||
.flags = RD_WatchCellFlag_Background,
|
||||
.px = floor_f32(ui_top_font_size()*5.f));
|
||||
.px = floor_f32(ui_top_font_size()*5.5f));
|
||||
}
|
||||
else if(cmd_kind != RD_CmdKind_Null)
|
||||
{
|
||||
@@ -1272,7 +1272,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
|
||||
entity->kind == CTRL_EntityKind_Thread)
|
||||
{
|
||||
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(row->eval, "active"),
|
||||
.px = floor_f32(ui_top_font_size()*5.f));
|
||||
.px = floor_f32(ui_top_font_size()*5.5f));
|
||||
}
|
||||
if(entity->kind == CTRL_EntityKind_Thread)
|
||||
{
|
||||
|
||||
+79
-54
@@ -3399,7 +3399,10 @@ rd_cell(RD_CellParams *params, String8 string)
|
||||
params->line_edit_key_out[0] = edit_box->key;
|
||||
}
|
||||
}
|
||||
ui_spacer(ui_em(1.f, 1.f));
|
||||
if(ui_top_text_alignment() == UI_TextAlign_Left)
|
||||
{
|
||||
ui_spacer(ui_em(1.f, 1.f));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3474,42 +3477,55 @@ rd_cell(RD_CellParams *params, String8 string)
|
||||
UI_HeightFill
|
||||
UI_Column UI_Padding(ui_px(padding_px, 1.f))
|
||||
UI_Row
|
||||
UI_PrefWidth(ui_em(3.5f, 1.f))
|
||||
UI_PrefHeight(ui_px(height_px, 1.f))
|
||||
UI_CornerRadius(floor_f32(height_px/2.f - 1.f))
|
||||
UI_TagF(is_toggled ? "good_pop" : "")
|
||||
{
|
||||
UI_Box *switch_box = ui_build_box_from_stringf(UI_BoxFlag_DrawHotEffects|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clickable, "toggle_switch");
|
||||
UI_Parent(switch_box)
|
||||
if(ui_top_text_alignment() == UI_TextAlign_Center)
|
||||
{
|
||||
RD_Font(RD_FontSlot_Icons) UI_PrefWidth(ui_pct(toggle_t, 0)) UI_Transparency(1.f - toggle_t)
|
||||
{
|
||||
ui_build_box_from_stringf(UI_BoxFlag_DisableTextTrunc | (toggle_t > 0.001f ? UI_BoxFlag_DrawText : 0),
|
||||
"%S", rd_icon_kind_text_table[RD_IconKind_Check]);
|
||||
}
|
||||
UI_BackgroundColor(ui_color_from_name(str8_lit("text")))
|
||||
UI_PrefWidth(ui_px(height_px, 1.f))
|
||||
{
|
||||
F32 extratoggler_padding_px = floor_f32(ui_top_font_size()*0.35f);
|
||||
F32 toggler_size_px = ceil_f32(height_px - extratoggler_padding_px*2.f) - 1.f;
|
||||
UI_Column UI_Padding(ui_px(extratoggler_padding_px, 1.f))
|
||||
UI_Row UI_Padding(ui_px(extratoggler_padding_px, 1.f))
|
||||
UI_PrefWidth(ui_px(toggler_size_px, 1.f))
|
||||
UI_PrefHeight(ui_px(toggler_size_px, 1.f))
|
||||
UI_CornerRadius(floor_f32(toggler_size_px/2.f - 1.f))
|
||||
{
|
||||
UI_Box *toggler = ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawDropShadow, ui_key_zero());
|
||||
}
|
||||
}
|
||||
ui_spacer(ui_pct(1.f-toggle_t, 0));
|
||||
ui_spacer(ui_em(1.f, 0.f));
|
||||
}
|
||||
UI_Signal switch_sig = ui_signal_from_box(switch_box);
|
||||
if(ui_pressed(switch_sig))
|
||||
UI_PrefWidth(ui_em(3.5f, 1.f))
|
||||
UI_PrefHeight(ui_px(height_px, 1.f))
|
||||
UI_CornerRadius(floor_f32(height_px/2.f - 1.f))
|
||||
UI_TagF(is_toggled ? "good_pop" : "")
|
||||
{
|
||||
params->toggled_out[0] ^= 1;
|
||||
UI_Box *switch_box = ui_build_box_from_stringf(UI_BoxFlag_DrawHotEffects|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clickable, "toggle_switch");
|
||||
UI_Parent(switch_box)
|
||||
{
|
||||
RD_Font(RD_FontSlot_Icons) UI_PrefWidth(ui_pct(toggle_t, 0)) UI_Transparency(1.f - toggle_t)
|
||||
{
|
||||
ui_build_box_from_stringf(UI_BoxFlag_DisableTextTrunc | (toggle_t > 0.001f ? UI_BoxFlag_DrawText : 0),
|
||||
"%S", rd_icon_kind_text_table[RD_IconKind_Check]);
|
||||
}
|
||||
UI_BackgroundColor(ui_color_from_name(str8_lit("text")))
|
||||
UI_PrefWidth(ui_px(height_px, 1.f))
|
||||
{
|
||||
F32 extratoggler_padding_px = floor_f32(ui_top_font_size()*0.35f);
|
||||
F32 toggler_size_px = ceil_f32(height_px - extratoggler_padding_px*2.f) - 1.f;
|
||||
UI_Column UI_Padding(ui_px(extratoggler_padding_px, 1.f))
|
||||
UI_Row UI_Padding(ui_px(extratoggler_padding_px, 1.f))
|
||||
UI_PrefWidth(ui_px(toggler_size_px, 1.f))
|
||||
UI_PrefHeight(ui_px(toggler_size_px, 1.f))
|
||||
UI_CornerRadius(floor_f32(toggler_size_px/2.f - 1.f))
|
||||
{
|
||||
UI_Box *toggler = ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawDropShadow, ui_key_zero());
|
||||
}
|
||||
}
|
||||
ui_spacer(ui_pct(1.f-toggle_t, 0));
|
||||
}
|
||||
UI_Signal switch_sig = ui_signal_from_box(switch_box);
|
||||
if(ui_pressed(switch_sig))
|
||||
{
|
||||
params->toggled_out[0] ^= 1;
|
||||
}
|
||||
}
|
||||
if(ui_top_text_alignment() == UI_TextAlign_Center)
|
||||
{
|
||||
ui_spacer(ui_em(1.f, 0.f));
|
||||
}
|
||||
}
|
||||
ui_spacer(ui_em(1.f, 1.f));
|
||||
if(ui_top_text_alignment() == UI_TextAlign_Left)
|
||||
{
|
||||
ui_spacer(ui_em(1.f, 1.f));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@@ -3684,12 +3700,14 @@ rd_cell(RD_CellParams *params, String8 string)
|
||||
// rjf: any valid *additive* op & autocomplete hint? -> perform autocomplete first, then re-compute op
|
||||
if(!(evt->flags & UI_EventFlag_Delete) && autocomplete_hint_string.size != 0)
|
||||
{
|
||||
RD_AutocompCursorInfo autocomp_cursor_info = rd_autocomp_cursor_info_from_input_string_off(scratch.arena, edit_string, params->cursor->column-1);
|
||||
String8 new_string = ui_push_string_replace_range(scratch.arena, edit_string, r1s64(autocomp_cursor_info.replaced_range.min+1, autocomp_cursor_info.replaced_range.max+1), autocomplete_hint_string);
|
||||
RD_Cfg *window = rd_cfg_from_id(rd_regs()->window);
|
||||
RD_WindowState *ws = rd_window_state_from_cfg(window);
|
||||
RD_AutocompCursorInfo *autocomp_cursor_info = &ws->autocomp_cursor_info;
|
||||
String8 new_string = ui_push_string_replace_range(scratch.arena, edit_string, r1s64(autocomp_cursor_info->replaced_range.min+1, autocomp_cursor_info->replaced_range.max+1), autocomplete_hint_string);
|
||||
new_string.size = Min(params->edit_buffer_size, new_string.size);
|
||||
MemoryCopy(params->edit_buffer, new_string.str, new_string.size);
|
||||
params->edit_string_size_out[0] = new_string.size;
|
||||
params->cursor[0] = params->mark[0] = txt_pt(1, 1+autocomp_cursor_info.replaced_range.min+autocomplete_hint_string.size);
|
||||
params->cursor[0] = params->mark[0] = txt_pt(1, 1+autocomp_cursor_info->replaced_range.min+autocomplete_hint_string.size);
|
||||
edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]);
|
||||
op = ui_single_line_txt_op_from_event(scratch.arena, evt, edit_string, params->cursor[0], params->mark[0]);
|
||||
MemoryZeroStruct(&autocomplete_hint_string);
|
||||
@@ -3761,18 +3779,30 @@ rd_cell(RD_CellParams *params, String8 string)
|
||||
}
|
||||
|
||||
//- rjf: (editing)
|
||||
else if((is_focus_active || is_focus_active_disabled) && params->flags & RD_CellFlag_CodeContents)
|
||||
else if(is_focus_active || is_focus_active_disabled)
|
||||
{
|
||||
String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]);
|
||||
DR_FStrList code_fstrs = rd_fstrs_from_code_string(scratch.arena, 1.f, 0, ui_color_from_name(str8_lit("text")), edit_string);
|
||||
DR_FStrList edit_string_fstrs = {0};
|
||||
if(params->flags & RD_CellFlag_CodeContents)
|
||||
{
|
||||
edit_string_fstrs = rd_fstrs_from_code_string(scratch.arena, 1.f, 0, ui_color_from_name(str8_lit("text")), edit_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]);
|
||||
DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()};
|
||||
dr_fstrs_push_new(scratch.arena, &edit_string_fstrs, ¶ms, edit_string);
|
||||
}
|
||||
if(autocomplete_hint_string.size != 0)
|
||||
{
|
||||
RD_AutocompCursorInfo autocomp_cursor_info = rd_autocomp_cursor_info_from_input_string_off(scratch.arena, edit_string, params->cursor->column-1);
|
||||
String8 autocomplete_append_string = str8_skip(autocomplete_hint_string, params->cursor->column-1 - autocomp_cursor_info.replaced_range.min);
|
||||
RD_Cfg *window = rd_cfg_from_id(rd_regs()->window);
|
||||
RD_WindowState *ws = rd_window_state_from_cfg(window);
|
||||
RD_AutocompCursorInfo *autocomp_cursor_info = &ws->autocomp_cursor_info;
|
||||
String8 autocomplete_append_string = str8_skip(autocomplete_hint_string, params->cursor->column-1 - autocomp_cursor_info->replaced_range.min);
|
||||
U64 off = 0;
|
||||
U64 cursor_off = params->cursor->column-1;
|
||||
DR_FStrNode *prev_n = 0;
|
||||
for(DR_FStrNode *n = code_fstrs.first; n != 0; n = n->next)
|
||||
for(DR_FStrNode *n = edit_string_fstrs.first; n != 0; n = n->next)
|
||||
{
|
||||
if(off <= cursor_off && cursor_off <= off+n->v.string.size)
|
||||
{
|
||||
@@ -3786,6 +3816,7 @@ rd_cell(RD_CellParams *params, String8 string)
|
||||
DR_FStr *fstr = &autocomp_fstr_n->v;
|
||||
fstr->string = autocomplete_append_string;
|
||||
fstr->params.font = ui_top_font();
|
||||
fstr->params.raster_flags = ui_top_text_raster_flags();
|
||||
fstr->params.color = ui_color_from_name(str8_lit("text"));
|
||||
fstr->params.color.w *= 0.5f;
|
||||
fstr->params.size = ui_top_font_size();
|
||||
@@ -3796,20 +3827,20 @@ rd_cell(RD_CellParams *params, String8 string)
|
||||
}
|
||||
if(prev_n == 0)
|
||||
{
|
||||
code_fstrs.first = code_fstrs.last = autocomp_fstr_n;
|
||||
edit_string_fstrs.first = edit_string_fstrs.last = autocomp_fstr_n;
|
||||
}
|
||||
if(prev_n != 0 && prev_n->next == 0)
|
||||
{
|
||||
code_fstrs.last = autocomp_fstr_n;
|
||||
edit_string_fstrs.last = autocomp_fstr_n;
|
||||
}
|
||||
code_fstrs.node_count += 1;
|
||||
code_fstrs.total_size += autocomplete_hint_string.size;
|
||||
edit_string_fstrs.node_count += 1;
|
||||
edit_string_fstrs.total_size += autocomplete_hint_string.size;
|
||||
if(prev_n != 0 && cursor_off - off < prev_n->v.string.size)
|
||||
{
|
||||
String8 full_string = prev_n->v.string;
|
||||
U64 chop_amt = full_string.size - (cursor_off - off);
|
||||
prev_n->v.string = str8_chop(full_string, chop_amt);
|
||||
code_fstrs.total_size -= chop_amt;
|
||||
edit_string_fstrs.total_size -= chop_amt;
|
||||
if(chop_amt != 0)
|
||||
{
|
||||
String8 post_cursor = str8_skip(full_string, cursor_off - off);
|
||||
@@ -3819,23 +3850,17 @@ rd_cell(RD_CellParams *params, String8 string)
|
||||
post_fstr->string = post_cursor;
|
||||
if(autocomp_fstr_n->next == 0)
|
||||
{
|
||||
code_fstrs.last = post_fstr_n;
|
||||
edit_string_fstrs.last = post_fstr_n;
|
||||
}
|
||||
post_fstr_n->next = autocomp_fstr_n->next;
|
||||
autocomp_fstr_n->next = post_fstr_n;
|
||||
code_fstrs.node_count += 1;
|
||||
code_fstrs.total_size += post_cursor.size;
|
||||
edit_string_fstrs.node_count += 1;
|
||||
edit_string_fstrs.total_size += post_cursor.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fstrs = code_fstrs;
|
||||
}
|
||||
else if((is_focus_active || is_focus_active_disabled) && !(params->flags & RD_CellFlag_CodeContents))
|
||||
{
|
||||
String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]);
|
||||
DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()};
|
||||
dr_fstrs_push_new(scratch.arena, &fstrs, ¶ms, edit_string);
|
||||
fstrs = edit_string_fstrs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -49,14 +49,14 @@ UI_MouseButtonKind;
|
||||
typedef U32 UI_PermissionFlags;
|
||||
enum
|
||||
{
|
||||
UI_PermissionFlag_ClicksLeft = (1<<0),
|
||||
UI_PermissionFlag_ClicksMiddle = (1<<1),
|
||||
UI_PermissionFlag_ClicksRight = (1<<2),
|
||||
UI_PermissionFlag_ScrollX = (1<<3),
|
||||
UI_PermissionFlag_ScrollY = (1<<4),
|
||||
UI_PermissionFlag_KeyboardPrimary = (1<<5),
|
||||
UI_PermissionFlag_KeyboardSecondary= (1<<6),
|
||||
UI_PermissionFlag_Text = (1<<7),
|
||||
UI_PermissionFlag_ClicksLeft = (1<<0),
|
||||
UI_PermissionFlag_ClicksMiddle = (1<<1),
|
||||
UI_PermissionFlag_ClicksRight = (1<<2),
|
||||
UI_PermissionFlag_ScrollX = (1<<3),
|
||||
UI_PermissionFlag_ScrollY = (1<<4),
|
||||
UI_PermissionFlag_KeyboardPrimary = (1<<5),
|
||||
UI_PermissionFlag_KeyboardSecondary = (1<<6),
|
||||
UI_PermissionFlag_Text = (1<<7),
|
||||
|
||||
//- rjf bundles
|
||||
UI_PermissionFlag_Keyboard = (UI_PermissionFlag_KeyboardPrimary|UI_PermissionFlag_KeyboardSecondary),
|
||||
|
||||
Reference in New Issue
Block a user