Super cool new scrolling contexts applicable to buffers and UIs; cubic scroll!!!

This commit is contained in:
Allen Webster 2019-10-14 20:26:00 -07:00
parent 6374d1bd19
commit b44eb002a6
21 changed files with 664 additions and 258 deletions

View File

@ -54,9 +54,8 @@ file_cursor_to_end(Models *models, Editing_File *file){
#define REQ_FILE(n,v) Editing_File *n = (v)->file_data.file; if (n == 0) return
#define REQ_FILE_HISTORY(n,v) Editing_File *n = (v)->file_data.file; if (n == 0 || n->state.undo.undo.edits == 0) return
DELTA_RULE_SIG(fallback_scroll_rule){
return(pending_delta);
return(pending);
}
#include "4ed_api_implementation.cpp"
@ -339,7 +338,6 @@ App_Init_Sig(app_init){
// NOTE(allen): live set
Arena *arena = models->arena;
{
models->live_set.node_arena = reserve_arena(models->tctx);
models->live_set.count = 0;
models->live_set.max = MAX_VIEWS;
models->live_set.views = push_array(arena, View, models->live_set.max);
@ -776,9 +774,10 @@ App_Step_Sig(app_step){
}
}
#if 0
// NOTE(allen): apply pending smooth deltas
{
Delta_Rule_Function *scroll_rule = models->scroll_rule;
Delta_Rule_Function *delta_rule = models->delta_rule;
for (Panel *panel = layout_get_first_open_panel(layout);
panel != 0;
panel = layout_get_next_open_panel(layout, panel)){
@ -803,6 +802,7 @@ App_Step_Sig(app_step){
}
}
}
#endif
// NOTE(allen): hook for files reloaded
{

View File

@ -450,6 +450,8 @@ buffer_pos_from_relative_character(Application_Links *app, Buffer_ID buffer_id,
return(result);
}
api(custom) function f32
view_line_y_difference(Application_Links *app, View_ID view_id, i64 line_a, i64 line_b){
Models *models = (Models*)app->cmd_context;
@ -1492,7 +1494,8 @@ view_set_cursor(Application_Links *app, View_ID view_id, Buffer_Seek seek)
}
api(custom) function b32
view_set_buffer_scroll(Application_Links *app, View_ID view_id, Buffer_Scroll scroll)
view_set_buffer_scroll(Application_Links *app, View_ID view_id, Buffer_Scroll scroll,
Set_Buffer_Scroll_Rule rule)
{
Models *models = (Models*)app->cmd_context;
b32 result = false;
@ -1505,7 +1508,14 @@ view_set_buffer_scroll(Application_Links *app, View_ID view_id, Buffer_Scroll sc
scroll.target.pixel_shift.x = clamp_bot(0.f, scroll.target.pixel_shift.x);
Buffer_Layout_Item_List line = view_get_line_layout(models, view, scroll.target.line_number);
scroll.target.pixel_shift.y = clamp(0.f, scroll.target.pixel_shift.y, line.height);
view_set_scroll(models, view, scroll);
if (rule == SetBufferScroll_SnapCursorIntoView){
view_set_scroll(models, view, scroll);
}
else{
File_Edit_Positions edit_pos = view_get_edit_pos(view);
edit_pos.scroll = scroll;
view_set_edit_pos(view, edit_pos);
}
view->new_scroll_target = true;
result = true;
}
@ -1580,7 +1590,7 @@ view_push_context(Application_Links *app, View_ID view_id, View_Context *ctx){
View *view = imp_get_view(models, view_id);
b32 result = false;
if (api_check_view(view)){
view_push_context(models, view, ctx);
view_push_context(view, ctx);
result = true;
}
return(result);
@ -1592,7 +1602,7 @@ view_pop_context(Application_Links *app, View_ID view_id){
View *view = imp_get_view(models, view_id);
b32 result = false;
if (api_check_view(view)){
view_pop_context(models, view);
view_pop_context(view);
result = true;
}
return(result);
@ -1609,6 +1619,27 @@ view_current_context(Application_Links *app, View_ID view_id){
return(result);
}
api(custom) function Data
view_current_context_hook_memory(Application_Links *app, View_ID view_id,
Hook_ID hook_id){
Models *models = (Models*)app->cmd_context;
View *view = imp_get_view(models, view_id);
Data result = {};
if (api_check_view(view)){
View_Context_Node *ctx = view_current_context_node(models, view);
if (ctx != 0){
switch (hook_id){
case HookID_DeltaRule:
{
result = make_data(ctx->delta_rule_memory,
ctx->ctx.delta_rule_memory_size);
}break;
}
}
}
return(result);
}
function Dynamic_Workspace*
get_dynamic_workspace(Models *models, Managed_Scope handle){
Dynamic_Workspace *result = 0;
@ -2062,9 +2093,9 @@ set_custom_hook(Application_Links *app, Hook_ID hook_id, Void_Func *func_ptr){
{
models->buffer_viewer_update = (Hook_Function*)func_ptr;
}break;
case HookID_ScrollRule:
case HookID_DeltaRule:
{
models->scroll_rule = (Delta_Rule_Function*)func_ptr;
models->delta_rule = (Delta_Rule_Function*)func_ptr;
}break;
case HookID_ViewEventHandler:
{
@ -2101,6 +2132,23 @@ set_custom_hook(Application_Links *app, Hook_ID hook_id, Void_Func *func_ptr){
}
}
api(custom) function b32
set_custom_hook_memory_size(Application_Links *app, Hook_ID hook_id, umem size){
Models *models = (Models*)app->cmd_context;
b32 result = true;
switch (hook_id){
case HookID_DeltaRule:
{
models->delta_rule_memory_size = size;
}break;
default:
{
result = false;
}break;
}
return(result);
}
api(custom) function Mouse_State
get_mouse_state(Application_Links *app)
{

View File

@ -52,10 +52,12 @@ struct Models{
Application_Links app_links;
Hook_Function *buffer_viewer_update;
Delta_Rule_Function *scroll_rule;
Custom_Command_Function *view_event_handler;
Render_Caller_Function *render_caller;
Delta_Rule_Function *delta_rule;
umem delta_rule_memory_size;
Hook_Function *buffer_viewer_update;
Custom_Command_Function *view_event_handler;
Buffer_Name_Resolver_Function *buffer_name_resolver;
Buffer_Hook_Function *begin_buffer;
Buffer_Hook_Function *end_buffer;

View File

@ -453,39 +453,30 @@ view_set_file(Models *models, View *view, Editing_File *file){
////////////////////////////////
function View_Context_Node*
view__alloc_context_node(Live_Views *views){
View_Context_Node *node = views->free_nodes;
if (node != 0){
sll_stack_pop(views->free_nodes);
}
else{
node = push_array(views->node_arena, View_Context_Node, 1);
}
return(node);
}
function void
view__free_context_node(Live_Views *views, View_Context_Node *node){
sll_stack_push(views->free_nodes, node);
}
function void
view_push_context(Models *models, View *view, View_Context *ctx){
View_Context_Node *node = view__alloc_context_node(&models->live_set);
view_push_context(View *view, View_Context *ctx){
Temp_Memory pop_me = begin_temp(view->node_arena);
View_Context_Node *node = push_array_zero(view->node_arena, View_Context_Node, 1);
sll_stack_push(view->ctx, node);
node->pop_me = pop_me;
block_copy_struct(&node->ctx, ctx);
node->delta_rule_memory = push_array_zero(view->node_arena, u8, ctx->delta_rule_memory_size);
}
function void
view_pop_context(Models *models, View *view){
view_pop_context(View *view){
View_Context_Node *node = view->ctx;
if (node != 0){
if (node != 0 && node->next != 0){
sll_stack_pop(view->ctx);
view__free_context_node(&models->live_set, node);
end_temp(node->pop_me);
}
}
function View_Context_Node*
view_current_context_node(Models *models, View *view){
return(view->ctx);
}
function View_Context
view_current_context(Models *models, View *view){
View_Context ctx = {};
@ -566,9 +557,13 @@ view_init(Models *models, View *view, Editing_File *initial_buffer,
Custom_Command_Function *event_context_base){
view_set_file(models, view, initial_buffer);
view->node_arena = reserve_arena(models->tctx);
View_Context first_ctx = {};
first_ctx.render_caller = models->render_caller;
view_push_context(models, view, &first_ctx);
first_ctx.delta_rule = models->delta_rule;
first_ctx.delta_rule_memory_size = models->delta_rule_memory_size;
view_push_context(view, &first_ctx);
view->co = coroutine_create(&models->coroutines, view_event_context_base__inner);
Co_In in = {};

View File

@ -58,7 +58,9 @@ struct Query_Set{
struct View_Context_Node{
View_Context_Node *next;
Temp_Memory pop_me;
View_Context ctx;
void *delta_rule_memory;
};
struct View{
@ -79,6 +81,7 @@ struct View{
Coroutine *co;
Co_Out co_out;
Arena *node_arena;
View_Context_Node *ctx;
b8 hide_scrollbar;
@ -89,8 +92,6 @@ struct View{
};
struct Live_Views{
Arena *node_arena;
View_Context_Node *free_nodes;
View *views;
View free_sentinel;
i32 count;

View File

@ -207,7 +207,7 @@ CUSTOM_DOC("Centers the view vertically on the line on which the cursor sits.")
Buffer_Scroll scroll = view_get_buffer_scroll(app, view);
scroll.target.line_number = cursor.line;
scroll.target.pixel_shift.y = -view_height*0.5f;
view_set_buffer_scroll(app, view, scroll);
view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView);
}
CUSTOM_COMMAND_SIG(left_adjust_view)
@ -219,7 +219,7 @@ CUSTOM_DOC("Sets the left size of the view near the x position of the cursor.")
Vec2_f32 p = view_relative_xy_of_pos(app, view, cursor.line, pos);
Buffer_Scroll scroll = view_get_buffer_scroll(app, view);
scroll.target.pixel_shift.x = clamp_bot(0.f, p.x - 30.f);
view_set_buffer_scroll(app, view, scroll);
view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView);
}
CUSTOM_COMMAND_SIG(click_set_cursor_and_mark)
@ -272,7 +272,7 @@ CUSTOM_DOC("Reads the scroll wheel value from the mouse state and scrolls accord
if (mouse.wheel != 0){
Buffer_Scroll scroll = view_get_buffer_scroll(app, view);
scroll.target = view_move_buffer_point(app, view, scroll.target, V2f32(0.f, (f32)mouse.wheel));
view_set_buffer_scroll(app, view, scroll);
view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView);
}
}
@ -1581,10 +1581,10 @@ CUSTOM_DOC("Set the other non-active panel to view the buffer that the active pa
view_set_cursor_and_preferred_x(app, view1, seek_pos(p2));
view_set_mark(app, view1, seek_pos(m2));
view_set_buffer_scroll(app, view1, sc2);
view_set_buffer_scroll(app, view1, sc2, SetBufferScroll_SnapCursorIntoView);
view_set_cursor_and_preferred_x(app, view2, seek_pos(p1));
view_set_mark(app, view2, seek_pos(m1));
view_set_buffer_scroll(app, view2, sc1);
view_set_buffer_scroll(app, view2, sc1, SetBufferScroll_SnapCursorIntoView);
}
}
}

View File

@ -2438,6 +2438,46 @@ rect_union(Rect_f32 a, Rect_f32 b){
////////////////////////////////
internal Rect_f32_Pair
rect_split_top_bottom(Rect_f32 rect, f32 y){
y = clamp(rect.y0, y, rect.y1);
Rect_f32_Pair pair = {};
pair.a = Rf32(rect.x0, rect.y0, rect.x1, y );
pair.b = Rf32(rect.x0, y , rect.x1, rect.y1);
return(pair);
}
internal Rect_f32_Pair
rect_split_left_right(Rect_f32 rect, f32 x){
x = clamp(rect.x0, x, rect.x1);
Rect_f32_Pair pair = {};
pair.a = Rf32(rect.x0, rect.y0, x , rect.y1);
pair.b = Rf32(x , rect.y0, rect.x1, rect.y1);
return(pair);
}
internal Rect_f32_Pair
rect_split_top_bottom_neg(Rect_f32 rect, f32 y){
return(rect_split_top_bottom(rect, rect.y1 - y));
}
internal Rect_f32_Pair
rect_split_left_right_neg(Rect_f32 rect, f32 x){
return(rect_split_left_right(rect, rect.x1 - x));
}
internal Rect_f32_Pair
rect_split_top_bottom_lerp(Rect_f32 rect, f32 t){
return(rect_split_top_bottom(rect, lerp(rect.y0, t, rect.y1)));
}
internal Rect_f32_Pair
rect_split_left_right_lerp(Rect_f32 rect, f32 t){
return(rect_split_left_right(rect, lerp(rect.x0, t, rect.x1)));
}
////////////////////////////////
internal Scan_Direction
flip_direction(Scan_Direction direction){
switch (direction){

View File

@ -760,8 +760,18 @@ typedef Vec2_f32 Vec2;
typedef Vec3_f32 Vec3;
typedef Vec4_f32 Vec4;
struct Rect_f32_Pair{
Rect_f32 e[2];
union Rect_f32_Pair{
struct{
Rect_f32 a;
Rect_f32 b;
};
struct{
Rect_f32 min;
Rect_f32 max;
};
struct{
Rect_f32 e[2];
};
};
////////////////////////////////

View File

@ -278,21 +278,31 @@ MODIFY_COLOR_TABLE_SIG(default_modify_color_table){
}
#endif
function Rect_f32_Pair
layout_file_bar_on_top(Rect_f32 rect, f32 line_height){
return(rect_split_top_bottom(rect, line_height + 2.f));
}
function Rect_f32_Pair
layout_file_bar_on_bot(Rect_f32 rect, f32 line_height){
return(rect_split_top_bottom_neg(rect, line_height + 2.f));
}
function Rect_f32
default_view_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 sub_region){
default_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 region){
region = rect_inner(region, 3.f);
Buffer_ID buffer = view_get_buffer(app, view_id, AccessAll);
Face_ID face_id = get_face_id(app, buffer);
Face_Metrics metrics = get_face_metrics(app, face_id);
i32 line_height = i32_ceil32(metrics.line_height);
f32 line_height = metrics.line_height;
// file bar
{
b64 showing_file_bar = false;
if (view_get_setting(app, view_id, ViewSetting_ShowFileBar, &showing_file_bar)){
if (showing_file_bar){
sub_region.y0 += line_height + 2;
}
}
b64 showing_file_bar = false;
if (view_get_setting(app, view_id, ViewSetting_ShowFileBar, &showing_file_bar) &&
showing_file_bar){
Rect_f32_Pair pair = layout_file_bar_on_top(region, line_height);
region = pair.b;
}
// query bar
@ -301,8 +311,8 @@ default_view_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 sub
Query_Bar_Ptr_Array query_bars = {};
query_bars.ptrs = space;
if (get_active_query_bars(app, view_id, ArrayCount(space), &query_bars)){
i32 widget_height = (line_height + 2)*query_bars.count;
sub_region.y0 += widget_height;
f32 widget_height = (line_height + 2)*query_bars.count;
region.y0 += widget_height;
}
}
@ -311,10 +321,10 @@ default_view_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 sub
i64 line_count = buffer_get_line_count(app, buffer);
i64 line_count_digit_count = digit_count_from_integer(line_count, 10);
i32 margin_width = i32_ceil32((f32)line_count_digit_count*metrics.normal_advance);
sub_region.x0 += margin_width + 2;
region.x0 += margin_width + 2;
}
return(sub_region);
return(region);
}
internal int_color
@ -447,10 +457,36 @@ default_render_caller(Application_Links *app, Frame_Info frame_info, View_ID vie
draw_fancy_string(app, face_id, list.first, p, Stag_Default, 0);
}
Rect_f32 sub_region = default_view_buffer_region(app, view_id, inner);
Rect_f32 buffer_rect = rect_intersect(sub_region, inner);
Rect_f32 buffer_rect = default_buffer_region(app, view_id, view_rect);
Buffer_Scroll scroll = view_get_buffer_scroll(app, view_id);
Buffer_Point_Delta_Result delta = delta_apply(app, view_id,
frame_info.animation_dt, scroll);
if (!block_match_struct(&scroll.position, &delta.point)){
block_copy_struct(&scroll.position, &delta.point);
view_set_buffer_scroll(app, view_id, scroll, SetBufferScroll_NoCursorChange);
}
if (delta.still_animating){
animate_in_n_milliseconds(app, 0);
}
#if 0
// NOTE(allen): clamp scroll target and position; smooth scroll rule
{
Vec2_f32 pending = view_point_difference(app, view_id, scroll.target, scroll.position);
if (!near_zero(pending, 0.5f)){
// TODO(allen): use the real delta rule from the context
Vec2_f32 partial = pending;
scroll.position = view_move_buffer_point(app, view_id, scroll.position, partial);
animate_in_n_milliseconds(app, 0);
}
else{
scroll.position = scroll.target;
}
view_set_buffer_scroll(app, view_id, scroll, SetBufferScroll_NoCursorChange);
}
#endif
Buffer_Point buffer_point = scroll.position;
Text_Layout_ID text_layout_id = text_layout_create(app, buffer, buffer_rect, buffer_point);
Interval_i64 visible_range = text_layout_get_visible_range(app, text_layout_id);
@ -762,8 +798,8 @@ default_render_caller(Application_Links *app, Frame_Info frame_info, View_ID vie
}
HOOK_SIG(default_view_adjust){
// NOTE(allen): Called whenever the view layout/sizes have been modified, including
// by full window resize.
// NOTE(allen): Called whenever the view layout/sizes have been modified,
// including by full window resize.
return(0);
}
@ -1120,85 +1156,6 @@ BUFFER_HOOK_SIG(default_end_file){
return(0);
}
// TODO(allen): FIX FIX FIX FIX
// NOTE(allen|a4): scroll rule information
//
// The parameters:
// target_x, target_y
// This is where the view would like to be for the purpose of
// following the cursor, doing mouse wheel work, etc.
//
// scroll_x, scroll_y
// These are pointers to where the scrolling actually is. If you bind
// the scroll rule it is you have to update these in some way to move
// the actual location of the scrolling.
//
// view_id
// This corresponds to which view is computing it's new scrolling position.
// This id DOES correspond to the views that View_ _Summary contains.
// This will always be between 1 and 16 (0 is a null id).
// See below for an example of having state that carries across scroll udpates.
//
// is_new_target
// If the target of the view is different from the last target in either x or y
// this is true, otherwise it is false.
//
// The return:
// Should be true if and only if scroll_x or scroll_y are changed.
//
// Don't try to use the app pointer in a scroll rule, you're asking for trouble.
//
// If you don't bind scroll_rule, nothing bad will happen, yo will get default
// 4coder scrolling behavior.
//
Vec2_f32 scroll_velocity_[16] = {};
Vec2_f32 *scroll_velocity = scroll_velocity_ - 1;
struct Smooth_Step{
f32 p;
f32 v;
};
internal Smooth_Step
smooth_camera_step(f32 target, f32 v, f32 S, f32 T){
Smooth_Step step = {};
step.v = v;
if (step.p != target){
if (step.p > target - .1f && step.p < target + .1f){
step.p = target;
step.v = 1.f;
}
else{
f32 L = step.p + T*(target - step.p);
i32 sign = (target > step.p) - (target < step.p);
f32 V = step.p + sign*step.v;
if (sign > 0){
step.p = (L<V)?(L):(V);
}
else{
step.p = (L>V)?(L):(V);
}
if (step.p == V){
step.v *= S;
}
}
}
return(step);
}
DELTA_RULE_SIG(smooth_scroll_rule){
Vec2_f32 *velocity = scroll_velocity + view_id;
if (velocity->x == 0.f){
velocity->x = 1.f;
velocity->y = 1.f;
}
Smooth_Step step_x = smooth_camera_step(pending_delta.x, velocity->x, 80.f, 1.f/2.f);
Smooth_Step step_y = smooth_camera_step(pending_delta.y, velocity->y, 80.f, 1.f/2.f);
*velocity = V2f32(step_x.v, step_y.v);
return(V2f32(step_x.p, step_y.p));
}
internal void
set_all_default_hooks(Application_Links *app){
#if 0
@ -1213,7 +1170,15 @@ set_all_default_hooks(Application_Links *app){
set_custom_hook(app, HookID_ViewEventHandler, default_view_input_handler);
set_custom_hook(app, HookID_RenderCaller, default_render_caller);
set_custom_hook(app, HookID_ScrollRule, smooth_scroll_rule);
#if 0
set_custom_hook(app, HookID_DeltaRule, original_delta);
set_custom_hook_memory_size(app, HookID_DeltaRule,
delta_ctx_size(original_delta_memory_size));
#else
set_custom_hook(app, HookID_DeltaRule, fixed_time_cubic_delta);
set_custom_hook_memory_size(app, HookID_DeltaRule,
delta_ctx_size(fixed_time_cubic_delta_memory_size));
#endif
set_custom_hook(app, HookID_BufferNameResolver, default_buffer_name_resolution);
set_custom_hook(app, HookID_BeginBuffer, default_file_settings);
@ -1221,7 +1186,7 @@ set_all_default_hooks(Application_Links *app){
set_custom_hook(app, HookID_NewFile, default_new_file);
set_custom_hook(app, HookID_SaveFile, default_file_save);
set_custom_hook(app, HookID_BufferEditRange, default_buffer_edit_range);
set_custom_hook(app, HookID_BufferRegion, default_view_buffer_region);
set_custom_hook(app, HookID_BufferRegion, default_buffer_region);
}
// BOTTOM

View File

@ -29,6 +29,7 @@
#include "4coder_command_map.h"
#include "4coder_string_match.h"
#include "4coder_helper.h"
#include "4coder_delta_rule.h"
#include "4coder_insertion.h"
#include "4coder_fancy.h"
#include "4coder_lister_base.h"
@ -66,6 +67,7 @@
#include "4coder_command_map.cpp"
#include "4coder_default_framework_variables.cpp"
#include "4coder_helper.cpp"
#include "4coder_delta_rule.cpp"
#include "4coder_fancy.cpp"
#include "4coder_lister_base.cpp"
#include "4coder_font_helper.cpp"

View File

@ -0,0 +1,218 @@
/*
4coder_delta_rule.cpp - Built in delta rules and delta rule helpers.
*/
// TOP
function umem
delta_ctx_size(umem base_size){
return(base_size + sizeof(Delta_Context_Header));
}
function Delta_Context_Header*
delta_ctx_get_header(Data delta_ctx){
return((Delta_Context_Header*)delta_ctx.data);
}
function void*
delta_ctx_get_user_data(Data delta_ctx){
Delta_Context_Header *ctx = (Delta_Context_Header*)delta_ctx.data;
return(ctx + 1);
}
function Buffer_Point_Delta_Result
delta_apply(Application_Links *app, View_ID view,
Delta_Rule_Function *func, Data delta_ctx,
f32 dt, Buffer_Point position, Buffer_Point target){
Buffer_Point_Delta_Result result = {};
Vec2_f32 pending = view_point_difference(app, view, target, position);
if (!near_zero(pending, 0.5f)){
Delta_Context_Header *ctx = delta_ctx_get_header(delta_ctx);
b32 is_new_target = false;
if (!block_match_struct(&ctx->point, &target)){
block_copy_struct(&ctx->point, &target);
is_new_target = true;
}
void *rule_data = delta_ctx_get_user_data(delta_ctx);
Vec2_f32 partial = func(pending, is_new_target, dt, rule_data);
// NOTE(allen): clamp partial into the box from the origin
// to the pending delta.
Range_f32 x = If32(pending.x, 0.f);
Range_f32 y = If32(pending.y, 0.f);
partial.x = clamp_range(x, partial.x);
partial.y = clamp_range(y, partial.y);
result.point = view_move_buffer_point(app, view, position, partial);
result.still_animating = true;
}
else{
result.point = target;
}
return(result);
}
function Buffer_Point_Delta_Result
delta_apply(Application_Links *app, View_ID view,
Delta_Rule_Function *func, Data delta_ctx,
f32 dt, Buffer_Scroll scroll){
return(delta_apply(app, view, func, delta_ctx,
dt, scroll.position, scroll.target));
}
function Buffer_Point_Delta_Result
delta_apply(Application_Links *app, View_ID view,
f32 dt, Buffer_Point position, Buffer_Point target){
View_Context ctx = view_current_context(app, view);
Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule);
return(delta_apply(app, view, ctx.delta_rule, delta_ctx,
dt, position, target));
}
function Buffer_Point_Delta_Result
delta_apply(Application_Links *app, View_ID view,
f32 dt, Buffer_Scroll scroll){
View_Context ctx = view_current_context(app, view);
Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule);
return(delta_apply(app, view, ctx.delta_rule, delta_ctx,
dt, scroll.position, scroll.target));
}
function Vec2_f32_Delta_Result
delta_apply(Application_Links *app, View_ID view,
Delta_Rule_Function *func, Data delta_ctx,
f32 dt, Vec2_f32 position, Vec2_f32 target){
Vec2_f32_Delta_Result result = {};
Vec2_f32 pending = target - position;
if (!near_zero(pending, 0.5f)){
Delta_Context_Header *ctx = delta_ctx_get_header(delta_ctx);
b32 is_new_target = false;
if (!near_zero(ctx->p - target, 0.1f)){
block_copy_struct(&ctx->p, &target);
is_new_target = true;
}
void *rule_data = delta_ctx_get_user_data(delta_ctx);
Vec2_f32 partial = func(pending, is_new_target, dt, rule_data);
// NOTE(allen): clamp partial into the box from the origin
// to the pending delta.
Range_f32 x = If32(pending.x, 0.f);
Range_f32 y = If32(pending.y, 0.f);
partial.x = clamp_range(x, partial.x);
partial.y = clamp_range(y, partial.y);
result.p = position + partial;
result.still_animating = true;
}
else{
result.p = target;
}
return(result);
}
function Vec2_f32_Delta_Result
delta_apply(Application_Links *app, View_ID view,
Delta_Rule_Function *func, Data delta_ctx,
f32 dt, Basic_Scroll scroll){
return(delta_apply(app, view, func, delta_ctx,
dt, scroll.position, scroll.target));
}
function Vec2_f32_Delta_Result
delta_apply(Application_Links *app, View_ID view,
f32 dt, Vec2_f32 position, Vec2_f32 target){
View_Context ctx = view_current_context(app, view);
Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule);
return(delta_apply(app, view, ctx.delta_rule, delta_ctx,
dt, position, target));
}
function Vec2_f32_Delta_Result
delta_apply(Application_Links *app, View_ID view,
f32 dt, Basic_Scroll scroll){
View_Context ctx = view_current_context(app, view);
Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule);
return(delta_apply(app, view, ctx.delta_rule, delta_ctx,
dt, scroll.position, scroll.target));
}
////////////////////////////////
internal Smooth_Step
smooth_camera_step(f32 target, f32 v, f32 S, f32 T){
Smooth_Step step = {};
step.v = v;
if (step.p != target){
if (step.p > target - .1f && step.p < target + .1f){
step.p = target;
step.v = 1.f;
}
else{
f32 L = step.p + T*(target - step.p);
i32 sign = (target > step.p) - (target < step.p);
f32 V = step.p + sign*step.v;
if (sign > 0){
step.p = (L<V)?(L):(V);
}
else{
step.p = (L>V)?(L):(V);
}
if (step.p == V){
step.v *= S;
}
}
}
return(step);
}
DELTA_RULE_SIG(original_delta){
Vec2_f32 *velocity = (Vec2_f32*)data;
if (velocity->x == 0.f){
velocity->x = 1.f;
velocity->y = 1.f;
}
Smooth_Step step_x = smooth_camera_step(pending.x, velocity->x, 80.f, 1.f/2.f);
Smooth_Step step_y = smooth_camera_step(pending.y, velocity->y, 80.f, 1.f/2.f);
*velocity = V2f32(step_x.v, step_y.v);
return(V2f32(step_x.p, step_y.p));
}
global_const umem original_delta_memory_size = sizeof(Vec2_f32);
DELTA_RULE_SIG(snap_delta){
return(pending);
}
global_const umem snap_delta_memory_size = 0;
function f32
cubic_reinterpolate(f32 t){
f32 t2 = t*t;
f32 t3 = t2*t;
return(3*t2 - 2*t3);
}
DELTA_RULE_SIG(fixed_time_cubic_delta){
local_const f32 duration_in_seconds = (1.f/8.f);
local_const f32 dt_multiplier = 1.f/duration_in_seconds;
f32 step = dt*dt_multiplier;
f32 *t = (f32*)data;
*t = clamp(0.f, *t, 1.f);
f32 prev_t = *t;
if (is_new_target){
prev_t = 0.f;
*t = step;
}
else{
*t += step;
}
*t = clamp(0.f, *t, 1.f);
Vec2_f32 result = pending;
if (*t < 1.f){
f32 prev_x = cubic_reinterpolate(prev_t);
f32 x = cubic_reinterpolate(*t);
f32 portion = ((x - prev_x)/(1.f - prev_x));
result *= portion;
}
return(result);
}
global_const umem fixed_time_cubic_delta_memory_size = sizeof(f32);
// BOTTOM

View File

@ -0,0 +1,31 @@
/*
4coder_delta_rule.h - Types for built in delta rules and delta rule helpers.
*/
// TOP
#if !defined(FCODER_DELTA_RULE_H)
#define FCODER_DELTA_RULE_H
union Delta_Context_Header{
Buffer_Point point;
Vec2_f32 p;
};
struct Buffer_Point_Delta_Result{
Buffer_Point point;
b32 still_animating;
};
struct Vec2_f32_Delta_Result{
Vec2_f32 p;
b32 still_animating;
};
struct Smooth_Step{
f32 p;
f32 v;
};
#endif
// BOTTOM

View File

@ -167,7 +167,7 @@ view_move_buffer_point(Application_Links *app, View_ID view, Buffer_Point buffer
internal void
view_zero_scroll(Application_Links *app, View_ID view){
Buffer_Scroll scroll = {};
view_set_buffer_scroll(app, view, scroll);
view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView);
}
internal void
@ -178,6 +178,23 @@ view_set_cursor_and_preferred_x(Application_Links *app, View_ID view, Buffer_See
view_set_preferred_x(app, view, p.x);
}
function Vec2_f32
buffer_point_difference(Application_Links *app, Buffer_ID buffer, f32 width, Face_ID face_id,
Buffer_Point a, Buffer_Point b){
f32 y_difference = buffer_line_y_difference(app, buffer, width, face_id, a.line_number, b.line_number);
Vec2_f32 result = a.pixel_shift - b.pixel_shift;
result.y += y_difference;
return(result);
}
function Vec2_f32
view_point_difference(Application_Links *app, View_ID view, Buffer_Point a, Buffer_Point b){
f32 y_difference = view_line_y_difference(app, view, a.line_number, b.line_number);
Vec2_f32 result = a.pixel_shift - b.pixel_shift;
result.y += y_difference;
return(result);
}
////////////////////////////////
internal Range_i64
@ -1625,7 +1642,7 @@ view_look_at_region(Application_Links *app, View_ID view, i64 major_pos, i64 min
Buffer_Scroll scroll = view_get_buffer_scroll(app, view);
scroll.target.line_number = major_line;
scroll.target.pixel_shift.y = -skirt_height;
view_set_buffer_scroll(app, view, scroll);
view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView);
}
else{
Buffer_Scroll scroll = view_get_buffer_scroll(app, view);
@ -1634,7 +1651,7 @@ view_look_at_region(Application_Links *app, View_ID view, i64 major_pos, i64 min
if (top_p.y < acceptable_y.min){
scroll.target.line_number = top.line;
scroll.target.pixel_shift.y = -skirt_height;
view_set_buffer_scroll(app, view, scroll);
view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView);
}
else{
Vec2_f32 bot_p = view_relative_xy_of_pos(app, view, scroll.position.line_number, range.max);
@ -1642,7 +1659,7 @@ view_look_at_region(Application_Links *app, View_ID view, i64 major_pos, i64 min
if (bot_p.y > acceptable_y.max){
scroll.target.line_number = bottom.line;
scroll.target.pixel_shift.y = skirt_height - view_height;
view_set_buffer_scroll(app, view, scroll);
view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView);
}
}
}

View File

@ -139,6 +139,11 @@ lister_append_key(Lister *lister, char *string){
lister_append_string(SCu8(string), &lister->key_string);
}
function void
lister_zero_scroll(Lister *lister){
block_zero_struct(&lister->scroll);
}
function void
lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){
Scratch_Block scratch(app);
@ -171,6 +176,9 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){
f32 block_height = lister_get_block_height(line_height);
f32 text_field_height = lister_get_text_field_height(line_height);
lister->visible_count = (i32)((rect_height(region)/block_height)) - 3;
lister->visible_count = clamp_bot(1, lister->visible_count);
Lister_Top_Level_Layout layout = lister_get_top_level_layout(region, text_field_height);
{
@ -188,19 +196,48 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){
Range_f32 x = rect_range_x(layout.list_rect);
draw_set_clip(app, layout.list_rect);
// NOTE(allen): auto scroll to the item if the flag is set.
f32 scroll_y = lister->scroll.position.y;
if (lister->set_vertical_focus_to_item){
lister->set_vertical_focus_to_item = false;
Range_f32 item_y = If32_size(lister->item_index*block_height, block_height);
f32 view_h = rect_height(layout.list_rect);
Range_f32 view_y = If32_size(scroll_y, view_h);
if (view_y.min > item_y.min || item_y.max > view_y.max){
f32 item_center = (item_y.min + item_y.max)*0.5f;
f32 view_center = (view_y.min + view_y.max)*0.5f;
f32 margin = view_h*.3f;
margin = clamp_top(margin, block_height*3.f);
if (item_center < view_center){
lister->scroll.target.y = item_y.min - margin;
}
else{
f32 target_bot = item_y.max + margin;
lister->scroll.target.y = target_bot - view_h;
}
}
}
// NOTE(allen): clamp scroll target and position; smooth scroll rule
i32 count = lister->filtered.count;
Range_f32 scroll_range = If32(0.f, clamp_bot(0.f, count*block_height - block_height));
lister->scroll.position.y = clamp_range(scroll_range, lister->scroll.position.y);
lister->scroll.position.x = 0.f;
lister->scroll.target.y = clamp_range(scroll_range, lister->scroll.target.y);
lister->scroll.target.x = 0.f;
// TODO(allen): get scroll rule from context
lister->scroll.position = lister->scroll.target;
Vec2_f32_Delta_Result delta = delta_apply(app, view,
frame_info.animation_dt, lister->scroll);
lister->scroll.position = delta.p;
if (delta.still_animating){
animate_in_n_milliseconds(app, 0);
}
f32 scroll_y = lister->scroll.position.y;
lister->scroll.position.y = clamp_range(scroll_range, lister->scroll.position.y);
lister->scroll.position.x = 0.f;
scroll_y = lister->scroll.position.y;
f32 y_pos = layout.list_rect.y0 - scroll_y;
i32 first_index = (i32)(scroll_y/block_height);
y_pos += first_index*block_height;
@ -308,6 +345,20 @@ lister_get_filtered(Arena *arena, Lister *lister){
return(filtered);
}
function void
lister_update_selection_values(Lister *lister){
lister->raw_item_index = -1;
lister->highlighted_node = 0;
i32 count = lister->filtered.count;
for (i32 i = 0; i < count; i += 1){
Lister_Node *node = lister->filtered.node_ptrs[i];
if (lister->item_index == i){
lister->highlighted_node = node;
lister->raw_item_index = node->raw_index;
}
}
}
function void
lister_update_filtered_list(Application_Links *app, View_ID view, Lister *lister){
Scratch_Block scratch(app, Scratch_Share);
@ -332,23 +383,17 @@ lister_update_filtered_list(Application_Links *app, View_ID view, Lister *lister
Lister_Node **node_ptrs = push_array(arena, Lister_Node*, total_count);
lister->filtered.node_ptrs = node_ptrs;
lister->filtered.count = total_count;
lister->raw_item_index = -1;
lister->highlighted_node = 0;
i32 counter = 0;
for (i32 array_index = 0; array_index < ArrayCount(node_ptr_arrays); array_index += 1){
Lister_Node_Ptr_Array node_ptr_array = node_ptr_arrays[array_index];
for (i32 node_index = 0; node_index < node_ptr_array.count; node_index += 1){
Lister_Node *node = node_ptr_array.node_ptrs[node_index];
node_ptrs[counter] = node;
if (lister->item_index == counter){
lister->highlighted_node = node;
lister->raw_item_index = node->raw_index;
}
counter += 1;
}
}
lister_update_selection_values(lister);
}
function void
@ -474,8 +519,8 @@ lister_run(Application_Links *app, View_ID view, Lister *lister){
case KeyCode_Up:
{
if (lister->handlers.navigate_up != 0){
lister->handlers.navigate_up(app);
if (lister->handlers.navigate != 0){
lister->handlers.navigate(app, view, lister, -1);
}
else{
handled = false;
@ -484,8 +529,30 @@ lister_run(Application_Links *app, View_ID view, Lister *lister){
case KeyCode_Down:
{
if (lister->handlers.navigate_down != 0){
lister->handlers.navigate_down(app);
if (lister->handlers.navigate != 0){
lister->handlers.navigate(app, view, lister, 1);
}
else{
handled = false;
}
}break;
case KeyCode_PageUp:
{
if (lister->handlers.navigate != 0){
lister->handlers.navigate(app, view, lister,
-lister->visible_count);
}
else{
handled = false;
}
}break;
case KeyCode_PageDown:
{
if (lister->handlers.navigate != 0){
lister->handlers.navigate(app, view, lister,
lister->visible_count);
}
else{
handled = false;
@ -645,5 +712,53 @@ lister_add_item(Lister *lister, String_Const_u8 string, String_Const_u8 status,
user_data, extra_space));
}
function void
lister__write_string__default(Application_Links *app){
View_ID view = get_active_view(app, AccessAll);
Lister *lister = view_get_lister(view);
if (lister != 0){
User_Input in = get_current_input(app);
String_Const_u8 string = to_writable(&in);
if (string.str != 0 && string.size > 0){
lister_append_text_field(lister, string);
lister_append_key(lister, string);
lister->item_index = 0;
lister_zero_scroll(lister);
lister_update_filtered_list(app, view, lister);
}
}
}
function void
lister__backspace_text_field__default(Application_Links *app){
View_ID view = get_active_view(app, AccessAll);
Lister *lister = view_get_lister(view);
if (lister != 0){
lister->text_field.string = backspace_utf8(lister->text_field.string);
lister->key_string.string = backspace_utf8(lister->key_string.string);
lister->item_index = 0;
lister_zero_scroll(lister);
lister_update_filtered_list(app, view, lister);
}
}
function void
lister__navigate__default(Application_Links *app, View_ID view, Lister *lister,
i32 delta){
i32 new_index = lister->item_index + delta;
if (new_index < 0 && lister->item_index == 0){
lister->item_index = lister->filtered.count - 1;
}
else if (new_index >= lister->filtered.count &&
lister->item_index == lister->filtered.count - 1){
lister->item_index = 0;
}
else{
lister->item_index = clamp(0, new_index, lister->filtered.count - 1);
}
lister->set_vertical_focus_to_item = true;
lister_update_selection_values(lister);
}
// BOTTOM

View File

@ -44,14 +44,16 @@ struct Lister_Node_Ptr_Array{
};
typedef Lister_Activation_Code Lister_Key_Stroke_Function(Application_Links *app);
typedef void Lister_Navigate_Function(Application_Links *app,
View_ID view, struct Lister *lister,
i32 index_delta);
struct Lister_Handlers{
Lister_Activation_Type *activate;
Lister_Regenerate_List_Function_Type *refresh;
Custom_Command_Function *write_character;
Custom_Command_Function *backspace;
Custom_Command_Function *navigate_up;
Custom_Command_Function *navigate_down;
Lister_Navigate_Function *navigate;
Lister_Key_Stroke_Function *key_stroke;
};
@ -78,13 +80,14 @@ struct Lister{
Temp_Memory filter_restore_point;
Lister_Node_Ptr_Array filtered;
b32 set_view_vertical_focus_to_item;
b32 set_vertical_focus_to_item;
Lister_Node *highlighted_node;
void *hot_user_data;
i32 item_index;
i32 raw_item_index;
Basic_Scroll scroll;
i32 visible_count;
};
struct Lister_Prealloced_String{

View File

@ -5,64 +5,6 @@ such as open file, switch buffer, or kill buffer.
// TOP
function void
lister__write_string__default(Application_Links *app){
View_ID view = get_active_view(app, AccessAll);
Lister *lister = view_get_lister(view);
if (lister != 0){
User_Input in = get_current_input(app);
String_Const_u8 string = to_writable(&in);
if (string.str != 0 && string.size > 0){
lister_append_text_field(lister, string);
lister_append_key(lister, string);
lister->item_index = 0;
view_zero_scroll(app, view);
lister_update_filtered_list(app, view, lister);
}
}
}
function void
lister__backspace_text_field__default(Application_Links *app){
View_ID view = get_active_view(app, AccessAll);
Lister *lister = view_get_lister(view);
if (lister != 0){
lister->text_field.string = backspace_utf8(lister->text_field.string);
lister->key_string.string = backspace_utf8(lister->key_string.string);
lister->item_index = 0;
view_zero_scroll(app, view);
lister_update_filtered_list(app, view, lister);
}
}
function void
lister__move_up__default(Application_Links *app){
View_ID view = get_active_view(app, AccessAll);
Lister *lister = view_get_lister(view);
if (lister != 0){
lister->item_index = lister->item_index - 1;
if (lister->item_index < 0){
lister->item_index = lister->filtered.count - 1;
}
lister->set_view_vertical_focus_to_item = true;
lister_update_filtered_list(app, view, lister);
}
}
function void
lister__move_down__default(Application_Links *app){
View_ID view = get_active_view(app, AccessAll);
Lister *lister = view_get_lister(view);
if (lister != 0){
lister->item_index = lister->item_index + 1;
if (lister->item_index > lister->filtered.count - 1){
lister->item_index = 0;
}
lister->set_view_vertical_focus_to_item = true;
lister_update_filtered_list(app, view, lister);
}
}
function void
lister__write_character__file_path(Application_Links *app){
View_ID view = get_active_view(app, AccessAll);
@ -80,7 +22,7 @@ lister__write_character__file_path(Application_Links *app){
lister_call_refresh_handler(app, view, lister);
}
lister->item_index = 0;
view_zero_scroll(app, view);
lister_zero_scroll(lister);
lister_update_filtered_list(app, view, lister);
}
}
@ -117,7 +59,7 @@ lister__backspace_text_field__file_path(Application_Links *app){
}
lister->item_index = 0;
view_zero_scroll(app, view);
lister_zero_scroll(lister);
lister_update_filtered_list(app, view, lister);
}
}
@ -158,16 +100,14 @@ lister_get_default_handlers(void){
Lister_Handlers handlers = {};
handlers.write_character = lister__write_string__default;
handlers.backspace = lister__backspace_text_field__default;
handlers.navigate_up = lister__move_up__default;
handlers.navigate_down = lister__move_down__default;
handlers.navigate = lister__navigate__default;
return(handlers);
}
function Lister_Handlers
lister_get_fixed_list_handlers(void){
Lister_Handlers handlers = {};
handlers.navigate_up = lister__move_up__default;
handlers.navigate_down = lister__move_down__default;
handlers.navigate = lister__navigate__default;
handlers.key_stroke = lister__key_stroke__fixed_list;
return(handlers);
}
@ -197,8 +137,6 @@ run_lister_with_refresh_handler(Application_Links *app, char *query_string,
}
}
global_const i32 default_string_size_estimation = 0;
function i32
lister__get_arena_size_(i32 option_count, i32 user_data_size,
i32 estimated_string_space_size){
@ -230,7 +168,6 @@ run_lister_with_fixed_options(Application_Links *app, char *query_string,
Lister_Handlers handlers,
void *user_data, i32 user_data_size,
Lister_Fixed_Option *options, i32 option_count,
i32 estimated_string_space_size,
View_ID view){
Scratch_Block scratch(app);
Lister *lister = begin_lister(app, scratch, view, user_data, user_data_size);
@ -252,14 +189,12 @@ run_lister_with_fixed_options(Application_Links *app, char *query_string,
Lister_Activation_Type *activate,
void *user_data, i32 user_data_size,
Lister_Fixed_Option *options, i32 option_count,
i32 estimated_string_space_size,
View_ID view){
Lister_Handlers handlers = lister_get_fixed_list_handlers();
handlers.activate = activate;
run_lister_with_fixed_options(app, query_string,
handlers, user_data, user_data_size,
options, option_count,
estimated_string_space_size,
view);
}
@ -486,7 +421,7 @@ do_gui_sure_to_kill(Application_Links *app, Buffer_ID buffer, View_ID view){
data.id = buffer;
run_lister_with_fixed_options(app, "There are unsaved changes, close anyway?",
activate_confirm_kill, &data, sizeof(data),
options, option_count, default_string_size_estimation,
options, option_count,
view);
return(data.do_kill);
}
@ -530,7 +465,7 @@ do_gui_sure_to_close_4coder(Application_Links *app, View_ID view){
run_lister_with_fixed_options(app, "There are one or more buffers with unsave changes, close anyway?",
activate_confirm_close_4coder,
&do_exit, sizeof(do_exit),
options, option_count, default_string_size_estimation,
options, option_count,
view);
return(do_exit);
}

View File

@ -253,6 +253,12 @@ STRUCT Buffer_Identifier{
Buffer_ID id;
};
typedef i32 Set_Buffer_Scroll_Rule;
enum{
SetBufferScroll_NoCursorChange,
SetBufferScroll_SnapCursorIntoView,
};
struct Buffer_Scroll{
Buffer_Point position;
Buffer_Point target;
@ -476,8 +482,8 @@ STRUCT User_Input{
typedef i32 Hook_ID;
enum{
HookID_RenderCaller,
HookID_DeltaRule,
HookID_BufferViewerUpdate,
HookID_ScrollRule,
HookID_ViewEventHandler,
HookID_BufferNameResolver,
HookID_BeginBuffer,
@ -512,9 +518,9 @@ typedef i32 Buffer_Edit_Range_Function(Application_Links *app, Buffer_ID buffer_
#define BUFFER_EDIT_RANGE_SIG(name) i32 name(Application_Links *app, Buffer_ID buffer_id,\
Interval_i64 range, String_Const_u8 text)
typedef Vec2_f32 Delta_Rule_Function(Vec2_f32 pending_delta, View_ID view_id, b32 is_new_target, f32 dt);
typedef Vec2_f32 Delta_Rule_Function(Vec2_f32 pending, b32 is_new_target, f32 dt, void *data);
#define DELTA_RULE_SIG(name) \
Vec2_f32 name(Vec2_f32 pending_delta, View_ID view_id, b32 is_new_target, f32 dt)
Vec2_f32 name(Vec2_f32 pending, b32 is_new_target, f32 dt, void *data)
typedef Rect_f32 Buffer_Region_Function(Application_Links *app, View_ID view_id, Rect_f32 region);
@ -532,6 +538,8 @@ typedef void Render_Caller_Function(Application_Links *app, Frame_Info frame_inf
struct View_Context{
Render_Caller_Function *render_caller;
Delta_Rule_Function *delta_rule;
umem delta_rule_memory_size;
b32 hides_buffer;
};

View File

@ -227,12 +227,12 @@ i32 line_number;
};
static Command_Metadata fcoder_metacmd_table[205] = {
{ PROC_LINKS(default_view_input_handler, 0), "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 56 },
{ PROC_LINKS(seek_beginning_of_textual_line, 0), "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 1979 },
{ PROC_LINKS(seek_end_of_textual_line, 0), "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 1985 },
{ PROC_LINKS(seek_beginning_of_line, 0), "seek_beginning_of_line", 22, "Seeks the cursor to the beginning of the visual line.", 53, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 1991 },
{ PROC_LINKS(seek_end_of_line, 0), "seek_end_of_line", 16, "Seeks the cursor to the end of the visual line.", 47, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 1997 },
{ PROC_LINKS(goto_beginning_of_file, 0), "goto_beginning_of_file", 22, "Sets the cursor to the beginning of the file.", 45, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2003 },
{ PROC_LINKS(goto_end_of_file, 0), "goto_end_of_file", 16, "Sets the cursor to the end of the file.", 39, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2011 },
{ PROC_LINKS(seek_beginning_of_textual_line, 0), "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 1996 },
{ PROC_LINKS(seek_end_of_textual_line, 0), "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2002 },
{ PROC_LINKS(seek_beginning_of_line, 0), "seek_beginning_of_line", 22, "Seeks the cursor to the beginning of the visual line.", 53, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2008 },
{ PROC_LINKS(seek_end_of_line, 0), "seek_end_of_line", 16, "Seeks the cursor to the end of the visual line.", 47, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2014 },
{ PROC_LINKS(goto_beginning_of_file, 0), "goto_beginning_of_file", 22, "Sets the cursor to the beginning of the file.", 45, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2020 },
{ PROC_LINKS(goto_end_of_file, 0), "goto_end_of_file", 16, "Sets the cursor to the end of the file.", 39, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2028 },
{ PROC_LINKS(change_active_panel, 0), "change_active_panel", 19, "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 196 },
{ PROC_LINKS(change_active_panel_backwards, 0), "change_active_panel_backwards", 29, "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 206 },
{ PROC_LINKS(open_panel_vsplit, 0), "open_panel_vsplit", 17, "Create a new panel by vertically splitting the active panel.", 60, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 216 },
@ -344,12 +344,12 @@ static Command_Metadata fcoder_metacmd_table[205] = {
{ PROC_LINKS(redo_all_buffers, 0), "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1939 },
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2040 },
{ PROC_LINKS(default_file_externally_modified, 0), "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2047 },
{ PROC_LINKS(interactive_switch_buffer, 0), "interactive_switch_buffer", 25, "Interactively switch to an open buffer.", 39, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 552 },
{ PROC_LINKS(interactive_kill_buffer, 0), "interactive_kill_buffer", 23, "Interactively kill an open buffer.", 34, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 571 },
{ PROC_LINKS(interactive_open_or_new, 0), "interactive_open_or_new", 23, "Interactively open a file out of the file system.", 49, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 642 },
{ PROC_LINKS(interactive_new, 0), "interactive_new", 15, "Interactively creates a new file.", 33, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 681 },
{ PROC_LINKS(interactive_open, 0), "interactive_open", 16, "Interactively opens a file.", 27, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 714 },
{ PROC_LINKS(command_lister, 0), "command_lister", 14, "Opens an interactive list of all registered commands.", 53, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 774 },
{ PROC_LINKS(interactive_switch_buffer, 0), "interactive_switch_buffer", 25, "Interactively switch to an open buffer.", 39, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 487 },
{ PROC_LINKS(interactive_kill_buffer, 0), "interactive_kill_buffer", 23, "Interactively kill an open buffer.", 34, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 506 },
{ PROC_LINKS(interactive_open_or_new, 0), "interactive_open_or_new", 23, "Interactively open a file out of the file system.", 49, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 577 },
{ PROC_LINKS(interactive_new, 0), "interactive_new", 15, "Interactively creates a new file.", 33, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 616 },
{ PROC_LINKS(interactive_open, 0), "interactive_open", 16, "Interactively opens a file.", 27, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 649 },
{ PROC_LINKS(command_lister, 0), "command_lister", 14, "Opens an interactive list of all registered commands.", 53, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 709 },
{ PROC_LINKS(auto_indent_whole_file, 0), "auto_indent_whole_file", 22, "Audo-indents the entire current buffer.", 39, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 356 },
{ PROC_LINKS(auto_indent_line_at_cursor, 0), "auto_indent_line_at_cursor", 26, "Auto-indents the line on which the cursor sits.", 47, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 365 },
{ PROC_LINKS(auto_indent_range, 0), "auto_indent_range", 17, "Auto-indents the range between the cursor and the mark.", 55, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 375 },

View File

@ -91,6 +91,7 @@ vtable->view_post_fade = view_post_fade;
vtable->view_push_context = view_push_context;
vtable->view_pop_context = view_pop_context;
vtable->view_current_context = view_current_context;
vtable->view_current_context_hook_memory = view_current_context_hook_memory;
vtable->create_user_managed_scope = create_user_managed_scope;
vtable->destroy_user_managed_scope = destroy_user_managed_scope;
vtable->get_global_managed_scope = get_global_managed_scope;
@ -117,6 +118,7 @@ vtable->get_current_input = get_current_input;
vtable->set_current_input = set_current_input;
vtable->leave_current_input_unhandled = leave_current_input_unhandled;
vtable->set_custom_hook = set_custom_hook;
vtable->set_custom_hook_memory_size = set_custom_hook_memory_size;
vtable->get_mouse_state = get_mouse_state;
vtable->get_active_query_bars = get_active_query_bars;
vtable->start_query_bar = start_query_bar;
@ -263,6 +265,7 @@ view_post_fade = vtable->view_post_fade;
view_push_context = vtable->view_push_context;
view_pop_context = vtable->view_pop_context;
view_current_context = vtable->view_current_context;
view_current_context_hook_memory = vtable->view_current_context_hook_memory;
create_user_managed_scope = vtable->create_user_managed_scope;
destroy_user_managed_scope = vtable->destroy_user_managed_scope;
get_global_managed_scope = vtable->get_global_managed_scope;
@ -289,6 +292,7 @@ get_current_input = vtable->get_current_input;
set_current_input = vtable->set_current_input;
leave_current_input_unhandled = vtable->leave_current_input_unhandled;
set_custom_hook = vtable->set_custom_hook;
set_custom_hook_memory_size = vtable->set_custom_hook_memory_size;
get_mouse_state = vtable->get_mouse_state;
get_active_query_bars = vtable->get_active_query_bars;
start_query_bar = vtable->start_query_bar;

View File

@ -82,13 +82,14 @@
#define custom_buffer_compute_cursor_sig() Buffer_Cursor custom_buffer_compute_cursor(Application_Links* app, Buffer_ID buffer, Buffer_Seek seek)
#define custom_view_compute_cursor_sig() Buffer_Cursor custom_view_compute_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek)
#define custom_view_set_cursor_sig() b32 custom_view_set_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek)
#define custom_view_set_buffer_scroll_sig() b32 custom_view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll)
#define custom_view_set_buffer_scroll_sig() b32 custom_view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll, Set_Buffer_Scroll_Rule rule)
#define custom_view_set_mark_sig() b32 custom_view_set_mark(Application_Links* app, View_ID view_id, Buffer_Seek seek)
#define custom_view_set_buffer_sig() b32 custom_view_set_buffer(Application_Links* app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags)
#define custom_view_post_fade_sig() b32 custom_view_post_fade(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, int_color color)
#define custom_view_push_context_sig() b32 custom_view_push_context(Application_Links* app, View_ID view_id, View_Context* ctx)
#define custom_view_pop_context_sig() b32 custom_view_pop_context(Application_Links* app, View_ID view_id)
#define custom_view_current_context_sig() View_Context custom_view_current_context(Application_Links* app, View_ID view_id)
#define custom_view_current_context_hook_memory_sig() Data custom_view_current_context_hook_memory(Application_Links* app, View_ID view_id, Hook_ID hook_id)
#define custom_create_user_managed_scope_sig() Managed_Scope custom_create_user_managed_scope(Application_Links* app)
#define custom_destroy_user_managed_scope_sig() b32 custom_destroy_user_managed_scope(Application_Links* app, Managed_Scope scope)
#define custom_get_global_managed_scope_sig() Managed_Scope custom_get_global_managed_scope(Application_Links* app)
@ -115,6 +116,7 @@
#define custom_set_current_input_sig() void custom_set_current_input(Application_Links* app, User_Input* input)
#define custom_leave_current_input_unhandled_sig() void custom_leave_current_input_unhandled(Application_Links* app)
#define custom_set_custom_hook_sig() void custom_set_custom_hook(Application_Links* app, Hook_ID hook_id, Void_Func* func_ptr)
#define custom_set_custom_hook_memory_size_sig() b32 custom_set_custom_hook_memory_size(Application_Links* app, Hook_ID hook_id, umem size)
#define custom_get_mouse_state_sig() Mouse_State custom_get_mouse_state(Application_Links* app)
#define custom_get_active_query_bars_sig() b32 custom_get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out)
#define custom_start_query_bar_sig() b32 custom_start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags)
@ -250,13 +252,14 @@ typedef Managed_Scope custom_view_get_managed_scope_type(Application_Links* app,
typedef Buffer_Cursor custom_buffer_compute_cursor_type(Application_Links* app, Buffer_ID buffer, Buffer_Seek seek);
typedef Buffer_Cursor custom_view_compute_cursor_type(Application_Links* app, View_ID view_id, Buffer_Seek seek);
typedef b32 custom_view_set_cursor_type(Application_Links* app, View_ID view_id, Buffer_Seek seek);
typedef b32 custom_view_set_buffer_scroll_type(Application_Links* app, View_ID view_id, Buffer_Scroll scroll);
typedef b32 custom_view_set_buffer_scroll_type(Application_Links* app, View_ID view_id, Buffer_Scroll scroll, Set_Buffer_Scroll_Rule rule);
typedef b32 custom_view_set_mark_type(Application_Links* app, View_ID view_id, Buffer_Seek seek);
typedef b32 custom_view_set_buffer_type(Application_Links* app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags);
typedef b32 custom_view_post_fade_type(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, int_color color);
typedef b32 custom_view_push_context_type(Application_Links* app, View_ID view_id, View_Context* ctx);
typedef b32 custom_view_pop_context_type(Application_Links* app, View_ID view_id);
typedef View_Context custom_view_current_context_type(Application_Links* app, View_ID view_id);
typedef Data custom_view_current_context_hook_memory_type(Application_Links* app, View_ID view_id, Hook_ID hook_id);
typedef Managed_Scope custom_create_user_managed_scope_type(Application_Links* app);
typedef b32 custom_destroy_user_managed_scope_type(Application_Links* app, Managed_Scope scope);
typedef Managed_Scope custom_get_global_managed_scope_type(Application_Links* app);
@ -283,6 +286,7 @@ typedef User_Input custom_get_current_input_type(Application_Links* app);
typedef void custom_set_current_input_type(Application_Links* app, User_Input* input);
typedef void custom_leave_current_input_unhandled_type(Application_Links* app);
typedef void custom_set_custom_hook_type(Application_Links* app, Hook_ID hook_id, Void_Func* func_ptr);
typedef b32 custom_set_custom_hook_memory_size_type(Application_Links* app, Hook_ID hook_id, umem size);
typedef Mouse_State custom_get_mouse_state_type(Application_Links* app);
typedef b32 custom_get_active_query_bars_type(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out);
typedef b32 custom_start_query_bar_type(Application_Links* app, Query_Bar* bar, u32 flags);
@ -426,6 +430,7 @@ custom_view_post_fade_type *view_post_fade;
custom_view_push_context_type *view_push_context;
custom_view_pop_context_type *view_pop_context;
custom_view_current_context_type *view_current_context;
custom_view_current_context_hook_memory_type *view_current_context_hook_memory;
custom_create_user_managed_scope_type *create_user_managed_scope;
custom_destroy_user_managed_scope_type *destroy_user_managed_scope;
custom_get_global_managed_scope_type *get_global_managed_scope;
@ -452,6 +457,7 @@ custom_get_current_input_type *get_current_input;
custom_set_current_input_type *set_current_input;
custom_leave_current_input_unhandled_type *leave_current_input_unhandled;
custom_set_custom_hook_type *set_custom_hook;
custom_set_custom_hook_memory_size_type *set_custom_hook_memory_size;
custom_get_mouse_state_type *get_mouse_state;
custom_get_active_query_bars_type *get_active_query_bars;
custom_start_query_bar_type *start_query_bar;
@ -589,13 +595,14 @@ internal Managed_Scope view_get_managed_scope(Application_Links* app, View_ID vi
internal Buffer_Cursor buffer_compute_cursor(Application_Links* app, Buffer_ID buffer, Buffer_Seek seek);
internal Buffer_Cursor view_compute_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek);
internal b32 view_set_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek);
internal b32 view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll);
internal b32 view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll, Set_Buffer_Scroll_Rule rule);
internal b32 view_set_mark(Application_Links* app, View_ID view_id, Buffer_Seek seek);
internal b32 view_set_buffer(Application_Links* app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags);
internal b32 view_post_fade(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, int_color color);
internal b32 view_push_context(Application_Links* app, View_ID view_id, View_Context* ctx);
internal b32 view_pop_context(Application_Links* app, View_ID view_id);
internal View_Context view_current_context(Application_Links* app, View_ID view_id);
internal Data view_current_context_hook_memory(Application_Links* app, View_ID view_id, Hook_ID hook_id);
internal Managed_Scope create_user_managed_scope(Application_Links* app);
internal b32 destroy_user_managed_scope(Application_Links* app, Managed_Scope scope);
internal Managed_Scope get_global_managed_scope(Application_Links* app);
@ -622,6 +629,7 @@ internal User_Input get_current_input(Application_Links* app);
internal void set_current_input(Application_Links* app, User_Input* input);
internal void leave_current_input_unhandled(Application_Links* app);
internal void set_custom_hook(Application_Links* app, Hook_ID hook_id, Void_Func* func_ptr);
internal b32 set_custom_hook_memory_size(Application_Links* app, Hook_ID hook_id, umem size);
internal Mouse_State get_mouse_state(Application_Links* app);
internal b32 get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out);
internal b32 start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags);
@ -766,6 +774,7 @@ global custom_view_post_fade_type *view_post_fade = 0;
global custom_view_push_context_type *view_push_context = 0;
global custom_view_pop_context_type *view_pop_context = 0;
global custom_view_current_context_type *view_current_context = 0;
global custom_view_current_context_hook_memory_type *view_current_context_hook_memory = 0;
global custom_create_user_managed_scope_type *create_user_managed_scope = 0;
global custom_destroy_user_managed_scope_type *destroy_user_managed_scope = 0;
global custom_get_global_managed_scope_type *get_global_managed_scope = 0;
@ -792,6 +801,7 @@ global custom_get_current_input_type *get_current_input = 0;
global custom_set_current_input_type *set_current_input = 0;
global custom_leave_current_input_unhandled_type *leave_current_input_unhandled = 0;
global custom_set_custom_hook_type *set_custom_hook = 0;
global custom_set_custom_hook_memory_size_type *set_custom_hook_memory_size = 0;
global custom_get_mouse_state_type *get_mouse_state = 0;
global custom_get_active_query_bars_type *get_active_query_bars = 0;
global custom_start_query_bar_type *start_query_bar = 0;

View File

@ -82,13 +82,14 @@ api(custom) function Managed_Scope view_get_managed_scope(Application_Links* app
api(custom) function Buffer_Cursor buffer_compute_cursor(Application_Links* app, Buffer_ID buffer, Buffer_Seek seek);
api(custom) function Buffer_Cursor view_compute_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek);
api(custom) function b32 view_set_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek);
api(custom) function b32 view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll);
api(custom) function b32 view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll, Set_Buffer_Scroll_Rule rule);
api(custom) function b32 view_set_mark(Application_Links* app, View_ID view_id, Buffer_Seek seek);
api(custom) function b32 view_set_buffer(Application_Links* app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags);
api(custom) function b32 view_post_fade(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, int_color color);
api(custom) function b32 view_push_context(Application_Links* app, View_ID view_id, View_Context* ctx);
api(custom) function b32 view_pop_context(Application_Links* app, View_ID view_id);
api(custom) function View_Context view_current_context(Application_Links* app, View_ID view_id);
api(custom) function Data view_current_context_hook_memory(Application_Links* app, View_ID view_id, Hook_ID hook_id);
api(custom) function Managed_Scope create_user_managed_scope(Application_Links* app);
api(custom) function b32 destroy_user_managed_scope(Application_Links* app, Managed_Scope scope);
api(custom) function Managed_Scope get_global_managed_scope(Application_Links* app);
@ -115,6 +116,7 @@ api(custom) function User_Input get_current_input(Application_Links* app);
api(custom) function void set_current_input(Application_Links* app, User_Input* input);
api(custom) function void leave_current_input_unhandled(Application_Links* app);
api(custom) function void set_custom_hook(Application_Links* app, Hook_ID hook_id, Void_Func* func_ptr);
api(custom) function b32 set_custom_hook_memory_size(Application_Links* app, Hook_ID hook_id, umem size);
api(custom) function Mouse_State get_mouse_state(Application_Links* app);
api(custom) function b32 get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out);
api(custom) function b32 start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags);