flexbox.cpp
algorithm
cstddef
memory
tuple
utility
vector
ftxui/dom/elements.hpp
ftxui/dom/flexbox_config.hpp
ftxui/dom/flexbox_helper.hpp
ftxui/dom/node.hpp
ftxui/dom/requirement.hpp
ftxui/dom/selection.hpp
ftxui/screen/box.hpp
ftxui/dom/canvas.hpp
ftxui/dom/deprecated.hpp
ftxui/dom/direction.hpp
ftxui/dom/elements.hpp
ftxui/dom/flexbox_config.hpp
ftxui/dom/linear_gradient.hpp
ftxui/dom/node.hpp
ftxui/dom/requirement.hpp
ftxui/dom/selection.hpp
ftxui/screen/box.hpp
ftxui/screen/color.hpp
ftxui/screen/image.hpp
ftxui/screen/pixel.hpp
ftxui/screen/screen.hpp
ftxui/screen/string.hpp
ftxui/screen/terminal.hpp
ftxui/util/autoreset.hpp
ftxui/util/ref.hpp
src/ftxui/dom/flexbox.cpp
ftxui/dom/flexbox_helper.hpp
algorithm
cstddef
cstdint
ftxui/dom/take_any_args.hpp
functional
memory
optional
sstream
string
tuple
unordered_map
utility
variant
vector
ftxui

    //Copyright2020ArthurSonzogni.Allrightsreserved.
    //UseofthissourcecodeisgovernedbytheMITlicensethatcanbefoundin
    //theLICENSEfile.
    #include<algorithm>//formin,max
    #include<cstddef>//forsize_t
    #include<memory>//for__shared_ptr_access,shared_ptr,allocator_traits<>::value_type,make_shared
    #include<tuple>//forignore
    #include<utility>//formove,swap
    #include<vector>//forvector

    #include"ftxui/dom/elements.hpp"//forElement,Elements,flexbox,hflow,vflow
    #include"ftxui/dom/flexbox_config.hpp"//forFlexboxConfig,FlexboxConfig::Direction,FlexboxConfig::Direction::Column,FlexboxConfig::AlignContent,FlexboxConfig::Direction::ColumnInversed,FlexboxConfig::Direction::Row,FlexboxConfig::JustifyContent,FlexboxConfig::Wrap,FlexboxConfig::AlignContent::FlexStart,FlexboxConfig::Direction::RowInversed,FlexboxConfig::JustifyContent::FlexStart,FlexboxConfig::Wrap::Wrap
    #include"ftxui/dom/flexbox_helper.hpp"//forBlock,Global,Compute
    #include"ftxui/dom/node.hpp"//forNode,Elements,Node::Status
    #include"ftxui/dom/requirement.hpp"//forRequirement
    #include"ftxui/dom/selection.hpp"//forSelection
    #include"ftxui/screen/box.hpp"//forBox

    namespaceftxui{

    namespace{
    voidNormalize(FlexboxConfig::Direction&direction){
    switch(direction){
    caseFlexboxConfig::Direction::Row:
    caseFlexboxConfig::Direction::RowInversed:{
    direction=FlexboxConfig::Direction::Row;
    }break;
    caseFlexboxConfig::Direction::Column:
    caseFlexboxConfig::Direction::ColumnInversed:{
    direction=FlexboxConfig::Direction::Column;
    }break;
    }
    }

    voidNormalize(FlexboxConfig::AlignContent&align_content){
    align_content=FlexboxConfig::AlignContent::FlexStart;
    }

    voidNormalize(FlexboxConfig::JustifyContent&justify_content){
    justify_content=FlexboxConfig::JustifyContent::FlexStart;
    }

    voidNormalize(FlexboxConfig::Wrap&wrap){
    wrap=FlexboxConfig::Wrap::Wrap;
    }

    FlexboxConfigNormalize(FlexboxConfigconfig){
    Normalize(config.direction);
    Normalize(config.wrap);
    Normalize(config.justify_content);
    Normalize(config.align_content);
    returnconfig;
    }

    classFlexbox:publicNode{
    public:
    Flexbox(Elementschildren,FlexboxConfigconfig)
    :Node(std::move(children)),
    config_(config),
    config_normalized_(Normalize(config)){
    requirement_.flex_grow_x=1;
    requirement_.flex_grow_y=0;

    if(IsColumnOriented()){
    std::swap(requirement_.flex_grow_x,requirement_.flex_grow_y);
    }
    }

    boolIsColumnOriented()const{
    returnconfig_.direction==FlexboxConfig::Direction::Column||
    config_.direction==FlexboxConfig::Direction::ColumnInversed;
    }

    voidLayout(flexbox_helper::Global&global,
    boolcompute_requirement=false){
    global.blocks.reserve(children_.size());
    for(auto&child:children_){
    flexbox_helper::Blockblock;
    block.min_size_x=child->requirement().min_x;
    block.min_size_y=child->requirement().min_y;
    if(!compute_requirement){
    block.flex_grow_x=child->requirement().flex_grow_x;
    block.flex_grow_y=child->requirement().flex_grow_y;
    block.flex_shrink_x=child->requirement().flex_shrink_x;
    block.flex_shrink_y=child->requirement().flex_shrink_y;
    }
    global.blocks.push_back(block);
    }

    flexbox_helper::Compute(global);
    }

    voidComputeRequirement()override{
    requirement_=Requirement{};
    for(auto&child:children_){
    child->ComputeRequirement();
    }
    global_=flexbox_helper::Global();
    global_.config=config_normalized_;
    if(IsColumnOriented()){
    global_.size_x=100000;//NOLINT
    global_.size_y=asked_;
    }else{
    global_.size_x=asked_;
    global_.size_y=100000;//NOLINT
    }
    Layout(global_,true);

    if(global_.blocks.empty()){
    return;
    }

    //Computetheunionofalltheblocks:
    Boxbox;
    box.x_min=global_.blocks[0].x;
    box.y_min=global_.blocks[0].y;
    box.x_max=global_.blocks[0].x+global_.blocks[0].dim_x;
    box.y_max=global_.blocks[0].y+global_.blocks[0].dim_y;
    for(auto&b:global_.blocks){
    box.x_min=std::min(box.x_min,b.x);
    box.y_min=std::min(box.y_min,b.y);
    box.x_max=std::max(box.x_max,b.x+b.dim_x);
    box.y_max=std::max(box.y_max,b.y+b.dim_y);
    }
    requirement_.min_x=box.x_max-box.x_min;
    requirement_.min_y=box.y_max-box.y_min;

    //Findtheselection:
    for(size_ti=0;i<children_.size();++i){
    if(requirement_.focused.Prefer(children_[i]->requirement().focused)){
    requirement_.focused=children_[i]->requirement().focused;
    //Shift|focused.box|accordingtoitspositioninsidethiscomponent:
    auto&b=global_.blocks[i];
    requirement_.focused.box.Shift(b.x,b.y);
    requirement_.focused.box=
    Box::Intersection(requirement_.focused.box,box);
    }
    }
    }

    voidSetBox(Boxbox)override{
    Node::SetBox(box);

    constintasked_previous=asked_;
    asked_=std::min(asked_,IsColumnOriented()?box.y_max-box.y_min+1
    :box.x_max-box.x_min+1);
    need_iteration_=(asked_!=asked_previous);

    flexbox_helper::Globalglobal;
    global.config=config_;
    global.size_x=box.x_max-box.x_min+1;
    global.size_y=box.y_max-box.y_min+1;
    Layout(global);

    for(size_ti=0;i<children_.size();++i){
    auto&child=children_[i];
    auto&b=global.blocks[i];

    Boxchildren_box;
    children_box.x_min=box.x_min+b.x;
    children_box.y_min=box.y_min+b.y;
    children_box.x_max=box.x_min+b.x+b.dim_x-1;
    children_box.y_max=box.y_min+b.y+b.dim_y-1;

    constBoxintersection=Box::Intersection(children_box,box);
    child->SetBox(intersection);

    need_iteration_|=(intersection!=children_box);
    }
    }

    voidSelect(Selection&selection)override{
    //IfthisNodebox_doesn'tintersectwiththeselection,thenno
    //selection.
    if(Box::Intersection(selection.GetBox(),box_).IsEmpty()){
    return;
    }

    Selectionselection_lines=IsColumnOriented()
    ?selection.SaturateVertical(box_)
    :selection.SaturateHorizontal(box_);

    size_ti=0;
    for(auto&line:global_.lines){
    Boxbox;
    box.x_min=box_.x_min+line.x;
    box.x_max=box_.x_min+line.x+line.dim_x-1;
    box.y_min=box_.y_min+line.y;
    box.y_max=box_.y_min+line.y+line.dim_y-1;

    //Ifthelineboxdoesn'tintersectwiththeselection,thenno
    //selection.
    if(Box::Intersection(selection.GetBox(),box).IsEmpty()){
    continue;
    }

    Selectionselection_line=IsColumnOriented()
    ?selection_lines.SaturateHorizontal(box)
    :selection_lines.SaturateVertical(box);

    for(auto&block:line.blocks){
    std::ignore=block;
    children_[i]->Select(selection_line);
    i++;
    }
    }
    }

    voidCheck(Status*status)override{
    for(auto&child:children_){
    child->Check(status);
    }

    if(status->iteration==0){
    asked_=6000;//NOLINT
    need_iteration_=true;
    }

    status->need_iteration|=need_iteration_;
    }

    intasked_=6000;//NOLINT
    boolneed_iteration_=true;
    constFlexboxConfigconfig_;
    constFlexboxConfigconfig_normalized_;
    flexbox_helper::Globalglobal_;
    };

    }//namespace

    ///@briefAcontainerdisplayingelementsonrow/columnsandcapableof
    ///wrappingonthenextcolumn/rowwhenfull.
    ///@paramchildrenTheelementsinthecontainer
    ///@paramconfigTheoption
    ///@returnThecontainer.
    ///
    ///####Example
    ///
    ///```cpp
    ///flexbox({
    ///text("element1"),
    ///text("element2"),
    ///text("element3"),
    ///},FlexboxConfig()
    //.Set(FlexboxConfig::Direction::Column)
    //.Set(FlexboxConfig::Wrap::WrapInversed)
    //.SetGapMainAxis(1)
    //.SetGapCrossAxis(1)
    //)
    ///```
    Elementflexbox(Elementschildren,FlexboxConfigconfig){
    returnstd::make_shared<Flexbox>(std::move(children),config);
    }

    ///@briefAcontainerdisplayingelementsinrowsfromlefttoright.When
    ///filled,itstartsonanewrowbelow.
    ///@paramchildrenTheelementsinthecontainer
    ///@returnThecontainer.
    ///
    ///####Example
    ///
    ///```cpp
    ///hflow({
    ///text("element1"),
    ///text("element2"),
    ///text("element3"),
    ///});
    ///```
    Elementhflow(Elementschildren){
    returnflexbox(std::move(children),FlexboxConfig());
    }

    ///@briefAcontainerdisplayingelementsinrowsfromtoptobottom.When
    ///filled,itstartsonanewcolumnsontheright.
    ///filled,itstartsonanewrow.
    ///isfull,itstartsanewrow.
    ///@paramchildrenTheelementsinthecontainer
    ///@returnThecontainer.
    ///
    ///####Example
    ///
    ///```cpp
    ///vflow({
    ///text("element1"),
    ///text("element2"),
    ///text("element3"),
    ///});
    ///```
    Elementvflow(Elementschildren){
    returnflexbox(std::move(children),
    FlexboxConfig().Set(FlexboxConfig::Direction::Column));
    }

    }//namespaceftxui