15 Decorator PositionAndSize(
int left,
int top,
int width,
int height) {
33 class ResizeDecorator :
public NodeDecorator {
41 : NodeDecorator(std::move(child)),
43 resize_left_(resize_left),
44 resize_right_(resize_right),
45 resize_top_(resize_top),
46 resize_down_(resize_down) {}
48 void Render(Screen& screen)
override {
52 for (
int y = box_.y_min; y <= box_.y_max; ++y) {
53 auto& cell = screen.PixelAt(box_.x_min, y);
54 cell.foreground_color = color_;
55 cell.automerge =
false;
59 for (
int y = box_.y_min; y <= box_.y_max; ++y) {
60 auto& cell = screen.PixelAt(box_.x_max, y);
61 cell.foreground_color = color_;
62 cell.automerge =
false;
66 for (
int x = box_.x_min; x <= box_.x_max; ++x) {
67 auto& cell = screen.PixelAt(x, box_.y_min);
68 cell.foreground_color = color_;
69 cell.automerge =
false;
73 for (
int x = box_.x_min; x <= box_.x_max; ++x) {
74 auto& cell = screen.PixelAt(x, box_.y_max);
75 cell.foreground_color = color_;
76 cell.automerge =
false;
82 const bool resize_left_;
83 const bool resize_right_;
84 const bool resize_top_;
85 const bool resize_down_;
88 Element DefaultRenderState(
const WindowRenderState& state) {
99 element = std::make_shared<ResizeDecorator>(
111 class WindowImpl :
public ComponentBase,
public WindowOptions {
113 explicit WindowImpl(WindowOptions option) : WindowOptions(std::move(option)) {
115 inner = Make<ComponentBase>();
124 const bool captureable =
127 const WindowRenderState state = {
132 resize_left_ || resize_right_ || resize_down_ || resize_top_,
133 (resize_left_hover_ || resize_left_) && captureable,
134 (resize_right_hover_ || resize_right_) && captureable,
135 (resize_top_hover_ || resize_top_) && captureable,
136 (resize_down_hover_ || resize_down_) && captureable,
139 element = render ? render(state) : DefaultRenderState(state);
142 element |=
reflect(box_window_);
143 element |= PositionAndSize(left(), top(), width(), height());
149 bool OnEvent(Event event)
final {
154 if (!event.is_mouse()) {
158 mouse_hover_ = box_window_.Contain(event.mouse().x, event.mouse().y);
160 resize_down_hover_ =
false;
161 resize_top_hover_ =
false;
162 resize_left_hover_ =
false;
163 resize_right_hover_ =
false;
166 resize_left_hover_ =
event.mouse().x == left() + box_.x_min;
167 resize_right_hover_ =
168 event.mouse().x == left() + width() - 1 + box_.x_min;
169 resize_top_hover_ =
event.mouse().y == top() + box_.y_min;
170 resize_down_hover_ =
event.mouse().y == top() + height() - 1 + box_.y_min;
173 resize_top_hover_ &= resize_top();
174 resize_left_hover_ &= resize_left();
175 resize_down_hover_ &= resize_down();
176 resize_right_hover_ &= resize_right();
179 if (captured_mouse_) {
181 captured_mouse_ =
nullptr;
186 width() = left() + width() -
event.mouse().x + box_.x_min;
187 left() =
event.mouse().x - box_.x_min;
191 width() =
event.mouse().x - resize_start_x - box_.x_min;
195 height() = top() + height() -
event.mouse().y + box_.y_min;
196 top() =
event.mouse().y - box_.y_min;
200 height() =
event.mouse().y - resize_start_y - box_.y_min;
204 left() =
event.mouse().x - drag_start_x - box_.x_min;
205 top() =
event.mouse().y - drag_start_y - box_.y_min;
209 width() = std::max<int>(width(), title().
size() + 2);
210 height() = std::max<int>(height(), 2);
215 resize_left_ =
false;
216 resize_right_ =
false;
218 resize_down_ =
false;
224 if (!CaptureMouse(event)) {
237 captured_mouse_ = CaptureMouse(event);
238 if (!captured_mouse_) {
242 resize_left_ = resize_left_hover_;
243 resize_right_ = resize_right_hover_;
244 resize_top_ = resize_top_hover_;
245 resize_down_ = resize_down_hover_;
247 resize_start_x =
event.mouse().x - width() - box_.x_min;
248 resize_start_y =
event.mouse().y - height() - box_.y_min;
249 drag_start_x =
event.mouse().x - left() - box_.x_min;
250 drag_start_y =
event.mouse().y - top() - box_.y_min;
253 drag_ = !resize_right_ && !resize_down_ && !resize_top_ && !resize_left_;
261 int drag_start_x = 0;
262 int drag_start_y = 0;
263 int resize_start_x = 0;
264 int resize_start_y = 0;
266 bool mouse_hover_ =
false;
268 bool resize_top_ =
false;
269 bool resize_left_ =
false;
270 bool resize_down_ =
false;
271 bool resize_right_ =
false;
273 bool resize_top_hover_ =
false;
274 bool resize_left_hover_ =
false;
275 bool resize_down_hover_ =
false;
276 bool resize_right_hover_ =
false;
307 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.