15Decorator PositionAndSize(
int left,
int top,
int width,
int height) {
33class 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_;
88Element DefaultRenderState(
int i,
const WindowRenderState& state) {
99 element = std::make_shared<ResizeDecorator>(
111class 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,
140 render ? render(state)
141 : DefaultRenderState(
reinterpret_cast<uintptr_t
>(
this), state);
144 element |=
reflect(box_window_);
145 element |= PositionAndSize(left(), top(), width(), height());
151 bool OnEvent(Event event)
final {
156 if (!event.is_mouse()) {
160 mouse_hover_ = box_window_.Contain(event.mouse().x, event.mouse().y);
162 resize_down_hover_ =
false;
163 resize_top_hover_ =
false;
164 resize_left_hover_ =
false;
165 resize_right_hover_ =
false;
168 resize_left_hover_ =
event.mouse().x == left() + box_.x_min;
169 resize_right_hover_ =
170 event.mouse().x == left() + width() - 1 + box_.x_min;
171 resize_top_hover_ =
event.mouse().y == top() + box_.y_min;
172 resize_down_hover_ =
event.mouse().y == top() + height() - 1 + box_.y_min;
175 resize_top_hover_ &= resize_top();
176 resize_left_hover_ &= resize_left();
177 resize_down_hover_ &= resize_down();
178 resize_right_hover_ &= resize_right();
181 if (captured_mouse_) {
183 captured_mouse_ =
nullptr;
188 width() = left() + width() -
event.mouse().x + box_.x_min;
189 left() =
event.mouse().x - box_.x_min;
193 width() =
event.mouse().x - resize_start_x - box_.x_min;
197 height() = top() + height() -
event.mouse().y + box_.y_min;
198 top() =
event.mouse().y - box_.y_min;
202 height() =
event.mouse().y - resize_start_y - box_.y_min;
206 left() =
event.mouse().x - drag_start_x - box_.x_min;
207 top() =
event.mouse().y - drag_start_y - box_.y_min;
211 width() = std::max<int>(width(), title().
size() + 2);
212 height() = std::max<int>(height(), 2);
217 resize_left_ =
false;
218 resize_right_ =
false;
220 resize_down_ =
false;
226 if (!CaptureMouse(event)) {
230 if (!event.mouse().IsPressed()) {
236 captured_mouse_ = CaptureMouse(event);
237 if (!captured_mouse_) {
241 resize_left_ = resize_left_hover_;
242 resize_right_ = resize_right_hover_;
243 resize_top_ = resize_top_hover_;
244 resize_down_ = resize_down_hover_;
246 resize_start_x =
event.mouse().x - width() - box_.x_min;
247 resize_start_y =
event.mouse().y - height() - box_.y_min;
248 drag_start_x =
event.mouse().x - left() - box_.x_min;
249 drag_start_y =
event.mouse().y - top() - box_.y_min;
252 drag_ = !resize_right_ && !resize_down_ && !resize_top_ && !resize_left_;
260 int drag_start_x = 0;
261 int drag_start_y = 0;
262 int resize_start_x = 0;
263 int resize_start_y = 0;
265 bool mouse_hover_ =
false;
267 bool resize_top_ =
false;
268 bool resize_left_ =
false;
269 bool resize_down_ =
false;
270 bool resize_right_ =
false;
272 bool resize_top_hover_ =
false;
273 bool resize_left_hover_ =
false;
274 bool resize_down_hover_ =
false;
275 bool resize_right_hover_ =
false;
306 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.
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 window(Element title, Element content)
Draw window with a title and a border around the element.
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.