21 Decorator PositionAndSize(
int left,
int top,
int width,
int height) {
39 class ResizeDecorator :
public NodeDecorator {
47 : NodeDecorator(std::move(child)),
49 resize_left_(resize_left),
50 resize_right_(resize_right),
51 resize_top_(resize_top),
52 resize_down_(resize_down) {}
54 void Render(Screen& screen)
override {
58 for (
int y = box_.y_min; y <= box_.y_max; ++y) {
59 auto& cell = screen.PixelAt(box_.x_min, y);
60 cell.foreground_color = color_;
61 cell.automerge =
false;
65 for (
int y = box_.y_min; y <= box_.y_max; ++y) {
66 auto& cell = screen.PixelAt(box_.x_max, y);
67 cell.foreground_color = color_;
68 cell.automerge =
false;
72 for (
int x = box_.x_min; x <= box_.x_max; ++x) {
73 auto& cell = screen.PixelAt(x, box_.y_min);
74 cell.foreground_color = color_;
75 cell.automerge =
false;
79 for (
int x = box_.x_min; x <= box_.x_max; ++x) {
80 auto& cell = screen.PixelAt(x, box_.y_max);
81 cell.foreground_color = color_;
82 cell.automerge =
false;
88 const bool resize_left_;
89 const bool resize_right_;
90 const bool resize_top_;
91 const bool resize_down_;
94 Element DefaultRenderState(
const WindowRenderState& state) {
105 element = std::make_shared<ResizeDecorator>(
117 class WindowImpl :
public ComponentBase,
public WindowOptions {
119 explicit WindowImpl(WindowOptions option) : WindowOptions(std::move(option)) {
121 inner = Make<ComponentBase>();
130 const bool captureable =
133 const WindowRenderState state = {
138 resize_left_ || resize_right_ || resize_down_ || resize_top_,
139 (resize_left_hover_ || resize_left_) && captureable,
140 (resize_right_hover_ || resize_right_) && captureable,
141 (resize_top_hover_ || resize_top_) && captureable,
142 (resize_down_hover_ || resize_down_) && captureable,
145 element = render ? render(state) : DefaultRenderState(state);
148 element |=
reflect(box_window_);
149 element |= PositionAndSize(left(), top(), width(), height());
155 bool OnEvent(Event event)
final {
160 if (!event.is_mouse()) {
164 mouse_hover_ = box_window_.Contain(event.mouse().x, event.mouse().y);
166 resize_down_hover_ =
false;
167 resize_top_hover_ =
false;
168 resize_left_hover_ =
false;
169 resize_right_hover_ =
false;
172 resize_left_hover_ =
event.mouse().x == left() + box_.x_min;
173 resize_right_hover_ =
174 event.mouse().x == left() + width() - 1 + box_.x_min;
175 resize_top_hover_ =
event.mouse().y == top() + box_.y_min;
176 resize_down_hover_ =
event.mouse().y == top() + height() - 1 + box_.y_min;
179 resize_top_hover_ &= resize_top();
180 resize_left_hover_ &= resize_left();
181 resize_down_hover_ &= resize_down();
182 resize_right_hover_ &= resize_right();
185 if (captured_mouse_) {
187 captured_mouse_ =
nullptr;
192 width() = left() + width() -
event.mouse().x + box_.x_min;
193 left() =
event.mouse().x - box_.x_min;
197 width() =
event.mouse().x - resize_start_x - box_.x_min;
201 height() = top() + height() -
event.mouse().y + box_.y_min;
202 top() =
event.mouse().y - box_.y_min;
206 height() =
event.mouse().y - resize_start_y - box_.y_min;
210 left() =
event.mouse().x - drag_start_x - box_.x_min;
211 top() =
event.mouse().y - drag_start_y - box_.y_min;
215 width() = std::max<int>(width(),
static_cast<int>(title().
size() + 2));
216 height() = std::max<int>(height(), 2);
221 resize_left_ =
false;
222 resize_right_ =
false;
224 resize_down_ =
false;
230 if (!CaptureMouse(event)) {
243 captured_mouse_ = CaptureMouse(event);
244 if (!captured_mouse_) {
248 resize_left_ = resize_left_hover_;
249 resize_right_ = resize_right_hover_;
250 resize_top_ = resize_top_hover_;
251 resize_down_ = resize_down_hover_;
253 resize_start_x =
event.mouse().x - width() - box_.x_min;
254 resize_start_y =
event.mouse().y - height() - box_.y_min;
255 drag_start_x =
event.mouse().x - left() - box_.x_min;
256 drag_start_y =
event.mouse().y - top() - box_.y_min;
259 drag_ = !resize_right_ && !resize_down_ && !resize_top_ && !resize_left_;
267 int drag_start_x = 0;
268 int drag_start_y = 0;
269 int resize_start_x = 0;
270 int resize_start_y = 0;
272 bool mouse_hover_ =
false;
274 bool resize_top_ =
false;
275 bool resize_left_ =
false;
276 bool resize_down_ =
false;
277 bool resize_right_ =
false;
279 bool resize_top_hover_ =
false;
280 bool resize_left_hover_ =
false;
281 bool resize_down_hover_ =
false;
282 bool resize_right_hover_ =
false;
313 return Make<WindowImpl>(std::move(option));
virtual Element Render()
Draw the component. Build a ftxui::Element to be drawn on the ftxi::Screen representing this ftxui::C...
virtual bool OnEvent(Event)
Called in response to an event.
virtual void Render(Screen &screen)
Display an element on a ftxui::Screen.
static ScreenInteractive * Active()
Return the currently active screen, or null if none.
CapturedMouse CaptureMouse()
Try to get the unique lock about behing able to capture the mouse.
Element window(Element title, Element content, BorderStyle border=ROUNDED)
Draw window with a title and a border around the element.
std::function< Element(Element)> Decorator
Element clear_under(Element element)
Before drawing |child|, clear the pixels below. This is useful in.
Decorator size(WidthOrHeight, Constraint, int value)
Apply a constraint on the size of an element.
std::unique_ptr< CapturedMouseInterface > CapturedMouse
std::shared_ptr< Node > Element
std::shared_ptr< ComponentBase > Component
Element hbox(Elements)
A container displaying elements horizontally one by one.
Component Window(WindowOptions option)
A draggeable / resizeable window. To use multiple of them, they must be stacked using Container::Stac...
Element text(std::wstring text)
Display a piece of unicode text.
Decorator reflect(Box &box)
Element dim(Element)
Use a light font, for elements with less emphasis.
void Render(Screen &screen, const Element &element)
Display an element on a ftxui::Screen.
Decorator color(Color)
Decorate using a foreground color.
Element vbox(Elements)
A container displaying elements vertically one by one.