mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-06 13:58:40 +00:00
fix ctx menu closing escape consumption rules; fix top bar prioritization rules
This commit is contained in:
+437
-436
@@ -6342,7 +6342,6 @@ rd_window_frame(void)
|
|||||||
U64 hover_eval_open_delay_us = 400000;
|
U64 hover_eval_open_delay_us = 400000;
|
||||||
B32 hover_eval_is_open = (!popup_is_open &&
|
B32 hover_eval_is_open = (!popup_is_open &&
|
||||||
!query_is_open &&
|
!query_is_open &&
|
||||||
!ws->menu_bar_focused &&
|
|
||||||
ws->hover_eval_string.size != 0 &&
|
ws->hover_eval_string.size != 0 &&
|
||||||
ws->hover_eval_firstt_us+hover_eval_open_delay_us < ws->hover_eval_lastt_us &&
|
ws->hover_eval_firstt_us+hover_eval_open_delay_us < ws->hover_eval_lastt_us &&
|
||||||
rd_state->time_in_us - ws->hover_eval_lastt_us < hover_eval_open_delay_us);
|
rd_state->time_in_us - ws->hover_eval_lastt_us < hover_eval_open_delay_us);
|
||||||
@@ -7434,440 +7433,6 @@ rd_window_frame(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////
|
|
||||||
//- rjf: @window_ui_part gather all tasks to build floating views
|
|
||||||
//
|
|
||||||
typedef struct FloatingViewTask FloatingViewTask;
|
|
||||||
struct FloatingViewTask
|
|
||||||
{
|
|
||||||
FloatingViewTask *next;
|
|
||||||
RD_Cfg *view;
|
|
||||||
F32 row_height_px;
|
|
||||||
Rng2F32 rect;
|
|
||||||
String8 view_name;
|
|
||||||
String8 expr;
|
|
||||||
B32 is_focused;
|
|
||||||
B32 is_anchored;
|
|
||||||
UI_Signal signal; // NOTE(rjf): output, from build
|
|
||||||
};
|
|
||||||
FloatingViewTask *hover_eval_floating_view_task = 0;
|
|
||||||
FloatingViewTask *query_floating_view_task = 0;
|
|
||||||
FloatingViewTask *first_floating_view_task = 0;
|
|
||||||
FloatingViewTask *last_floating_view_task = 0;
|
|
||||||
RD_Font(RD_FontSlot_Code)
|
|
||||||
UI_FontSize(rd_font_size_from_slot(RD_FontSlot_Main))
|
|
||||||
{
|
|
||||||
//- rjf: try to add hover eval first
|
|
||||||
{
|
|
||||||
B32 build_hover_eval = (hover_eval_is_open && (!rd_drag_is_active() || rd_state->drag_drop_regs_slot == RD_RegSlot_View));
|
|
||||||
|
|
||||||
// rjf: disable hover eval if hovered view is actively scrolling
|
|
||||||
if(hover_eval_is_open)
|
|
||||||
{
|
|
||||||
for(RD_PanelNode *panel = panel_tree.root;
|
|
||||||
panel != &rd_nil_panel_node;
|
|
||||||
panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next)
|
|
||||||
{
|
|
||||||
if(panel->first != &rd_nil_panel_node) { continue; }
|
|
||||||
RD_Cfg *tab = panel->selected_tab;
|
|
||||||
if(tab != &rd_nil_cfg)
|
|
||||||
{
|
|
||||||
RD_ViewState *vs = rd_view_state_from_cfg(tab);
|
|
||||||
Rng2F32 panel_rect = rd_target_rect_from_panel_node(content_rect, panel_tree.root, panel);
|
|
||||||
if(contains_2f32(panel_rect, ui_mouse()) &&
|
|
||||||
(abs_f32(vs->scroll_pos.x.off) > 0.01f ||
|
|
||||||
abs_f32(vs->scroll_pos.y.off) > 0.01f))
|
|
||||||
{
|
|
||||||
build_hover_eval = 0;
|
|
||||||
ws->hover_eval_firstt_us = rd_state->time_in_us;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: choose hover evaluation expression
|
|
||||||
String8 hover_eval_expr = push_str8f(scratch.arena, "%S%s%S", ws->hover_eval_string, ws->hover_eval_view_rules.size != 0 ? " => " : "", ws->hover_eval_view_rules);
|
|
||||||
|
|
||||||
// rjf: evaluate hover evaluation expression, & determine if it evaluates
|
|
||||||
// such that we want to build a hover eval.
|
|
||||||
E_Eval hover_eval = e_eval_from_string(scratch.arena, hover_eval_expr);
|
|
||||||
{
|
|
||||||
if(hover_eval.msgs.max_kind > E_MsgKind_Null)
|
|
||||||
{
|
|
||||||
build_hover_eval = 0;
|
|
||||||
}
|
|
||||||
else if(hover_eval.space.kind == RD_EvalSpaceKind_MetaCfg &&
|
|
||||||
rd_cfg_from_eval_space(hover_eval.space) == &rd_nil_cfg)
|
|
||||||
{
|
|
||||||
build_hover_eval = 0;
|
|
||||||
}
|
|
||||||
else if((hover_eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity ||
|
|
||||||
hover_eval.space.kind == RD_EvalSpaceKind_CtrlEntity) &&
|
|
||||||
rd_ctrl_entity_from_eval_space(hover_eval.space) == &ctrl_entity_nil)
|
|
||||||
{
|
|
||||||
build_hover_eval = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: determine if we have a top-level visualizer
|
|
||||||
EV_ExpandRuleTagPair expand_rule_tag = ev_expand_rule_tag_pair_from_expr_irtree(hover_eval.exprs.last, &hover_eval.irtree);
|
|
||||||
RD_ViewUIRule *view_ui_rule = rd_view_ui_rule_from_string(expand_rule_tag.rule->string);
|
|
||||||
|
|
||||||
// rjf: determine view name
|
|
||||||
String8 view_name = str8_lit("watch");
|
|
||||||
if(view_ui_rule != &rd_nil_view_ui_rule)
|
|
||||||
{
|
|
||||||
view_name = view_ui_rule->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: build view
|
|
||||||
RD_Cfg *root = rd_immediate_cfg_from_keyf("hover_eval_view");
|
|
||||||
RD_Cfg *view = rd_cfg_child_from_string_or_alloc(root, view_name);
|
|
||||||
RD_Cfg *explicit_root = rd_cfg_child_from_string_or_alloc(view, str8_lit("explicit_root"));
|
|
||||||
rd_cfg_new(explicit_root, str8_lit("1"));
|
|
||||||
|
|
||||||
// rjf: request frames if we're waiting to open
|
|
||||||
if(ws->hover_eval_string.size != 0 &&
|
|
||||||
!hover_eval_is_open &&
|
|
||||||
ws->hover_eval_lastt_us < ws->hover_eval_firstt_us+hover_eval_open_delay_us &&
|
|
||||||
rd_state->time_in_us - ws->hover_eval_lastt_us < hover_eval_open_delay_us*2)
|
|
||||||
{
|
|
||||||
rd_request_frame();
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: determine size of hover evaluation container
|
|
||||||
EV_BlockTree predicted_block_tree = {0};
|
|
||||||
RD_RegsScope(.view = view->id)
|
|
||||||
{
|
|
||||||
predicted_block_tree = ev_block_tree_from_exprs(scratch.arena, rd_view_eval_view(), str8_zero(), hover_eval.exprs);
|
|
||||||
}
|
|
||||||
F32 row_height_px = floor_f32(ui_top_font_size()*2.5f);
|
|
||||||
U64 max_row_count = (U64)floor_f32(ui_top_font_size()*10.f / row_height_px);
|
|
||||||
if(ws->hover_eval_focused)
|
|
||||||
{
|
|
||||||
max_row_count *= 3;
|
|
||||||
}
|
|
||||||
U64 needed_row_count = Min(max_row_count, predicted_block_tree.total_row_count);
|
|
||||||
F32 num_rows_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "hover_eval_num_rows_t"), (F32)needed_row_count);
|
|
||||||
F32 width_px = 60.f*ui_top_font_size();
|
|
||||||
F32 height_px = num_rows_t*row_height_px;
|
|
||||||
|
|
||||||
// rjf: if arbitrary visualizer, pick catchall size
|
|
||||||
if(view_ui_rule != &rd_nil_view_ui_rule)
|
|
||||||
{
|
|
||||||
height_px = 40.f*ui_top_font_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: determine hover eval top-level rect
|
|
||||||
Rng2F32 rect = r2f32p(ws->hover_eval_spawn_pos.x,
|
|
||||||
ws->hover_eval_spawn_pos.y,
|
|
||||||
ws->hover_eval_spawn_pos.x + width_px,
|
|
||||||
ws->hover_eval_spawn_pos.y + height_px);
|
|
||||||
|
|
||||||
// rjf: push hover eval task
|
|
||||||
if(build_hover_eval)
|
|
||||||
{
|
|
||||||
FloatingViewTask *t = push_array(scratch.arena, FloatingViewTask, 1);
|
|
||||||
SLLQueuePush(first_floating_view_task, last_floating_view_task, t);
|
|
||||||
hover_eval_floating_view_task = t;
|
|
||||||
t->view = view;
|
|
||||||
t->row_height_px = row_height_px;
|
|
||||||
t->rect = rect;
|
|
||||||
t->view_name = view_name;
|
|
||||||
t->expr = hover_eval_expr;
|
|
||||||
t->is_focused = ws->hover_eval_focused;
|
|
||||||
t->is_anchored = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: reset focus state if hover eval is not being built
|
|
||||||
if(!build_hover_eval || ws->hover_eval_string.size == 0 || !hover_eval_is_open)
|
|
||||||
{
|
|
||||||
ws->hover_eval_focused = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: try to add opened query
|
|
||||||
if(query_is_open)
|
|
||||||
{
|
|
||||||
if(ui_slot_press(UI_EventActionSlot_Cancel))
|
|
||||||
{
|
|
||||||
rd_cmd(RD_CmdKind_CancelQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: unpack query info
|
|
||||||
String8 cmd_name = ws->query_cmd_name;
|
|
||||||
RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name);
|
|
||||||
B32 size_query_by_expr_eval = (cmd_kind_info->query.expr.size == 0);
|
|
||||||
B32 query_is_anchored = (!ui_box_is_nil(ui_box_from_key(ws->query_regs->ui_key)));
|
|
||||||
F32 row_height_px = floor_f32(ui_top_font_size()*2.5f);
|
|
||||||
|
|
||||||
// rjf: build view for query
|
|
||||||
RD_Cfg *root = rd_immediate_cfg_from_keyf("window_query_%p", window);
|
|
||||||
RD_Cfg *view = rd_cfg_child_from_string_or_alloc(root, str8_lit("watch"));
|
|
||||||
RD_Cfg *query = rd_cfg_child_from_string_or_alloc(view, str8_lit("query"));
|
|
||||||
RD_Cfg *cmd = rd_cfg_child_from_string_or_alloc(query, str8_lit("cmd"));
|
|
||||||
rd_cfg_new_replace(cmd, cmd_name);
|
|
||||||
rd_cfg_child_from_string_or_alloc(view, str8_lit("lister"));
|
|
||||||
RD_ViewState *vs = rd_view_state_from_cfg(view);
|
|
||||||
vs->query_is_selected = 1;
|
|
||||||
|
|
||||||
// rjf: compute query expression
|
|
||||||
String8 query_expression = cmd_kind_info->query.expr;
|
|
||||||
if(query_expression.size == 0)
|
|
||||||
{
|
|
||||||
query_expression = str8(vs->query_buffer, vs->query_string_size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
U64 input_insertion_pos = str8_find_needle(query_expression, 0, str8_lit("$input"), 0);
|
|
||||||
if(input_insertion_pos < query_expression.size)
|
|
||||||
{
|
|
||||||
String8 pre_insertion = str8_prefix(query_expression, input_insertion_pos);
|
|
||||||
String8 post_insertion = str8_skip(query_expression, input_insertion_pos + 6);
|
|
||||||
query_expression = push_str8f(scratch.arena, "%S%S%S", pre_insertion, str8(vs->query_buffer, vs->query_string_size), post_insertion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: based on query expression, determine if we have an explicit root
|
|
||||||
if(query_expression.size == 0)
|
|
||||||
{
|
|
||||||
RD_Cfg *explicit_root = rd_cfg_child_from_string_or_alloc(view, str8_lit("explicit_root"));
|
|
||||||
rd_cfg_new(explicit_root, str8_lit("1"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rd_cfg_release(rd_cfg_child_from_string(view, str8_lit("explicit_root")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: evaluate query expression
|
|
||||||
E_Eval query_eval = e_eval_from_string(scratch.arena, query_expression);
|
|
||||||
|
|
||||||
// rjf: compute query view's top-level rectangle
|
|
||||||
Rng2F32 rect = {0};
|
|
||||||
RD_RegsScope(.view = view->id)
|
|
||||||
{
|
|
||||||
Vec2F32 content_rect_center = center_2f32(content_rect);
|
|
||||||
Vec2F32 content_rect_dim = dim_2f32(content_rect);
|
|
||||||
EV_BlockTree predicted_block_tree = ev_block_tree_from_exprs(scratch.arena, rd_view_eval_view(), rd_view_query_input(), query_eval.exprs);
|
|
||||||
F32 query_width_px = floor_f32(content_rect_dim.x * 0.35f);
|
|
||||||
F32 max_query_height_px = content_rect_dim.y*0.8f;
|
|
||||||
F32 query_height_px = max_query_height_px;
|
|
||||||
if(size_query_by_expr_eval)
|
|
||||||
{
|
|
||||||
query_height_px = row_height_px*predicted_block_tree.total_row_count;
|
|
||||||
query_height_px = Min(query_height_px, max_query_height_px);
|
|
||||||
}
|
|
||||||
rect = r2f32p(content_rect_center.x - query_width_px/2,
|
|
||||||
content_rect_center.y - max_query_height_px/2.f,
|
|
||||||
content_rect_center.x + query_width_px/2,
|
|
||||||
content_rect_center.y - max_query_height_px/2.f + query_height_px);
|
|
||||||
if(!ui_key_match(ui_key_zero(), ws->query_regs->ui_key))
|
|
||||||
{
|
|
||||||
UI_Box *anchor_box = ui_box_from_key(ws->query_regs->ui_key);
|
|
||||||
if(anchor_box != &ui_nil_box)
|
|
||||||
{
|
|
||||||
rect.x0 = anchor_box->rect.x0;
|
|
||||||
rect.y0 = anchor_box->rect.y1;
|
|
||||||
rect.x1 = rect.x0 + ui_top_font_size()*40.f;
|
|
||||||
rect.y1 = rect.y0 + query_height_px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: push query task
|
|
||||||
{
|
|
||||||
FloatingViewTask *t = push_array(scratch.arena, FloatingViewTask, 1);
|
|
||||||
SLLQueuePush(first_floating_view_task, last_floating_view_task, t);
|
|
||||||
query_floating_view_task = t;
|
|
||||||
t->view = view;
|
|
||||||
t->row_height_px = row_height_px;
|
|
||||||
t->rect = rect;
|
|
||||||
t->view_name = str8_lit("watch");
|
|
||||||
t->expr = query_expression;
|
|
||||||
t->is_focused = 1;
|
|
||||||
t->is_anchored = query_is_anchored;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////
|
|
||||||
//- rjf: @window_ui_part build all floating views
|
|
||||||
//
|
|
||||||
ProfScope("build all floating views")
|
|
||||||
RD_Font(RD_FontSlot_Code)
|
|
||||||
UI_FontSize(rd_font_size_from_slot(RD_FontSlot_Main))
|
|
||||||
UI_TagF("floating")
|
|
||||||
{
|
|
||||||
F32 fast_open_rate = 1 - pow_f32(2, (-70.f * ui_state->animation_dt));
|
|
||||||
F32 slow_open_rate = 1 - pow_f32(2, (-40.f * ui_state->animation_dt));
|
|
||||||
for(FloatingViewTask *t = first_floating_view_task; t != 0; t = t->next)
|
|
||||||
{
|
|
||||||
// rjf: unpack
|
|
||||||
RD_Cfg *view = t->view;
|
|
||||||
F32 row_height_px = t->row_height_px;
|
|
||||||
Rng2F32 rect = t->rect;
|
|
||||||
String8 view_name = t->view_name;
|
|
||||||
String8 expr = t->expr;
|
|
||||||
B32 is_focused = t->is_focused;
|
|
||||||
B32 is_anchored = t->is_anchored;
|
|
||||||
F32 open_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "floating_view_open_%p", view), 1.f, .rate = is_anchored ? fast_open_rate : slow_open_rate);
|
|
||||||
|
|
||||||
// rjf: build cfg tree
|
|
||||||
RD_Cfg *expr_root = rd_cfg_child_from_string_or_alloc(view, str8_lit("expression"));
|
|
||||||
rd_cfg_new(view, str8_lit("selected"));
|
|
||||||
rd_cfg_new_replace(expr_root, expr);
|
|
||||||
|
|
||||||
// rjf: push view regs
|
|
||||||
rd_push_regs(.view = view->id);
|
|
||||||
{
|
|
||||||
String8 view_expr = rd_expr_from_cfg(view);
|
|
||||||
String8 view_file_path = rd_file_path_from_eval_string(rd_frame_arena(), view_expr);
|
|
||||||
// NOTE(rjf): we want to only fill out this view's file path slot if it
|
|
||||||
// evaluates one - this way, a view can use the slot to know the selected
|
|
||||||
// file path (if there is one). this is useful when pushing commandas which
|
|
||||||
// apply to a cursor, for example.
|
|
||||||
if(view_file_path.size != 0)
|
|
||||||
{
|
|
||||||
rd_regs()->file_path = view_file_path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: build
|
|
||||||
UI_Focus(is_focused ? UI_FocusKind_On : UI_FocusKind_Off)
|
|
||||||
UI_PrefHeight(ui_px(row_height_px, 1.f))
|
|
||||||
{
|
|
||||||
// rjf: build top-level container box
|
|
||||||
UI_Box *container = &ui_nil_box;
|
|
||||||
UI_Rect(rect) UI_ChildLayoutAxis(Axis2_Y) UI_Squish(0.1f-0.1f*open_t) UI_Transparency(1.f-open_t)
|
|
||||||
{
|
|
||||||
container = ui_build_box_from_stringf(UI_BoxFlag_Clickable|
|
|
||||||
UI_BoxFlag_DrawBorder|
|
|
||||||
UI_BoxFlag_DrawBackground|
|
|
||||||
UI_BoxFlag_DrawBackgroundBlur|
|
|
||||||
UI_BoxFlag_DisableFocusOverlay|
|
|
||||||
UI_BoxFlag_DrawDropShadow|
|
|
||||||
(UI_BoxFlag_SquishAnchored*!!is_anchored),
|
|
||||||
"floating_view_container_%p", view);
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: peek press events -> focus hover eval if we have a press
|
|
||||||
if(!ws->hover_eval_focused)
|
|
||||||
{
|
|
||||||
for(UI_Event *evt = 0; ui_next_event(&evt);)
|
|
||||||
{
|
|
||||||
if(evt->kind == UI_EventKind_Press &&
|
|
||||||
evt->key == OS_Key_LeftMouseButton &&
|
|
||||||
contains_2f32(container->rect, evt->pos))
|
|
||||||
{
|
|
||||||
ws->hover_eval_focused = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: build overlay container for loading animation
|
|
||||||
UI_Box *loading_overlay_container = &ui_nil_box;
|
|
||||||
UI_Parent(container) UI_WidthFill UI_HeightFill
|
|
||||||
{
|
|
||||||
loading_overlay_container = ui_build_box_from_key(UI_BoxFlag_Floating, ui_key_zero());
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: build contents
|
|
||||||
UI_Parent(container) UI_Focus(is_focused ? UI_FocusKind_Null : UI_FocusKind_Off)
|
|
||||||
{
|
|
||||||
ui_set_next_pref_width(ui_pct(1, 0));
|
|
||||||
ui_set_next_pref_height(ui_pct(1, 0));
|
|
||||||
ui_set_next_child_layout_axis(Axis2_Y);
|
|
||||||
UI_Box *view_contents_container = ui_build_box_from_stringf(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clip, "###view_contents_container");
|
|
||||||
UI_Parent(view_contents_container) UI_WidthFill
|
|
||||||
{
|
|
||||||
rd_view_ui(rect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: build loading overlay
|
|
||||||
{
|
|
||||||
RD_ViewState *vs = rd_view_state_from_cfg(view);
|
|
||||||
F32 loading_t = vs->loading_t;
|
|
||||||
if(loading_t > 0.01f) UI_Parent(loading_overlay_container)
|
|
||||||
{
|
|
||||||
rd_loading_overlay(rect, loading_t, vs->loading_progress_v, vs->loading_progress_v_target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: interact with container
|
|
||||||
UI_Signal sig = ui_signal_from_box(container);
|
|
||||||
t->signal = sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: pop interaction registers; commit if this is focused
|
|
||||||
RD_Regs *view_regs = rd_pop_regs();
|
|
||||||
if(is_focused)
|
|
||||||
{
|
|
||||||
MemoryCopyStruct(rd_regs(), view_regs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////
|
|
||||||
//- rjf: @window_ui_part do special handling of floating view interactions
|
|
||||||
//
|
|
||||||
{
|
|
||||||
//- rjf: hover eval focus rules
|
|
||||||
if(hover_eval_floating_view_task)
|
|
||||||
{
|
|
||||||
UI_Signal sig = hover_eval_floating_view_task->signal;
|
|
||||||
if(ui_pressed(sig))
|
|
||||||
{
|
|
||||||
ws->hover_eval_focused = 1;
|
|
||||||
}
|
|
||||||
if(ui_mouse_over(sig) || ws->hover_eval_focused)
|
|
||||||
{
|
|
||||||
ws->hover_eval_lastt_us = rd_state->time_in_us;
|
|
||||||
}
|
|
||||||
else if(ws->hover_eval_lastt_us+1000000 < rd_state->time_in_us)
|
|
||||||
{
|
|
||||||
rd_request_frame();
|
|
||||||
}
|
|
||||||
if(ws->hover_eval_focused)
|
|
||||||
{
|
|
||||||
for(UI_Event *evt = 0; ui_next_event(&evt);)
|
|
||||||
{
|
|
||||||
if(evt->kind == UI_EventKind_Press &&
|
|
||||||
evt->key == OS_Key_LeftMouseButton &&
|
|
||||||
!contains_2f32(hover_eval_floating_view_task->rect, evt->pos))
|
|
||||||
{
|
|
||||||
ws->hover_eval_focused = 0;
|
|
||||||
MemoryZeroStruct(&ws->hover_eval_string);
|
|
||||||
arena_clear(ws->hover_eval_arena);
|
|
||||||
rd_request_frame();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: query interactions
|
|
||||||
if(query_floating_view_task)
|
|
||||||
{
|
|
||||||
String8 cmd_name = ws->query_cmd_name;
|
|
||||||
RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name);
|
|
||||||
|
|
||||||
// rjf: any queries which take a file path mutate the debugger's "current path"
|
|
||||||
if(cmd_kind_info->query.slot == RD_RegSlot_FilePath)
|
|
||||||
{
|
|
||||||
RD_Cfg *view = query_floating_view_task->view;
|
|
||||||
RD_Cfg *query = rd_cfg_child_from_string(view, str8_lit("query"));
|
|
||||||
RD_Cfg *input = rd_cfg_child_from_string(query, str8_lit("input"));
|
|
||||||
if(input != &rd_nil_cfg)
|
|
||||||
{
|
|
||||||
String8 path_chopped = str8_chop_last_slash(input->first->string);
|
|
||||||
rd_cmd(RD_CmdKind_SetCurrentPath, .file_path = path_chopped);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: @window_ui_part top bar
|
//- rjf: @window_ui_part top bar
|
||||||
//
|
//
|
||||||
@@ -7877,7 +7442,7 @@ rd_window_frame(void)
|
|||||||
os_window_push_custom_edges(ws->os, window_edge_px);
|
os_window_push_custom_edges(ws->os, window_edge_px);
|
||||||
os_window_push_custom_title_bar(ws->os, dim_2f32(top_bar_rect).y);
|
os_window_push_custom_title_bar(ws->os, dim_2f32(top_bar_rect).y);
|
||||||
ui_set_next_flags(UI_BoxFlag_DefaultFocusNav|UI_BoxFlag_DisableFocusOverlay);
|
ui_set_next_flags(UI_BoxFlag_DefaultFocusNav|UI_BoxFlag_DisableFocusOverlay);
|
||||||
UI_Focus((ws->menu_bar_focused && window_is_focused && !ui_any_ctx_menu_is_open() && !ws->hover_eval_focused) ? UI_FocusKind_On : UI_FocusKind_Null)
|
UI_Focus((ws->menu_bar_focused && window_is_focused && !ui_any_ctx_menu_is_open()) ? UI_FocusKind_On : UI_FocusKind_Null)
|
||||||
UI_TagF("menu_bar")
|
UI_TagF("menu_bar")
|
||||||
UI_Pane(top_bar_rect, str8_lit("###top_bar"))
|
UI_Pane(top_bar_rect, str8_lit("###top_bar"))
|
||||||
UI_WidthFill UI_Row
|
UI_WidthFill UI_Row
|
||||||
@@ -8636,6 +8201,442 @@ rd_window_frame(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: @window_ui_part gather all tasks to build floating views
|
||||||
|
//
|
||||||
|
typedef struct FloatingViewTask FloatingViewTask;
|
||||||
|
struct FloatingViewTask
|
||||||
|
{
|
||||||
|
FloatingViewTask *next;
|
||||||
|
RD_Cfg *view;
|
||||||
|
F32 row_height_px;
|
||||||
|
Rng2F32 rect;
|
||||||
|
String8 view_name;
|
||||||
|
String8 expr;
|
||||||
|
B32 is_focused;
|
||||||
|
B32 is_anchored;
|
||||||
|
UI_Signal signal; // NOTE(rjf): output, from build
|
||||||
|
};
|
||||||
|
FloatingViewTask *hover_eval_floating_view_task = 0;
|
||||||
|
FloatingViewTask *query_floating_view_task = 0;
|
||||||
|
FloatingViewTask *first_floating_view_task = 0;
|
||||||
|
FloatingViewTask *last_floating_view_task = 0;
|
||||||
|
RD_Font(RD_FontSlot_Code)
|
||||||
|
UI_FontSize(rd_font_size_from_slot(RD_FontSlot_Main))
|
||||||
|
{
|
||||||
|
//- rjf: try to add hover eval first
|
||||||
|
{
|
||||||
|
B32 build_hover_eval = (hover_eval_is_open && (!rd_drag_is_active() || rd_state->drag_drop_regs_slot == RD_RegSlot_View));
|
||||||
|
|
||||||
|
// rjf: disable hover eval if hovered view is actively scrolling
|
||||||
|
if(hover_eval_is_open)
|
||||||
|
{
|
||||||
|
for(RD_PanelNode *panel = panel_tree.root;
|
||||||
|
panel != &rd_nil_panel_node;
|
||||||
|
panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next)
|
||||||
|
{
|
||||||
|
if(panel->first != &rd_nil_panel_node) { continue; }
|
||||||
|
RD_Cfg *tab = panel->selected_tab;
|
||||||
|
if(tab != &rd_nil_cfg)
|
||||||
|
{
|
||||||
|
RD_ViewState *vs = rd_view_state_from_cfg(tab);
|
||||||
|
Rng2F32 panel_rect = rd_target_rect_from_panel_node(content_rect, panel_tree.root, panel);
|
||||||
|
if(contains_2f32(panel_rect, ui_mouse()) &&
|
||||||
|
(abs_f32(vs->scroll_pos.x.off) > 0.01f ||
|
||||||
|
abs_f32(vs->scroll_pos.y.off) > 0.01f))
|
||||||
|
{
|
||||||
|
build_hover_eval = 0;
|
||||||
|
ws->hover_eval_firstt_us = rd_state->time_in_us;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: choose hover evaluation expression
|
||||||
|
String8 hover_eval_expr = push_str8f(scratch.arena, "%S%s%S", ws->hover_eval_string, ws->hover_eval_view_rules.size != 0 ? " => " : "", ws->hover_eval_view_rules);
|
||||||
|
|
||||||
|
// rjf: evaluate hover evaluation expression, & determine if it evaluates
|
||||||
|
// such that we want to build a hover eval.
|
||||||
|
E_Eval hover_eval = e_eval_from_string(scratch.arena, hover_eval_expr);
|
||||||
|
{
|
||||||
|
if(hover_eval.msgs.max_kind > E_MsgKind_Null)
|
||||||
|
{
|
||||||
|
build_hover_eval = 0;
|
||||||
|
}
|
||||||
|
else if(hover_eval.space.kind == RD_EvalSpaceKind_MetaCfg &&
|
||||||
|
rd_cfg_from_eval_space(hover_eval.space) == &rd_nil_cfg)
|
||||||
|
{
|
||||||
|
build_hover_eval = 0;
|
||||||
|
}
|
||||||
|
else if((hover_eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity ||
|
||||||
|
hover_eval.space.kind == RD_EvalSpaceKind_CtrlEntity) &&
|
||||||
|
rd_ctrl_entity_from_eval_space(hover_eval.space) == &ctrl_entity_nil)
|
||||||
|
{
|
||||||
|
build_hover_eval = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: determine if we have a top-level visualizer
|
||||||
|
EV_ExpandRuleTagPair expand_rule_tag = ev_expand_rule_tag_pair_from_expr_irtree(hover_eval.exprs.last, &hover_eval.irtree);
|
||||||
|
RD_ViewUIRule *view_ui_rule = rd_view_ui_rule_from_string(expand_rule_tag.rule->string);
|
||||||
|
|
||||||
|
// rjf: determine view name
|
||||||
|
String8 view_name = str8_lit("watch");
|
||||||
|
if(view_ui_rule != &rd_nil_view_ui_rule)
|
||||||
|
{
|
||||||
|
view_name = view_ui_rule->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: build view
|
||||||
|
RD_Cfg *root = rd_immediate_cfg_from_keyf("hover_eval_view");
|
||||||
|
RD_Cfg *view = rd_cfg_child_from_string_or_alloc(root, view_name);
|
||||||
|
RD_Cfg *explicit_root = rd_cfg_child_from_string_or_alloc(view, str8_lit("explicit_root"));
|
||||||
|
rd_cfg_new(explicit_root, str8_lit("1"));
|
||||||
|
|
||||||
|
// rjf: request frames if we're waiting to open
|
||||||
|
if(ws->hover_eval_string.size != 0 &&
|
||||||
|
!hover_eval_is_open &&
|
||||||
|
ws->hover_eval_lastt_us < ws->hover_eval_firstt_us+hover_eval_open_delay_us &&
|
||||||
|
rd_state->time_in_us - ws->hover_eval_lastt_us < hover_eval_open_delay_us*2)
|
||||||
|
{
|
||||||
|
rd_request_frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: determine size of hover evaluation container
|
||||||
|
EV_BlockTree predicted_block_tree = {0};
|
||||||
|
RD_RegsScope(.view = view->id)
|
||||||
|
{
|
||||||
|
predicted_block_tree = ev_block_tree_from_exprs(scratch.arena, rd_view_eval_view(), str8_zero(), hover_eval.exprs);
|
||||||
|
}
|
||||||
|
F32 row_height_px = floor_f32(ui_top_font_size()*2.5f);
|
||||||
|
U64 max_row_count = (U64)floor_f32(ui_top_font_size()*10.f / row_height_px);
|
||||||
|
if(ws->hover_eval_focused)
|
||||||
|
{
|
||||||
|
max_row_count *= 3;
|
||||||
|
}
|
||||||
|
U64 needed_row_count = Min(max_row_count, predicted_block_tree.total_row_count);
|
||||||
|
F32 num_rows_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "hover_eval_num_rows_t"), (F32)needed_row_count);
|
||||||
|
F32 width_px = 60.f*ui_top_font_size();
|
||||||
|
F32 height_px = num_rows_t*row_height_px;
|
||||||
|
|
||||||
|
// rjf: if arbitrary visualizer, pick catchall size
|
||||||
|
if(view_ui_rule != &rd_nil_view_ui_rule)
|
||||||
|
{
|
||||||
|
height_px = 40.f*ui_top_font_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: determine hover eval top-level rect
|
||||||
|
Rng2F32 rect = r2f32p(ws->hover_eval_spawn_pos.x,
|
||||||
|
ws->hover_eval_spawn_pos.y,
|
||||||
|
ws->hover_eval_spawn_pos.x + width_px,
|
||||||
|
ws->hover_eval_spawn_pos.y + height_px);
|
||||||
|
|
||||||
|
// rjf: push hover eval task
|
||||||
|
if(build_hover_eval)
|
||||||
|
{
|
||||||
|
FloatingViewTask *t = push_array(scratch.arena, FloatingViewTask, 1);
|
||||||
|
SLLQueuePush(first_floating_view_task, last_floating_view_task, t);
|
||||||
|
hover_eval_floating_view_task = t;
|
||||||
|
t->view = view;
|
||||||
|
t->row_height_px = row_height_px;
|
||||||
|
t->rect = rect;
|
||||||
|
t->view_name = view_name;
|
||||||
|
t->expr = hover_eval_expr;
|
||||||
|
t->is_focused = ws->hover_eval_focused;
|
||||||
|
t->is_anchored = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: reset focus state if hover eval is not being built
|
||||||
|
if(!build_hover_eval || ws->hover_eval_string.size == 0 || !hover_eval_is_open)
|
||||||
|
{
|
||||||
|
ws->hover_eval_focused = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: try to add opened query
|
||||||
|
if(query_is_open)
|
||||||
|
{
|
||||||
|
// rjf: close queries
|
||||||
|
if(ui_slot_press(UI_EventActionSlot_Cancel))
|
||||||
|
{
|
||||||
|
rd_cmd(RD_CmdKind_CancelQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: unpack query info
|
||||||
|
String8 cmd_name = ws->query_cmd_name;
|
||||||
|
RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name);
|
||||||
|
B32 size_query_by_expr_eval = (cmd_kind_info->query.expr.size == 0);
|
||||||
|
B32 query_is_anchored = (!ui_box_is_nil(ui_box_from_key(ws->query_regs->ui_key)));
|
||||||
|
F32 row_height_px = floor_f32(ui_top_font_size()*2.5f);
|
||||||
|
|
||||||
|
// rjf: build view for query
|
||||||
|
RD_Cfg *root = rd_immediate_cfg_from_keyf("window_query_%p", window);
|
||||||
|
RD_Cfg *view = rd_cfg_child_from_string_or_alloc(root, str8_lit("watch"));
|
||||||
|
RD_Cfg *query = rd_cfg_child_from_string_or_alloc(view, str8_lit("query"));
|
||||||
|
RD_Cfg *cmd = rd_cfg_child_from_string_or_alloc(query, str8_lit("cmd"));
|
||||||
|
rd_cfg_new_replace(cmd, cmd_name);
|
||||||
|
rd_cfg_child_from_string_or_alloc(view, str8_lit("lister"));
|
||||||
|
RD_ViewState *vs = rd_view_state_from_cfg(view);
|
||||||
|
vs->query_is_selected = 1;
|
||||||
|
|
||||||
|
// rjf: compute query expression
|
||||||
|
String8 query_expression = cmd_kind_info->query.expr;
|
||||||
|
if(query_expression.size == 0)
|
||||||
|
{
|
||||||
|
query_expression = str8(vs->query_buffer, vs->query_string_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
U64 input_insertion_pos = str8_find_needle(query_expression, 0, str8_lit("$input"), 0);
|
||||||
|
if(input_insertion_pos < query_expression.size)
|
||||||
|
{
|
||||||
|
String8 pre_insertion = str8_prefix(query_expression, input_insertion_pos);
|
||||||
|
String8 post_insertion = str8_skip(query_expression, input_insertion_pos + 6);
|
||||||
|
query_expression = push_str8f(scratch.arena, "%S%S%S", pre_insertion, str8(vs->query_buffer, vs->query_string_size), post_insertion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: based on query expression, determine if we have an explicit root
|
||||||
|
if(query_expression.size == 0)
|
||||||
|
{
|
||||||
|
RD_Cfg *explicit_root = rd_cfg_child_from_string_or_alloc(view, str8_lit("explicit_root"));
|
||||||
|
rd_cfg_new(explicit_root, str8_lit("1"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rd_cfg_release(rd_cfg_child_from_string(view, str8_lit("explicit_root")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: evaluate query expression
|
||||||
|
E_Eval query_eval = e_eval_from_string(scratch.arena, query_expression);
|
||||||
|
|
||||||
|
// rjf: compute query view's top-level rectangle
|
||||||
|
Rng2F32 rect = {0};
|
||||||
|
RD_RegsScope(.view = view->id)
|
||||||
|
{
|
||||||
|
Vec2F32 content_rect_center = center_2f32(content_rect);
|
||||||
|
Vec2F32 content_rect_dim = dim_2f32(content_rect);
|
||||||
|
EV_BlockTree predicted_block_tree = ev_block_tree_from_exprs(scratch.arena, rd_view_eval_view(), rd_view_query_input(), query_eval.exprs);
|
||||||
|
F32 query_width_px = floor_f32(content_rect_dim.x * 0.35f);
|
||||||
|
F32 max_query_height_px = content_rect_dim.y*0.8f;
|
||||||
|
F32 query_height_px = max_query_height_px;
|
||||||
|
if(size_query_by_expr_eval)
|
||||||
|
{
|
||||||
|
query_height_px = row_height_px*predicted_block_tree.total_row_count;
|
||||||
|
query_height_px = Min(query_height_px, max_query_height_px);
|
||||||
|
}
|
||||||
|
rect = r2f32p(content_rect_center.x - query_width_px/2,
|
||||||
|
content_rect_center.y - max_query_height_px/2.f,
|
||||||
|
content_rect_center.x + query_width_px/2,
|
||||||
|
content_rect_center.y - max_query_height_px/2.f + query_height_px);
|
||||||
|
if(!ui_key_match(ui_key_zero(), ws->query_regs->ui_key))
|
||||||
|
{
|
||||||
|
UI_Box *anchor_box = ui_box_from_key(ws->query_regs->ui_key);
|
||||||
|
if(anchor_box != &ui_nil_box)
|
||||||
|
{
|
||||||
|
rect.x0 = anchor_box->rect.x0;
|
||||||
|
rect.y0 = anchor_box->rect.y1;
|
||||||
|
rect.x1 = rect.x0 + ui_top_font_size()*40.f;
|
||||||
|
rect.y1 = rect.y0 + query_height_px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: push query task
|
||||||
|
{
|
||||||
|
FloatingViewTask *t = push_array(scratch.arena, FloatingViewTask, 1);
|
||||||
|
SLLQueuePush(first_floating_view_task, last_floating_view_task, t);
|
||||||
|
query_floating_view_task = t;
|
||||||
|
t->view = view;
|
||||||
|
t->row_height_px = row_height_px;
|
||||||
|
t->rect = rect;
|
||||||
|
t->view_name = str8_lit("watch");
|
||||||
|
t->expr = query_expression;
|
||||||
|
t->is_focused = 1;
|
||||||
|
t->is_anchored = query_is_anchored;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: @window_ui_part build all floating views
|
||||||
|
//
|
||||||
|
ProfScope("build all floating views")
|
||||||
|
RD_Font(RD_FontSlot_Code)
|
||||||
|
UI_FontSize(rd_font_size_from_slot(RD_FontSlot_Main))
|
||||||
|
UI_TagF("floating")
|
||||||
|
UI_Focus(ws->menu_bar_focused ? UI_FocusKind_Off : UI_FocusKind_Null)
|
||||||
|
{
|
||||||
|
F32 fast_open_rate = 1 - pow_f32(2, (-70.f * ui_state->animation_dt));
|
||||||
|
F32 slow_open_rate = 1 - pow_f32(2, (-40.f * ui_state->animation_dt));
|
||||||
|
for(FloatingViewTask *t = first_floating_view_task; t != 0; t = t->next)
|
||||||
|
{
|
||||||
|
// rjf: unpack
|
||||||
|
RD_Cfg *view = t->view;
|
||||||
|
F32 row_height_px = t->row_height_px;
|
||||||
|
Rng2F32 rect = t->rect;
|
||||||
|
String8 view_name = t->view_name;
|
||||||
|
String8 expr = t->expr;
|
||||||
|
B32 is_focused = t->is_focused;
|
||||||
|
B32 is_anchored = t->is_anchored;
|
||||||
|
F32 open_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "floating_view_open_%p", view), 1.f, .rate = is_anchored ? fast_open_rate : slow_open_rate);
|
||||||
|
|
||||||
|
// rjf: build cfg tree
|
||||||
|
RD_Cfg *expr_root = rd_cfg_child_from_string_or_alloc(view, str8_lit("expression"));
|
||||||
|
rd_cfg_new(view, str8_lit("selected"));
|
||||||
|
rd_cfg_new_replace(expr_root, expr);
|
||||||
|
|
||||||
|
// rjf: push view regs
|
||||||
|
rd_push_regs(.view = view->id);
|
||||||
|
{
|
||||||
|
String8 view_expr = rd_expr_from_cfg(view);
|
||||||
|
String8 view_file_path = rd_file_path_from_eval_string(rd_frame_arena(), view_expr);
|
||||||
|
// NOTE(rjf): we want to only fill out this view's file path slot if it
|
||||||
|
// evaluates one - this way, a view can use the slot to know the selected
|
||||||
|
// file path (if there is one). this is useful when pushing commandas which
|
||||||
|
// apply to a cursor, for example.
|
||||||
|
if(view_file_path.size != 0)
|
||||||
|
{
|
||||||
|
rd_regs()->file_path = view_file_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: build
|
||||||
|
UI_Focus(is_focused ? UI_FocusKind_On : UI_FocusKind_Off)
|
||||||
|
UI_PrefHeight(ui_px(row_height_px, 1.f))
|
||||||
|
{
|
||||||
|
// rjf: build top-level container box
|
||||||
|
UI_Box *container = &ui_nil_box;
|
||||||
|
UI_Rect(rect) UI_ChildLayoutAxis(Axis2_Y) UI_Squish(0.1f-0.1f*open_t) UI_Transparency(1.f-open_t)
|
||||||
|
{
|
||||||
|
container = ui_build_box_from_stringf(UI_BoxFlag_Clickable|
|
||||||
|
UI_BoxFlag_DrawBorder|
|
||||||
|
UI_BoxFlag_DrawBackground|
|
||||||
|
UI_BoxFlag_DrawBackgroundBlur|
|
||||||
|
UI_BoxFlag_DisableFocusOverlay|
|
||||||
|
UI_BoxFlag_DrawDropShadow|
|
||||||
|
(UI_BoxFlag_SquishAnchored*!!is_anchored),
|
||||||
|
"floating_view_container_%p", view);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: peek press events -> focus hover eval if we have a press
|
||||||
|
if(!ws->hover_eval_focused)
|
||||||
|
{
|
||||||
|
for(UI_Event *evt = 0; ui_next_event(&evt);)
|
||||||
|
{
|
||||||
|
if(evt->kind == UI_EventKind_Press &&
|
||||||
|
evt->key == OS_Key_LeftMouseButton &&
|
||||||
|
contains_2f32(container->rect, evt->pos))
|
||||||
|
{
|
||||||
|
ws->hover_eval_focused = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: build overlay container for loading animation
|
||||||
|
UI_Box *loading_overlay_container = &ui_nil_box;
|
||||||
|
UI_Parent(container) UI_WidthFill UI_HeightFill
|
||||||
|
{
|
||||||
|
loading_overlay_container = ui_build_box_from_key(UI_BoxFlag_Floating, ui_key_zero());
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: build contents
|
||||||
|
UI_Parent(container) UI_Focus(is_focused ? UI_FocusKind_Null : UI_FocusKind_Off)
|
||||||
|
{
|
||||||
|
ui_set_next_pref_width(ui_pct(1, 0));
|
||||||
|
ui_set_next_pref_height(ui_pct(1, 0));
|
||||||
|
ui_set_next_child_layout_axis(Axis2_Y);
|
||||||
|
UI_Box *view_contents_container = ui_build_box_from_stringf(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clip, "###view_contents_container");
|
||||||
|
UI_Parent(view_contents_container) UI_WidthFill
|
||||||
|
{
|
||||||
|
rd_view_ui(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: build loading overlay
|
||||||
|
{
|
||||||
|
RD_ViewState *vs = rd_view_state_from_cfg(view);
|
||||||
|
F32 loading_t = vs->loading_t;
|
||||||
|
if(loading_t > 0.01f) UI_Parent(loading_overlay_container)
|
||||||
|
{
|
||||||
|
rd_loading_overlay(rect, loading_t, vs->loading_progress_v, vs->loading_progress_v_target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: interact with container
|
||||||
|
UI_Signal sig = ui_signal_from_box(container);
|
||||||
|
t->signal = sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: pop interaction registers; commit if this is focused
|
||||||
|
RD_Regs *view_regs = rd_pop_regs();
|
||||||
|
if(is_focused)
|
||||||
|
{
|
||||||
|
MemoryCopyStruct(rd_regs(), view_regs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: @window_ui_part do special handling of floating view interactions
|
||||||
|
//
|
||||||
|
{
|
||||||
|
//- rjf: hover eval focus rules
|
||||||
|
if(hover_eval_floating_view_task)
|
||||||
|
{
|
||||||
|
UI_Signal sig = hover_eval_floating_view_task->signal;
|
||||||
|
if(ui_pressed(sig))
|
||||||
|
{
|
||||||
|
ws->hover_eval_focused = 1;
|
||||||
|
}
|
||||||
|
if(ui_mouse_over(sig) || ws->hover_eval_focused)
|
||||||
|
{
|
||||||
|
ws->hover_eval_lastt_us = rd_state->time_in_us;
|
||||||
|
}
|
||||||
|
else if(ws->hover_eval_lastt_us+1000000 < rd_state->time_in_us)
|
||||||
|
{
|
||||||
|
rd_request_frame();
|
||||||
|
}
|
||||||
|
if(ws->hover_eval_focused)
|
||||||
|
{
|
||||||
|
for(UI_Event *evt = 0; ui_next_event(&evt);)
|
||||||
|
{
|
||||||
|
if(evt->kind == UI_EventKind_Press &&
|
||||||
|
evt->key == OS_Key_LeftMouseButton &&
|
||||||
|
!contains_2f32(hover_eval_floating_view_task->rect, evt->pos))
|
||||||
|
{
|
||||||
|
ws->hover_eval_focused = 0;
|
||||||
|
MemoryZeroStruct(&ws->hover_eval_string);
|
||||||
|
arena_clear(ws->hover_eval_arena);
|
||||||
|
rd_request_frame();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: query interactions
|
||||||
|
if(query_floating_view_task)
|
||||||
|
{
|
||||||
|
String8 cmd_name = ws->query_cmd_name;
|
||||||
|
RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name);
|
||||||
|
|
||||||
|
// rjf: any queries which take a file path mutate the debugger's "current path"
|
||||||
|
if(cmd_kind_info->query.slot == RD_RegSlot_FilePath)
|
||||||
|
{
|
||||||
|
RD_Cfg *view = query_floating_view_task->view;
|
||||||
|
RD_Cfg *query = rd_cfg_child_from_string(view, str8_lit("query"));
|
||||||
|
RD_Cfg *input = rd_cfg_child_from_string(query, str8_lit("input"));
|
||||||
|
if(input != &rd_nil_cfg)
|
||||||
|
{
|
||||||
|
String8 path_chopped = str8_chop_last_slash(input->first->string);
|
||||||
|
rd_cmd(RD_CmdKind_SetCurrentPath, .file_path = path_chopped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: @window_ui_part bottom bar
|
//- rjf: @window_ui_part bottom bar
|
||||||
//
|
//
|
||||||
|
|||||||
+6
-6
@@ -1172,6 +1172,12 @@ ui_begin_build(OS_Handle window, UI_EventList *events, UI_IconInfo *icon_info, U
|
|||||||
ui_state->active_box_key[k] = ui_key_zero();
|
ui_state->active_box_key[k] = ui_key_zero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- rjf: escape -> close context menu
|
||||||
|
if(ui_any_ctx_menu_is_open() && ui_slot_press(UI_EventActionSlot_Cancel))
|
||||||
|
{
|
||||||
|
ui_ctx_menu_close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
@@ -1179,12 +1185,6 @@ ui_end_build(void)
|
|||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
|
|
||||||
//- rjf: escape -> close context menu
|
|
||||||
if(ui_state->ctx_menu_open != 0 && ui_slot_press(UI_EventActionSlot_Cancel))
|
|
||||||
{
|
|
||||||
ui_ctx_menu_close();
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: prune untouched or transient boxes in the cache
|
//- rjf: prune untouched or transient boxes in the cache
|
||||||
ProfScope("ui prune unused boxes")
|
ProfScope("ui prune unused boxes")
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user