From df300c94fe5253ac9d0e88f7b9f5d833f6303a46 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Mon, 4 Apr 2016 23:13:13 -0400 Subject: [PATCH] sure to kill is basically working --- 4ed.cpp | 4 +- 4ed_file_view.cpp | 152 +++++++++++++++++++++++++++++++++++++++------- 4ed_gui.cpp | 138 ++++++++++++++++++++++++++++------------- 3 files changed, 227 insertions(+), 67 deletions(-) diff --git a/4ed.cpp b/4ed.cpp index 5e9a1e76..e3be48c6 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -4501,11 +4501,9 @@ App_Step_Sig(app_step){ if (file && !file->settings.never_kill){ if (buffer_needs_save(file)){ + copy(&view->dest, file->name.live_name); view_show_interactive(system, view, &models->map_ui, IAct_Sure_To_Kill, IInt_Sure_To_Kill, make_lit_string("Are you sure?")); -#if 0 - copy(&view->dest, file->name.live_name); -#endif } else{ working_set_remove(system, working_set, file->name.source_path); diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index a6477f78..7b908e30 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -2659,6 +2659,9 @@ view_show_interactive(System_Functions *system, View *view, view->interaction = interaction; view->dest = make_fixed_width_string(view->dest_); + view->map_for_file = view->map; + view->map = gui_map; + hot_directory_clean_end(&models->hot_directory); hot_directory_reload(system, &models->hot_directory, &models->working_set); } @@ -2723,7 +2726,7 @@ interactive_view_complete(View *view, String dest, i32 user_action){ break; } break; - + case IAct_Sure_To_Kill: switch (user_action){ case 0: @@ -2735,7 +2738,7 @@ interactive_view_complete(View *view, String dest, i32 user_action){ case 2: // TODO(allen): This is fishy! What if the save doesn't happen this time around? - // We need to ensure delayed acts happen in order I think. + // We need to ensure delayed acts happen in order I think... or better yet destroy delayed action entirely. delayed_save(&models->delay1, dest); delayed_kill(&models->delay1, dest); break; @@ -3784,6 +3787,65 @@ step_file_view(System_Functions *system, View *view, b32 is_active){ gui_end_scrollable(target); }break; + case IInt_Sure_To_Close: + { + i32 action = -1; + + GUI_id id; + String empty_str = {0}; + String message = make_lit_string("There is one or more files unsaved changes, close anyway?"); + + gui_do_text_field(target, message, empty_str); + + id.id[0] = (u64)('y' + (IInt_Sure_To_Close << 8)); + message = make_lit_string("(Y)es"); + if (gui_do_fixed_option(target, id, message, 'y')){ + action = 0; + } + + id.id[0] = (u64)('n' + (IInt_Sure_To_Close << 8)); + message = make_lit_string("(N)o"); + if (gui_do_fixed_option(target, id, message, 'n')){ + action = 1; + } + + if (action != -1){ + interactive_view_complete(view, view->dest, action); + } + }break; + + case IInt_Sure_To_Kill: + { + i32 action = -1; + + GUI_id id; + String empty_str = {0}; + String message = make_lit_string("There are unsaved changes, close anyway?"); + + gui_do_text_field(target, message, empty_str); + + id.id[0] = (u64)('y' + (IInt_Sure_To_Close << 8)); + message = make_lit_string("(Y)es"); + if (gui_do_fixed_option(target, id, message, 'y')){ + action = 0; + } + + id.id[0] = (u64)('n' + (IInt_Sure_To_Close << 8)); + message = make_lit_string("(N)o"); + if (gui_do_fixed_option(target, id, message, 'n')){ + action = 1; + } + + id.id[0] = (u64)('s' + (IInt_Sure_To_Close << 8)); + message = make_lit_string("(S)ave and kill"); + if (gui_do_fixed_option(target, id, message, 's')){ + action = 2; + } + + if (action != -1){ + interactive_view_complete(view, {0}, action); + } + }break; }break; } } @@ -3832,7 +3894,7 @@ struct Single_Line_Mode{ internal Single_Line_Input_Step app_single_line_input_core(System_Functions *system, Working_Set *working_set, Key_Event_Data key, Single_Line_Mode mode){ - Single_Line_Input_Step result = {}; + Single_Line_Input_Step result = {0}; if (key.keycode == key_back){ result.hit_backspace = 1; @@ -3841,7 +3903,9 @@ app_single_line_input_core(System_Functions *system, Working_Set *working_set, --mode.string->size; switch (mode.type){ case SINGLE_LINE_STRING: - mode.string->str[mode.string->size] = 0; break; + { + mode.string->str[mode.string->size] = 0; + }break; case SINGLE_LINE_FILE: { @@ -4056,6 +4120,7 @@ do_input_file_view(System_Functions *system, Exchange *exchange, i32 mx = user_input->mouse.x; i32 my = user_input->mouse.y; + // TODO(allen): deduplicate button related stuff if (hit_check(mx, my, gui_session.rect)){ target->hover = b->id; if (user_input->mouse.press_l){ @@ -4070,7 +4135,49 @@ do_input_file_view(System_Functions *system, Exchange *exchange, target->hover = {0}; } }break; - + + case guicom_fixed_option: + { + Key_Event_Data key; + Key_Summary *keys = &user_input->keys; + + GUI_Interactive *b = (GUI_Interactive*)h; + void *ptr = (b + 1); + String string; + char activation_key; + + i32 mx = user_input->mouse.x; + i32 my = user_input->mouse.y; + + i32 i, count; + + if (hit_check(mx, my, gui_session.rect)){ + target->hover = b->id; + if (user_input->mouse.press_l){ + target->hot = b->id; + } + if (user_input->mouse.release_l && gui_id_eq(target->hot, b->id)){ + target->active = b->id; + target->hot = {0}; + } + } + else if (gui_id_eq(target->hover, b->id)){ + target->hover = {0}; + } + + string = gui_read_string(&ptr); + activation_key = *(char*)ptr; + + count = keys->count; + for (i = 0; i < count; ++i){ + key = get_single_key(keys, i); + if (char_to_upper(key.character) == char_to_upper(activation_key)){ + target->active = b->id; + break; + } + } + }break; + case guicom_scrollable_top: { GUI_id id = gui_id_scrollbar_top(); @@ -4159,20 +4266,14 @@ do_input_file_view(System_Functions *system, Exchange *exchange, } }break; - case guicom_scrollable_section_end: + case guicom_end_scrollable_section: { if (!is_file_scroll){ - f32 old_min_y = view->gui_target.scroll_updated.min_y; f32 new_min_y = gui_session.suggested_min_y; - if (old_min_y != new_min_y){ - view->gui_target.scroll_updated.min_y = new_min_y; - } - - f32 old_max_y = view->gui_target.scroll_updated.max_y; f32 new_max_y = gui_session.suggested_max_y; - if (old_max_y != new_max_y){ - view->gui_target.scroll_updated.max_y = new_max_y; - } + + view->gui_target.scroll_updated.min_y = new_min_y; + view->gui_target.scroll_updated.max_y = new_max_y; } }break; } @@ -4588,6 +4689,16 @@ do_render_file_view(System_Functions *system, Exchange *exchange, draw_fat_option_block(gui_target, target, view, gui_session.rect, b->id, f, m); }break; + case guicom_fixed_option: + { + GUI_Interactive *b = (GUI_Interactive*)h; + void *ptr = (b + 1); + String f = gui_read_string(&ptr); + String m = {0}; + + draw_fat_option_block(gui_target, target, view, gui_session.rect, b->id, f, m); + }break; + case guicom_scrollable: { Models *models = view->models; @@ -4617,14 +4728,13 @@ do_render_file_view(System_Functions *system, Exchange *exchange, GUI_id id; Models *models = view->models; Style *style = &models->style; + i32_Rect box = gui_session.rect; i32 active_level; u32 back; u32 outline; - i32_Rect box = gui_session.rect; - switch (h->type){ case guicom_scrollable_top: id = gui_id_scrollbar_top(); break; case guicom_scrollable_bottom: id = gui_id_scrollbar_bottom(); break; @@ -4635,7 +4745,7 @@ do_render_file_view(System_Functions *system, Exchange *exchange, switch (active_level){ case 0: back = style->main.back_color; break; - case 1: case 2: back = style->main.margin_hover_color; break; + case 1: back = style->main.margin_hover_color; break; default: back = style->main.margin_active_color; break; } @@ -4647,15 +4757,15 @@ do_render_file_view(System_Functions *system, Exchange *exchange, } draw_rectangle(target, box, back); - draw_rectangle_outline(target, box, outline); + draw_margin(target, box, get_inner_rect(box, 2), outline); }break; - case guicom_scrollable_section_begin: + case guicom_begin_scrollable_section: { target->push_clip(target, gui_session.absolute_rect); }break; - case guicom_scrollable_section_end: + case guicom_end_scrollable_section: { target->pop_clip(target); }break; diff --git a/4ed_gui.cpp b/4ed_gui.cpp index a4e94d83..39f4cd0d 100644 --- a/4ed_gui.cpp +++ b/4ed_gui.cpp @@ -127,12 +127,13 @@ enum GUI_Command_Type{ guicom_text_input, guicom_file_input, guicom_file_option, + guicom_fixed_option, guicom_scrollable, guicom_scrollable_top, guicom_scrollable_slider, guicom_scrollable_bottom, - guicom_scrollable_section_begin, - guicom_scrollable_section_end, + guicom_begin_scrollable_section, + guicom_end_scrollable_section, }; internal b32 @@ -184,6 +185,15 @@ gui_align(GUI_Target *target){ return(ptr); } +internal void* +gui_align(GUI_Target *target, GUI_Header *h){ + void *ptr; + partition_align(&target->push, 8); + ptr = partition_current(&target->push); + h->size = (i32)((char*)ptr - (char*)h); + return(ptr); +} + internal void* advance_to_alignment(void *ptr){ u64 p = (u64)ptr; @@ -193,15 +203,14 @@ advance_to_alignment(void *ptr){ internal void* gui_push_aligned_item(GUI_Target *target, GUI_Header *h, void *item, i32 size){ - char *start, *end; - start = (char*)partition_allocate(&target->push, size); - if (start){ - memcpy(start, item, size); + char *ptr, *end; + ptr = (char*)partition_allocate(&target->push, size); + if (ptr){ + memcpy(ptr, item, size); } end = (char*)gui_align(target); - size = (i32)(end - start); - h->size += size; - return(start); + h->size = (i32)(end - (char*)h); + return(ptr); } internal void* @@ -339,7 +348,6 @@ gui_do_file_input(GUI_Target *target, GUI_id id, void *out){ internal b32 gui_do_file_option(GUI_Target *target, GUI_id id, String filename, b32 is_folder, String message){ b32 result = 0; - GUI_Interactive *b = gui_push_button_command(target, guicom_file_option, id); GUI_Header *h = (GUI_Header*)b; gui_push_item(target, h, &is_folder, sizeof(is_folder)); @@ -353,6 +361,22 @@ gui_do_file_option(GUI_Target *target, GUI_id id, String filename, b32 is_folder return(result); } +internal b32 +gui_do_fixed_option(GUI_Target *target, GUI_id id, String message, char key){ + b32 result = 0; + GUI_Interactive *b = gui_push_button_command(target, guicom_fixed_option, id); + GUI_Header *h = (GUI_Header*)b; + gui_push_string(target, h, message); + gui_push_item(target, h, &key, 1); + gui_align(target, h); + + if (gui_id_eq(id, target->active)){ + result = 1; + } + + return(result); +} + internal GUI_id gui_id_scrollbar(){ GUI_id id; @@ -407,12 +431,12 @@ gui_begin_scrollable(GUI_Target *target, u32 scroll_id, GUI_Scroll_Vars scroll_v gui_push_simple_command(target, guicom_scrollable_top); gui_push_simple_command(target, guicom_scrollable_slider); gui_push_simple_command(target, guicom_scrollable_bottom); - gui_push_simple_command(target, guicom_scrollable_section_begin); + gui_push_simple_command(target, guicom_begin_scrollable_section); } internal void gui_end_scrollable(GUI_Target *target){ - gui_push_simple_command(target, guicom_scrollable_section_end); + gui_push_simple_command(target, guicom_end_scrollable_section); } internal void @@ -437,6 +461,7 @@ struct GUI_Session{ i32 line_height; i32 scroll_bar_w; b32 is_scrollable; + i32 scrollable_items_bottom; i32_Rect scroll_rect; f32 scroll_top, scroll_bottom; @@ -493,7 +518,6 @@ gui_layout_fixed_h(GUI_Session *session, i32 y, i32 h){ internal void gui_scrollbar_top(i32_Rect bar, i32_Rect *top){ i32 w = (bar.x1 - bar.x0); - top->x0 = bar.x0; top->x1 = bar.x1; top->y0 = bar.y0; @@ -501,20 +525,37 @@ gui_scrollbar_top(i32_Rect bar, i32_Rect *top){ } internal void -gui_scrollbar_slider(i32_Rect bar, i32_Rect *slider, f32 s, f32 *min_out, f32 *max_out){ - i32 w = (bar.x1 - bar.x0); +gui_scrollbar_slider(i32_Rect bar, i32_Rect *slider, f32 s, f32 *min_out, f32 *max_out, f32 target_min, f32 target_max){ + i32 h, w = (bar.x1 - bar.x0); i32 min, max, pos; + f32 screen_size; + f32 full_size; + f32 ratio; + + screen_size = (f32)(bar.y1 - bar.y0); + full_size = (f32)(target_max - target_min + screen_size); + ratio = 1.f; + if (full_size > screen_size){ + ratio = screen_size/full_size; + } + + h = (i32)(ratio * bar.y1 - bar.y0 - w*2); + + if (h < w){ + h = w; + } + slider->x0 = bar.x0; slider->x1 = bar.x1; - - min = bar.y0 + w + w/2; - max = bar.y1 - w - w/2; + + min = bar.y0 + w + h/2; + max = bar.y1 - w - h/2; pos = lerp(min, s, max); - slider->y0 = pos - w/2; - slider->y1 = slider->y0 + w; + slider->y0 = pos - h/2; + slider->y1 = slider->y0 + h; *min_out = (f32)min; *max_out = (f32)max; @@ -523,7 +564,6 @@ gui_scrollbar_slider(i32_Rect bar, i32_Rect *slider, f32 s, f32 *min_out, f32 *m internal void gui_scrollbar_bottom(i32_Rect bar, i32_Rect *bottom){ i32 w = (bar.x1 - bar.x0); - bottom->x0 = bar.x0; bottom->x1 = bar.x1; bottom->y1 = bar.y1; @@ -538,6 +578,7 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ GUI_Section *end_section = 0; b32 give_to_user = 0; b32 always_give_to_user = 0; + b32 do_layout = 1; i32_Rect rect = {0}; i32 y = 0; i32 end_v = -1; @@ -612,15 +653,17 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ case guicom_text_input: case guicom_file_input: always_give_to_user = 1; + do_layout = 0; break; case guicom_file_option: + case guicom_fixed_option: give_to_user = 1; rect = gui_layout_fixed_h(session, y, session->line_height * 2); end_v = rect.y1; end_section = section; break; - + case guicom_scrollable: Assert(session->is_scrollable == 0); Assert(!section->overlapped); @@ -638,7 +681,6 @@ 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; } break; @@ -655,9 +697,14 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ Assert(session->is_scrollable); Assert(!section->overlapped); give_to_user = 1; + 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); + (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, target->scroll_original.min_y, target->scroll_original.max_y); scroll_v = 0; break; @@ -669,33 +716,38 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ scroll_v = 0; break; - case guicom_scrollable_section_begin: + case guicom_begin_scrollable_section: always_give_to_user = 1; - session->suggested_min_y = -(f32)(session->clip_rect.y0 - session->rect.y0); - session->suggested_max_y = (f32)(session->absolute_rect.y1 - session->full_rect.y1 * .5f); + session->scrollable_items_bottom = 0; rect = gui_layout_top_bottom(session, y, session->full_rect.y1); end_v = rect.y1; break; - case guicom_scrollable_section_end: + case guicom_end_scrollable_section: always_give_to_user = 1; + session->suggested_min_y = -(f32)(session->clip_rect.y0 - session->rect.y0); + session->suggested_max_y = (f32)(session->scrollable_items_bottom - session->full_rect.y1 * .5f); break; } - { + if (do_layout){ GUI_Section *section = session->sections; i32 max_v = 0; i32 i = 0; - - for (i = 0; i <= session->t; ++i, ++section){ - if (section->overlapped){ - max_v = Max(max_v, section->max_v); - } - } - + session->absolute_rect = rect; if (give_to_user){ + for (i = 0; i <= session->t; ++i, ++section){ + if (section->overlapped){ + max_v = Max(max_v, section->max_v); + } + } + + if (session->is_scrollable){ + session->scrollable_items_bottom = Max(session->scrollable_items_bottom, rect.y1); + } + rect.y0 -= scroll_v; rect.y1 -= scroll_v; @@ -713,14 +765,14 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){ give_to_user = 0; } } - } - if (end_section){ - gui_section_end_item(end_section, end_v); - } + if (end_section){ + gui_section_end_item(end_section, end_v); + } - if (y - scroll_v >= session->full_rect.y1){ - give_to_user = 0; + if (y - scroll_v >= session->full_rect.y1){ + give_to_user = 0; + } } return(give_to_user || always_give_to_user);