Progress on GUI scrolling
This commit is contained in:
parent
af5d6c8360
commit
468a7a33bc
|
@ -737,6 +737,8 @@ STRUCT UI_List{
|
||||||
STRUCT UI_Control{
|
STRUCT UI_Control{
|
||||||
UI_Item *items;
|
UI_Item *items;
|
||||||
int32_t count;
|
int32_t count;
|
||||||
|
|
||||||
|
i32_Rect bounding_box;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1509,16 +1509,27 @@ CUSTOM_DOC("Interactively switch to an open buffer.")
|
||||||
int32_t line_height = (int32_t)view.line_height;
|
int32_t line_height = (int32_t)view.line_height;
|
||||||
int32_t block_height = line_height*2;
|
int32_t block_height = line_height*2;
|
||||||
|
|
||||||
|
int32_t hot_buffer_id = 0;
|
||||||
|
int32_t item_index = 0;
|
||||||
|
|
||||||
Temp_Memory temp = begin_temp_memory(scratch);
|
Temp_Memory temp = begin_temp_memory(scratch);
|
||||||
String text_field = push_string(scratch, 256);
|
String text_field = push_string(scratch, 256);
|
||||||
Temp_Memory list_restore_point = begin_temp_memory(scratch);
|
|
||||||
for(;;){
|
for(;;){
|
||||||
end_temp_memory(list_restore_point);
|
Temp_Memory full_temp = begin_temp_memory(scratch);
|
||||||
|
|
||||||
|
refresh_view(app, &view);
|
||||||
|
Mouse_State mouse_state = get_mouse_state(app);
|
||||||
|
int32_t mx = mouse_state.x - view.file_region.x0 + (int32_t)view.scroll_vars.scroll_x;
|
||||||
|
int32_t my = mouse_state.y - view.file_region.y0 + (int32_t)view.scroll_vars.scroll_y;
|
||||||
|
|
||||||
int32_t y_pos = line_height;
|
int32_t y_pos = line_height;
|
||||||
|
|
||||||
UI_List list = {0};
|
UI_List list = {0};
|
||||||
|
int32_t item_index_counter = 0;
|
||||||
UI_Item *highlighted_item = 0;
|
UI_Item *highlighted_item = 0;
|
||||||
|
UI_Item *hot_item = 0;
|
||||||
|
UI_Item *hovered_item = 0;
|
||||||
|
int32_t option_item_count = 0;
|
||||||
for (Buffer_Summary buffer = get_buffer_first(app, AccessAll);
|
for (Buffer_Summary buffer = get_buffer_first(app, AccessAll);
|
||||||
buffer.exists;
|
buffer.exists;
|
||||||
get_buffer_next(app, &buffer, AccessAll)){
|
get_buffer_next(app, &buffer, AccessAll)){
|
||||||
|
@ -1543,17 +1554,39 @@ CUSTOM_DOC("Interactively switch to an open buffer.")
|
||||||
item.user_data = (void*)buffer.buffer_id;
|
item.user_data = (void*)buffer.buffer_id;
|
||||||
item.activation_level = UIActivation_None;
|
item.activation_level = UIActivation_None;
|
||||||
item.rectangle = item_rect;
|
item.rectangle = item_rect;
|
||||||
if (highlighted_item == 0){
|
|
||||||
item.activation_level = UIActivation_Hover;
|
UI_Item *item_ptr = ui_list_add_item(scratch, &list, item);
|
||||||
UI_Item *item_ptr = ui_list_add_item(scratch, &list, item);
|
option_item_count += 1;
|
||||||
|
|
||||||
|
if (item_rect.x0 <= mx && mx < item_rect.x1 &&
|
||||||
|
item_rect.y0 <= my && my < item_rect.y1){
|
||||||
|
hovered_item = item_ptr;
|
||||||
|
}
|
||||||
|
if (item_index_counter == item_index){
|
||||||
highlighted_item = item_ptr;
|
highlighted_item = item_ptr;
|
||||||
}
|
}
|
||||||
else{
|
item_index_counter += 1;
|
||||||
ui_list_add_item(scratch, &list, item);
|
if (buffer.buffer_id == hot_buffer_id){
|
||||||
|
hot_item = item_ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hovered_item != 0){
|
||||||
|
hovered_item->activation_level = UIActivation_Hover;
|
||||||
|
}
|
||||||
|
if (hot_item != 0){
|
||||||
|
if (hot_item == hovered_item){
|
||||||
|
hot_item->activation_level = UIActivation_Active;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
hot_item->activation_level = UIActivation_Hover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (highlighted_item != 0){
|
||||||
|
highlighted_item->activation_level = UIActivation_Active;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
i32_Rect item_rect = {0};
|
i32_Rect item_rect = {0};
|
||||||
item_rect.x0 = x0;
|
item_rect.x0 = x0;
|
||||||
|
@ -1566,6 +1599,7 @@ CUSTOM_DOC("Interactively switch to an open buffer.")
|
||||||
item.type = UIType_TextField;
|
item.type = UIType_TextField;
|
||||||
item.query = push_string_copy(scratch, "Switch: ");
|
item.query = push_string_copy(scratch, "Switch: ");
|
||||||
item.string = text_field;
|
item.string = text_field;
|
||||||
|
item.activation_level = UIActivation_Active;
|
||||||
item.user_data = 0;
|
item.user_data = 0;
|
||||||
item.rectangle = item_rect;
|
item.rectangle = item_rect;
|
||||||
ui_list_add_item(scratch, &list, item);
|
ui_list_add_item(scratch, &list, item);
|
||||||
|
@ -1574,45 +1608,94 @@ CUSTOM_DOC("Interactively switch to an open buffer.")
|
||||||
UI_Control control = ui_list_to_ui_control(scratch, &list);
|
UI_Control control = ui_list_to_ui_control(scratch, &list);
|
||||||
view_set_ui(app, &view, &control);
|
view_set_ui(app, &view, &control);
|
||||||
|
|
||||||
User_Input in = get_user_input(app, EventAll, EventOnEsc);
|
for (;;){
|
||||||
if (in.abort){
|
bool32 needs_full_update = false;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
UI_Item *activated_item = 0;
|
|
||||||
switch (in.type){
|
|
||||||
case UserInputKey:
|
|
||||||
{
|
|
||||||
if (in.key.keycode == '\n' || in.key.keycode == '\t'){
|
|
||||||
activated_item = highlighted_item;
|
|
||||||
}
|
|
||||||
else if (in.key.keycode == key_back){
|
|
||||||
backspace_utf8(&text_field);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
uint8_t character[4];
|
|
||||||
uint32_t length = to_writable_character(in, character);
|
|
||||||
if (length > 0){
|
|
||||||
append(&text_field, make_string(character, length));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case UserInputMouse:
|
User_Input in = get_user_input(app, EventAll, EventOnEsc);
|
||||||
{
|
if (in.abort){
|
||||||
if (in.mouse.press_l){
|
goto done;
|
||||||
int32_t mx = in.mouse.x - view.view_region.x0;
|
}
|
||||||
int32_t my = in.mouse.y - view.view_region.y0;
|
|
||||||
activated_item = ui_control_get_mouse_hit(&control, mx, my);
|
UI_Item *activated_item = 0;
|
||||||
}
|
switch (in.type){
|
||||||
}break;
|
case UserInputKey:
|
||||||
}
|
{
|
||||||
|
if (in.key.keycode == '\n' || in.key.keycode == '\t'){
|
||||||
if (activated_item != 0){
|
activated_item = highlighted_item;
|
||||||
int32_t buffer_id = (int32_t)activated_item->user_data;
|
}
|
||||||
view_set_buffer(app, &view, buffer_id, 0);
|
else if (in.key.keycode == key_back){
|
||||||
goto done;
|
backspace_utf8(&text_field);
|
||||||
|
needs_full_update = true;
|
||||||
|
item_index = 0;
|
||||||
|
}
|
||||||
|
else if (in.key.keycode == key_up || in.key.keycode == key_page_up){
|
||||||
|
item_index = item_index - 1;
|
||||||
|
if (item_index < 0){
|
||||||
|
item_index = 0;
|
||||||
|
}
|
||||||
|
needs_full_update = true;
|
||||||
|
}
|
||||||
|
else if (in.key.keycode == key_down || in.key.keycode == key_page_down){
|
||||||
|
item_index = item_index + 1;
|
||||||
|
if (item_index > option_item_count - 1){
|
||||||
|
item_index = option_item_count - 1;
|
||||||
|
}
|
||||||
|
needs_full_update = true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
uint8_t character[4];
|
||||||
|
uint32_t length = to_writable_character(in, character);
|
||||||
|
if (length > 0){
|
||||||
|
append(&text_field, make_string(character, length));
|
||||||
|
needs_full_update = true;
|
||||||
|
item_index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case UserInputMouse:
|
||||||
|
{
|
||||||
|
if (in.mouse.wheel != 0){
|
||||||
|
GUI_Scroll_Vars scroll = view.scroll_vars;
|
||||||
|
scroll.target_y += in.mouse.wheel;
|
||||||
|
view_set_scroll(app, &view, scroll);
|
||||||
|
}
|
||||||
|
if (in.mouse.press_l || in.mouse.release_l){
|
||||||
|
int32_t mx = in.mouse.x - view.file_region.x0;
|
||||||
|
int32_t my = in.mouse.y - view.file_region.y0;
|
||||||
|
UI_Item *clicked = ui_control_get_mouse_hit(&control, mx, my);
|
||||||
|
if (in.mouse.press_l){
|
||||||
|
if (clicked != 0){
|
||||||
|
hot_buffer_id = (int32_t)clicked->user_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (in.mouse.release_l){
|
||||||
|
if (clicked != 0){
|
||||||
|
if (hot_buffer_id == (int32_t)clicked->user_data){
|
||||||
|
activated_item = clicked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hot_buffer_id = 0;
|
||||||
|
}
|
||||||
|
needs_full_update = true;
|
||||||
|
}
|
||||||
|
if (mx != in.mouse.x || my != in.mouse.y){
|
||||||
|
needs_full_update = true;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activated_item != 0){
|
||||||
|
int32_t buffer_id = (int32_t)activated_item->user_data;
|
||||||
|
view_set_buffer(app, &view, buffer_id, 0);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (needs_full_update){
|
||||||
|
goto full_update;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
full_update:;
|
||||||
|
end_temp_memory(full_temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:;
|
done:;
|
||||||
|
|
|
@ -307,7 +307,7 @@ static Command_Metadata fcoder_metacmd_table[185] = {
|
||||||
{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\4coder_project_commands.cpp", 42, 1062 },
|
{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\4coder_project_commands.cpp", 42, 1062 },
|
||||||
{ PROC_LINKS(open_color_tweaker, 0), "open_color_tweaker", 18, "Opens the 4coder colors and fonts selector menu.", 48, "w:\\4ed\\code\\4coder_base_commands.cpp", 39, 1492 },
|
{ PROC_LINKS(open_color_tweaker, 0), "open_color_tweaker", 18, "Opens the 4coder colors and fonts selector menu.", 48, "w:\\4ed\\code\\4coder_base_commands.cpp", 39, 1492 },
|
||||||
{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 39, 1339 },
|
{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 39, 1339 },
|
||||||
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 39, 1625 },
|
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 39, 1708 },
|
||||||
{ PROC_LINKS(open_long_braces, 0), "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 49, 58 },
|
{ PROC_LINKS(open_long_braces, 0), "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 49, 58 },
|
||||||
{ PROC_LINKS(open_long_braces_break, 0), "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 49, 74 },
|
{ PROC_LINKS(open_long_braces_break, 0), "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 49, 74 },
|
||||||
{ PROC_LINKS(open_long_braces_semicolon, 0), "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 49, 66 },
|
{ PROC_LINKS(open_long_braces_semicolon, 0), "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 49, 66 },
|
||||||
|
|
|
@ -17,22 +17,50 @@ static UI_Control
|
||||||
ui_list_to_ui_control(Partition *arena, UI_List *list){
|
ui_list_to_ui_control(Partition *arena, UI_List *list){
|
||||||
UI_Control control = {0};
|
UI_Control control = {0};
|
||||||
control.items = push_array(arena, UI_Item, list->count);
|
control.items = push_array(arena, UI_Item, list->count);
|
||||||
|
if (list->count > 0){
|
||||||
|
control.bounding_box = list->first->fixed.rectangle;
|
||||||
|
}
|
||||||
for (UI_Item_Node *node = list->first;
|
for (UI_Item_Node *node = list->first;
|
||||||
node != 0;
|
node != 0;
|
||||||
node = node->next){
|
node = node->next){
|
||||||
control.items[control.count++] = node->fixed;
|
control.items[control.count++] = node->fixed;
|
||||||
|
if (control.bounding_box.x0 > node->fixed.rectangle.x0){
|
||||||
|
control.bounding_box.x0 = node->fixed.rectangle.x0;
|
||||||
|
}
|
||||||
|
if (control.bounding_box.x1 < node->fixed.rectangle.x1){
|
||||||
|
control.bounding_box.x1 = node->fixed.rectangle.x1;
|
||||||
|
}
|
||||||
|
if (control.bounding_box.y0 > node->fixed.rectangle.y0){
|
||||||
|
control.bounding_box.y0 = node->fixed.rectangle.y0;
|
||||||
|
}
|
||||||
|
if (control.bounding_box.y1 < node->fixed.rectangle.y1){
|
||||||
|
control.bounding_box.y1 = node->fixed.rectangle.y1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return(control);
|
return(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ui_control_set_top(UI_Control *control, int32_t top_y){
|
||||||
|
control->bounding_box.y0 = top_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ui_control_set_bottom(UI_Control *control, int32_t bottom_y){
|
||||||
|
control->bounding_box.y1 = bottom_y;
|
||||||
|
}
|
||||||
|
|
||||||
static UI_Item*
|
static UI_Item*
|
||||||
ui_control_get_mouse_hit(UI_Control *control, int32_t mx, int32_t my){
|
ui_control_get_mouse_hit(UI_Control *control, int32_t mx, int32_t my){
|
||||||
int32_t count = control->count;
|
if (control->bounding_box.x0 <= mx && mx < control->bounding_box.x1 &&
|
||||||
UI_Item *item = control->items + count - 1;
|
control->bounding_box.y0 <= my && my < control->bounding_box.y1){
|
||||||
for (int32_t i = 0; i < count; ++i, item -= 1){
|
int32_t count = control->count;
|
||||||
i32_Rect r = item->rectangle;
|
UI_Item *item = control->items + count - 1;
|
||||||
if (r.x0 <= mx && mx < r.x1 && r.y0 <= my && my < r.y1){
|
for (int32_t i = 0; i < count; ++i, item -= 1){
|
||||||
return(item);
|
i32_Rect r = item->rectangle;
|
||||||
|
if (r.x0 <= mx && mx < r.x1 && r.y0 <= my && my < r.y1){
|
||||||
|
return(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
|
75
4ed.cpp
75
4ed.cpp
|
@ -1868,51 +1868,46 @@ App_Step_Sig(app_step){
|
||||||
b32 active = (panel == active_panel);
|
b32 active = (panel == active_panel);
|
||||||
Input_Summary summary = (active)?(active_input):(dead_input);
|
Input_Summary summary = (active)?(active_input):(dead_input);
|
||||||
|
|
||||||
view->transient.changed_context_in_step = 0;
|
if (panel == mouse_panel && !input->mouse.out_of_window){
|
||||||
|
summary.mouse = mouse_state;
|
||||||
|
}
|
||||||
|
|
||||||
if (view->transient.changed_context_in_step == 0){
|
GUI_Scroll_Vars *scroll_vars = 0;
|
||||||
active = (panel == active_panel);
|
i32 max_y = 0;
|
||||||
summary = (active)?(active_input):(dead_input);
|
b32 file_scroll = false;
|
||||||
if (panel == mouse_panel && !input->mouse.out_of_window){
|
if (view->transient.ui_mode_counter == 0){
|
||||||
summary.mouse = mouse_state;
|
scroll_vars = &view->transient.edit_pos->scroll;
|
||||||
}
|
max_y = view_compute_max_target_y(view);
|
||||||
|
file_scroll = true;
|
||||||
b32 file_scroll = true;
|
}
|
||||||
GUI_Scroll_Vars *scroll_vars = &view->transient.edit_pos->scroll;
|
else{
|
||||||
|
scroll_vars = &view->transient.ui_scroll;
|
||||||
i32 max_y = 0;
|
i32 bottom = view->transient.ui_control.bounding_box.y1;
|
||||||
if (view->transient.ui_mode_counter == 0){
|
max_y = view_compute_max_target_y_from_bottom_y(view, (f32)bottom);
|
||||||
max_y = view_compute_max_target_y(view);
|
file_scroll = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Input_Process_Result ip_result = do_step_file_view(system, view, models, panel->inner, active, &summary, *scroll_vars, max_y);
|
||||||
|
|
||||||
|
if (ip_result.is_animating){
|
||||||
|
app_result.animating = true;
|
||||||
|
}
|
||||||
|
if (ip_result.consumed_l){
|
||||||
|
consume_input(&vars->available_input, Input_MouseLeftButton, "file view step");
|
||||||
|
}
|
||||||
|
if (ip_result.consumed_r){
|
||||||
|
consume_input(&vars->available_input, Input_MouseRightButton, "file view step");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(scroll_vars, &ip_result.scroll, sizeof(*scroll_vars)) != 0){
|
||||||
|
if (file_scroll){
|
||||||
|
view_set_scroll(system, view, ip_result.scroll);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
#if 0
|
*scroll_vars = ip_result.scroll;
|
||||||
max_y = view->transient.gui_max_y;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Input_Process_Result ip_result = do_step_file_view(system, view, models, panel->inner, active, &summary, *scroll_vars, view->transient.scroll_region, max_y);
|
|
||||||
|
|
||||||
if (ip_result.is_animating){
|
|
||||||
app_result.animating = 1;
|
|
||||||
}
|
|
||||||
if (ip_result.consumed_l){
|
|
||||||
consume_input(&vars->available_input, Input_MouseLeftButton, "file view step");
|
|
||||||
}
|
|
||||||
if (ip_result.consumed_r){
|
|
||||||
consume_input(&vars->available_input, Input_MouseRightButton, "file view step");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp(scroll_vars, &ip_result.vars, sizeof(*scroll_vars)) != 0){
|
|
||||||
if (file_scroll){
|
|
||||||
view_set_scroll(system, view, ip_result.vars);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
*scroll_vars = ip_result.vars;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
view->transient.scroll_region = ip_result.region;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,12 @@ fill_view_summary(System_Functions *system, View_Summary *view, View *vptr, Live
|
||||||
|
|
||||||
view->view_region = vptr->transient.panel->inner;
|
view->view_region = vptr->transient.panel->inner;
|
||||||
view->file_region = vptr->transient.file_region;
|
view->file_region = vptr->transient.file_region;
|
||||||
view->scroll_vars = vptr->transient.edit_pos->scroll;
|
if (vptr->transient.ui_mode_counter == 0){
|
||||||
|
view->scroll_vars = vptr->transient.edit_pos->scroll;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
view->scroll_vars = vptr->transient.ui_scroll;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2001,7 +2006,12 @@ DOC_SEE(GUI_Scroll_Vars)
|
||||||
Assert(file != 0);
|
Assert(file != 0);
|
||||||
if (!file->is_loading){
|
if (!file->is_loading){
|
||||||
result = true;
|
result = true;
|
||||||
view_set_scroll(system, vptr, scroll);
|
if (vptr->transient.ui_mode_counter == 0){
|
||||||
|
view_set_scroll(system, vptr, scroll);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
vptr->transient.ui_scroll = scroll;
|
||||||
|
}
|
||||||
fill_view_summary(system, view, vptr, cmd);
|
fill_view_summary(system, view, vptr, cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2228,7 +2238,7 @@ View_Set_UI(Application_Links *app, View_Summary *view, UI_Control *control){
|
||||||
if (vptr->transient.ui_control.items != 0){
|
if (vptr->transient.ui_control.items != 0){
|
||||||
general_memory_free(general, vptr->transient.ui_control.items);
|
general_memory_free(general, vptr->transient.ui_control.items);
|
||||||
}
|
}
|
||||||
vptr->transient.ui_control.count = 0;
|
memset(&vptr->transient.ui_control, 0, sizeof(vptr->transient.ui_control));
|
||||||
if (control->count > 0){
|
if (control->count > 0){
|
||||||
i32 memory_size = sizeof(UI_Item)*control->count;
|
i32 memory_size = sizeof(UI_Item)*control->count;
|
||||||
vptr->transient.ui_control.items = (UI_Item*)general_memory_allocate(general, memory_size);
|
vptr->transient.ui_control.items = (UI_Item*)general_memory_allocate(general, memory_size);
|
||||||
|
@ -2240,9 +2250,7 @@ View_Set_UI(Application_Links *app, View_Summary *view, UI_Control *control){
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
vptr->transient.ui_control.bounding_box = control->bounding_box;
|
||||||
vptr->transient.ui_control.items = 0;
|
|
||||||
}
|
|
||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
return(false);
|
return(false);
|
||||||
|
|
18
4ed_math.h
18
4ed_math.h
|
@ -657,5 +657,23 @@ fits_inside(i32_Rect rect, i32_Rect outer){
|
||||||
return(rect.x0 >= outer.x0 && rect.x1 <= outer.x1 && rect.y0 >= outer.y0 && rect.y1 <= outer.y1);
|
return(rect.x0 >= outer.x0 && rect.x1 <= outer.x1 && rect.y0 >= outer.y0 && rect.y1 <= outer.y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t
|
||||||
|
interval_overlap(float a0, float a1, float b0, float b1){
|
||||||
|
if (a0 <= b0 && b0 < a1 ||
|
||||||
|
b0 <= a0 && a0 < b1){
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t
|
||||||
|
rect_opverlap(f32_Rect a, f32_Rect b){
|
||||||
|
if (interval_overlap(a.x0, a.x1, b.x0, b.x1) &&
|
||||||
|
interval_overlap(a.y0, a.y1, b.y0, b.y1)){
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,20 @@ draw_rectangle_outline(Render_Target *target, i32_Rect rect, u32 color){
|
||||||
draw_rectangle_outline(target, f32R(rect), color);
|
draw_rectangle_outline(target, f32R(rect), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
draw_margin(Render_Target *target, f32_Rect outer, f32_Rect inner, u32 color){
|
||||||
|
draw_rectangle(target, f32R(outer.x0, outer.y0, outer.x1, inner.y0), color);
|
||||||
|
draw_rectangle(target, f32R(outer.x0, inner.y1, outer.x1, outer.y1), color);
|
||||||
|
draw_rectangle(target, f32R(outer.x0, inner.y0, inner.x0, inner.y1), color);
|
||||||
|
draw_rectangle(target, f32R(inner.x1, inner.y0, outer.x1, inner.y1), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
draw_margin(Render_Target *target, f32_Rect outer, f32 width, u32 color){
|
||||||
|
f32_Rect inner = get_inner_rect(outer, width);
|
||||||
|
draw_margin(target, outer, inner, color);
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
draw_margin(Render_Target *target, i32_Rect outer, i32_Rect inner, u32 color){
|
draw_margin(Render_Target *target, i32_Rect outer, i32_Rect inner, u32 color){
|
||||||
draw_rectangle(target, i32R(outer.x0, outer.y0, outer.x1, inner.y0), color);
|
draw_rectangle(target, i32R(outer.x0, outer.y0, outer.x1, inner.y0), color);
|
||||||
|
|
12
4ed_view.cpp
12
4ed_view.cpp
|
@ -138,6 +138,14 @@ view_cursor_limits(View *view){
|
||||||
return(limits);
|
return(limits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline i32
|
||||||
|
view_compute_max_target_y_from_bottom_y(View *view, f32 max_item_y){
|
||||||
|
i32 line_height = view->transient.line_height;
|
||||||
|
f32 height = clamp_bottom((f32)line_height, view_height(view));
|
||||||
|
f32 max_target_y = clamp_bottom(0.f, max_item_y - height*0.5f);
|
||||||
|
return(ceil32(max_target_y));
|
||||||
|
}
|
||||||
|
|
||||||
inline i32
|
inline i32
|
||||||
view_compute_max_target_y(View *view){
|
view_compute_max_target_y(View *view){
|
||||||
i32 line_height = view->transient.line_height;
|
i32 line_height = view->transient.line_height;
|
||||||
|
@ -147,9 +155,7 @@ view_compute_max_target_y(View *view){
|
||||||
if (!file->settings.unwrapped_lines){
|
if (!file->settings.unwrapped_lines){
|
||||||
lowest_line = file->state.wrap_line_index[buffer->line_count];
|
lowest_line = file->state.wrap_line_index[buffer->line_count];
|
||||||
}
|
}
|
||||||
f32 height = clamp_bottom((f32)line_height, view_height(view));
|
return(view_compute_max_target_y_from_bottom_y(view, (lowest_line + 0.5f)*(f32)line_height));
|
||||||
f32 max_target_y = clamp_bottom(0.f, ((lowest_line + 0.5f)*line_height) - height*0.5f);
|
|
||||||
return(ceil32(max_target_y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u32
|
inline u32
|
||||||
|
|
|
@ -48,6 +48,7 @@ struct View_Transient{
|
||||||
|
|
||||||
i32 ui_mode_counter;
|
i32 ui_mode_counter;
|
||||||
UI_Control ui_control;
|
UI_Control ui_control;
|
||||||
|
GUI_Scroll_Vars ui_scroll;
|
||||||
|
|
||||||
b32 hide_scrollbar;
|
b32 hide_scrollbar;
|
||||||
b32 hide_file_bar;
|
b32 hide_file_bar;
|
||||||
|
@ -184,14 +185,10 @@ struct View_Step_Result{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Input_Process_Result{
|
struct Input_Process_Result{
|
||||||
GUI_Scroll_Vars vars;
|
GUI_Scroll_Vars scroll;
|
||||||
i32_Rect region;
|
|
||||||
b32 is_animating;
|
b32 is_animating;
|
||||||
b32 consumed_l;
|
b32 consumed_l;
|
||||||
b32 consumed_r;
|
b32 consumed_r;
|
||||||
|
|
||||||
b32 has_max_y_suggestion;
|
|
||||||
i32 max_y;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum{
|
enum{
|
||||||
|
|
108
4ed_view_ui.cpp
108
4ed_view_ui.cpp
|
@ -146,13 +146,11 @@ global_const Style_Color_Edit colors_to_edit[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
internal Input_Process_Result
|
internal Input_Process_Result
|
||||||
do_step_file_view(System_Functions *system, View *view, Models *models, i32_Rect rect, b32 is_active, Input_Summary *user_input, GUI_Scroll_Vars vars, i32_Rect region, i32 max_y){
|
do_step_file_view(System_Functions *system, View *view, Models *models, i32_Rect rect, b32 is_active, Input_Summary *user_input, GUI_Scroll_Vars scroll, i32 max_y){
|
||||||
|
scroll.target_y = clamp(0, scroll.target_y, max_y);
|
||||||
|
|
||||||
Input_Process_Result result = {0};
|
Input_Process_Result result = {0};
|
||||||
|
result.scroll = scroll;
|
||||||
vars.target_y = clamp(0, vars.target_y, max_y);
|
|
||||||
|
|
||||||
result.vars = vars;
|
|
||||||
result.region = region;
|
|
||||||
|
|
||||||
i32 line_height = view->transient.line_height;
|
i32 line_height = view->transient.line_height;
|
||||||
|
|
||||||
|
@ -166,8 +164,8 @@ do_step_file_view(System_Functions *system, View *view, Models *models, i32_Rect
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user_input->mouse.wheel != 0){
|
if (user_input->mouse.wheel != 0){
|
||||||
result.vars.target_y += user_input->mouse.wheel;
|
result.scroll.target_y += user_input->mouse.wheel;
|
||||||
result.vars.target_y = clamp(0, result.vars.target_y, max_y);
|
result.scroll.target_y = clamp(0, result.scroll.target_y, max_y);
|
||||||
result.is_animating = true;
|
result.is_animating = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,26 +192,23 @@ do_step_file_view(System_Functions *system, View *view, Models *models, i32_Rect
|
||||||
target_y = clamp_bottom(0, floor32(cursor.y - height*.5f));
|
target_y = clamp_bottom(0, floor32(cursor.y - height*.5f));
|
||||||
}
|
}
|
||||||
|
|
||||||
result.vars.target_y = target_y;
|
result.scroll.target_y = target_y;
|
||||||
result.vars.scroll_y = (f32)target_y;
|
result.scroll.scroll_y = (f32)target_y;
|
||||||
result.vars.prev_target_y = -1000;
|
result.scroll.prev_target_y = -1000;
|
||||||
|
|
||||||
result.vars.target_x = target_x;
|
result.scroll.target_x = target_x;
|
||||||
result.vars.scroll_x = (f32)target_x;
|
result.scroll.scroll_x = (f32)target_x;
|
||||||
result.vars.prev_target_x = -1000;
|
result.scroll.prev_target_x = -1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file->is_loading && file->state.paste_effect.seconds_down > 0.f){
|
if (!file->is_loading && file->state.paste_effect.seconds_down > 0.f){
|
||||||
file->state.paste_effect.seconds_down -= user_input->dt;
|
file->state.paste_effect.seconds_down -= user_input->dt;
|
||||||
result.is_animating = true;
|
result.is_animating = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.has_max_y_suggestion = true;
|
|
||||||
result.max_y = view_compute_max_target_y(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
GUI_Scroll_Vars scroll_vars = result.vars;
|
GUI_Scroll_Vars scroll_vars = result.scroll;
|
||||||
b32 is_new_target = (scroll_vars.target_x != scroll_vars.prev_target_x ||
|
b32 is_new_target = (scroll_vars.target_x != scroll_vars.prev_target_x ||
|
||||||
scroll_vars.target_y != scroll_vars.prev_target_y);
|
scroll_vars.target_y != scroll_vars.prev_target_y);
|
||||||
|
|
||||||
|
@ -227,7 +222,7 @@ do_step_file_view(System_Functions *system, View *view, Models *models, i32_Rect
|
||||||
scroll_vars.prev_target_x = scroll_vars.target_x;
|
scroll_vars.prev_target_x = scroll_vars.target_x;
|
||||||
scroll_vars.prev_target_y = scroll_vars.target_y;
|
scroll_vars.prev_target_y = scroll_vars.target_y;
|
||||||
|
|
||||||
result.vars = scroll_vars;
|
result.scroll = scroll_vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
|
@ -398,46 +393,47 @@ do_render_file_view(System_Functions *system, View *view, Models *models, GUI_Sc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
f32_Rect rect_f32 = f32R(rect);
|
||||||
|
|
||||||
i32 item_count = view->transient.ui_control.count;
|
i32 item_count = view->transient.ui_control.count;
|
||||||
UI_Item *item = view->transient.ui_control.items;
|
UI_Item *item = view->transient.ui_control.items;
|
||||||
|
GUI_Scroll_Vars scroll = view->transient.ui_scroll;
|
||||||
for (i32 i = 0; i < item_count; ++i, item += 1){
|
for (i32 i = 0; i < item_count; ++i, item += 1){
|
||||||
switch (item->type){
|
f32_Rect item_rect = f32R(item->rectangle);
|
||||||
case UIType_Option:
|
item_rect.x0 += rect_f32.x0 - scroll.scroll_x;
|
||||||
{
|
item_rect.y0 += rect_f32.y0 - scroll.scroll_y;
|
||||||
u32 back = style->main.back_color;
|
item_rect.x1 += rect_f32.x0 - scroll.scroll_x;
|
||||||
u32 margin = style_get_margin_color(item->activation_level, style);
|
item_rect.y1 += rect_f32.y0 - scroll.scroll_y;
|
||||||
u32 text_color = style->main.default_color;
|
|
||||||
u32 pop_color = style->main.file_info_style.pop2_color;
|
if (rect_opverlap(item_rect, rect_f32)){
|
||||||
i32_Rect item_rect = item->rectangle;
|
switch (item->type){
|
||||||
item_rect.x0 += rect.x0;
|
case UIType_Option:
|
||||||
item_rect.y0 += rect.y0;
|
{
|
||||||
item_rect.x1 += rect.x0;
|
u32 back = style->main.back_color;
|
||||||
item_rect.y1 += rect.y0;
|
u32 margin_color = style_get_margin_color(item->activation_level, style);
|
||||||
i32_Rect inner = get_inner_rect(item_rect, 3);
|
u32 text_color = style->main.default_color;
|
||||||
draw_rectangle(target, inner, back);
|
u32 pop_color = style->main.file_info_style.pop2_color;
|
||||||
draw_margin(target, item_rect, inner, margin);
|
f32_Rect inner = get_inner_rect(item_rect, 3);
|
||||||
i32 x = inner.x0 + 3;
|
draw_rectangle(target, inner, back);
|
||||||
i32 y = inner.y0 + line_height/2 - 1;
|
draw_margin(target, item_rect, inner, margin_color);
|
||||||
x = ceil32(draw_string(system, target, font_id, item->string, x, y, text_color));
|
i32 x = (i32)inner.x0 + 3;
|
||||||
draw_string(system, target, font_id, item->status, x, y, pop_color);
|
i32 y = (i32)inner.y0 + line_height/2 - 1;
|
||||||
}break;
|
x = ceil32(draw_string(system, target, font_id, item->string, x, y, text_color));
|
||||||
|
draw_string(system, target, font_id, item->status, x, y, pop_color);
|
||||||
case UIType_TextField:
|
}break;
|
||||||
{
|
|
||||||
u32 back_color = style->main.margin_color;
|
case UIType_TextField:
|
||||||
u32 text1_color = style->main.default_color;
|
{
|
||||||
u32 text2_color = style->main.file_info_style.pop1_color;
|
u32 back_color = style->main.margin_color;
|
||||||
i32_Rect item_rect = item->rectangle;
|
u32 text1_color = style->main.default_color;
|
||||||
item_rect.x0 += rect.x0;
|
u32 text2_color = style->main.file_info_style.pop1_color;
|
||||||
item_rect.y0 += rect.y0;
|
draw_rectangle(target, item_rect, back_color);
|
||||||
item_rect.x1 += rect.x0;
|
i32 x = (i32)item_rect.x0;
|
||||||
item_rect.y1 += rect.y0;
|
i32 y = (i32)item_rect.y0 + 2;
|
||||||
draw_rectangle(target, item_rect, back_color);
|
x = ceil32(draw_string(system, target, font_id, item->query, x, y, text2_color));
|
||||||
i32 x = item_rect.x0;
|
draw_string(system, target, font_id, item->string, x, y, text1_color);
|
||||||
i32 y = item_rect.y0 + 2;
|
}break;
|
||||||
x = ceil32(draw_string(system, target, font_id, item->query, x, y, text2_color));
|
}
|
||||||
draw_string(system, target, font_id, item->string, x, y, text1_color);
|
|
||||||
}break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue