FTXUI 7.0.3
C++ functional terminal UI.
Loading...
Searching...
No Matches
src/ftxui/component/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 <algorithm> // for max
5#include <ftxui/component/component_options.hpp> // for ResizableSplitOption
6#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
7#include <ftxui/util/ref.hpp> // for Ref
8#include <functional> // for function
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, public ResizableSplitOption {
23 public:
24 explicit ResizableSplitBase(ResizableSplitOption options)
25 : ResizableSplitOption(std::move(options)) {
26 switch (direction()) {
27 case Direction::Left:
28 Add(Container::Horizontal({main, back}));
29 break;
31 Add(Container::Horizontal({back, main}));
32 break;
33 case Direction::Up:
34 Add(Container::Vertical({main, back}));
35 break;
36 case Direction::Down:
37 Add(Container::Vertical({back, main}));
38 break;
39 }
40 }
41
42 bool OnEvent(Event event) final {
43 if (event.is_mouse()) {
44 return OnMouseEvent(std::move(event));
45 }
46 return ComponentBase::OnEvent(std::move(event));
47 }
48
49 bool OnMouseEvent(Event event) {
50 if (captured_mouse_ && event.mouse().motion == Mouse::Released) {
51 captured_mouse_.reset();
52 return true;
53 }
54
55 if (event.mouse().button == Mouse::Left &&
56 event.mouse().motion == Mouse::Pressed &&
57 separator_box_.Contain(event.mouse().x, event.mouse().y) &&
58 !captured_mouse_) {
59 captured_mouse_ = CaptureMouse(event);
60 return true;
61 }
62
63 if (!captured_mouse_) {
64 return ComponentBase::OnEvent(event);
65 }
66
67 switch (direction()) {
68 case Direction::Left:
69 main_size() = std::max(0, event.mouse().x - box_.x_min);
70 break;
72 main_size() = std::max(0, box_.x_max - event.mouse().x);
73 break;
74 case Direction::Up:
75 main_size() = std::max(0, event.mouse().y - box_.y_min);
76 break;
77 case Direction::Down:
78 main_size() = std::max(0, box_.y_max - event.mouse().y);
79 break;
80 }
81
82 main_size() = std::clamp(main_size(), min(), max());
83 return true;
84 }
85
86 Element OnRender() final {
87 switch (direction()) {
88 case Direction::Left:
89 return RenderLeft();
91 return RenderRight();
92 case Direction::Up:
93 return RenderTop();
94 case Direction::Down:
95 return RenderBottom();
96 }
97 // NOTREACHED()
98 return text("unreachable");
99 }
100
101 Element RenderLeft() {
102 return hbox({
103 main->Render() | size(WIDTH, EQUAL, main_size()),
104 separator_func() | reflect(separator_box_),
105 back->Render() | xflex,
106 }) |
107 reflect(box_);
108 }
109
110 Element RenderRight() {
111 return hbox({
112 back->Render() | xflex,
113 separator_func() | reflect(separator_box_),
114 main->Render() | size(WIDTH, EQUAL, main_size()),
115 }) |
116 reflect(box_);
117 }
118
119 Element RenderTop() {
120 return vbox({
121 main->Render() | size(HEIGHT, EQUAL, main_size()),
122 separator_func() | reflect(separator_box_),
123 back->Render() | yflex,
124 }) |
125 reflect(box_);
126 }
127
128 Element RenderBottom() {
129 return vbox({
130 back->Render() | yflex,
131 separator_func() | reflect(separator_box_),
132 main->Render() | size(HEIGHT, EQUAL, main_size()),
133 }) |
134 reflect(box_);
135 }
136
137 private:
138 CapturedMouse captured_mouse_;
139 Box separator_box_;
140 Box box_;
141};
142
143} // namespace
144
145/// @brief Une séparation entre deux composants.
146/// @param options tous les paramètres.
147///
148/// ### Exemple
149///
150/// ```cpp
151/// auto left = Renderer([] { return text("Left") | center;});
152/// auto right = Renderer([] { return text("right") | center;});
153/// int left_size = 10;
154/// auto component = ResizableSplit({
155/// .main = left,
156/// .back = right,
157/// .direction = Direction::Left,
158/// .main_size = &left_size,
159/// .separator_func = [] { return separatorDouble(); },
160/// });
161/// ```
162///
163/// ### Sortie
164///
165/// ```bash
166/// ║
167/// left ║ right
168/// ║
169/// ```
170Component ResizableSplit(ResizableSplitOption options) {
171 return Make<ResizableSplitBase>(std::move(options));
172}
173
174/// @brief Une division horizontale entre deux composants, configurable en utilisant la
175/// souris.
176/// @param main Le composant principal de taille |main_size|, à gauche.
177/// @param back Le composant arrière prenant la taille restante, à droite.
178/// @param main_size La taille du composant |main|.
179/// @ingroup component
180///
181/// ### Exemple
182///
183/// ```cpp
184/// auto screen = App::Fullscreen();
185/// int left_size = 10;
186/// auto left = Renderer([] { return text("Left") | center;});
187/// auto right = Renderer([] { return text("right") | center;});
188/// auto split = ResizableSplitLeft(left, right, &left_size);
189/// screen.Loop(split);
190/// ```
191///
192/// ### Sortie
193///
194/// ```bash
195/// │
196/// left │ right
197/// │
198/// ```
200 return ResizableSplit({
201 std::move(main),
202 std::move(back),
204 main_size,
205 });
206}
207
208/// @brief Une division horizontale entre deux composants, configurable en utilisant la
209/// souris.
210/// @param main Le composant principal de taille |main_size|, à droite.
211/// @param back Le composant arrière prenant la taille restante, à gauche.
212/// @param main_size La taille du composant |main|.
213/// @ingroup component
214///
215/// ### Exemple
216///
217/// ```cpp
218/// auto screen = App::Fullscreen();
219/// int right_size = 10;
220/// auto left = Renderer([] { return text("Left") | center;});
221/// auto right = Renderer([] { return text("right") | center;});
222/// auto split = ResizableSplitRight(right, left, &right_size)
223/// screen.Loop(split);
224/// ```
225///
226/// ### Sortie
227///
228/// ```bash
229/// │
230/// left │ right
231/// │
232/// ```
234 return ResizableSplit({
235 std::move(main),
236 std::move(back),
238 main_size,
239 });
240}
241
242/// @brief Une division verticale entre deux composants, configurable en utilisant la
243/// souris.
244/// @param main Le composant principal de taille |main_size|, en haut.
245/// @param back Le composant arrière prenant la taille restante, en bas.
246/// @param main_size La taille du composant |main|.
247/// @ingroup component
248///
249/// ### Exemple
250///
251/// ```cpp
252/// auto screen = App::Fullscreen();
253/// int top_size = 1;
254/// auto top = Renderer([] { return text("Top") | center;});
255/// auto bottom = Renderer([] { return text("Bottom") | center;});
256/// auto split = ResizableSplitTop(top, bottom, &top_size)
257/// screen.Loop(split);
258/// ```
259///
260/// ### Sortie
261///
262/// ```bash
263/// top
264/// ────────────
265/// bottom
266/// ```
268 return ResizableSplit({
269 std::move(main),
270 std::move(back),
272 main_size,
273 });
274}
275
276/// @brief Une division verticale entre deux composants, configurable en utilisant la
277/// souris.
278/// @param main Le composant principal de taille |main_size|, en bas.
279/// @param back Le composant arrière prenant la taille restante, en haut.
280/// @param main_size La taille du composant |main|.
281/// @ingroup component
282///
283/// ### Exemple
284///
285/// ```cpp
286/// auto screen = App::Fullscreen();
287/// int bottom_size = 1;
288/// auto top = Renderer([] { return text("Top") | center;});
289/// auto bottom = Renderer([] { return text("Bottom") | center;});
290/// auto split = ResizableSplit::Bottom(bottom, top, &bottom_size)
291/// screen.Loop(split);
292/// ```
293///
294/// ### Sortie
295///
296/// ```bash
297/// top
298/// ────────────
299/// bottom
300/// ```
302 return ResizableSplit({
303 std::move(main),
304 std::move(back),
306 main_size,
307 });
308}
309
310} // namespace ftxui
Component ResizableSplitTop(Component main, Component back, int *main_size)
Une division verticale entre deux composants, configurable en utilisant la souris.
Component Horizontal(Components children, int *selector)
Une liste de composants, dessinés un par un horizontalement et navigués horizontalement en utilisant ...
Component Vertical(Components children)
Une liste de composants, dessinés un par un verticalement et navigués verticalement en utilisant les ...
Component ResizableSplitRight(Component main, Component back, int *main_size)
Une division horizontale entre deux composants, configurable en utilisant la souris.
Component ResizableSplitBottom(Component main, Component back, int *main_size)
Une division verticale entre deux composants, configurable en utilisant la souris.
Component ResizableSplitLeft(Component main, Component back, int *main_size)
Une division horizontale entre deux composants, configurable en utilisant la souris.
Element text(std::string_view text)
Affiche un morceau de texte unicode encodé en UTF8.
Element xflex(Element)
Développer/Réduire si possible/nécessaire sur l'axe X.
Definition flex.cpp:101
Decorator size(WidthOrHeight direction, Constraint constraint, int value)
Applique une contrainte sur la taille d'un élément.
Element yflex(Element)
Développer/Réduire si possible/nécessaire sur l'axe Y.
Definition flex.cpp:107
Element vbox(Elements children)
Un conteneur affichant les éléments verticalement un par un.
Definition vbox.cpp:96
L'espace de noms FTXUI ftxui::
Definition animation.hpp:11
std::unique_ptr< CapturedMouseInterface > CapturedMouse
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:28
std::shared_ptr< Node > Element
Definition elements.hpp:25
Direction direction
Definition elements.hpp:83
Element hbox(Elements children)
Un conteneur affichant les éléments horizontalement un par un.
Definition hbox.cpp:94
Component ResizableSplit(ResizableSplitOption options)
Une séparation entre deux composants.
Decorator reflect(Box &box)
Definition reflect.cpp:43
std::shared_ptr< ComponentBase > Component
Definition app.hpp:23