diff --git a/4ed.cpp b/4ed.cpp index f8aa2e95..5e9a1e76 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -422,9 +422,9 @@ COMMAND_DECL(center_view){ h = view_file_height(view); y -= h * .5f; - if (y < view->scroll_min_limit) y = view->scroll_min_limit; + if (y < view->file_scroll.min_y) y = view->file_scroll.min_y; - view->target_y = y; + view->file_scroll.target_y = y; } COMMAND_DECL(word_complete){ @@ -1076,9 +1076,9 @@ COMMAND_DECL(toggle_line_wrap){ if (view->unwrapped_lines){ view->unwrapped_lines = 0; file->settings.unwrapped_lines = 0; - view->target_x = 0; - view->cursor = - view_compute_cursor_from_pos(view, view->cursor.pos); + view->file_scroll.target_x = 0; + view->cursor =view_compute_cursor_from_pos( + view, view->cursor.pos); view->preferred_x = view->cursor.wrapped_x; } else{ @@ -1484,13 +1484,13 @@ COMMAND_DECL(page_down){ REQ_READABLE_VIEW(view); f32 height = view_file_height(view); - f32 max_target_y = view_compute_max_target_y(view); + f32 max_target_y = view->file_scroll.max_y; - view->target_y += height; - if (view->target_y > max_target_y) view->target_y = max_target_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->cursor = view_compute_cursor_from_xy( - view, 0, view->target_y + (height - view->font_height)*.5f); + view, 0, view->file_scroll.target_y + (height - view->font_height)*.5f); } COMMAND_DECL(page_up){ @@ -1498,12 +1498,13 @@ COMMAND_DECL(page_up){ REQ_READABLE_VIEW(view); f32 height = view_file_height(view); + f32 min_target_y = view->file_scroll.min_y; - view->target_y -= height; - if (view->target_y < 0) view->target_y = 0; + view->file_scroll.target_y -= height; + if (view->file_scroll.target_y < min_target_y) view->file_scroll.target_y = min_target_y; view->cursor = view_compute_cursor_from_xy( - view, 0, view->target_y + (height - view->font_height)*.5f); + view, 0, view->file_scroll.target_y + (height - view->font_height)*.5f); } COMMAND_DECL(open_color_tweaker){ @@ -1593,7 +1594,7 @@ COMMAND_DECL(set_settings){ if (!file->state.is_loading){ Relative_Scrolling scrolling = view_get_relative_scrolling(view); - view->target_x = 0; + view->file_scroll.target_x = 0; view->cursor = view_compute_cursor_from_pos(view, view->cursor.pos); view_set_relative_scrolling(view, scrolling); diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index efe727b0..5357608f 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -75,11 +75,11 @@ struct View{ Command_Map *map; Editing_File *file; - i32_Rect file_rect; View_UI showing_ui; GUI_Target gui_target; void *gui_mem; + GUI_Scroll_Vars gui_scroll; Interactive_Interaction interaction; Interactive_Action action; @@ -110,11 +110,10 @@ struct View{ Full_Cursor cursor; i32 mark; - f32 scroll_y, target_y, prev_target_y; - f32 scroll_x, target_x, prev_target_x; f32 preferred_x; i32 scroll_i; - f32 scroll_min_limit; + + GUI_Scroll_Vars file_scroll; Full_Cursor temp_highlight; i32 temp_highlight_end_pos; @@ -156,14 +155,14 @@ view_lock_level(View *view){ inline f32 view_file_width(View *view){ - i32_Rect file_rect = view->file_rect; + i32_Rect file_rect = view->file_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_rect; + i32_Rect file_rect = view->file_scroll.region; f32 result = (f32)(file_rect.y1 - file_rect.y0); return (result); } @@ -1332,19 +1331,19 @@ 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->scroll_y; - result.target_y = cursor_y - view->target_y; - result.scroll_min_limit = view->scroll_min_limit; - return result; + 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; + return(result); } internal void view_set_relative_scrolling(View *view, Relative_Scrolling scrolling){ f32 cursor_y; cursor_y = view_get_cursor_y(view); - view->scroll_y = cursor_y - scrolling.scroll_y; - view->target_y = cursor_y - scrolling.target_y; - if (view->target_y < scrolling.scroll_min_limit) view->target_y = scrolling.scroll_min_limit; + 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; } inline void @@ -1638,17 +1637,17 @@ file_edit_cursor_fix(System_Functions *system, if (view->scroll_i != new_scroll_i){ view->scroll_i = new_scroll_i; temp_cursor = view_compute_cursor_from_pos(view, view->scroll_i); - y_offset = MOD(view->scroll_y, view->font_height); + y_offset = MOD(view->file_scroll.scroll_y, view->font_height); if (view->unwrapped_lines){ y_position = temp_cursor.unwrapped_y + y_offset; - view->target_y += (y_position - view->scroll_y); - view->scroll_y = y_position; + view->file_scroll.target_y += (y_position - view->file_scroll.scroll_y); + view->file_scroll.scroll_y = y_position; } else{ y_position = temp_cursor.wrapped_y + y_offset; - view->target_y += (y_position - view->scroll_y); - view->scroll_y = y_position; + view->file_scroll.target_y += (y_position - view->file_scroll.scroll_y); + view->file_scroll.scroll_y = y_position; } } } @@ -2654,6 +2653,7 @@ view_show_interactive(System_Functions *system, View *view, Models *models = view->models; view->showing_ui = VUI_Interactive; + view->gui_scroll = {0}; view->action = action; view->interaction = interaction; @@ -2683,23 +2683,6 @@ interactive_view_complete(View *view, String dest, i32 user_action){ Editing_File *old_file = view->file; switch (view->action){ -#if 0 - case IAct_Open: - delayed_open(&models->delay1, models->hot_directory.string, panel); - delayed_touch_file(&models->delay1, old_file); - break; - - case IAct_Save_As: - delayed_save_as(&models->delay1, models->hot_directory.string, panel); - break; - - case IAct_New: - if (models->hot_directory.string.size > 0 && - !char_is_slash(models->hot_directory.string.str[models->hot_directory.string.size-1])){ - delayed_new(&models->delay1, models->hot_directory.string, panel); - }break; -#endif - case IAct_Open: delayed_open(&models->delay1, dest, panel); delayed_touch_file(&models->delay1, old_file); @@ -3435,6 +3418,7 @@ intbar_draw_string(Render_Target *target, File_Bar *bar, String str, u32 char_co bar->pos_x += font_string_width(target, font_id, str); } +// TODO(allen): wtf is this? internal void view_reinit_scrolling(View *view){ Editing_File *file = view->file; @@ -3459,83 +3443,83 @@ view_reinit_scrolling(View *view){ } target_y = (f32)FLOOR32(cursor_y - h*.5f); - if (target_y < view->scroll_min_limit) target_y = view->scroll_min_limit; + if (target_y < view->file_scroll.min_y) target_y = view->file_scroll.min_y; } - view->target_x = target_x; - view->target_y = target_y; - view->scroll_x = target_x; - view->scroll_y = target_y; - view->prev_target_x = -1000.f; - view->prev_target_y = -1000.f; + 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.target_x = target_x; + view->file_scroll.scroll_x = target_x; + view->file_scroll.prev_target_x = -1000.f; } +#define CursorMaxY_(m,h) ((m) - (h)*3) +#define CursorMinY_(m,h) (-(m) + (h)*2) + +#define CursorMaxY(m,h) (CursorMaxY_(m,h) > 0)?(CursorMaxY_(m,h)):(0) +#define CursorMinY(m,h) (CursorMinY_(m,h) > 0)?(CursorMinY_(m,h)):(0) + internal i32 file_step(View *view, i32_Rect region, Input_Summary *user_input, b32 is_active){ i32 result = 0; Editing_File *file = view->file; if (file && !file->state.is_loading){ + // TODO(allen): rewrite with real scrolling system now. f32 line_height = (f32)view->font_height; - f32 cursor_y = view_get_cursor_y(view); - f32 target_y = view->target_y; - i32 lowest_line = view_compute_lowest_line(view); - f32 delta_y = 3.f*line_height; - f32 max_y = view_file_height(view); + f32 cursor_y = view_get_cursor_y(view); + + f32 max_visible_y = view_file_height(view); f32 max_x = view_file_width(view); - f32 max_target_y = view_compute_max_target_y(lowest_line, (i32)line_height, max_y); - f32 cursor_max_y = max_y - view->font_height * 3; - + f32 cursor_x = view_get_cursor_x(view); + + + GUI_Scroll_Vars scroll_vars = view->gui_target.scroll_original; + f32 target_y = scroll_vars.target_y; + f32 target_x = scroll_vars.target_x; + + f32 cursor_max_y = CursorMaxY(max_visible_y, line_height); + f32 cursor_min_y = CursorMinY(scroll_vars.min_y, line_height); + if (cursor_y > target_y + cursor_max_y){ target_y = cursor_y - cursor_max_y + delta_y; } - if (cursor_y < target_y - view->scroll_min_limit){ - target_y = cursor_y - delta_y + view->scroll_min_limit; + if (cursor_y < target_y + cursor_min_y){ + target_y = cursor_y - delta_y - cursor_min_y; } - - if (target_y > max_target_y) target_y = max_target_y; - if (target_y < view->scroll_min_limit) target_y = view->scroll_min_limit; - view->target_y = target_y; - - f32 cursor_x = view_get_cursor_x(view); - f32 target_x = view->target_x; + + 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 (cursor_x < target_x){ target_x = (f32)Max(0, cursor_x - max_x/2); } else if (cursor_x >= target_x + max_x){ target_x = (f32)(cursor_x - max_x/2); } - - view->target_x = target_x; - - b32 is_new_target = 0; - if (view->target_x != view->prev_target_x) is_new_target = 1; - if (view->target_y != view->prev_target_y) is_new_target = 1; - - if (view->models->scroll_rule( - view->target_x, view->target_y, - &view->scroll_x, &view->scroll_y, - (view->id) + 1, is_new_target)){ - result = 1; + + if (target_x != scroll_vars.target_x || target_y != scroll_vars.target_y){ + view->gui_target.scroll_updated.target_x = target_x; + view->gui_target.scroll_updated.target_y = target_y; + gui_activate_scrolling(&view->gui_target); } - - view->prev_target_x = view->target_x; - view->prev_target_y = view->target_y; - + if (file->state.paste_effect.tick_down > 0){ --file->state.paste_effect.tick_down; result = 1; } - + if (user_input->mouse.press_l && is_active){ f32 rx = (f32)(user_input->mouse.x - region.x0); f32 ry = (f32)(user_input->mouse.y - region.y0); - if (ry >= -view->scroll_min_limit){ + if (ry >= -view->file_scroll.min_y){ view_set_widget(view, FWIDG_NONE); - if (rx >= 0 && rx < max_x && ry >= 0 && ry < max_y){ - view_cursor_move(view, rx + view->scroll_x, ry + view->scroll_y, 1); + 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); view->mode = {}; } } @@ -3551,7 +3535,6 @@ internal void view_do_queries(View *view, GUI_Target *target){ Query_Slot *slot; Query_Bar *bar; - for (slot = view->query_set.used_slot; slot != 0; slot = slot->next){ bar = slot->query_bar; gui_do_text_field(target, bar->prompt, bar->string); @@ -3561,9 +3544,7 @@ view_do_queries(View *view, GUI_Target *target){ internal void do_widget(View *view, GUI_Target *target){ gui_begin_serial_section(target); - { - view_do_queries(view, target); - } + view_do_queries(view, target); gui_end_serial_section(target); } @@ -3572,44 +3553,36 @@ step_file_view(System_Functions *system, View *view, b32 is_active){ GUI_Target *target = &view->gui_target; Models *models = view->models; - f32 max_y = view_file_height(view); + f32 min_target_y = view->file_scroll.min_y; + f32 max_target_y = view->file_scroll.max_y; - i32 lowest_line = view_compute_lowest_line(view); - f32 min_target_y = view->scroll_min_limit; - f32 max_target_y = view_compute_max_target_y(lowest_line, view->font_height, max_y); - - gui_begin_top_level(target); { gui_do_top_bar(target); - + if (view->showing_ui == VUI_None){ gui_begin_overlap(target); do_widget(view, target); - + gui_begin_serial_section(target); { - i32_Rect scroll_rect = {0}; - f32 v = unlerp(min_target_y, view->target_y, max_target_y); + i32 line_height = view->font_height; f32 old_cursor_y = view_get_cursor_y(view); f32 cursor_y = old_cursor_y; - f32 cursor_max_y = max_y - view->font_height * 3; - + f32 cursor_max_y = CursorMaxY(view_file_height(view), line_height); + f32 cursor_min_y = CursorMinY(min_target_y, line_height); f32 delta = 9.f * view->font_height; - f32 lerp_space_delta = (delta); - if (max_target_y > min_target_y){ - lerp_space_delta /= (max_target_y - min_target_y); - } - - if (gui_start_scrollable(target, view->showing_ui, &v, lerp_space_delta, &scroll_rect)){ - view->target_y = lerp(min_target_y, v, max_target_y); - - if (view->target_y < min_target_y) view->target_y = min_target_y; - if (view->target_y > max_target_y) view->target_y = max_target_y; - - if (cursor_y > view->target_y + cursor_max_y) cursor_y = view->target_y + cursor_max_y; - if (cursor_y < view->target_y - view->scroll_min_limit) cursor_y = view->target_y - view->scroll_min_limit; - + f32 target_y; + + if (gui_get_scroll_vars(target, view->showing_ui, &view->file_scroll)){ + target_y = view->file_scroll.target_y; + if (cursor_y > target_y + cursor_max_y){ + cursor_y = target_y + cursor_max_y; + } + if (target_y != 0 && cursor_y < target_y + cursor_min_y){ + cursor_y = target_y + cursor_min_y; + } + if (cursor_y != old_cursor_y){ if (cursor_y > old_cursor_y){ cursor_y += view->font_height; @@ -3619,17 +3592,17 @@ step_file_view(System_Functions *system, View *view, b32 is_active){ } view->cursor = view_compute_cursor_from_xy(view, view->preferred_x, cursor_y); } - } + } - view->file_rect = scroll_rect; + gui_start_scrollable(target, view->showing_ui, view->file_scroll, delta); + + if (view->file_scroll.scroll_y < min_target_y) view->file_scroll.scroll_y = min_target_y; + if (view->file_scroll.scroll_y > max_target_y) view->file_scroll.scroll_y = max_target_y; - if (view->scroll_y < min_target_y) view->scroll_y = min_target_y; - if (view->scroll_y > max_target_y) view->scroll_y = max_target_y; - gui_do_file(target); } gui_end_serial_section(target); - + gui_end_overlap(target); } else{ @@ -3675,8 +3648,9 @@ step_file_view(System_Functions *system, View *view, b32 is_active){ } gui_do_text_field(target, message, text); - i32_Rect scroll_rect = {0}; - gui_start_scrollable(target, view->showing_ui, 0, 3.f, &scroll_rect); + gui_get_scroll_vars(target, view->showing_ui, &view->gui_scroll); + gui_start_scrollable(target, view->showing_ui, view->gui_scroll, 9.f * view->font_height); + for (i = 0; i < files->count; ++i, ++info){ append(&full_path, info->filename); terminate_with_null(&full_path); @@ -3709,10 +3683,21 @@ step_file_view(System_Functions *system, View *view, b32 is_active){ } } gui_end_top_level(target); - return(1); } +internal f32 +view_get_scroll_y(View *view){ + f32 v; + if (view->showing_ui == VUI_None){ + v = view->file_scroll.scroll_y; + } + else{ + v = view->gui_scroll.scroll_y; + } + return(v); +} + internal i32 do_input_file_view(System_Functions *system, Exchange *exchange, View *view, i32_Rect rect, b32 is_active, Input_Summary *user_input){ @@ -3722,7 +3707,7 @@ do_input_file_view(System_Functions *system, Exchange *exchange, GUI_Session gui_session; GUI_Header *h; GUI_Target *target = &view->gui_target; - + gui_session_init(&gui_session, rect, view->font_height); target->active = {0}; @@ -3736,7 +3721,20 @@ do_input_file_view(System_Functions *system, Exchange *exchange, case guicom_file: { - view->scroll_min_limit = -(f32)(gui_session.clip_rect.y0 - gui_session.rect.y0); + f32 old_min_y = view->gui_target.scroll_updated.min_y; + f32 new_min_y = -(f32)(gui_session.clip_rect.y0 - gui_session.rect.y0); + if (old_min_y != new_min_y){ + view->gui_target.scroll_updated.min_y = new_min_y; + gui_activate_scrolling(&view->gui_target); + } + + f32 old_max_y = view->gui_target.scroll_updated.max_y; + f32 new_max_y = view_compute_max_target_y(view); + if (old_max_y != new_max_y){ + view->gui_target.scroll_updated.max_y = new_max_y; + gui_activate_scrolling(&view->gui_target); + } + if (view->reinit_scrolling){ view_reinit_scrolling(view); } @@ -3780,10 +3778,12 @@ do_input_file_view(System_Functions *system, Exchange *exchange, target->hot = id; } if (user_input->mouse.release_l && gui_id_eq(target->hot, id)){ - target->active = gui_id_scrollbar(); target->hot = {0}; - target->scroll_v -= target->scroll_delta; - if (target->scroll_v < 0) target->scroll_v = 0; + target->scroll_updated.target_y -= target->delta; + if (target->scroll_updated.target_y < target->scroll_updated.min_y){ + target->scroll_updated.target_y = target->scroll_updated.min_y; + } + gui_activate_scrolling(target); } } else if (gui_id_eq(target->hover, id)){ @@ -3796,6 +3796,7 @@ do_input_file_view(System_Functions *system, Exchange *exchange, GUI_id id = gui_id_scrollbar_slider(); i32 mx = user_input->mouse.x; i32 my = user_input->mouse.y; + f32 v = 0; if (hit_check(mx, my, gui_session.rect)){ target->hover = id; @@ -3808,17 +3809,23 @@ do_input_file_view(System_Functions *system, Exchange *exchange, } if (gui_id_eq(target->hot, id)){ - target->active = gui_id_scrollbar(); - target->scroll_v = unlerp(gui_session.scroll_top, (f32)my, gui_session.scroll_bottom); - if (target->scroll_v < 0) target->scroll_v = 0; - if (target->scroll_v > 1) target->scroll_v = 1; + v = unlerp(gui_session.scroll_top, (f32)my, gui_session.scroll_bottom); + if (v < 0) v = 0; + if (v > 1.f) v = 1.f; + target->scroll_updated.target_y = lerp(target->scroll_updated.min_y, v, target->scroll_updated.max_y); + gui_activate_scrolling(target); } if (user_input->mouse.wheel != 0){ - target->active = gui_id_scrollbar(); - target->scroll_v += user_input->mouse.wheel*target->scroll_delta; - if (target->scroll_v < 0) target->scroll_v = 0; - if (target->scroll_v > 1) target->scroll_v = 1; + target->scroll_updated.target_y += user_input->mouse.wheel*target->delta; + + if (target->scroll_updated.target_y < target->scroll_updated.min_y){ + target->scroll_updated.target_y = target->scroll_updated.min_y; + } + if (target->scroll_updated.target_y > target->scroll_updated.max_y){ + target->scroll_updated.target_y = target->scroll_updated.max_y; + } + gui_activate_scrolling(target); } }break; @@ -3834,10 +3841,12 @@ do_input_file_view(System_Functions *system, Exchange *exchange, target->hot = id; } if (user_input->mouse.release_l && gui_id_eq(target->hot, id)){ - target->active = gui_id_scrollbar(); target->hot = {0}; - target->scroll_v += target->scroll_delta; - if (target->scroll_v > 1) target->scroll_v = 1; + target->scroll_updated.target_y += target->delta; + if (target->scroll_updated.target_y > target->scroll_updated.max_y){ + target->scroll_updated.target_y = target->scroll_updated.max_y; + } + gui_activate_scrolling(target); } } else if (gui_id_eq(target->hover, id)){ @@ -3852,6 +3861,26 @@ do_input_file_view(System_Functions *system, Exchange *exchange, target->hot = {0}; } + { + GUI_Scroll_Vars scroll_vars = view->gui_target.scroll_updated; + b32 is_new_target = 0; + if (scroll_vars.target_x != scroll_vars.prev_target_x) is_new_target = 1; + if (scroll_vars.target_y != scroll_vars.prev_target_y) is_new_target = 1; + + if (view->models->scroll_rule( + scroll_vars.target_x, scroll_vars.target_y, + &scroll_vars.scroll_x, &scroll_vars.scroll_y, + (view->id) + 1, is_new_target)){ + result = 1; + gui_activate_scrolling(&view->gui_target); + } + + scroll_vars.prev_target_x = scroll_vars.target_x; + scroll_vars.prev_target_y = scroll_vars.target_y; + + view->gui_target.scroll_updated = scroll_vars; + } + return(result); #if 0 @@ -3994,8 +4023,8 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target Buffer_Render_Options opts = {}; f32 *wraps = view->line_wrap_y; - f32 scroll_x = view->scroll_x; - f32 scroll_y = view->scroll_y; + f32 scroll_x = view->file_scroll.scroll_x; + f32 scroll_y = view->file_scroll.scroll_y; { render_cursor = buffer_get_start_cursor(&file->state.buffer, wraps, scroll_y, @@ -4180,7 +4209,7 @@ do_render_file_bar(Render_Target *target, View *view, Editing_File *file, i32_Re } else{ char line_number_space[30]; - String line_number = make_string(line_number_space, 0, 30); + String line_number = make_fixed_width_string(line_number_space); append(&line_number, " L#"); append_int_to_str(view->cursor.line, &line_number); @@ -4271,8 +4300,12 @@ do_render_file_view(System_Functions *system, Exchange *exchange, GUI_Header *h; GUI_Target *gui_target = &view->gui_target; + f32 v; + gui_session_init(&gui_session, rect, view->font_height); + v = view_get_scroll_y(view); + for (h = (GUI_Header*)gui_target->push.base; h->type; h = NextHeader(h)){ @@ -4281,13 +4314,11 @@ do_render_file_view(System_Functions *system, Exchange *exchange, case guicom_top_bar: { do_render_file_bar(target, view, file, gui_session.rect); - } - break; + }break; case guicom_file: { target->push_clip(target, gui_session.clip_rect); - view->scroll_min_limit = -(f32)(gui_session.clip_rect.y0 - gui_session.rect.y0); if (view->reinit_scrolling){ view_reinit_scrolling(view); } @@ -4753,12 +4784,6 @@ live_set_alloc_view(Live_Views *live_set, Panel *panel, Models *models){ result.view->models = models; result.view->scrub_max = 1; -#if 0 - // TODO(allen): Make "interactive" mode customizable just like the query bars! - result.view->query = make_fixed_width_string(result.view->query_); - result.view->dest = make_fixed_width_string(result.view->dest_); -#endif - init_query_set(&result.view->query_set); { diff --git a/4ed_gui.cpp b/4ed_gui.cpp index 9ac3e083..95bb0a78 100644 --- a/4ed_gui.cpp +++ b/4ed_gui.cpp @@ -50,7 +50,7 @@ free_query_slot(Query_Set *set, Query_Bar *match_bar){ if (slot->query_bar == match_bar) break; prev = slot; } - + if (slot){ if (prev){ prev->next = slot->next; @@ -73,6 +73,19 @@ struct GUI_id{ u64 id[1]; }; +struct GUI_Scroll_Vars{ + f32 scroll_y; + f32 target_y; + f32 prev_target_y; + f32 min_y, max_y; + + f32 scroll_x; + f32 target_x; + f32 prev_target_x; + + i32_Rect region; +}; + struct GUI_Target{ Partition push; @@ -80,10 +93,10 @@ struct GUI_Target{ GUI_id hot; GUI_id hover; - f32 scroll_v; - f32 scroll_delta; + GUI_Scroll_Vars scroll_original; + GUI_Scroll_Vars scroll_updated; + f32 delta; u32 scroll_id; - i32_Rect scrollable_area; }; struct GUI_Header{ @@ -237,7 +250,6 @@ gui_push_string(GUI_Target *target, GUI_Header *h, String s){ internal void gui_begin_top_level(GUI_Target *target){ target->push.pos = 0; - target->scroll_delta = 0; } internal void @@ -328,31 +340,35 @@ gui_id_scrollbar_bottom(){ } internal b32 -gui_start_scrollable(GUI_Target *target, u32 scroll_id, f32 *v, f32 d, i32_Rect *rect){ +gui_get_scroll_vars(GUI_Target *target, u32 scroll_id, GUI_Scroll_Vars *vars_out){ b32 result = 0; - GUI_Header *h; - - target->scroll_delta = d; - h = gui_push_simple_command(target, guicom_scrollable); - if (gui_id_eq(gui_id_scrollbar(), target->active) && target->scroll_id == scroll_id){ - if (v) *v = target->scroll_v; + if (gui_id_eq(target->active, gui_id_scrollbar()) && target->scroll_id == scroll_id){ + *vars_out = target->scroll_updated; result = 1; } - else{ - if (v) target->scroll_v = *v; - } - if (target->scroll_id == scroll_id){ - *rect = target->scrollable_area; - } + return(result); +} + +internal void +gui_start_scrollable(GUI_Target *target, u32 scroll_id, GUI_Scroll_Vars scroll_vars, f32 delta){ + GUI_Header *h; + + target->delta = delta; + h = gui_push_simple_command(target, guicom_scrollable); + + target->scroll_original = scroll_vars; + target->scroll_updated = scroll_vars; target->scroll_id = scroll_id; gui_push_simple_command(target, guicom_scrollable_top); gui_push_simple_command(target, guicom_scrollable_slider); gui_push_simple_command(target, guicom_scrollable_bottom); - - return(result); } +internal void +gui_activate_scrolling(GUI_Target *target){ + target->active = gui_id_scrollbar(); +} struct GUI_Section{ b32 overlapped; @@ -470,12 +486,16 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ i32_Rect rect = {0}; i32 y = 0; i32 end_v = -1; + f32 lerp_space_scroll_v = 0; + i32 scroll_v = (i32)target->scroll_original.scroll_y; Assert(session->t < ArrayCount(session->sections)); section = session->sections + session->t; y = section->v; - if (y < session->full_rect.y1){ + if (!session->is_scrollable) scroll_v = 0; + + if (y - scroll_v < session->full_rect.y1){ switch (h->type){ case guicom_null: Assert(0); break; @@ -525,6 +545,7 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ rect = gui_layout_top_bottom(session, y, session->full_rect.y1); end_v = rect.y1; end_section = section; + scroll_v = 0; break; case guicom_text_field: @@ -552,10 +573,15 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ session->scroll_rect = rect; session->is_scrollable = 1; - target->scrollable_area.x0 = session->full_rect.x0; - target->scrollable_area.x1 = rect.x0; - target->scrollable_area.y0 = rect.y0; - target->scrollable_area.y1 = rect.y1; + { + i32_Rect scrollable_rect; + scrollable_rect.x0 = session->full_rect.x0; + scrollable_rect.x1 = rect.x0; + scrollable_rect.y0 = rect.y0; + scrollable_rect.y1 = rect.y1; + + target->scroll_updated.region = scrollable_rect; + } break; case guicom_scrollable_top: @@ -563,13 +589,17 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ Assert(!section->overlapped); give_to_user = 1; gui_scrollbar_top(session->scroll_rect, &rect); + scroll_v = 0; break; case guicom_scrollable_slider: Assert(session->is_scrollable); Assert(!section->overlapped); give_to_user = 1; - gui_scrollbar_slider(session->scroll_rect, &rect, target->scroll_v, &session->scroll_top, &session->scroll_bottom); + lerp_space_scroll_v = unlerp( + (f32)target->scroll_original.min_y, (f32)target->scroll_original.target_y, (f32)target->scroll_original.max_y); + gui_scrollbar_slider(session->scroll_rect, &rect, lerp_space_scroll_v, &session->scroll_top, &session->scroll_bottom); + scroll_v = 0; break; case guicom_scrollable_bottom: @@ -577,6 +607,7 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ Assert(!section->overlapped); give_to_user = 1; gui_scrollbar_bottom(session->scroll_rect, &rect); + scroll_v = 0; break; } @@ -591,11 +622,22 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ } } - session->rect = rect; - if (rect.y0 < max_v){ - rect.y0 = max_v; + rect.y0 -= scroll_v; + rect.y1 -= scroll_v; + + if (rect.y1 > session->full_rect.y0){ + session->rect = rect; + + rect.y0 += scroll_v; + if (rect.y0 < max_v){ + rect.y0 = max_v; + } + rect.y0 -= scroll_v; + session->clip_rect = rect; } - session->clip_rect = rect; + else{ + give_to_user = 0; + } } if (end_section){