FTXUI  5.0.0
C++ functional terminal UI.
Loading...
Searching...
No Matches
resizable_split.cpp
Go to the documentation of this file.
1// Copyright 2021 Arthur Sonzogni. All rights reserved.
2// Use of this source code is governed by the MIT license that can be found in
3// the LICENSE file.
4#include <ftxui/component/component_options.hpp> // for ResizableSplitOption
5#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
6#include <ftxui/util/ref.hpp> // for Ref
7#include <functional> // for function
8#include <memory> // for __shared_ptr_access, shared_ptr, allocator
9#include <utility> // for move
10
11#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
12#include "ftxui/component/component.hpp" // for Horizontal, Make, ResizableSplit, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop
13#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
14#include "ftxui/component/event.hpp" // for Event
15#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released
16#include "ftxui/dom/elements.hpp" // for operator|, reflect, Element, size, EQUAL, xflex, yflex, hbox, vbox, HEIGHT, WIDTH, text
17#include "ftxui/screen/box.hpp" // for Box
18
19namespace ftxui {
20namespace {
21
22class ResizableSplitBase : public ComponentBase {
23 public:
24 explicit ResizableSplitBase(ResizableSplitOption options)
25 : options_(std::move(options)) {
27 options_->main,
28 options_->back,
29 }));
30 }
31
32 bool OnEvent(Event event) final {
33 if (event.is_mouse()) {
34 return OnMouseEvent(std::move(event));
35 }
36 return ComponentBase::OnEvent(std::move(event));
37 }
38
39 bool OnMouseEvent(Event event) {
40 if (captured_mouse_ && event.mouse().motion == Mouse::Released) {
41 captured_mouse_.reset();
42 return true;
43 }
44
45 if (event.mouse().button == Mouse::Left &&
46 event.mouse().motion == Mouse::Pressed &&
47 separator_box_.Contain(event.mouse().x, event.mouse().y) &&
48 !captured_mouse_) {
49 captured_mouse_ = CaptureMouse(event);
50 return true;
51 }
52
53 if (!captured_mouse_) {
55 }
56
57 switch (options_->direction()) {
58 case Direction::Left:
59 options_->main_size() = event.mouse().x - box_.x_min;
60 return true;
62 options_->main_size() = box_.x_max - event.mouse().x;
63 return true;
64 case Direction::Up:
65 options_->main_size() = event.mouse().y - box_.y_min;
66 return true;
67 case Direction::Down:
68 options_->main_size() = box_.y_max - event.mouse().y;
69 return true;
70 }
71
72 // NOTREACHED()
73 return false;
74 }
75
77 switch (options_->direction()) {
78 case Direction::Left:
79 return RenderLeft();
81 return RenderRight();
82 case Direction::Up:
83 return RenderTop();
84 case Direction::Down:
85 return RenderBottom();
86 }
87 // NOTREACHED()
88 return text("unreacheable");
89 }
90
92 return hbox({
93 options_->main->Render() |
94 size(WIDTH, EQUAL, options_->main_size()),
95 options_->separator_func() | reflect(separator_box_),
96 options_->back->Render() | xflex,
97 }) |
98 reflect(box_);
99 }
100
102 return hbox({
103 options_->back->Render() | xflex,
104 options_->separator_func() | reflect(separator_box_),
105 options_->main->Render() |
106 size(WIDTH, EQUAL, options_->main_size()),
107 }) |
108 reflect(box_);
109 }
110
112 return vbox({
113 options_->main->Render() |
114 size(HEIGHT, EQUAL, options_->main_size()),
115 options_->separator_func() | reflect(separator_box_),
116 options_->back->Render() | yflex,
117 }) |
118 reflect(box_);
119 }
120
122 return vbox({
123 options_->back->Render() | yflex,
124 options_->separator_func() | reflect(separator_box_),
125 options_->main->Render() |
126 size(HEIGHT, EQUAL, options_->main_size()),
127 }) |
128 reflect(box_);
129 }
130
131 private:
133 CapturedMouse captured_mouse_;
134 Box separator_box_;
135 Box box_;
136};
137
138} // namespace
139
140/// @brief A split in between two components.
141/// @param options all the parameters.
142///
143/// ### Example
144///
145/// ```cpp
146/// auto left = Renderer([] { return text("Left") | center;});
147/// auto right = Renderer([] { return text("right") | center;});
148/// int left_size = 10;
149/// auto component = ResizableSplit({
150/// .main = left,
151/// .back = right,
152/// .direction = Direction::Left,
153/// .main_size = &left_size,
154/// .separator_func = [] { return separatorDouble(); },
155/// });
156/// ```
157///
158/// ### Output
159///
160/// ```bash
161/// ║
162/// left ║ right
163/// ║
164/// ```
168
169/// @brief An horizontal split in between two components, configurable using the
170/// mouse.
171/// @param main The main component of size |main_size|, on the left.
172/// @param back The back component taking the remaining size, on the right.
173/// @param main_size The size of the |main| component.
174/// @ingroup component
175///
176/// ### Example
177///
178/// ```cpp
179/// auto screen = ScreenInteractive::Fullscreen();
180/// int left_size = 10;
181/// auto left = Renderer([] { return text("Left") | center;});
182/// auto right = Renderer([] { return text("right") | center;});
183/// auto split = ResizableSplitLeft(left, right, &left_size);
184/// screen.Loop(split);
185/// ```
186///
187/// ### Output
188///
189/// ```bash
190/// │
191/// left │ right
192/// │
193/// ```
194Component ResizableSplitLeft(Component main, Component back, int* main_size) {
195 return ResizableSplit({
196 std::move(main),
197 std::move(back),
199 main_size,
200 });
201}
202
203/// @brief An horizontal split in between two components, configurable using the
204/// mouse.
205/// @param main The main component of size |main_size|, on the right.
206/// @param back The back component taking the remaining size, on the left.
207/// @param main_size The size of the |main| component.
208/// @ingroup component
209///
210/// ### Example
211///
212/// ```cpp
213/// auto screen = ScreenInteractive::Fullscreen();
214/// int right_size = 10;
215/// auto left = Renderer([] { return text("Left") | center;});
216/// auto right = Renderer([] { return text("right") | center;});
217/// auto split = ResizableSplitRight(right, left, &right_size)
218/// screen.Loop(split);
219/// ```
220///
221/// ### Output
222///
223/// ```bash
224/// │
225/// left │ right
226/// │
227/// ```
229 return ResizableSplit({
230 std::move(main),
231 std::move(back),
233 main_size,
234 });
235}
236
237/// @brief An vertical split in between two components, configurable using the
238/// mouse.
239/// @param main The main component of size |main_size|, on the top.
240/// @param back The back component taking the remaining size, on the bottom.
241/// @param main_size The size of the |main| component.
242/// @ingroup component
243///
244/// ### Example
245///
246/// ```cpp
247/// auto screen = ScreenInteractive::Fullscreen();
248/// int top_size = 1;
249/// auto top = Renderer([] { return text("Top") | center;});
250/// auto bottom = Renderer([] { return text("Bottom") | center;});
251/// auto split = ResizableSplitTop(top, bottom, &top_size)
252/// screen.Loop(split);
253/// ```
254///
255/// ### Output
256///
257/// ```bash
258/// top
259/// ────────────
260/// bottom
261/// ```
262Component ResizableSplitTop(Component main, Component back, int* main_size) {
263 return ResizableSplit({
264 std::move(main),
265 std::move(back),
267 main_size,
268 });
269}
270
271/// @brief An vertical split in between two components, configurable using the
272/// mouse.
273/// @param main The main component of size |main_size|, on the bottom.
274/// @param back The back component taking the remaining size, on the top.
275/// @param main_size The size of the |main| component.
276/// @ingroup component
277///
278/// ### Example
279///
280/// ```cpp
281/// auto screen = ScreenInteractive::Fullscreen();
282/// int bottom_size = 1;
283/// auto top = Renderer([] { return text("Top") | center;});
284/// auto bottom = Renderer([] { return text("Bottom") | center;});
285/// auto split = ResizableSplit::Bottom(bottom, top, &bottom_size)
286/// screen.Loop(split);
287/// ```
288///
289/// ### Output
290///
291/// ```bash
292/// top
293/// ────────────
294/// bottom
295/// ```
297 return ResizableSplit({
298 std::move(main),
299 std::move(back),
301 main_size,
302 });
303}
304
305} // namespace ftxui
virtual bool OnEvent(Event)
Called in response to an event.
Component Horizontal(Components children)
A list of components, drawn one by one horizontally and navigated horizontally using left/right arrow...
Element xflex(Element)
Expand/Minimize if possible/needed on the X axis.
Definition flex.cpp:129
Decorator size(WidthOrHeight, Constraint, int value)
Apply a constraint on the size of an element.
Definition size.cpp:90
Component ResizableSplitTop(Component main, Component back, int *main_size)
An vertical split in between two components, configurable using the mouse.
std::unique_ptr< CapturedMouseInterface > CapturedMouse
std::shared_ptr< Node > Element
Definition elements.hpp:23
std::shared_ptr< ComponentBase > Component
Element yflex(Element)
Expand/Minimize if possible/needed on the Y axis.
Definition flex.cpp:135
Element hbox(Elements)
A container displaying elements horizontally one by one.
Definition hbox.cpp:83
Component ResizableSplit(ResizableSplitOption options)
A split in between two components.
Element text(std::wstring text)
Display a piece of unicode text.
Definition text.cpp:120
Component ResizableSplitRight(Component main, Component back, int *main_size)
An horizontal split in between two components, configurable using the mouse.
Component Slider(SliderOption< T > options)
A slider in any direction.
Definition slider.cpp:339
Decorator reflect(Box &box)
Definition reflect.cpp:44
Component ResizableSplitBottom(Component main, Component back, int *main_size)
An vertical split in between two components, configurable using the mouse.
void Render(Screen &screen, const Element &element)
Display an element on a ftxui::Screen.
Definition node.cpp:47
Component ResizableSplitLeft(Component main, Component back, int *main_size)
An horizontal split in between two components, configurable using the mouse.
Element vbox(Elements)
A container displaying elements vertically one by one.
Definition vbox.cpp:83