keep recent scroll position for files-view pairs

This commit is contained in:
Allen Webster 2016-05-19 14:01:36 -04:00
parent d6cfdf7413
commit 8bf8e36723
5 changed files with 154 additions and 118 deletions

42
4ed.cpp
View File

@ -1,11 +1,11 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 12.12.2014
*
* Application layer for project codename "4ed"
*
*/
* Mr. 4th Dimention - Allen Webster
*
* 12.12.2014
*
* Application layer for project codename "4ed"
*
*/
// TOP
@ -464,9 +464,9 @@ COMMAND_DECL(center_view){
h = view_file_height(view);
y -= h * .5f;
if (y < view->file_scroll.min_y) y = view->file_scroll.min_y;
if (y < view->recent->scroll.min_y) y = view->recent->scroll.min_y;
view->file_scroll.target_y = y;
view->recent->scroll.target_y = y;
}
COMMAND_DECL(word_complete){
@ -1105,7 +1105,7 @@ COMMAND_DECL(toggle_line_wrap){
if (view->file_data.unwrapped_lines){
view->file_data.unwrapped_lines = 0;
file->settings.unwrapped_lines = 0;
view->file_scroll.target_x = 0;
view->recent->scroll.target_x = 0;
view->file_data.cursor =view_compute_cursor_from_pos(
view, view->file_data.cursor.pos);
view->file_data.preferred_x = view->file_data.cursor.wrapped_x;
@ -1505,26 +1505,26 @@ COMMAND_DECL(page_down){
REQ_READABLE_VIEW(view);
f32 height = view_file_height(view);
f32 max_target_y = view->file_scroll.max_y;
f32 max_target_y = view->recent->scroll.max_y;
view->file_scroll.target_y += height;
if (view->file_scroll.target_y > max_target_y) view->file_scroll.target_y = max_target_y;
view->recent->scroll.target_y += height;
if (view->recent->scroll.target_y > max_target_y) view->recent->scroll.target_y = max_target_y;
view->file_data.cursor = view_compute_cursor_from_xy(
view, 0, view->file_scroll.target_y + (height - view->font_height)*.5f);
view, 0, view->recent->scroll.target_y + (height - view->font_height)*.5f);
}
COMMAND_DECL(page_up){
REQ_READABLE_VIEW(view);
f32 height = view_file_height(view);
f32 min_target_y = view->file_scroll.min_y;
f32 min_target_y = view->recent->scroll.min_y;
view->file_scroll.target_y -= height;
if (view->file_scroll.target_y < min_target_y) view->file_scroll.target_y = min_target_y;
view->recent->scroll.target_y -= height;
if (view->recent->scroll.target_y < min_target_y) view->recent->scroll.target_y = min_target_y;
view->file_data.cursor = view_compute_cursor_from_xy(
view, 0, view->file_scroll.target_y + (height - view->font_height)*.5f);
view, 0, view->recent->scroll.target_y + (height - view->font_height)*.5f);
}
COMMAND_DECL(open_color_tweaker){
@ -4029,12 +4029,12 @@ App_Step_Sig(app_step){
// TODO(allen): This is perhaps not the best system...
// The problem is that the exact region and scroll position is pretty important
// for some commands, so this is here to eliminate the one frame of lag.
// Going to leave this here for now because the oder of events is going to
// change a lot soon.
// Going to leave this here for now because the order of events is going to
// change a lot soon anyway.
for (dll_items(panel, used_panels)){
view = panel->view;
if (view->current_scroll){
gui_get_scroll_vars(&view->gui_target, view->showing_ui, view->current_scroll);
gui_get_scroll_vars(&view->gui_target, view->showing_ui, view->current_scroll, &view->scroll_region);
}
}
}

View File

@ -152,14 +152,14 @@ struct File_Node{
File_Node *next, *prev;
};
union File_ID{
union Buffer_Slot_ID{
i32 id;
i16 part[2];
};
inline File_ID
inline Buffer_Slot_ID
to_file_id(i32 id){
File_ID result;
Buffer_Slot_ID result;
result.id = id;
return(result);
}
@ -173,12 +173,13 @@ struct Editing_File{
Editing_File_Preload preload;
};
Editing_File_Name name;
File_ID id;
Buffer_Slot_ID id;
u64 unique_buffer_id;
};
struct Non_File_Table_Entry{
String name;
File_ID id;
Buffer_Slot_ID id;
};
struct File_Array{
@ -199,12 +200,14 @@ struct Working_Set{
String clipboards[64];
i32 clipboard_size, clipboard_max_size;
i32 clipboard_current, clipboard_rolling;
u64 unique_file_counter;
};
struct File_Entry{
String short_name;
String long_name;
File_ID id;
Buffer_Slot_ID id;
};
struct File_Entry_Comparison{
@ -239,7 +242,7 @@ tbl_file_compare(void *a, void *b, void *arg){
internal void
working_set_extend_memory(Working_Set *working_set, Editing_File *new_space, i16 number_of_files){
File_ID id;
Buffer_Slot_ID id;
i16 i, high_part;
Editing_File *file_ptr;
File_Node *free_sentinel;
@ -273,7 +276,7 @@ internal Editing_File*
working_set_alloc(Working_Set *working_set){
Editing_File *result = 0;
File_Node *node;
File_ID id;
Buffer_Slot_ID id;
if (working_set->file_count < working_set->file_max){
node = working_set->free_sentinel.next;
@ -281,11 +284,10 @@ working_set_alloc(Working_Set *working_set){
result = (Editing_File*)node;
dll_remove(node);
// NOTE(allen): What I really want to do here is clear everything
// except id, but writing that out will be a pain to maintain.
id = result->id;
*result = editing_file_zero();
result->id = id;
result->unique_buffer_id = ++working_set->unique_file_counter;
dll_insert(&working_set->used_sentinel, node);
++working_set->file_count;
}
@ -322,7 +324,7 @@ working_set_free_file(Working_Set *working_set, Editing_File *file){
}
inline Editing_File*
working_set_index(Working_Set *working_set, File_ID id){
working_set_index(Working_Set *working_set, Buffer_Slot_ID id){
Editing_File *result = 0;
File_Array *array;
@ -344,7 +346,7 @@ working_set_index(Working_Set *working_set, i32 id){
}
inline Editing_File*
working_set_get_active_file(Working_Set *working_set, File_ID id){
working_set_get_active_file(Working_Set *working_set, Buffer_Slot_ID id){
Editing_File *result = 0;
result = working_set_index(working_set, id);
if (result && result->state.is_dummy){

View File

@ -90,6 +90,11 @@ file_viewing_data_zero(){
return(data);
}
struct Recent_File_Data{
u64 unique_buffer_id;
GUI_Scroll_Vars scroll;
};
struct View{
View *next, *prev;
b32 in_use;
@ -104,9 +109,13 @@ struct View{
File_Viewing_Data file_data;
GUI_Scroll_Vars file_scroll;
//GUI_Scroll_Vars file_scroll;
i32_Rect scroll_region;
Recent_File_Data recent[16];
GUI_Scroll_Vars *current_scroll;
View_UI showing_ui;
GUI_Target gui_target;
void *gui_mem;
@ -164,14 +173,14 @@ view_lock_level(View *view){
inline f32
view_file_width(View *view){
i32_Rect file_rect = view->file_scroll.region;
i32_Rect file_rect = view->scroll_region;
f32 result = (f32)(file_rect.x1 - file_rect.x0);
return (result);
}
inline f32
view_file_height(View *view){
i32_Rect file_rect = view->file_scroll.region;
i32_Rect file_rect = view->scroll_region;
f32 result = (f32)(file_rect.y1 - file_rect.y0);
return (result);
}
@ -1289,30 +1298,49 @@ view_set_file(View *view, Editing_File *file, Models *models){
// NOTE(allen): Stuff that doesn't assume file exists.
// TODO(allen): Use a proper file changer here.
view->file_data = file_viewing_data_zero();;
view->file_data = file_viewing_data_zero();
view->file_data.file = file;
// NOTE(allen): Stuff that does assume file exists.
if (file){
u64 unique_buffer_id = file->unique_buffer_id;
Recent_File_Data *recent = view->recent;
Recent_File_Data temp_recent = {0};
i32 i = 0;
i32 max = ArrayCount(view->recent)-1;
b32 found_recent_entry = 0;
for (; i < max; ++i, ++recent){
if (recent->unique_buffer_id == unique_buffer_id){
temp_recent = *recent;
memmove(view->recent+1, view->recent, sizeof(*recent)*i);
view->recent[0] = temp_recent;
found_recent_entry = 1;
break;
}
}
if (!found_recent_entry){
i = 15;
recent = view->recent + i;
temp_recent = *recent;
memmove(view->recent+1, view->recent, sizeof(*recent)*i);
view->recent[0] = temp_recent;
recent = view->recent;
recent->unique_buffer_id = unique_buffer_id;
}
view->file_data.unwrapped_lines = file->settings.unwrapped_lines;
if (file_is_ready(file)){
view_measure_wraps(&models->mem.general, view);
view->file_data.cursor = view_compute_cursor_from_pos(view, file->state.cursor_pos);
if (!found_recent_entry){
view->reinit_scrolling = 1;
}
}
#if 0
if (file){
if (open_hook && file->settings.is_initialized == 0){
models->buffer_param_indices[models->buffer_param_count++] = file->id.id;
open_hook(app);
models->buffer_param_count = 0;
file->settings.is_initialized = 1;
}
}
#endif
}
struct Relative_Scrolling{
@ -1326,9 +1354,9 @@ view_get_relative_scrolling(View *view){
Relative_Scrolling result;
f32 cursor_y;
cursor_y = view_get_cursor_y(view);
result.scroll_y = cursor_y - view->file_scroll.scroll_y;
result.target_y = cursor_y - view->file_scroll.target_y;
result.scroll_min_limit = view->file_scroll.min_y;
result.scroll_y = cursor_y - view->recent->scroll.scroll_y;
result.target_y = cursor_y - view->recent->scroll.target_y;
result.scroll_min_limit = view->recent->scroll.min_y;
return(result);
}
@ -1336,10 +1364,10 @@ internal void
view_set_relative_scrolling(View *view, Relative_Scrolling scrolling){
f32 cursor_y;
cursor_y = view_get_cursor_y(view);
view->file_scroll.scroll_y = cursor_y - scrolling.scroll_y;
view->file_scroll.target_y = cursor_y - scrolling.target_y;
if (view->file_scroll.target_y < scrolling.scroll_min_limit){
view->file_scroll.target_y = scrolling.scroll_min_limit;
view->recent->scroll.scroll_y = cursor_y - scrolling.scroll_y;
view->recent->scroll.target_y = cursor_y - scrolling.target_y;
if (view->recent->scroll.target_y < scrolling.scroll_min_limit){
view->recent->scroll.target_y = scrolling.scroll_min_limit;
}
}
@ -1634,17 +1662,17 @@ file_edit_cursor_fix(System_Functions *system,
if (view->file_data.scroll_i != new_scroll_i){
view->file_data.scroll_i = new_scroll_i;
temp_cursor = view_compute_cursor_from_pos(view, view->file_data.scroll_i);
y_offset = MOD(view->file_scroll.scroll_y, view->font_height);
y_offset = MOD(view->recent->scroll.scroll_y, view->font_height);
if (view->file_data.unwrapped_lines){
y_position = temp_cursor.unwrapped_y + y_offset;
view->file_scroll.target_y += (y_position - view->file_scroll.scroll_y);
view->file_scroll.scroll_y = y_position;
view->recent->scroll.target_y += (y_position - view->recent->scroll.scroll_y);
view->recent->scroll.scroll_y = y_position;
}
else{
y_position = temp_cursor.wrapped_y + y_offset;
view->file_scroll.target_y += (y_position - view->file_scroll.scroll_y);
view->file_scroll.scroll_y = y_position;
view->recent->scroll.target_y += (y_position - view->recent->scroll.scroll_y);
view->recent->scroll.scroll_y = y_position;
}
}
}
@ -2765,7 +2793,6 @@ view_show_theme(View *view, Command_Map *gui_map){
view->current_scroll = &view->gui_scroll;
}
inline void
view_show_file(View *view, Command_Map *file_map){
if (file_map){
@ -2775,7 +2802,7 @@ view_show_file(View *view, Command_Map *file_map){
view->map = view->map_for_file;
}
view->showing_ui = VUI_None;
view->current_scroll = &view->file_scroll;
view->current_scroll = &view->recent->scroll;
}
inline void
@ -2982,22 +3009,22 @@ view_reinit_scrolling(View *view){
}
target_y = (f32)FLOOR32(cursor_y - h*.5f);
if (target_y < view->file_scroll.min_y){
target_y = view->file_scroll.min_y;
if (target_y < view->recent->scroll.min_y){
target_y = view->recent->scroll.min_y;
}
}
view->file_scroll.target_y = target_y;
view->file_scroll.scroll_y = target_y;
view->file_scroll.prev_target_y = -1000.f;
view->file_scroll.min_y = view->gui_target.scroll_updated.min_y;
view->file_scroll.max_y = view->gui_target.scroll_updated.max_y;
view->recent->scroll.target_y = target_y;
view->recent->scroll.scroll_y = target_y;
view->recent->scroll.prev_target_y = -1000.f;
view->recent->scroll.min_y = view->gui_target.scroll_updated.min_y;
view->recent->scroll.max_y = view->gui_target.scroll_updated.max_y;
view->file_scroll.target_x = target_x;
view->file_scroll.scroll_x = target_x;
view->file_scroll.prev_target_x = -1000.f;
view->recent->scroll.target_x = target_x;
view->recent->scroll.scroll_x = target_x;
view->recent->scroll.prev_target_x = -1000.f;
gui_post_scroll_vars(&view->gui_target, &view->file_scroll);
gui_post_scroll_vars(&view->gui_target, &view->recent->scroll);
}
#define CursorMaxY_(m,h) ((m) - (h)*3)
@ -3036,7 +3063,7 @@ file_step(View *view, i32_Rect region, Input_Summary *user_input, b32 is_active)
}
if (target_y > scroll_vars.max_y) target_y = scroll_vars.max_y;
if (target_y < scroll_vars.min_y) target_y = view->file_scroll.min_y;
if (target_y < scroll_vars.min_y) target_y = view->recent->scroll.min_y;
if (cursor_x < target_x){
target_x = (f32)Max(0, cursor_x - max_x/2);
@ -3060,7 +3087,7 @@ file_step(View *view, i32_Rect region, Input_Summary *user_input, b32 is_active)
f32 rx = (f32)(user_input->mouse.x - region.x0);
f32 ry = (f32)(user_input->mouse.y - region.y0);
if (ry >= -view->file_scroll.min_y){
if (ry >= -view->recent->scroll.min_y){
view_set_widget(view, FWIDG_NONE);
if (rx >= 0 && rx < max_x && ry >= 0 && ry < max_visible_y){
view_cursor_move(view, rx + scroll_vars.scroll_x, ry + scroll_vars.scroll_y, 1);
@ -3367,7 +3394,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
Models *models = view->models;
Key_Summary keys = input.keys;
f32 min_target_y = view->file_scroll.min_y;
f32 min_target_y = view->recent->scroll.min_y;
view->current_scroll = 0;
@ -3390,9 +3417,9 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
f32 delta = 9.f * view->font_height;
f32 target_y = 0;
view->current_scroll = &view->file_scroll;
if (gui_get_scroll_vars(target, view->showing_ui, &view->file_scroll)){
target_y = view->file_scroll.target_y;
view->current_scroll = &view->recent->scroll;
if (gui_get_scroll_vars(target, view->showing_ui, &view->recent->scroll, &view->scroll_region)){
target_y = view->recent->scroll.target_y;
if (cursor_y > target_y + cursor_max_y){
cursor_y = target_y + cursor_max_y;
}
@ -3411,7 +3438,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
}
}
gui_begin_scrollable(target, view->showing_ui, view->file_scroll, delta);
gui_begin_scrollable(target, view->showing_ui, view->recent->scroll, delta);
gui_do_file(target);
gui_end_scrollable(target);
}
@ -3491,7 +3518,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
gui_do_text_field(target, message, empty_string);
view->current_scroll = &view->gui_scroll;
gui_get_scroll_vars(target, view->showing_ui, &view->gui_scroll);
gui_get_scroll_vars(target, view->showing_ui, &view->gui_scroll, &view->scroll_region);
gui_begin_scrollable(target, view->showing_ui, view->gui_scroll, 9.f * view->font_height);
{
@ -3564,7 +3591,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
}
view->current_scroll = &view->gui_scroll;
gui_get_scroll_vars(target, view->showing_ui, &view->gui_scroll);
gui_get_scroll_vars(target, view->showing_ui, &view->gui_scroll, &view->scroll_region);
gui_begin_scrollable(target, view->showing_ui, view->gui_scroll, 9.f * view->font_height);
i32 next_color_editing = view->current_color_editing;
@ -3692,7 +3719,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
gui_do_text_field(target, message, hdir->string);
view->current_scroll = &view->gui_scroll;
if (gui_get_scroll_vars(target, view->showing_ui, &view->gui_scroll)){
if (gui_get_scroll_vars(target, view->showing_ui, &view->gui_scroll, &view->scroll_region)){
snap_into_view = 1;
}
gui_begin_scrollable(target, view->showing_ui,
@ -3702,7 +3729,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
if (gui_begin_list(target, id, view->list_i, 0,
snap_into_view, &update)){
gui_standard_list(target, id, view->gui_scroll,
gui_standard_list(target, id, view->scroll_region,
&keys, &view->list_i, &update);
}
@ -3776,7 +3803,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
gui_do_text_field(target, message, view->dest);
view->current_scroll = &view->gui_scroll;
if (gui_get_scroll_vars(target, view->showing_ui, &view->gui_scroll)){
if (gui_get_scroll_vars(target, view->showing_ui, &view->gui_scroll, &view->scroll_region)){
snap_into_view = 1;
}
gui_begin_scrollable(target, view->showing_ui, view->gui_scroll, 9.f * view->font_height);
@ -3784,7 +3811,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
id.id[0] = (u64)(working_set) + 1;
if (gui_begin_list(target, id, view->list_i,
0, snap_into_view, &update)){
gui_standard_list(target, id, view->gui_scroll,
gui_standard_list(target, id, view->scroll_region,
&keys, &view->list_i, &update);
}
@ -3922,7 +3949,7 @@ internal f32
view_get_scroll_y(View *view){
f32 v;
if (view->showing_ui == VUI_None){
v = view->file_scroll.scroll_y;
v = view->recent->scroll.scroll_y;
}
else{
v = view->gui_scroll.scroll_y;
@ -4083,6 +4110,11 @@ do_input_file_view(System_Functions *system, Exchange *exchange,
}
}break;
case guicom_scrollable:
{
view->scroll_region = target->region_updated;
}break;
case guicom_scrollable_slider:
{
GUI_id id = gui_id_scrollbar_slider();
@ -4247,8 +4279,8 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
Buffer_Render_Options opts = {};
f32 *wraps = view->file_data.line_wrap_y;
f32 scroll_x = view->file_scroll.scroll_x;
f32 scroll_y = view->file_scroll.scroll_y;
f32 scroll_x = view->recent->scroll.scroll_x;
f32 scroll_y = view->recent->scroll.scroll_y;
{
render_cursor = buffer_get_start_cursor(&file->state.buffer, wraps, scroll_y,

View File

@ -130,8 +130,6 @@ struct GUI_Scroll_Vars{
f32 scroll_x;
f32 target_x;
f32 prev_target_x;
i32_Rect region;
};
struct GUI_Target{
@ -144,7 +142,10 @@ struct GUI_Target{
// TODO(allen): Can we remove original yet?
GUI_Scroll_Vars scroll_original;
i32_Rect region_original;
GUI_Scroll_Vars scroll_updated;
i32_Rect region_updated;
// TODO(allen): Would rather have a way of tracking this
// for more than one list. Perhaps just throw in a hash table?
@ -669,10 +670,11 @@ gui_scroll_eq(GUI_Scroll_Vars *a, GUI_Scroll_Vars *b){
// TODO(allen): Rethink this a little, seems like there are two separate things we want to do here:
// Getting the updated scroll vars, and telling the user when scrolling actions occur.
internal b32
gui_get_scroll_vars(GUI_Target *target, u32 scroll_id, GUI_Scroll_Vars *vars_out){
gui_get_scroll_vars(GUI_Target *target, u32 scroll_id, GUI_Scroll_Vars *vars_out, i32_Rect *region_out){
b32 result = 0;
if (target->scroll_id == scroll_id){
*vars_out = target->scroll_updated;
*region_out = target->region_updated;
if (vars_out->target_y < vars_out->min_y) vars_out->target_y = vars_out->min_y;
if (vars_out->target_y > vars_out->max_y) vars_out->target_y = vars_out->max_y;
@ -1129,7 +1131,7 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){
scrollable_rect.x1 = rect.x0;
scrollable_rect.y0 = rect.y0;
scrollable_rect.y1 = rect.y1;
target->scroll_updated.region = scrollable_rect;
target->region_updated = scrollable_rect;
}
break;
@ -1189,7 +1191,7 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){
if (do_layout){
if (session->list.in_list && is_list_item){
i32 list_i = session->list.index - 1;
i32_Rect region = target->scroll_updated.region;
i32_Rect region = target->region_updated;
if (rect.y0 - target_v >= region.y0 &&
rect.y1 - target_v <= region.y1){
@ -1244,11 +1246,11 @@ struct GUI_View_Jump{
};
internal GUI_View_Jump
gui_compute_view_jump(GUI_Scroll_Vars scroll, i32_Rect position){
gui_compute_view_jump(i32_Rect scroll_region, i32_Rect position){
GUI_View_Jump jump = {0};
i32 region_h = scroll.region.y1 - scroll.region.y0;
jump.view_min = (f32)position.y1 - region_h - scroll.region.y0;
jump.view_max = (f32)position.y0 - scroll.region.y0;
i32 region_h = scroll_region.y1 - scroll_region.y0;
jump.view_min = (f32)position.y1 - region_h - scroll_region.y0;
jump.view_max = (f32)position.y0 - scroll_region.y0;
return(jump);
}
@ -1266,7 +1268,7 @@ gui_do_jump(GUI_Target *target, GUI_View_Jump jump){
}
internal void
gui_standard_list(GUI_Target *target, GUI_id id, GUI_Scroll_Vars scroll,
gui_standard_list(GUI_Target *target, GUI_id id, i32_Rect scroll_region,
Key_Summary *keys, i32 *list_i, GUI_Item_Update *update){
if (update->has_adjustment){
@ -1275,7 +1277,7 @@ gui_standard_list(GUI_Target *target, GUI_id id, GUI_Scroll_Vars scroll,
if (update->has_index_position){
GUI_View_Jump jump =
gui_compute_view_jump(scroll, update->index_position);
gui_compute_view_jump(scroll_region, update->index_position);
jump.view_min += 45.f;
jump.view_max -= 45.f;
gui_do_jump(target, jump);