scrolling system at minimal-suckage
parent
3b17899d8e
commit
c877b57f65
|
@ -3504,7 +3504,6 @@ file_step(View *view, i32_Rect region, Input_Summary *user_input, b32 is_active)
|
|||
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);
|
||||
}
|
||||
|
||||
if (file->state.paste_effect.tick_down > 0){
|
||||
|
@ -3594,12 +3593,14 @@ step_file_view(System_Functions *system, View *view, b32 is_active){
|
|||
}
|
||||
}
|
||||
|
||||
gui_start_scrollable(target, view->showing_ui, view->file_scroll, delta);
|
||||
gui_begin_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;
|
||||
|
||||
gui_do_file(target);
|
||||
|
||||
gui_end_scrollable(target);
|
||||
}
|
||||
gui_end_serial_section(target);
|
||||
|
||||
|
@ -3649,7 +3650,7 @@ step_file_view(System_Functions *system, View *view, b32 is_active){
|
|||
gui_do_text_field(target, message, text);
|
||||
|
||||
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);
|
||||
gui_begin_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);
|
||||
|
@ -3677,6 +3678,8 @@ step_file_view(System_Functions *system, View *view, b32 is_active){
|
|||
}
|
||||
full_path.size = r;
|
||||
}
|
||||
|
||||
gui_end_scrollable(target);
|
||||
}break;
|
||||
}break;
|
||||
}
|
||||
|
@ -3703,6 +3706,7 @@ do_input_file_view(System_Functions *system, Exchange *exchange,
|
|||
View *view, i32_Rect rect, b32 is_active, Input_Summary *user_input){
|
||||
|
||||
i32 result = 0;
|
||||
b32 is_file_scroll = 0;
|
||||
|
||||
GUI_Session gui_session;
|
||||
GUI_Header *h;
|
||||
|
@ -3725,14 +3729,12 @@ do_input_file_view(System_Functions *system, Exchange *exchange,
|
|||
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){
|
||||
|
@ -3741,6 +3743,7 @@ do_input_file_view(System_Functions *system, Exchange *exchange,
|
|||
if (file_step(view, gui_session.rect, user_input, is_active)){
|
||||
result = 1;
|
||||
}
|
||||
is_file_scroll = 1;
|
||||
}break;
|
||||
|
||||
case guicom_text_field: break;
|
||||
|
@ -3853,6 +3856,23 @@ do_input_file_view(System_Functions *system, Exchange *exchange,
|
|||
target->hover = {0};
|
||||
}
|
||||
}break;
|
||||
|
||||
case guicom_scrollable_section_end:
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3872,7 +3892,6 @@ do_input_file_view(System_Functions *system, Exchange *exchange,
|
|||
&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;
|
||||
|
@ -4318,14 +4337,12 @@ do_render_file_view(System_Functions *system, Exchange *exchange,
|
|||
|
||||
case guicom_file:
|
||||
{
|
||||
target->push_clip(target, gui_session.clip_rect);
|
||||
if (view->reinit_scrolling){
|
||||
view_reinit_scrolling(view);
|
||||
}
|
||||
if (file && file_is_ready(file)){
|
||||
result = draw_file_loaded(view, gui_session.rect, is_active, target);
|
||||
}
|
||||
target->pop_clip(target);
|
||||
}break;
|
||||
|
||||
case guicom_text_field:
|
||||
|
@ -4412,6 +4429,16 @@ do_render_file_view(System_Functions *system, Exchange *exchange,
|
|||
draw_rectangle(target, box, back);
|
||||
draw_rectangle_outline(target, box, outline);
|
||||
}break;
|
||||
|
||||
case guicom_scrollable_section_begin:
|
||||
{
|
||||
target->push_clip(target, gui_session.absolute_rect);
|
||||
}break;
|
||||
|
||||
case guicom_scrollable_section_end:
|
||||
{
|
||||
target->pop_clip(target);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
291
4ed_gui.cpp
291
4ed_gui.cpp
|
@ -123,6 +123,8 @@ enum GUI_Command_Type{
|
|||
guicom_scrollable_top,
|
||||
guicom_scrollable_slider,
|
||||
guicom_scrollable_bottom,
|
||||
guicom_scrollable_section_begin,
|
||||
guicom_scrollable_section_end,
|
||||
};
|
||||
|
||||
internal b32
|
||||
|
@ -247,16 +249,6 @@ gui_push_string(GUI_Target *target, GUI_Header *h, String s){
|
|||
gui_push_string(target, h, s, 0);
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_begin_top_level(GUI_Target *target){
|
||||
target->push.pos = 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_end_top_level(GUI_Target *target){
|
||||
gui_push_simple_command(target, guicom_null);
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_begin_overlap(GUI_Target *target){
|
||||
gui_push_simple_command(target, guicom_begin_overlap);
|
||||
|
@ -277,6 +269,16 @@ gui_end_serial_section(GUI_Target *target){
|
|||
gui_push_simple_command(target, guicom_end_serial);
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_begin_top_level(GUI_Target *target){
|
||||
target->push.pos = 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_end_top_level(GUI_Target *target){
|
||||
gui_push_simple_command(target, guicom_null);
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_do_top_bar(GUI_Target *target){
|
||||
gui_push_simple_command(target, guicom_top_bar);
|
||||
|
@ -342,15 +344,17 @@ gui_id_scrollbar_bottom(){
|
|||
internal b32
|
||||
gui_get_scroll_vars(GUI_Target *target, u32 scroll_id, GUI_Scroll_Vars *vars_out){
|
||||
b32 result = 0;
|
||||
if (gui_id_eq(target->active, gui_id_scrollbar()) && target->scroll_id == scroll_id){
|
||||
if (target->scroll_id == scroll_id){
|
||||
*vars_out = target->scroll_updated;
|
||||
result = 1;
|
||||
if (gui_id_eq(target->active, gui_id_scrollbar())){
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_start_scrollable(GUI_Target *target, u32 scroll_id, GUI_Scroll_Vars scroll_vars, f32 delta){
|
||||
gui_begin_scrollable(GUI_Target *target, u32 scroll_id, GUI_Scroll_Vars scroll_vars, f32 delta){
|
||||
GUI_Header *h;
|
||||
|
||||
target->delta = delta;
|
||||
|
@ -363,6 +367,12 @@ gui_start_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);
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_end_scrollable(GUI_Target *target){
|
||||
gui_push_simple_command(target, guicom_scrollable_section_end);
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -379,6 +389,10 @@ struct GUI_Session{
|
|||
i32_Rect full_rect;
|
||||
i32_Rect clip_rect;
|
||||
i32_Rect rect;
|
||||
i32_Rect absolute_rect;
|
||||
|
||||
f32 suggested_min_y;
|
||||
f32 suggested_max_y;
|
||||
|
||||
i32 line_height;
|
||||
i32 scroll_bar_w;
|
||||
|
@ -483,6 +497,7 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){
|
|||
GUI_Section *prev_section = 0;
|
||||
GUI_Section *end_section = 0;
|
||||
b32 give_to_user = 0;
|
||||
b32 always_give_to_user = 0;
|
||||
i32_Rect rect = {0};
|
||||
i32 y = 0;
|
||||
i32 end_v = -1;
|
||||
|
@ -495,133 +510,147 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){
|
|||
|
||||
if (!session->is_scrollable) scroll_v = 0;
|
||||
|
||||
if (y - scroll_v < session->full_rect.y1){
|
||||
switch (h->type){
|
||||
case guicom_null: Assert(0); break;
|
||||
switch (h->type){
|
||||
case guicom_null: Assert(0); break;
|
||||
|
||||
case guicom_begin_overlap:
|
||||
++session->t;
|
||||
Assert(session->t < ArrayCount(session->sections));
|
||||
new_section = &session->sections[session->t];
|
||||
new_section->overlapped = 1;
|
||||
new_section->v = y;
|
||||
new_section->max_v = y;
|
||||
break;
|
||||
case guicom_begin_overlap:
|
||||
++session->t;
|
||||
Assert(session->t < ArrayCount(session->sections));
|
||||
new_section = &session->sections[session->t];
|
||||
new_section->overlapped = 1;
|
||||
new_section->v = y;
|
||||
new_section->max_v = y;
|
||||
break;
|
||||
|
||||
case guicom_end_overlap:
|
||||
Assert(session->t > 0);
|
||||
Assert(section->overlapped);
|
||||
prev_section = &session->sections[--session->t];
|
||||
end_v = section->max_v;
|
||||
end_section = prev_section;
|
||||
break;
|
||||
case guicom_end_overlap:
|
||||
Assert(session->t > 0);
|
||||
Assert(section->overlapped);
|
||||
prev_section = &session->sections[--session->t];
|
||||
end_v = section->max_v;
|
||||
end_section = prev_section;
|
||||
break;
|
||||
|
||||
case guicom_begin_serial:
|
||||
++session->t;
|
||||
Assert(session->t < ArrayCount(session->sections));
|
||||
new_section = &session->sections[session->t];
|
||||
new_section->overlapped = 0;
|
||||
new_section->v = y;
|
||||
new_section->max_v = y;
|
||||
break;
|
||||
case guicom_begin_serial:
|
||||
++session->t;
|
||||
Assert(session->t < ArrayCount(session->sections));
|
||||
new_section = &session->sections[session->t];
|
||||
new_section->overlapped = 0;
|
||||
new_section->v = y;
|
||||
new_section->max_v = y;
|
||||
break;
|
||||
|
||||
case guicom_end_serial:
|
||||
Assert(session->t > 0);
|
||||
Assert(!section->overlapped);
|
||||
prev_section = &session->sections[--session->t];
|
||||
end_v = section->max_v;
|
||||
end_section = prev_section;
|
||||
break;
|
||||
case guicom_end_serial:
|
||||
Assert(session->t > 0);
|
||||
Assert(!section->overlapped);
|
||||
prev_section = &session->sections[--session->t];
|
||||
end_v = section->max_v;
|
||||
end_section = prev_section;
|
||||
break;
|
||||
|
||||
case guicom_top_bar:
|
||||
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_top_bar:
|
||||
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_file:
|
||||
give_to_user = 1;
|
||||
rect = gui_layout_top_bottom(session, y, session->full_rect.y1);
|
||||
end_v = rect.y1;
|
||||
end_section = section;
|
||||
scroll_v = 0;
|
||||
break;
|
||||
case guicom_file:
|
||||
give_to_user = 1;
|
||||
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:
|
||||
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_text_field:
|
||||
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_file_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_file_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);
|
||||
give_to_user = 1;
|
||||
rect.x1 = session->full_rect.x1;
|
||||
rect.x0 = rect.x1 - session->scroll_bar_w;
|
||||
rect.y0 = y;
|
||||
rect.y1 = session->full_rect.y1;
|
||||
session->scroll_rect = rect;
|
||||
session->is_scrollable = 1;
|
||||
case guicom_scrollable:
|
||||
Assert(session->is_scrollable == 0);
|
||||
Assert(!section->overlapped);
|
||||
give_to_user = 1;
|
||||
rect.x1 = session->full_rect.x1;
|
||||
rect.x0 = rect.x1 - session->scroll_bar_w;
|
||||
rect.y0 = y;
|
||||
rect.y1 = session->full_rect.y1;
|
||||
session->scroll_rect = rect;
|
||||
session->is_scrollable = 1;
|
||||
|
||||
{
|
||||
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;
|
||||
{
|
||||
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;
|
||||
target->scroll_updated.region = scrollable_rect;
|
||||
}
|
||||
break;
|
||||
|
||||
case guicom_scrollable_top:
|
||||
Assert(session->is_scrollable);
|
||||
Assert(!section->overlapped);
|
||||
give_to_user = 1;
|
||||
gui_scrollbar_top(session->scroll_rect, &rect);
|
||||
scroll_v = 0;
|
||||
break;
|
||||
case guicom_scrollable_top:
|
||||
Assert(session->is_scrollable);
|
||||
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;
|
||||
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_slider:
|
||||
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);
|
||||
scroll_v = 0;
|
||||
break;
|
||||
|
||||
case guicom_scrollable_bottom:
|
||||
Assert(session->is_scrollable);
|
||||
Assert(!section->overlapped);
|
||||
give_to_user = 1;
|
||||
gui_scrollbar_bottom(session->scroll_rect, &rect);
|
||||
scroll_v = 0;
|
||||
break;
|
||||
case guicom_scrollable_bottom:
|
||||
Assert(session->is_scrollable);
|
||||
Assert(!section->overlapped);
|
||||
give_to_user = 1;
|
||||
gui_scrollbar_bottom(session->scroll_rect, &rect);
|
||||
scroll_v = 0;
|
||||
break;
|
||||
|
||||
case guicom_scrollable_section_begin:
|
||||
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);
|
||||
rect = gui_layout_top_bottom(session, y, session->full_rect.y1);
|
||||
end_v = rect.y1;
|
||||
break;
|
||||
|
||||
case guicom_scrollable_section_end:
|
||||
always_give_to_user = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
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){
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
rect.y0 -= scroll_v;
|
||||
rect.y1 -= scroll_v;
|
||||
|
||||
|
@ -637,15 +666,19 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){
|
|||
}
|
||||
else{
|
||||
give_to_user = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_section){
|
||||
gui_section_end_item(end_section, end_v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(give_to_user);
|
||||
if (end_section){
|
||||
gui_section_end_item(end_section, end_v);
|
||||
}
|
||||
|
||||
if (y - scroll_v >= session->full_rect.y1){
|
||||
give_to_user = 0;
|
||||
}
|
||||
|
||||
return(give_to_user || always_give_to_user);
|
||||
}
|
||||
|
||||
#define NextHeader(h) ((GUI_Header*)((char*)(h) + (h)->size))
|
||||
|
|
Loading…
Reference in New Issue