Simplify the requirement struct.

This commit is contained in:
ArthurSonzogni 2020-06-01 16:13:29 +02:00 committed by Arthur Sonzogni
parent 3490d56662
commit 7f7775ba62
15 changed files with 92 additions and 95 deletions

View File

@ -11,23 +11,20 @@ namespace ftxui {
struct Requirement { struct Requirement {
// The required size to fully draw the element. // The required size to fully draw the element.
struct { int min_x = 0;
int x = 0; int min_y = 0;
int y = 0;
} min;
// How much flexibility is given to the component. // How much flexibility is given to the component.
struct { int flex_x = 0;
int x = 0; int flex_y = 0;
int y = 0;
} flex;
// Frame. // Focus management to support the frame/focus/select element.
enum Selection { enum Selection {
NORMAL = 0, NORMAL = 0,
SELECTED = 1, SELECTED = 1,
FOCUSED = 2, FOCUSED = 2,
} selection = NORMAL; };
Selection selection = NORMAL;
Box selected_box; Box selected_box;
}; };

View File

@ -300,7 +300,7 @@ void ScreenInteractive::Draw(Component* component) {
case Dimension::TerminalOutput: case Dimension::TerminalOutput:
document->ComputeRequirement(); document->ComputeRequirement();
dimx = Terminal::Size().dimx; dimx = Terminal::Size().dimx;
dimy = document->requirement().min.y; dimy = document->requirement().min_y;
break; break;
case Dimension::Fullscreen: case Dimension::Fullscreen:
dimx = Terminal::Size().dimx; dimx = Terminal::Size().dimx;
@ -309,8 +309,8 @@ void ScreenInteractive::Draw(Component* component) {
case Dimension::FitComponent: case Dimension::FitComponent:
auto terminal = Terminal::Size(); auto terminal = Terminal::Size();
document->ComputeRequirement(); document->ComputeRequirement();
dimx = std::min(document->requirement().min.x, terminal.dimx); dimx = std::min(document->requirement().min_x, terminal.dimx);
dimy = std::min(document->requirement().min.y, terminal.dimy); dimy = std::min(document->requirement().min_y, terminal.dimy);
break; break;
} }

View File

@ -27,11 +27,11 @@ class Border : public Node {
void ComputeRequirement() override { void ComputeRequirement() override {
Node::ComputeRequirement(); Node::ComputeRequirement();
requirement_ = children[0]->requirement(); requirement_ = children[0]->requirement();
requirement_.min.x += 2; requirement_.min_x += 2;
requirement_.min.y += 2; requirement_.min_y += 2;
if (children.size() == 2) { if (children.size() == 2) {
requirement_.min.x = requirement_.min_x =
std::max(requirement_.min.x, children[1]->requirement().min.x + 2); std::max(requirement_.min_x, children[1]->requirement().min_x + 2);
} }
requirement_.selected_box.x_min++; requirement_.selected_box.x_min++;
requirement_.selected_box.x_max++; requirement_.selected_box.x_max++;

View File

@ -15,16 +15,16 @@ class DBox : public Node {
~DBox() {} ~DBox() {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.min.x = 0; requirement_.min_x = 0;
requirement_.min.y = 0; requirement_.min_y = 0;
requirement_.flex.x = 1; requirement_.flex_x = 1;
requirement_.flex.y = 0; requirement_.flex_y = 0;
for (auto& child : children) { for (auto& child : children) {
child->ComputeRequirement(); child->ComputeRequirement();
requirement_.min.x = requirement_.min_x =
std::max(requirement_.min.x, child->requirement().min.x); std::max(requirement_.min_x, child->requirement().min_x);
requirement_.min.y = requirement_.min_y =
std::max(requirement_.min.y, child->requirement().min.y); std::max(requirement_.min_y, child->requirement().min_y);
if (requirement_.selection < child->requirement().selection) { if (requirement_.selection < child->requirement().selection) {
requirement_.selection = child->requirement().selection; requirement_.selection = child->requirement().selection;

View File

@ -13,14 +13,14 @@ class Flex : public Node {
Flex(Element child) : Node(unpack(std::move(child))) {} Flex(Element child) : Node(unpack(std::move(child))) {}
~Flex() override {} ~Flex() override {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.min.x = 0; requirement_.min_x = 0;
requirement_.min.y = 0; requirement_.min_y = 0;
if (!children.empty()) { if (!children.empty()) {
children[0]->ComputeRequirement(); children[0]->ComputeRequirement();
requirement_ = children[0]->requirement(); requirement_ = children[0]->requirement();
} }
requirement_.flex.x = 1; requirement_.flex_x = 1;
requirement_.flex.y = 1; requirement_.flex_y = 1;
} }
void SetBox(Box box) override { void SetBox(Box box) override {
@ -36,14 +36,14 @@ class NotFlex : public Flex {
NotFlex(Element child) : Flex(std::move(child)) {} NotFlex(Element child) : Flex(std::move(child)) {}
~NotFlex() override {} ~NotFlex() override {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.min.x = 0; requirement_.min_x = 0;
requirement_.min.y = 0; requirement_.min_y = 0;
if (!children.empty()) { if (!children.empty()) {
children[0]->ComputeRequirement(); children[0]->ComputeRequirement();
requirement_ = children[0]->requirement(); requirement_ = children[0]->requirement();
} }
requirement_.flex.x = 0; requirement_.flex_x = 0;
requirement_.flex.y = 0; requirement_.flex_y = 0;
} }
}; };

View File

@ -23,8 +23,8 @@ class Select : public Node {
auto& selected_box = requirement_.selected_box; auto& selected_box = requirement_.selected_box;
selected_box.x_min = 0; selected_box.x_min = 0;
selected_box.y_min = 0; selected_box.y_min = 0;
selected_box.x_max = requirement_.min.x; selected_box.x_max = requirement_.min_x;
selected_box.y_max = requirement_.min.y; selected_box.y_max = requirement_.min_y;
requirement_.selection = Requirement::SELECTED; requirement_.selection = Requirement::SELECTED;
}; };
@ -76,8 +76,8 @@ class Frame : public Node {
int external_dimx = box.x_max - box.x_min; int external_dimx = box.x_max - box.x_min;
int external_dimy = box.y_max - box.y_min; int external_dimy = box.y_max - box.y_min;
int internal_dimx = std::max(requirement_.min.x, external_dimx); int internal_dimx = std::max(requirement_.min_x, external_dimx);
int internal_dimy = std::max(requirement_.min.y, external_dimy); int internal_dimy = std::max(requirement_.min_y, external_dimy);
auto& selected_box = requirement_.selected_box; auto& selected_box = requirement_.selected_box;
int focused_dimx = selected_box.x_max - selected_box.x_min; int focused_dimx = selected_box.x_max - selected_box.x_min;
@ -96,13 +96,13 @@ class Frame : public Node {
// int dx = box.x_max - box.x_min; // int dx = box.x_max - box.x_min;
// int dy = box.y_max - box.y_min; // int dy = box.y_max - box.y_min;
// int cdx = std::min(children[0].requirement().min.x // int cdx = std::min(children[0].requirement().min_x
// Box children_box; // Box children_box;
// children_box.x_min = // children_box.x_min =
// if (box.x_max - box.x_min >= children[0].requirement().min.x && // // if (box.x_max - box.x_min >= children[0].requirement().min_x && //
// box.y_max - box.y_min >= children[0].requirement().min.y) { // box.y_max - box.y_min >= children[0].requirement().min_y) {
// children_[0]->SetBox(box); // children_[0]->SetBox(box);
// dx = 0; // dx = 0;
// dy = 0; // dy = 0;

View File

@ -15,8 +15,8 @@ class Gauge : public Node {
~Gauge() override {} ~Gauge() override {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.flex.x = 1; requirement_.flex_x = 1;
requirement_.min.y = 1; requirement_.min_y = 1;
} }
void Render(Screen& screen) override { void Render(Screen& screen) override {

View File

@ -14,10 +14,10 @@ class Graph : public Node {
~Graph() override {} ~Graph() override {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.flex.x = 1; requirement_.flex_x = 1;
requirement_.flex.y = 1; requirement_.flex_y = 1;
requirement_.min.x = 1; requirement_.min_x = 1;
requirement_.min.y = 1; requirement_.min_y = 1;
} }
void Render(Screen& screen) override { void Render(Screen& screen) override {

View File

@ -15,21 +15,21 @@ class HBox : public Node {
~HBox() {} ~HBox() {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.min.x = 0; requirement_.min_x = 0;
requirement_.min.y = 0; requirement_.min_y = 0;
requirement_.flex.x = 1; requirement_.flex_x = 1;
requirement_.flex.y = 0; requirement_.flex_y = 0;
for (auto& child : children) { for (auto& child : children) {
child->ComputeRequirement(); child->ComputeRequirement();
if (requirement_.selection < child->requirement().selection) { if (requirement_.selection < child->requirement().selection) {
requirement_.selection = child->requirement().selection; requirement_.selection = child->requirement().selection;
requirement_.selected_box = child->requirement().selected_box; requirement_.selected_box = child->requirement().selected_box;
requirement_.selected_box.x_min += requirement_.min.x; requirement_.selected_box.x_min += requirement_.min_x;
requirement_.selected_box.x_max += requirement_.min.x; requirement_.selected_box.x_max += requirement_.min_x;
} }
requirement_.min.x += child->requirement().min.x; requirement_.min_x += child->requirement().min_x;
requirement_.min.y = requirement_.min_y =
std::max(requirement_.min.y, child->requirement().min.y); std::max(requirement_.min_y, child->requirement().min_y);
} }
} }
@ -38,10 +38,10 @@ class HBox : public Node {
int flex_sum = 0; int flex_sum = 0;
for (auto& child : children) for (auto& child : children)
flex_sum += child->requirement().flex.x; flex_sum += child->requirement().flex_x;
int space = box.x_max - box.x_min + 1; int space = box.x_max - box.x_min + 1;
int extra_space = space - requirement_.min.x; int extra_space = space - requirement_.min_x;
int remaining_flex = flex_sum; int remaining_flex = flex_sum;
int remaining_extra_space = extra_space; int remaining_extra_space = extra_space;
@ -51,13 +51,13 @@ class HBox : public Node {
Box child_box = box; Box child_box = box;
child_box.x_min = x; child_box.x_min = x;
child_box.x_max = x + child->requirement().min.x - 1; child_box.x_max = x + child->requirement().min_x - 1;
if (child->requirement().flex.x) { if (child->requirement().flex_x) {
int added_space = remaining_extra_space * child->requirement().flex.x / int added_space = remaining_extra_space * child->requirement().flex_x /
remaining_flex; remaining_flex;
remaining_extra_space -= added_space; remaining_extra_space -= added_space;
remaining_flex -= child->requirement().flex.x; remaining_flex -= child->requirement().flex_x;
child_box.x_max += added_space; child_box.x_max += added_space;
} }
child_box.x_max = std::min(child_box.x_max, box.x_max); child_box.x_max = std::min(child_box.x_max, box.x_max);

View File

@ -15,10 +15,10 @@ class HFlow : public Node {
~HFlow() {} ~HFlow() {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.min.x = 0; requirement_.min_x = 0;
requirement_.min.y = 0; requirement_.min_y = 0;
requirement_.flex.x = 1; requirement_.flex_x = 1;
requirement_.flex.y = 1; requirement_.flex_y = 1;
for (auto& child : children) for (auto& child : children)
child->ComputeRequirement(); child->ComputeRequirement();
} }
@ -35,25 +35,25 @@ class HFlow : public Node {
Requirement requirement = child->requirement(); Requirement requirement = child->requirement();
// Does it fit the end of the row? // Does it fit the end of the row?
if (x + requirement.min.x > box.x_max) { if (x + requirement.min_x > box.x_max) {
// No? Use the next row. // No? Use the next row.
x = box.x_min; x = box.x_min;
y = y_next; y = y_next;
} }
// Does the current row big enough to contain the element? // Does the current row big enough to contain the element?
if (y + requirement.min.y > box.y_max + 1) if (y + requirement.min_y > box.y_max + 1)
break; // No? Ignore the element. break; // No? Ignore the element.
Box children_box; Box children_box;
children_box.x_min = x; children_box.x_min = x;
children_box.x_max = x + requirement.min.x - 1; children_box.x_max = x + requirement.min_x - 1;
children_box.y_min = y; children_box.y_min = y;
children_box.y_max = y + requirement.min.y - 1; children_box.y_max = y + requirement.min_y - 1;
child->SetBox(children_box); child->SetBox(children_box);
x = x + requirement.min.x; x = x + requirement.min_x;
y_next = std::max(y_next, y + requirement.min.y); y_next = std::max(y_next, y + requirement.min_y);
} }
} }
}; };

View File

@ -13,8 +13,8 @@ class Separator : public Node {
Separator() {} Separator() {}
~Separator() override {} ~Separator() override {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.min.x = 1; requirement_.min_x = 1;
requirement_.min.y = 1; requirement_.min_y = 1;
} }
void Render(Screen& screen) override { void Render(Screen& screen) override {

View File

@ -23,7 +23,7 @@ class Size : public Node {
Node::ComputeRequirement(); Node::ComputeRequirement();
requirement_ = children[0]->requirement(); requirement_ = children[0]->requirement();
auto& value = direction_ == WIDTH ? requirement_.min.x : requirement_.min.y; auto& value = direction_ == WIDTH ? requirement_.min_x : requirement_.min_y;
switch (constraint_) { switch (constraint_) {
case LESS_THAN: case LESS_THAN:
@ -38,9 +38,9 @@ class Size : public Node {
} }
if (direction_ == WIDTH) if (direction_ == WIDTH)
requirement_.flex.x = 0; requirement_.flex_x = 0;
else else
requirement_.flex.y = 0; requirement_.flex_y = 0;
} }
void SetBox(Box box) override { void SetBox(Box box) override {

View File

@ -15,8 +15,8 @@ class Text : public Node {
~Text() {} ~Text() {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.min.x = wstring_width(text_); requirement_.min_x = wstring_width(text_);
requirement_.min.y = 1; requirement_.min_y = 1;
} }
void Render(Screen& screen) override { void Render(Screen& screen) override {

View File

@ -16,21 +16,21 @@ class VBox : public Node {
~VBox() {} ~VBox() {}
void ComputeRequirement() { void ComputeRequirement() {
requirement_.min.x = 0; requirement_.min_x = 0;
requirement_.min.y = 0; requirement_.min_y = 0;
requirement_.flex.x = 0; requirement_.flex_x = 0;
requirement_.flex.y = 1; requirement_.flex_y = 1;
for (auto& child : children) { for (auto& child : children) {
child->ComputeRequirement(); child->ComputeRequirement();
if (requirement_.selection < child->requirement().selection) { if (requirement_.selection < child->requirement().selection) {
requirement_.selection = child->requirement().selection; requirement_.selection = child->requirement().selection;
requirement_.selected_box = child->requirement().selected_box; requirement_.selected_box = child->requirement().selected_box;
requirement_.selected_box.y_min += requirement_.min.y; requirement_.selected_box.y_min += requirement_.min_y;
requirement_.selected_box.y_max += requirement_.min.y; requirement_.selected_box.y_max += requirement_.min_y;
} }
requirement_.min.y += child->requirement().min.y; requirement_.min_y += child->requirement().min_y;
requirement_.min.x = requirement_.min_x =
std::max(requirement_.min.x, child->requirement().min.x); std::max(requirement_.min_x, child->requirement().min_x);
} }
} }
@ -39,10 +39,10 @@ class VBox : public Node {
int flex_sum = 0; int flex_sum = 0;
for (auto& child : children) for (auto& child : children)
flex_sum += child->requirement().flex.y; flex_sum += child->requirement().flex_y;
int space = box.y_max - box.y_min + 1; int space = box.y_max - box.y_min + 1;
int extra_space = space - requirement_.min.y; int extra_space = space - requirement_.min_y;
int remaining_flex = flex_sum; int remaining_flex = flex_sum;
int remaining_extra_space = extra_space; int remaining_extra_space = extra_space;
@ -52,13 +52,13 @@ class VBox : public Node {
Box child_box = box; Box child_box = box;
child_box.y_min = y; child_box.y_min = y;
child_box.y_max = y + child->requirement().min.y - 1; child_box.y_max = y + child->requirement().min_y - 1;
if (child->requirement().flex.y) { if (child->requirement().flex_y) {
int added_space = remaining_extra_space * child->requirement().flex.y / int added_space = remaining_extra_space * child->requirement().flex_y /
remaining_flex; remaining_flex;
remaining_extra_space -= added_space; remaining_extra_space -= added_space;
remaining_flex -= child->requirement().flex.y; remaining_flex -= child->requirement().flex_y;
child_box.y_max += added_space; child_box.y_max += added_space;
} }
child_box.y_max = std::min(child_box.y_max, box.y_max); child_box.y_max = std::min(child_box.y_max, box.y_max);

View File

@ -55,8 +55,8 @@ Dimension Dimension::Fixed(int v) {
Dimension Dimension::Fit(std::shared_ptr<Node>& e) { Dimension Dimension::Fit(std::shared_ptr<Node>& e) {
e->ComputeRequirement(); e->ComputeRequirement();
Terminal::Dimensions size = Terminal::Size(); Terminal::Dimensions size = Terminal::Size();
return Dimension{std::min(e->requirement().min.x, size.dimx), return Dimension{std::min(e->requirement().min_x, size.dimx),
std::min(e->requirement().min.y, size.dimy)}; std::min(e->requirement().min_y, size.dimy)};
} }
Dimension Dimension::Full() { Dimension Dimension::Full() {