FTXUI 6.1.9
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// このソースコードの使用は、MITライセンスに従います。
3// LICENSEファイルに記載されています。
4#include <algorithm> // max用
5#include <ftxui/component/component_options.hpp> // ResizableSplitOption用
6#include <ftxui/dom/direction.hpp> // Direction、Direction::Down、Direction::Left、Direction::Right、Direction::Up用
7#include <ftxui/util/ref.hpp> // Ref用
8#include <functional> // function用
9#include <utility> // move用
10
11#include "ftxui/component/captured_mouse.hpp" // CapturedMouse用
12#include "ftxui/component/component.hpp" // Horizontal、Make、ResizableSplit、ResizableSplitBottom、ResizableSplitLeft、ResizableSplitRight、ResizableSplitTop用
13#include "ftxui/component/component_base.hpp" // Component、ComponentBase用
14#include "ftxui/component/event.hpp" // Event用
15#include "ftxui/component/mouse.hpp" // Mouse、Mouse::Left、Mouse::Pressed、Mouse::Released用
16#include "ftxui/dom/elements.hpp" // operator|、reflect、Element、size、EQUAL、xflex、yflex、hbox、vbox、HEIGHT、WIDTH、text用
17#include "ftxui/screen/box.hpp" // 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 // 到達不能
98 return text("unreacheable");
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 2つのコンポーネント間の分割。
146/// @param options すべてのパラメータ。
147///
148/// ### 例
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/// ### 出力
164///
165/// ```bash
166/// ║
167/// left ║ right
168/// ║
169/// ```
171 return Make<ResizableSplitBase>(std::move(options));
172}
173
174/// @brief 2つのコンポーネント間の水平分割。マウスで設定可能。
175/// @param main 左側の|main_size|サイズのメインコンポーネント。
176/// @param back 右側に残りのサイズを占めるバックコンポーネント。
177/// @param main_size |main|コンポーネントのサイズ。
178/// @ingroup component
179///
180/// ### 例
181///
182/// ```cpp
183/// auto screen = ScreenInteractive::Fullscreen();
184/// int left_size = 10;
185/// auto left = Renderer([] { return text("Left") | center;});
186/// auto right = Renderer([] { return text("right") | center;});
187/// auto split = ResizableSplitLeft(left, right, &left_size);
188/// screen.Loop(split);
189/// ```
190///
191/// ### 出力
192///
193/// ```bash
194/// │
195/// left │ right
196/// │
197/// ```
199 return ResizableSplit({
200 std::move(main),
201 std::move(back),
203 main_size,
204 });
205}
206
207/// @brief 2つのコンポーネント間の水平分割。マウスで設定可能。
208/// @param main 右側の|main_size|サイズのメインコンポーネント。
209/// @param back 左側に残りのサイズを占めるバックコンポーネント。
210/// @param main_size |main|コンポーネントのサイズ。
211/// @ingroup component
212///
213/// ### 例
214///
215/// ```cpp
216/// auto screen = ScreenInteractive::Fullscreen();
217/// int right_size = 10;
218/// auto left = Renderer([] { return text("Left") | center;});
219/// auto right = Renderer([] { return text("right") | center;});
220/// auto split = ResizableSplitRight(right, left, &right_size)
221/// screen.Loop(split);
222/// ```
223///
224/// ### 出力
225///
226/// ```bash
227/// │
228/// left │ right
229/// │
230/// ```
232 return ResizableSplit({
233 std::move(main),
234 std::move(back),
236 main_size,
237 });
238}
239
240/// @brief 2つのコンポーネント間の垂直分割。マウスで設定可能。
241/// @param main 上部の|main_size|サイズのメインコンポーネント。
242/// @param back 下部に残りのサイズを占めるバックコンポーネント。
243/// @param main_size |main|コンポーネントのサイズ。
244/// @ingroup component
245///
246/// ### 例
247///
248/// ```cpp
249/// auto screen = ScreenInteractive::Fullscreen();
250/// int top_size = 1;
251/// auto top = Renderer([] { return text("Top") | center;});
252/// auto bottom = Renderer([] { return text("Bottom") | center;});
253/// auto split = ResizableSplitTop(top, bottom, &top_size)
254/// screen.Loop(split);
255/// ```
256///
257/// ### 出力
258///
259/// ```bash
260/// top
261/// ────────────
262/// bottom
263/// ```
265 return ResizableSplit({
266 std::move(main),
267 std::move(back),
269 main_size,
270 });
271}
272
273/// @brief 2つのコンポーネント間の垂直分割。マウスで設定可能。
274/// @param main 下部の|main_size|サイズのメインコンポーネント。
275/// @param back 上部に残りのサイズを占めるバックコンポーネント。
276/// @param main_size |main|コンポーネントのサイズ。
277/// @ingroup component
278///
279/// ### 例
280///
281/// ```cpp
282/// auto screen = ScreenInteractive::Fullscreen();
283/// int bottom_size = 1;
284/// auto top = Renderer([] { return text("Top") | center;});
285/// auto bottom = Renderer([] { return text("Bottom") | center;});
286/// auto split = ResizableSplit::Bottom(bottom, top, &bottom_size)
287/// screen.Loop(split);
288/// ```
289///
290/// ### 出力
291///
292/// ```bash
293/// top
294/// ────────────
295/// bottom
296/// ```
298 return ResizableSplit({
299 std::move(main),
300 std::move(back),
302 main_size,
303 });
304}
305
306} // namespace ftxui
virtual bool OnEvent(Event)
イベントに応じて呼び出されます。
Component Horizontal(Components children)
コンポーネントのリスト。水平方向に1つずつ描画され、左右の矢印キーまたは'h'/'l'キーを使用して水平方向にナビゲートされます。
Component ResizableSplitTop(Component main, Component back, int *main_size)
2つのコンポーネント間の垂直分割。マウスで設定可能。
Component Vertical(Components children)
コンポーネントのリスト。垂直方向に1つずつ描画され、上下の矢印キーまたは'j'/'k'キーを使用して垂直方向にナビゲートされます。
Component ResizableSplitRight(Component main, Component back, int *main_size)
2つのコンポーネント間の水平分割。マウスで設定可能。
Component ResizableSplitBottom(Component main, Component back, int *main_size)
2つのコンポーネント間の垂直分割。マウスで設定可能。
Component ResizableSplitLeft(Component main, Component back, int *main_size)
2つのコンポーネント間の水平分割。マウスで設定可能。
Element xflex(Element)
必要に応じてX軸上で拡大・縮小します。
Definition flex.cpp:126
Element yflex(Element)
必要に応じてY軸上で拡大・縮小します。
Definition flex.cpp:132
Element text(std::wstring text)
ユニコードテキストを表示します。
Definition text.cpp:160
Element vbox(Elements)
要素を縦に一つずつ表示するコンテナ。
Definition vbox.cpp:94
FTXUI ftxui:: 名前空間
Definition animation.hpp:9
std::unique_ptr< CapturedMouseInterface > CapturedMouse
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:26
std::shared_ptr< Node > Element
Definition elements.hpp:21
Element hbox(Elements)
要素を水平方向に1つずつ表示するコンテナ。
Definition hbox.cpp:93
Component ResizableSplit(ResizableSplitOption options)
2つのコンポーネント間の分割。
Decorator reflect(Box &box)
Definition reflect.cpp:42
std::shared_ptr< ComponentBase > Component
return size
Definition string.cpp:1516