flexbox_helper.cpp
ftxui/dom/flexbox_helper.hpp
algorithm
cstddef
ftxui/dom/flexbox_config.hpp
utility
vector
ftxui/dom/box_helper.hpp
ftxui/dom/flexbox_config.hpp
ftxui/dom/requirement.hpp
ftxui/screen/box.hpp
ftxui/screen/color.hpp
ftxui/screen/image.hpp
ftxui/screen/pixel.hpp
ftxui/screen/screen.hpp
ftxui/screen/terminal.hpp
ftxui/util/autoreset.hpp
ftxui/dom/box_helper.hpp
src/ftxui/dom/flexbox_helper.cpp
ftxui/dom/flexbox_helper.hpp
algorithm
cstddef
cstdint
functional
string
utility
vector
ftxui
ftxui::flexbox_helper

    //Copyright2021ArthurSonzogni.Allrightsreserved.
    //UseofthissourcecodeisgovernedbytheMITlicensethatcanbefoundin
    //theLICENSEfile.
    #include"ftxui/dom/flexbox_helper.hpp"

    #include<algorithm>//formax,min
    #include<cstddef>//forsize_t
    #include<ftxui/dom/flexbox_config.hpp>//forFlexboxConfig,FlexboxConfig::Direction,FlexboxConfig::AlignContent,FlexboxConfig::JustifyContent,FlexboxConfig::Wrap,FlexboxConfig::Direction::RowInversed,FlexboxConfig::AlignItems,FlexboxConfig::Direction::Row,FlexboxConfig::Direction::Column,FlexboxConfig::Direction::ColumnInversed,FlexboxConfig::Wrap::WrapInversed,FlexboxConfig::AlignContent::Stretch,FlexboxConfig::JustifyContent::Stretch,FlexboxConfig::Wrap::Wrap,FlexboxConfig::AlignContent::Center,FlexboxConfig::AlignContent::FlexEnd,FlexboxConfig::AlignContent::FlexStart,FlexboxConfig::AlignContent::SpaceAround,FlexboxConfig::AlignContent::SpaceBetween,FlexboxConfig::AlignContent::SpaceEvenly,FlexboxConfig::AlignItems::Center,FlexboxConfig::AlignItems::FlexEnd,FlexboxConfig::AlignItems::FlexStart,FlexboxConfig::AlignItems::Stretch,FlexboxConfig::JustifyContent::Center,FlexboxConfig::JustifyContent::FlexEnd,FlexboxConfig::JustifyContent::FlexStart,FlexboxConfig::JustifyContent::SpaceAround,FlexboxConfig::JustifyContent::SpaceBetween,FlexboxConfig::JustifyContent::SpaceEvenly,FlexboxConfig::Wrap::NoWrap
    #include<utility>//forswap,move
    #include<vector>

    #include"ftxui/dom/box_helper.hpp"//forElement,Compute

    namespaceftxui::flexbox_helper{

    namespace{
    voidSymmetryXY(FlexboxConfig&c){
    std::swap(c.gap_x,c.gap_y);
    switch(c.direction){
    caseFlexboxConfig::Direction::Row:
    c.direction=FlexboxConfig::Direction::Column;
    break;
    caseFlexboxConfig::Direction::RowInversed:
    c.direction=FlexboxConfig::Direction::ColumnInversed;
    break;
    caseFlexboxConfig::Direction::Column:
    c.direction=FlexboxConfig::Direction::Row;
    break;
    caseFlexboxConfig::Direction::ColumnInversed:
    c.direction=FlexboxConfig::Direction::RowInversed;
    break;
    }
    }

    voidSymmetryX(FlexboxConfig&c){
    switch(c.direction){
    caseFlexboxConfig::Direction::Row:
    c.direction=FlexboxConfig::Direction::RowInversed;
    break;
    caseFlexboxConfig::Direction::RowInversed:
    c.direction=FlexboxConfig::Direction::Row;
    break;
    default:
    break;
    }
    }

    voidSymmetryY(FlexboxConfig&c){
    switch(c.wrap){
    caseFlexboxConfig::Wrap::NoWrap:
    break;
    caseFlexboxConfig::Wrap::Wrap:
    c.wrap=FlexboxConfig::Wrap::WrapInversed;
    break;
    caseFlexboxConfig::Wrap::WrapInversed:
    c.wrap=FlexboxConfig::Wrap::Wrap;
    break;
    }
    }

    voidSymmetryXY(Global&g){
    SymmetryXY(g.config);
    std::swap(g.size_x,g.size_y);
    for(auto&b:g.blocks){
    std::swap(b.min_size_x,b.min_size_y);
    std::swap(b.flex_grow_x,b.flex_grow_y);
    std::swap(b.flex_shrink_x,b.flex_shrink_y);
    std::swap(b.x,b.y);
    std::swap(b.dim_x,b.dim_y);
    }
    for(auto&l:g.lines){
    std::swap(l.x,l.y);
    std::swap(l.dim_x,l.dim_y);
    }
    }

    voidSymmetryX(Global&g){
    SymmetryX(g.config);
    for(auto&b:g.blocks){
    b.x=g.size_x-b.x-b.dim_x;
    }
    for(auto&l:g.lines){
    l.x=g.size_x-l.x-l.dim_x;
    }
    }

    voidSymmetryY(Global&g){
    SymmetryY(g.config);
    for(auto&b:g.blocks){
    b.y=g.size_y-b.y-b.dim_y;
    }
    for(auto&l:g.lines){
    l.y=g.size_y-l.y-l.dim_y;
    }
    }

    voidSetX(Global&global){
    for(auto&line:global.lines){
    std::vector<box_helper::Element>elements;
    elements.reserve(line.blocks.size());
    for(auto*block:line.blocks){
    box_helper::Elementelement;
    element.min_size=block->min_size_x;
    element.flex_grow=
    block->flex_grow_x!=0||global.config.justify_content==
    FlexboxConfig::JustifyContent::Stretch
    ?1
    :0;
    element.flex_shrink=block->flex_shrink_x;
    elements.push_back(element);
    }

    box_helper::Compute(
    &elements,
    global.size_x-global.config.gap_x*(int(line.blocks.size())-1));

    intx=0;
    for(size_ti=0;i<line.blocks.size();++i){
    line.blocks[i]->x=x;
    line.blocks[i]->dim_x=elements[i].size;
    x+=elements[i].size;
    x+=global.config.gap_x;
    }
    }

    for(auto&line:global.lines){
    line.x=0;
    line.dim_x=global.size_x;
    }
    }

    //NOLINTNEXTLINE(readability-function-cognitive-complexity)
    voidSetY(Global&g){
    std::vector<box_helper::Element>elements;
    elements.reserve(g.lines.size());
    for(auto&line:g.lines){
    box_helper::Elementelement;
    element.flex_shrink=line.blocks.front()->flex_shrink_y;
    element.flex_grow=line.blocks.front()->flex_grow_y;
    for(auto*block:line.blocks){
    element.min_size=std::max(element.min_size,block->min_size_y);
    element.flex_shrink=std::min(element.flex_shrink,block->flex_shrink_y);
    element.flex_grow=std::min(element.flex_grow,block->flex_grow_y);
    }
    elements.push_back(element);
    }

    //box_helper::Compute(&elements,g.size_y);
    box_helper::Compute(&elements,10000);//NOLINT

    //[Align-content]
    std::vector<int>ys(elements.size());
    inty=0;
    for(size_ti=0;i<elements.size();++i){
    ys[i]=y;
    y+=elements[i].size;
    y+=g.config.gap_y;
    }
    intremaining_space=std::max(0,g.size_y-y);
    switch(g.config.align_content){
    caseFlexboxConfig::AlignContent::FlexStart:{
    break;
    }

    caseFlexboxConfig::AlignContent::FlexEnd:{
    for(size_ti=0;i<ys.size();++i){//NOLINT
    ys[i]+=remaining_space;
    }
    break;
    }

    caseFlexboxConfig::AlignContent::Center:{
    for(size_ti=0;i<ys.size();++i){//NOLINT
    ys[i]+=remaining_space/2;
    }
    break;
    }

    caseFlexboxConfig::AlignContent::Stretch:{
    for(inti=static_cast<int>(ys.size())-1;i>=0;--i){//NOLINT
    constintshifted=remaining_space*(i+0)/(i+1);
    ys[i]+=shifted;
    constintconsumed=remaining_space-shifted;
    elements[i].size+=consumed;
    remaining_space-=consumed;
    }
    break;
    }

    caseFlexboxConfig::AlignContent::SpaceBetween:{
    for(inti=static_cast<int>(ys.size())-1;i>=1;--i){//NOLINT
    ys[i]+=remaining_space;
    remaining_space=remaining_space*(i-1)/i;
    }
    break;
    }

    caseFlexboxConfig::AlignContent::SpaceAround:{
    for(inti=static_cast<int>(ys.size())-1;i>=0;--i){//NOLINT
    ys[i]+=remaining_space*(2*i+1)/(2*i+2);
    remaining_space=remaining_space*(2*i)/(2*i+2);
    }
    break;
    }

    caseFlexboxConfig::AlignContent::SpaceEvenly:{
    for(inti=static_cast<int>(ys.size())-1;i>=0;--i){//NOLINT
    ys[i]+=remaining_space*(i+1)/(i+2);
    remaining_space=remaining_space*(i+1)/(i+2);
    }
    break;
    }
    }

    //[Alignitems]
    for(size_ti=0;i<g.lines.size();++i){
    auto&element=elements[i];
    for(auto*block:g.lines[i].blocks){
    constboolstretch=
    block->flex_grow_y!=0||
    g.config.align_content==FlexboxConfig::AlignContent::Stretch;
    constintsize=
    stretch?element.size:std::min(element.size,block->min_size_y);
    switch(g.config.align_items){
    caseFlexboxConfig::AlignItems::FlexStart:{
    block->y=ys[i];
    block->dim_y=size;
    break;
    }

    caseFlexboxConfig::AlignItems::Center:{
    block->y=ys[i]+(element.size-size)/2;
    block->dim_y=size;
    break;
    }

    caseFlexboxConfig::AlignItems::FlexEnd:{
    block->y=ys[i]+element.size-size;
    block->dim_y=size;
    break;
    }

    caseFlexboxConfig::AlignItems::Stretch:{
    block->y=ys[i];
    block->dim_y=element.size;
    break;
    }
    }
    }
    }

    ys.push_back(g.size_y);
    for(size_ti=0;i<g.lines.size();++i){
    g.lines[i].y=ys[i];
    g.lines[i].dim_y=ys[i+1]-ys[i];
    }
    }

    voidJustifyContent(Global&g){
    for(auto&line:g.lines){
    Block*last=line.blocks.back();
    intremaining_space=g.size_x-last->x-last->dim_x;
    switch(g.config.justify_content){
    caseFlexboxConfig::JustifyContent::FlexStart:
    caseFlexboxConfig::JustifyContent::Stretch:
    break;

    caseFlexboxConfig::JustifyContent::FlexEnd:{
    for(auto*block:line.blocks){
    block->x+=remaining_space;
    }
    break;
    }

    caseFlexboxConfig::JustifyContent::Center:{
    for(auto*block:line.blocks){
    block->x+=remaining_space/2;
    }
    break;
    }

    caseFlexboxConfig::JustifyContent::SpaceBetween:{
    for(inti=(int)line.blocks.size()-1;i>=1;--i){
    line.blocks[i]->x+=remaining_space;
    remaining_space=remaining_space*(i-1)/i;
    }
    break;
    }

    caseFlexboxConfig::JustifyContent::SpaceAround:{
    for(inti=(int)line.blocks.size()-1;i>=0;--i){
    line.blocks[i]->x+=remaining_space*(2*i+1)/(2*i+2);
    remaining_space=remaining_space*(2*i)/(2*i+2);
    }
    break;
    }

    caseFlexboxConfig::JustifyContent::SpaceEvenly:{
    for(inti=(int)line.blocks.size()-1;i>=0;--i){
    line.blocks[i]->x+=remaining_space*(i+1)/(i+2);
    remaining_space=remaining_space*(i+1)/(i+2);
    }
    break;
    }
    }
    }
    }

    voidCompute1(Global&global);
    voidCompute2(Global&global);
    voidCompute3(Global&global);

    voidCompute1(Global&global){
    if(global.config.direction==FlexboxConfig::Direction::RowInversed){
    SymmetryX(global);
    Compute2(global);
    SymmetryX(global);
    return;
    }
    Compute2(global);
    }

    voidCompute2(Global&global){
    if(global.config.wrap==FlexboxConfig::Wrap::WrapInversed){
    SymmetryY(global);
    Compute3(global);
    SymmetryY(global);
    return;
    }
    Compute3(global);
    }

    voidCompute3(Global&global){
    //Step1:Layouteveryelementsintorows:
    {
    Lineline;
    intx=0;
    for(auto&block:global.blocks){
    //Doesitfittheendoftherow?
    //No?Thenweneedtostartanewone:
    if(x+block.min_size_x>global.size_x){
    x=0;
    if(!line.blocks.empty()){
    global.lines.push_back(std::move(line));
    }
    line=Line();
    }

    block.line=static_cast<int>(global.lines.size());
    block.line_position=static_cast<int>(line.blocks.size());
    line.blocks.push_back(&block);
    x+=block.min_size_x+global.config.gap_x;
    }
    if(!line.blocks.empty()){
    global.lines.push_back(std::move(line));
    }
    }

    //Step2:SetpositionsontheXaxis.
    SetX(global);
    JustifyContent(global);//Distributeremainingspace.

    //Step3:SetpositionsontheYaxis.
    SetY(global);
    }

    }//namespace

    voidCompute(Global&global){
    if(global.config.direction==FlexboxConfig::Direction::Column||
    global.config.direction==FlexboxConfig::Direction::ColumnInversed){
    SymmetryXY(global);
    Compute1(global);
    SymmetryXY(global);
    return;
    }
    Compute1(global);
    }

    }//namespaceftxui::flexbox_helper