FTXUI 6.1.9
C++ functional terminal UI.
载入中...
搜索中...
未找到
src/ftxui/component/resizable_split.cpp
浏览该文件的文档.
1// 版权所有 2021 Arthur Sonzogni. 保留所有权利。
2// 本源代码的使用受 MIT 许可证的约束,该许可证可在 LICENSE 文件中找到。
3#include <algorithm> // for max
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 <utility> // for move
9
10#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
11#include "ftxui/component/component.hpp" // for Horizontal, Make, ResizableSplit, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop
12#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
13#include "ftxui/component/event.hpp" // for Event
14#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released
15#include "ftxui/dom/elements.hpp" // for operator|, reflect, Element, size, EQUAL, xflex, yflex, hbox, vbox, HEIGHT, WIDTH, text
16#include "ftxui/screen/box.hpp" // for Box
17
18namespace ftxui {
19namespace {
20
21class ResizableSplitBase : public ComponentBase, public ResizableSplitOption {
22 public:
23 explicit ResizableSplitBase(ResizableSplitOption options)
24 : ResizableSplitOption(std::move(options)) {
25 switch (direction()) {
26 case Direction::Left:
27 Add(Container::Horizontal({main, back}));
28 break;
30 Add(Container::Horizontal({back, main}));
31 break;
32 case Direction::Up:
33 Add(Container::Vertical({main, back}));
34 break;
35 case Direction::Down:
36 Add(Container::Vertical({back, main}));
37 break;
38 }
39 }
40
41 bool OnEvent(Event event) final {
42 if (event.is_mouse()) {
43 return OnMouseEvent(std::move(event));
44 }
45 return ComponentBase::OnEvent(std::move(event));
46 }
47
48 bool OnMouseEvent(Event event) {
49 if (captured_mouse_ && event.mouse().motion == Mouse::Released) {
50 captured_mouse_.reset();
51 return true;
52 }
53
54 if (event.mouse().button == Mouse::Left &&
55 event.mouse().motion == Mouse::Pressed &&
56 separator_box_.Contain(event.mouse().x, event.mouse().y) &&
57 !captured_mouse_) {
58 captured_mouse_ = CaptureMouse(event);
59 return true;
60 }
61
62 if (!captured_mouse_) {
63 return ComponentBase::OnEvent(event);
64 }
65
66 switch (direction()) {
67 case Direction::Left:
68 main_size() = std::max(0, event.mouse().x - box_.x_min);
69 break;
71 main_size() = std::max(0, box_.x_max - event.mouse().x);
72 break;
73 case Direction::Up:
74 main_size() = std::max(0, event.mouse().y - box_.y_min);
75 break;
76 case Direction::Down:
77 main_size() = std::max(0, box_.y_max - event.mouse().y);
78 break;
79 }
80
81 main_size() = std::clamp(main_size(), min(), max());
82 return true;
83 }
84
85 Element OnRender() final {
86 switch (direction()) {
87 case Direction::Left:
88 return RenderLeft();
90 return RenderRight();
91 case Direction::Up:
92 return RenderTop();
93 case Direction::Down:
94 return RenderBottom();
95 }
96 // NOTREACHED()
97 return text("unreacheable");
98 }
99
100 Element RenderLeft() {
101 return hbox({
102 main->Render() | size(WIDTH, EQUAL, main_size()),
103 separator_func() | reflect(separator_box_),
104 back->Render() | xflex,
105 }) |
106 reflect(box_);
107 }
108
109 Element RenderRight() {
110 return hbox({
111 back->Render() | xflex,
112 separator_func() | reflect(separator_box_),
113 main->Render() | size(WIDTH, EQUAL, main_size()),
114 }) |
115 reflect(box_);
116 }
117
118 Element RenderTop() {
119 return vbox({
120 main->Render() | size(HEIGHT, EQUAL, main_size()),
121 separator_func() | reflect(separator_box_),
122 back->Render() | yflex,
123 }) |
124 reflect(box_);
125 }
126
127 Element RenderBottom() {
128 return vbox({
129 back->Render() | yflex,
130 separator_func() | reflect(separator_box_),
131 main->Render() | size(HEIGHT, EQUAL, main_size()),
132 }) |
133 reflect(box_);
134 }
135
136 private:
137 CapturedMouse captured_mouse_;
138 Box separator_box_;
139 Box box_;
140};
141
142} // namespace
143
144/// @brief 两个组件之间的分割。
145/// @param options 所有参数。
146///
147/// ### Example
148///
149/// ```cpp
150/// auto left = Renderer([] { return text("Left") | center;});
151/// auto right = Renderer([] { return text("right") | center;});
152/// int left_size = 10;
153/// auto component = ResizableSplit({
154/// .main = left,
155/// .back = right,
156/// .direction = Direction::Left,
157/// .main_size = &left_size,
158/// .separator_func = [] { return separatorDouble(); },
159/// });
160/// ```
161///
162/// ### Output
163///
164/// ```bash
165/// ║
166/// left ║ right
167/// ║
168/// ```
170 return Make<ResizableSplitBase>(std::move(options));
171}
172
173/// @brief 两个组件之间的水平分割,可通过鼠标配置。
174/// @param main 大小为 |main_size| 的主组件,位于左侧。
175/// @param back 占用剩余大小的后备组件,位于右侧。
176/// @param main_size |main| 组件的大小。
177/// @ingroup component
178///
179/// ### Example
180///
181/// ```cpp
182/// auto screen = ScreenInteractive::Fullscreen();
183/// int left_size = 10;
184/// auto left = Renderer([] { return text("Left") | center;});
185/// auto right = Renderer([] { return text("right") | center;});
186/// auto split = ResizableSplitLeft(left, right, &left_size);
187/// screen.Loop(split);
188/// ```
189///
190/// ### Output
191///
192/// ```bash
193/// │
194/// left │ right
195/// │
196/// ```
198 return ResizableSplit({
199 std::move(main),
200 std::move(back),
202 main_size,
203 });
204}
205
206/// @brief 两个组件之间的水平分割,可通过鼠标配置。
207/// @param main 大小为 |main_size| 的主组件,位于右侧。
208/// @param back 占用剩余大小的后备组件,位于左侧。
209/// @param main_size |main| 组件的大小。
210/// @ingroup component
211///
212/// ### Example
213///
214/// ```cpp
215/// auto screen = ScreenInteractive::Fullscreen();
216/// int right_size = 10;
217/// auto left = Renderer([] { return text("Left") | center;});
218/// auto right = Renderer([] { return text("right") | center;});
219/// auto split = ResizableSplitRight(right, left, &right_size)
220/// screen.Loop(split);
221/// ```
222///
223/// ### Output
224///
225/// ```bash
226/// │
227/// left │ right
228/// │
229/// ```
231 return ResizableSplit({
232 std::move(main),
233 std::move(back),
235 main_size,
236 });
237}
238
239/// @brief 两个组件之间的垂直分割,可通过鼠标配置。
240/// @param main 大小为 |main_size| 的主组件,位于顶部。
241/// @param back 占用剩余大小的后备组件,位于底部。
242/// @param main_size |main| 组件的大小。
243/// @ingroup component
244///
245/// ### Example
246///
247/// ```cpp
248/// auto screen = ScreenInteractive::Fullscreen();
249/// int top_size = 1;
250/// auto top = Renderer([] { return text("Top") | center;});
251/// auto bottom = Renderer([] { return text("Bottom") | center;});
252/// auto split = ResizableSplitTop(top, bottom, &top_size)
253/// screen.Loop(split);
254/// ```
255///
256/// ### Output
257///
258/// ```bash
259/// top
260/// ────────────
261/// bottom
262/// ```
264 return ResizableSplit({
265 std::move(main),
266 std::move(back),
268 main_size,
269 });
270}
271
272/// @brief 两个组件之间的垂直分割,可通过鼠标配置。
273/// @param main 大小为 |main_size| 的主组件,位于底部。
274/// @param back 占用剩余大小的后备组件,位于顶部。
275/// @param main_size |main| 组件的大小。
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)
响应事件时调用。
Component Horizontal(Components children)
一个组件列表,水平逐个绘制,并使用左/右箭头键或“h”/“l”键水平导航。
Component ResizableSplitTop(Component main, Component back, int *main_size)
两个组件之间的垂直分割,可通过鼠标配置。
Component Vertical(Components children)
一个组件列表,垂直逐个绘制,并使用上/下箭头键或“j”/“k”键垂直导航。
Component ResizableSplitRight(Component main, Component back, int *main_size)
两个组件之间的水平分割,可通过鼠标配置。
Component ResizableSplitBottom(Component main, Component back, int *main_size)
两个组件之间的垂直分割,可通过鼠标配置。
Component ResizableSplitLeft(Component main, Component back, int *main_size)
两个组件之间的水平分割,可通过鼠标配置。
Element xflex(Element)
在 X 轴上尽可能地扩展/收缩。
Decorator size(WidthOrHeight, Constraint, int value)
对元素大小应用约束。
Element yflex(Element)
在 Y 轴上尽可能地扩展/收缩。
Element text(std::wstring text)
显示一段Unicode文本。
Element vbox(Elements)
垂直一个接一个显示元素的容器。
#include "ftxui/component/component_base.hpp" // 用于 ComponentBase
std::unique_ptr< CapturedMouseInterface > CapturedMouse
std::shared_ptr< T > Make(Args &&... args)
std::shared_ptr< Node > Element
Element hbox(Elements)
一个按水平顺序逐一显示元素的容器。
Component ResizableSplit(ResizableSplitOption options)
两个组件之间的分割。
Decorator reflect(Box &box)
std::shared_ptr< ComponentBase > Component