panel division is now based on lerp position

This commit is contained in:
Allen Webster 2016-06-28 17:12:17 -04:00
parent 9240b4a457
commit ee9ef5d6aa
2 changed files with 173 additions and 84 deletions

51
4ed.cpp
View File

@ -20,7 +20,7 @@ enum App_State{
struct App_State_Resizing{
Panel_Divider *divider;
i32 min, max;
f32 min, max;
};
struct CLI_Process{
@ -797,9 +797,14 @@ COMMAND_DECL(open_panel_vsplit){
panel2->screen_region = panel1->screen_region;
panel2->full.x0 = split.divider->pos;
i32 x_pos = ROUND32(lerp((f32)panel1->full.x0,
split.divider->pos,
(f32)panel1->full.x1)
);
panel2->full.x0 = x_pos;
panel2->full.x1 = panel1->full.x1;
panel1->full.x1 = split.divider->pos;
panel1->full.x1 = x_pos;
panel_fix_internal_area(panel1);
panel_fix_internal_area(panel2);
@ -823,9 +828,14 @@ COMMAND_DECL(open_panel_hsplit){
panel2->screen_region = panel1->screen_region;
panel2->full.y0 = split.divider->pos;
i32 y_pos = ROUND32(lerp((f32)panel1->full.y0,
split.divider->pos,
(f32)panel1->full.y1)
);
panel2->full.y0 = y_pos;
panel2->full.y1 = panel1->full.y1;
panel1->full.y1 = split.divider->pos;
panel1->full.y1 = y_pos;
panel_fix_internal_area(panel1);
panel_fix_internal_area(panel2);
@ -2697,26 +2707,22 @@ App_Step_Sig(app_step){
Divider_And_ID div = layout_get_divider(&models->layout, mouse_divider_id);
vars->resizing.divider = div.divider;
i32 min, max;
f32 min = 0;
f32 max = 0;
{
i32 mid, MIN, MAX;
mid = div.divider->pos;
f32 mid = layout_get_position(&models->layout, mouse_divider_id);
if (mouse_divider_vertical){
MIN = 0;
MAX = MIN + models->layout.full_width;
max = (f32)models->layout.full_width;
}
else{
MIN = 0;
MAX = MIN + models->layout.full_height;
max = (f32)models->layout.full_height;
}
min = MIN;
max = MAX;
i32 divider_id = div.id;
do{
Divider_And_ID other_div = layout_get_divider(&models->layout, divider_id);
b32 divider_match = (other_div.divider->v_divider == mouse_divider_vertical);
i32 pos = other_div.divider->pos;
f32 pos = layout_get_position(&models->layout, divider_id);
if (divider_match && pos > mid && pos < max){
max = pos;
}
@ -2732,9 +2738,10 @@ App_Step_Sig(app_step){
divider_stack[top++] = div.id;
while (top > 0){
Divider_And_ID other_div = layout_get_divider(&models->layout, divider_stack[--top]);
--top;
Divider_And_ID other_div = layout_get_divider(&models->layout, divider_stack[top]);
b32 divider_match = (other_div.divider->v_divider == mouse_divider_vertical);
i32 pos = other_div.divider->pos;
f32 pos = layout_get_position(&models->layout, divider_stack[top]);
if (divider_match && pos > mid && pos < max){
max = pos;
}
@ -2752,8 +2759,8 @@ App_Step_Sig(app_step){
end_temp_memory(temp);
}
vars->resizing.min = min;
vars->resizing.max = max;
vars->resizing.min = 0.f;
vars->resizing.max = 1.f;
}
}break;
@ -2761,12 +2768,14 @@ App_Step_Sig(app_step){
{
if (input->mouse.l){
Panel_Divider *divider = vars->resizing.divider;
i32 pos = 0;
if (divider->v_divider){
divider->pos = mx;
pos = clamp(0, mx, models->layout.full_width);
}
else{
divider->pos = my;
pos = clamp(0, my, models->layout.full_height);
}
divider->pos = layout_compute_position(&models->layout, divider, pos);
if (divider->pos < vars->resizing.min){
divider->pos = vars->resizing.min;

View File

@ -15,7 +15,7 @@ struct Panel_Divider{
i32 which_child;
i32 child1, child2;
b32 v_divider;
i32 pos;
f32 pos;
};
struct Screen_Region{
@ -188,11 +188,13 @@ layout_split_panel(Editing_Layout *layout, Panel *panel, b32 vertical){
div.divider->which_child = panel->which_child;
if (vertical){
div.divider->v_divider = 1;
div.divider->pos = (panel->full.x0 + panel->full.x1) / 2;
//div.divider->pos = (panel->full.x0 + panel->full.x1) / 2;
div.divider->pos = 0.5f;
}
else{
div.divider->v_divider = 0;
div.divider->pos = (panel->full.y0 + panel->full.y1) / 2;
//div.divider->pos = (panel->full.y0 + panel->full.y1) / 2;
div.divider->pos = 0.5f;
}
new_panel = layout_alloc_panel(layout);
@ -215,60 +217,107 @@ panel_fix_internal_area(Panel *panel){
panel->inner.y1 = panel->full.y1 - panel->b_margin;
}
internal i32_Rect
layout_get_rect(Editing_Layout *layout, i32 id, i32 which_child){
i32 divider_chain[16];
i32 chain_count = 0;
Panel_Divider *dividers = layout->dividers;
Panel_Divider *original_div = dividers + id;
i32 root = layout->root;
Assert(0 <= id && id <= layout->panel_max_count - 1);
divider_chain[chain_count++] = id;
for (;id != root;){
Panel_Divider *div = dividers + id;
id = div->parent;
divider_chain[chain_count++] = id;
}
i32_Rect r = i32R(0, 0, layout->full_width, layout->full_height);
for (i32 i = chain_count-1; i > 0; --i){
Panel_Divider *div = dividers + divider_chain[i];
if (div->v_divider){
if (div->child1 == divider_chain[i-1]){
r.x1 = ROUND32(lerp((f32)r.x0,
div->pos,
(f32)r.x1));
}
else{
r.x0 = ROUND32(lerp((f32)r.x0,
div->pos,
(f32)r.x1));
}
}
else{
if (div->child1 == divider_chain[i-1]){
r.y1 = ROUND32(lerp((f32)r.y0,
div->pos,
(f32)r.y1));
}
else{
r.y0 = ROUND32(lerp((f32)r.y0,
div->pos,
(f32)r.y1));
}
}
}
switch (which_child){
case 1:
{
if (original_div->v_divider){
r.x0 = ROUND32(lerp((f32)r.x0,
original_div->pos,
(f32)r.x1));
}
else{
r.y0 = ROUND32(lerp((f32)r.y0,
original_div->pos,
(f32)r.y1));
}
}break;
case -1:
{
if (original_div->v_divider){
r.x1 = ROUND32(lerp((f32)r.x0,
original_div->pos,
(f32)r.x1));
}
else{
r.y1 = ROUND32(lerp((f32)r.y0,
original_div->pos,
(f32)r.y1));
}
}break;
}
return(r);
}
internal i32_Rect
layout_get_panel_rect(Editing_Layout *layout, Panel *panel){
Assert(layout->panel_count > 1);
i32_Rect r = layout_get_rect(layout, panel->parent, panel->which_child);
return(r);
}
internal void
layout_fix_all_panels(Editing_Layout *layout){
Panel *panel;
Panel_Divider *dividers = layout->dividers;
Panel_Divider *dividers = layout->dividers; AllowLocal(dividers);
i32 panel_count = layout->panel_count;
i32_Rect r;
i32 pos, which_child, action;
Divider_And_ID div;
if (panel_count > 1){
for (panel = layout->used_sentinel.next;
panel != &layout->used_sentinel;
panel = panel->next){
r.x0 = 0;
r.x1 = r.x0 + layout->full_width;
r.y0 = 0;
r.y1 = r.y0 + layout->full_height;
which_child = panel->which_child;
div.id = panel->parent;
for (;;){
Assert(div.id != -1);
div.divider = dividers + div.id;
pos = div.divider->pos;
action = (div.divider->v_divider << 1) | (which_child > 0);
switch (action){
case 0: // v_divider : 0, which_child : -1
if (pos < r.y1) r.y1 = pos;
break;
case 1: // v_divider : 0, which_child : 1
if (pos > r.y0) r.y0 = pos;
break;
case 2: // v_divider : 1, which_child : -1
if (pos < r.x1) r.x1 = pos;
break;
case 3: // v_divider : 1, which_child : 1
if (pos > r.x0) r.x0 = pos;
break;
}
if (div.id != layout->root){
div.id = div.divider->parent;
which_child = div.divider->which_child;
}
else{
break;
}
}
panel->full = r;
panel != &layout->used_sentinel;
panel = panel->next){
panel->full = layout_get_panel_rect(layout, panel);
panel_fix_internal_area(panel);
}
}
@ -289,23 +338,17 @@ layout_refit(Editing_Layout *layout, i32 prev_width, i32 prev_height){
Panel_Divider *dividers = layout->dividers;
i32 max = layout->panel_max_count - 1;
f32 h_ratio, v_ratio;
Panel_Divider *divider = dividers;
i32 i;
if (layout->panel_count > 1){
Assert(prev_width != 0 && prev_height != 0);
h_ratio = ((f32)layout->full_width) / prev_width;
v_ratio = ((f32)layout->full_height) / prev_height;
for (i = 0; i < max; ++i, ++divider){
for (i32 i = 0; i < max; ++i, ++divider){
if (divider->v_divider){
divider->pos = ROUND32((divider->pos) * h_ratio);
divider->pos = divider->pos;
}
else{
divider->pos = ROUND32((divider->pos) * v_ratio);
divider->pos = divider->pos;
}
}
}
@ -313,5 +356,42 @@ layout_refit(Editing_Layout *layout, i32 prev_width, i32 prev_height){
layout_fix_all_panels(layout);
}
internal f32
layout_get_position(Editing_Layout *layout, i32 id){
Panel_Divider *dividers = layout->dividers;
Panel_Divider *original_div = dividers + id;
i32_Rect r = layout_get_rect(layout, id, 0);
f32 pos = 0;
if (original_div->v_divider){
pos = lerp((f32)r.x0, original_div->pos, (f32)r.x1);
}
else{
pos = lerp((f32)r.y0, original_div->pos, (f32)r.y1);
}
return(pos);
}
internal f32
layout_compute_position(Editing_Layout *layout, Panel_Divider *divider, i32 pos){
Panel_Divider *dividers = layout->dividers;
Panel_Divider *original_div = divider;
i32 id = (i32)(divider - dividers);
i32_Rect r = layout_get_rect(layout, id, 0);
f32 l = 0;
if (original_div->v_divider){
l = unlerp((f32)r.x0, (f32)pos, (f32)r.x1);
}
else{
l = unlerp((f32)r.y0, (f32)pos, (f32)r.y1);
}
Assert(0.f <= l && l <= 1.f);
return(l);
}
// BOTTOM