2020-04-20 03:00:37 +08:00
|
|
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
|
|
|
// Use of this source code is governed by the MIT license that can be found in
|
|
|
|
// the LICENSE file.
|
|
|
|
|
2020-03-23 05:32:44 +08:00
|
|
|
#include <algorithm>
|
|
|
|
|
2018-10-10 01:06:03 +08:00
|
|
|
#include "ftxui/dom/elements.hpp"
|
2019-01-20 05:06:05 +08:00
|
|
|
#include "ftxui/dom/node.hpp"
|
|
|
|
#include "ftxui/util/autoreset.hpp"
|
2018-10-10 01:06:03 +08:00
|
|
|
|
2019-01-12 22:00:08 +08:00
|
|
|
namespace ftxui {
|
2019-01-07 00:10:35 +08:00
|
|
|
|
2019-01-20 05:06:05 +08:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class Select : public Node {
|
|
|
|
public:
|
2020-05-21 02:36:47 +08:00
|
|
|
Select(std::vector<std::shared_ptr<Node>> children)
|
2019-01-20 05:06:05 +08:00
|
|
|
: Node(std::move(children)) {}
|
|
|
|
|
|
|
|
void ComputeRequirement() override {
|
|
|
|
Node::ComputeRequirement();
|
|
|
|
requirement_ = children[0]->requirement();
|
|
|
|
auto& selected_box = requirement_.selected_box;
|
|
|
|
selected_box.x_min = 0;
|
|
|
|
selected_box.y_min = 0;
|
|
|
|
selected_box.x_max = requirement_.min.x;
|
|
|
|
selected_box.y_max = requirement_.min.y;
|
|
|
|
requirement_.selection = Requirement::SELECTED;
|
|
|
|
};
|
|
|
|
|
|
|
|
void SetBox(Box box) override {
|
|
|
|
box_ = box;
|
|
|
|
children[0]->SetBox(box);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-21 02:36:47 +08:00
|
|
|
Element select(Element child) {
|
|
|
|
return std::make_shared<Select>(unpack(std::move(child)));
|
2019-01-20 05:06:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class Focus : public Select {
|
|
|
|
public:
|
2020-05-21 02:51:07 +08:00
|
|
|
Focus(std::vector<Element> children) : Select(std::move(children)) {}
|
2019-01-20 05:06:05 +08:00
|
|
|
|
|
|
|
void ComputeRequirement() override {
|
|
|
|
Select::ComputeRequirement();
|
|
|
|
requirement_.selection = Requirement::FOCUSED;
|
|
|
|
};
|
2019-06-30 00:52:58 +08:00
|
|
|
|
|
|
|
void Render(Screen& screen) override {
|
|
|
|
Select::Render(screen);
|
|
|
|
screen.SetCursor(Screen::Cursor{box_.x_min, box_.y_min});
|
|
|
|
}
|
2019-01-20 05:06:05 +08:00
|
|
|
};
|
|
|
|
|
2020-05-21 02:36:47 +08:00
|
|
|
Element focus(Element child) {
|
|
|
|
return std::make_shared<Focus>(unpack(std::move(child)));
|
2019-01-20 05:06:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
2018-10-10 01:06:03 +08:00
|
|
|
|
|
|
|
class Frame : public Node {
|
|
|
|
public:
|
2020-05-21 02:51:07 +08:00
|
|
|
Frame(std::vector<Element> children) : Node(std::move(children)) {}
|
2018-10-10 01:06:03 +08:00
|
|
|
|
|
|
|
void ComputeRequirement() override {
|
|
|
|
Node::ComputeRequirement();
|
|
|
|
requirement_ = children[0]->requirement();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetBox(Box box) override {
|
|
|
|
Node::SetBox(box);
|
2019-01-20 05:06:05 +08:00
|
|
|
|
|
|
|
int external_dimx = box.x_max - box.x_min;
|
|
|
|
int external_dimy = box.y_max - box.y_min;
|
|
|
|
|
|
|
|
int internal_dimx = std::max(requirement_.min.x, external_dimx);
|
|
|
|
int internal_dimy = std::max(requirement_.min.y, external_dimy);
|
|
|
|
|
|
|
|
auto& selected_box = requirement_.selected_box;
|
|
|
|
int focused_dimx = selected_box.x_max - selected_box.x_min;
|
|
|
|
int focused_dimy = selected_box.y_max - selected_box.y_min;
|
|
|
|
int dx = selected_box.x_min - external_dimx / 2 + focused_dimx / 2;
|
|
|
|
int dy = selected_box.y_min - external_dimy / 2 + focused_dimy / 2;
|
|
|
|
dx = std::max(0, std::min(internal_dimx - external_dimx - 1, dx));
|
|
|
|
dy = std::max(0, std::min(internal_dimy - external_dimy - 1, dy));
|
|
|
|
|
|
|
|
Box children_box = box;
|
|
|
|
children_box.x_min = box.x_min - dx;
|
|
|
|
children_box.y_min = box.y_min - dy;
|
|
|
|
children_box.x_max = box.x_min + internal_dimx - dx;
|
|
|
|
children_box.y_max = box.y_min + internal_dimy - dy;
|
|
|
|
children[0]->SetBox(children_box);
|
|
|
|
|
|
|
|
// int dx = box.x_max - box.x_min;
|
|
|
|
// int dy = box.y_max - box.y_min;
|
|
|
|
// int cdx = std::min(children[0].requirement().min.x
|
|
|
|
|
|
|
|
// Box children_box;
|
|
|
|
// children_box.x_min =
|
|
|
|
// if (box.x_max - box.x_min >= children[0].requirement().min.x && //
|
|
|
|
|
|
|
|
// box.y_max - box.y_min >= children[0].requirement().min.y) {
|
|
|
|
// children_[0]->SetBox(box);
|
|
|
|
// dx = 0;
|
|
|
|
// dy = 0;
|
|
|
|
// return;
|
|
|
|
//}
|
|
|
|
|
|
|
|
// Box children_box;
|
|
|
|
// children_box.x_min = box.x_min;
|
|
|
|
// children_box.y_min = box.x_min;
|
2018-10-10 01:06:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Render(Screen& screen) override {
|
2019-01-20 05:06:05 +08:00
|
|
|
AutoReset<Box> stencil(&screen.stencil,
|
|
|
|
Box::Intersection(box_, screen.stencil));
|
2018-10-10 01:06:03 +08:00
|
|
|
children[0]->Render(screen);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-21 02:36:47 +08:00
|
|
|
Element frame(Element child) {
|
|
|
|
return std::make_shared<Frame>(unpack(std::move(child)));
|
2018-10-10 01:06:03 +08:00
|
|
|
}
|
|
|
|
|
2020-02-12 04:44:55 +08:00
|
|
|
} // namespace ftxui
|