FTXUI 6.1.9
C++ functional terminal UI.
载入中...
搜索中...
未找到
homescreen.cpp
浏览该文件的文档.
1// 版权所有 2020 Arthur Sonzogni。保留所有权利。
2// 本源代码的使用受 MIT 许可协议的约束,该协议可在
3// LICENSE 文件中找到。
4#include <stddef.h> // for size_t
5#include <array> // for array
6#include <atomic> // for atomic
7#include <chrono> // for operator""s, chrono_literals
8#include <cmath> // for sin
10#include <functional> // for ref, reference_wrapper, function
11#include <memory> // for allocator, shared_ptr, __shared_ptr_access
12#include <string> // for string, basic_string, char_traits, operator+, to_string
13#include <thread> // for sleep_for, thread
14#include <utility> // for move
15#include <vector> // for vector
16
17#include "../dom/color_info_sorted_2d.ipp" // for ColorInfoSorted2D
18#include "ftxui/component/component.hpp" // for Checkbox, Renderer, Horizontal, Vertical, Input, Menu, Radiobox, ResizableSplitLeft, Tab
19#include "ftxui/component/component_base.hpp" // for ComponentBase, Component
20#include "ftxui/component/component_options.hpp" // for MenuOption, InputOption
21#include "ftxui/component/event.hpp" // for Event, Event::Custom
22#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
23#include "ftxui/dom/elements.hpp" // for text, color, operator|, bgcolor, filler, Element, vbox, size, hbox, separator, flex, window, graph, EQUAL, paragraph, WIDTH, hcenter, Elements, bold, vscroll_indicator, HEIGHT, flexbox, hflow, border, frame, flex_grow, gauge, paragraphAlignCenter, paragraphAlignJustify, paragraphAlignLeft, paragraphAlignRight, dim, spinner, LESS_THAN, center, yframe, GREATER_THAN
24#include "ftxui/dom/flexbox_config.hpp" // for FlexboxConfig
25#include "ftxui/screen/color.hpp" // for Color, Color::BlueLight, Color::RedLight, Color::Black, Color::Blue, Color::Cyan, Color::CyanLight, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::White, Color::Yellow, Color::YellowLight, Color::Default, Color::Palette256, ftxui
26#include "ftxui/screen/color_info.hpp" // for ColorInfo
27#include "ftxui/screen/terminal.hpp" // for Size, Dimensions
28
29using namespace ftxui;
30
31int main() {
32 auto screen = ScreenInteractive::Fullscreen();
33
34 // ---------------------------------------------------------------------------
35 // HTOP 进程管理器
36 // ---------------------------------------------------------------------------
37 int shift = 0;
38
39 auto my_graph = [&shift](int width, int height) {
40 std::vector<int> output(width);
41 for (int i = 0; i < width; ++i) {
42 float v = 0.5f;
43 v += 0.1f * sin((i + shift) * 0.1f);
44 v += 0.2f * sin((i + shift + 10) * 0.15f);
45 v += 0.1f * sin((i + shift) * 0.03f);
46 v *= height;
47 output[i] = (int)v;
48 }
49 return output;
50 };
51
52 auto htop = Renderer([&] {
53 auto frequency = vbox({
54 text("Frequency [Mhz]") | hcenter,
55 hbox({
56 vbox({
57 text("2400 "),
58 filler(),
59 text("1200 "),
60 filler(),
61 text("0 "),
62 }),
63 graph(std::ref(my_graph)) | flex,
64 }) | flex,
65 });
66
67 auto utilization = vbox({
68 text("Utilization [%]") | hcenter,
69 hbox({
70 vbox({
71 text("100 "),
72 filler(),
73 text("50 "),
74 filler(),
75 text("0 "),
76 }),
77 graph(std::ref(my_graph)) | color(Color::RedLight),
78 }) | flex,
79 });
80
81 auto ram = vbox({
82 text("Ram [Mo]") | hcenter,
83 hbox({
84 vbox({
85 text("8192"),
86 filler(),
87 text("4096 "),
88 filler(),
89 text("0 "),
90 }),
91 graph(std::ref(my_graph)) | color(Color::BlueLight),
92 }) | flex,
93 });
94
95 return hbox({
96 vbox({
97 frequency | flex,
98 separator(),
99 utilization | flex,
100 }) | flex,
101 separator(),
102 ram | flex,
103 }) |
104 flex;
105 });
106
107 // ---------------------------------------------------------------------------
108 // 编译器
109 // ---------------------------------------------------------------------------
110
111 const std::vector<std::string> compiler_entries = {
112 "gcc",
113 "clang",
114 "emcc",
115 "game_maker",
116 "Ada compilers",
117 "ALGOL 60 compilers",
118 "ALGOL 68 compilers",
119 "Assemblers (Intel *86)",
120 "Assemblers (Motorola 68*)",
121 "Assemblers (Zilog Z80)",
122 "Assemblers (other)",
123 "BASIC Compilers",
124 "BASIC interpreters",
125 "Batch compilers",
126 "C compilers",
127 "Source-to-source compilers",
128 "C++ compilers",
129 "C# compilers",
130 "COBOL compilers",
131 "Common Lisp compilers",
132 "D compilers",
133 "DIBOL/DBL compilers",
134 "ECMAScript interpreters",
135 "Eiffel compilers",
136 "Fortran compilers",
137 "Go compilers",
138 "Haskell compilers",
139 "Java compilers",
140 "Pascal compilers",
141 "Perl Interpreters",
142 "PHP compilers",
143 "PL/I compilers",
144 "Python compilers",
145 "Scheme compilers and interpreters",
146 "Smalltalk compilers",
147 "Tcl Interpreters",
148 "VMS Interpreters",
149 "Rexx Interpreters",
150 "CLI compilers",
151 };
152
153 int compiler_selected = 0;
154 Component compiler = Radiobox(&compiler_entries, &compiler_selected);
155
156 std::array<std::string, 8> options_label = {
157 "-Wall",
158 "-Werror",
159 "-lpthread",
160 "-O3",
161 "-Wabi-tag",
162 "-Wno-class-conversion",
163 "-Wcomma-subscript",
164 "-Wno-conversion-null",
165 };
166 std::array<bool, 8> options_state = {
167 false, false, false, false, false, false, false, false,
168 };
169
170 std::vector<std::string> input_entries;
171 int input_selected = 0;
172 Component input = Menu(&input_entries, &input_selected);
173
174 auto input_option = InputOption();
175 std::string input_add_content;
176 input_option.on_enter = [&] {
177 input_entries.push_back(input_add_content);
178 input_add_content = "";
179 };
180 Component input_add = Input(&input_add_content, "input files", input_option);
181
182 std::string executable_content_ = "";
183 Component executable_ = Input(&executable_content_, "executable");
184
185 Component flags = Container::Vertical({
186 Checkbox(&options_label[0], &options_state[0]),
187 Checkbox(&options_label[1], &options_state[1]),
188 Checkbox(&options_label[2], &options_state[2]),
189 Checkbox(&options_label[3], &options_state[3]),
190 Checkbox(&options_label[4], &options_state[4]),
191 Checkbox(&options_label[5], &options_state[5]),
192 Checkbox(&options_label[6], &options_state[6]),
193 Checkbox(&options_label[7], &options_state[7]),
194 });
195
196 auto compiler_component = Container::Horizontal({
197 compiler,
198 flags,
199 Container::Vertical({
200 executable_,
201 Container::Horizontal({
202 input_add,
203 input,
204 }),
205 }),
206 });
207
208 auto render_command = [&] {
209 Elements line;
210 // 编译器
211 line.push_back(text(compiler_entries[compiler_selected]) | bold);
212 // 标志
213 for (int i = 0; i < 8; ++i) {
214 if (options_state[i]) {
215 line.push_back(text(" "));
216 line.push_back(text(options_label[i]) | dim);
217 }
218 }
219 // 可执行文件
220 if (!executable_content_.empty()) {
221 line.push_back(text(" -o ") | bold);
222 line.push_back(text(executable_content_) | color(Color::BlueLight) |
223 bold);
224 }
225 // 输入
226 for (auto& it : input_entries) {
227 line.push_back(text(" " + it) | color(Color::RedLight));
228 }
229 return line;
230 };
231
232 auto compiler_renderer = Renderer(compiler_component, [&] {
233 auto compiler_win = window(text("Compiler"),
234 compiler->Render() | vscroll_indicator | frame);
235 auto flags_win =
236 window(text("Flags"), flags->Render() | vscroll_indicator | frame);
237 auto executable_win = window(text("Executable:"), executable_->Render());
238 auto input_win =
239 window(text("Input"), hbox({
240 vbox({
241 hbox({
242 text("Add: "),
243 input_add->Render(),
244 }) | size(WIDTH, EQUAL, 20) |
245 size(HEIGHT, EQUAL, 1),
246 filler(),
247 }),
248 separator(),
249 input->Render() | vscroll_indicator | frame |
250 size(HEIGHT, EQUAL, 3) | flex,
251 }));
252 return vbox({
253 hbox({
254 compiler_win,
255 flags_win,
256 vbox({
257 executable_win | size(WIDTH, EQUAL, 20),
258 input_win | size(WIDTH, EQUAL, 60),
259 }),
260 filler(),
261 }) | size(HEIGHT, LESS_THAN, 8),
262 hflow(render_command()) | flex_grow,
263 }) |
264 flex_grow;
265 });
266
267 // ---------------------------------------------------------------------------
268 // 旋转器
269 // ---------------------------------------------------------------------------
270 auto spinner_tab_renderer = Renderer([&] {
271 Elements entries;
272 for (int i = 0; i < 22; ++i) {
273 entries.push_back(spinner(i, shift / 5) | bold |
274 size(WIDTH, GREATER_THAN, 2) | border);
275 }
276 return hflow(std::move(entries));
277 });
278
279 // ---------------------------------------------------------------------------
280 // 颜色
281 // ---------------------------------------------------------------------------
282 auto color_tab_renderer = Renderer([] {
283 auto basic_color_display =
284 vbox({
285 text("16 color palette:"),
286 separator(),
287 hbox({
288 vbox({
289 color(Color::Default, text("Default")),
290 color(Color::Black, text("Black")),
291 color(Color::GrayDark, text("GrayDark")),
292 color(Color::GrayLight, text("GrayLight")),
293 color(Color::White, text("White")),
294 color(Color::Blue, text("Blue")),
295 color(Color::BlueLight, text("BlueLight")),
296 color(Color::Cyan, text("Cyan")),
297 color(Color::CyanLight, text("CyanLight")),
298 color(Color::Green, text("Green")),
299 color(Color::GreenLight, text("GreenLight")),
300 color(Color::Magenta, text("Magenta")),
301 color(Color::MagentaLight, text("MagentaLight")),
302 color(Color::Red, text("Red")),
303 color(Color::RedLight, text("RedLight")),
304 color(Color::Yellow, text("Yellow")),
305 color(Color::YellowLight, text("YellowLight")),
306 }),
307 vbox({
308 bgcolor(Color::Default, text("Default")),
309 bgcolor(Color::Black, text("Black")),
310 bgcolor(Color::GrayDark, text("GrayDark")),
311 bgcolor(Color::GrayLight, text("GrayLight")),
312 bgcolor(Color::White, text("White")),
313 bgcolor(Color::Blue, text("Blue")),
314 bgcolor(Color::BlueLight, text("BlueLight")),
315 bgcolor(Color::Cyan, text("Cyan")),
316 bgcolor(Color::CyanLight, text("CyanLight")),
317 bgcolor(Color::Green, text("Green")),
318 bgcolor(Color::GreenLight, text("GreenLight")),
319 bgcolor(Color::Magenta, text("Magenta")),
320 bgcolor(Color::MagentaLight, text("MagentaLight")),
321 bgcolor(Color::Red, text("Red")),
322 bgcolor(Color::RedLight, text("RedLight")),
323 bgcolor(Color::Yellow, text("Yellow")),
324 bgcolor(Color::YellowLight, text("YellowLight")),
325 }),
326 }),
327 }) |
328 border;
329
330 auto palette_256_color_display = text("256 colors palette:");
331 {
332 std::vector<std::vector<ColorInfo>> info_columns = ColorInfoSorted2D();
333 Elements columns;
334 for (auto& column : info_columns) {
335 Elements column_elements;
336 for (auto& it : column) {
337 column_elements.push_back(
338 text(" ") | bgcolor(Color(Color::Palette256(it.index_256))));
339 }
340 columns.push_back(hbox(std::move(column_elements)));
341 }
342 palette_256_color_display = vbox({
343 palette_256_color_display,
344 separator(),
345 vbox(columns),
346 }) |
347 border;
348 }
349
350 // 真彩色显示。
351 auto true_color_display = text("TrueColors: 24bits:");
352 {
353 int saturation = 255;
354 Elements array;
355 for (int value = 0; value < 255; value += 16) {
356 Elements line;
357 for (int hue = 0; hue < 255; hue += 6) {
358 line.push_back(text("▀") //
359 | color(Color::HSV(hue, saturation, value)) //
360 | bgcolor(Color::HSV(hue, saturation, value + 8)));
361 }
362 array.push_back(hbox(std::move(line)));
363 }
364 true_color_display = vbox({
365 true_color_display,
366 separator(),
367 vbox(std::move(array)),
368 }) |
369 border;
370 }
371
372 return flexbox(
373 {
374 basic_color_display,
375 palette_256_color_display,
376 true_color_display,
377 },
378 FlexboxConfig().SetGap(1, 1));
379 });
380
381 // ---------------------------------------------------------------------------
382 // 仪表
383 // ---------------------------------------------------------------------------
384 auto render_gauge = [&shift](int delta) {
385 float progress = (shift + delta) % 500 / 500.f;
386 return hbox({
387 text(std::to_string(int(progress * 100)) + "% ") |
388 size(WIDTH, EQUAL, 5),
389 gauge(progress),
390 });
391 };
392
393 auto gauge_component = Renderer([render_gauge] {
394 return vbox({
395 render_gauge(0) | color(Color::Black),
396 render_gauge(100) | color(Color::GrayDark),
397 render_gauge(50) | color(Color::GrayLight),
398 render_gauge(6894) | color(Color::White),
399 separator(),
400 render_gauge(6841) | color(Color::Blue),
401 render_gauge(9813) | color(Color::BlueLight),
402 render_gauge(98765) | color(Color::Cyan),
403 render_gauge(98) | color(Color::CyanLight),
404 render_gauge(9846) | color(Color::Green),
405 render_gauge(1122) | color(Color::GreenLight),
406 render_gauge(84) | color(Color::Magenta),
407 render_gauge(645) | color(Color::MagentaLight),
408 render_gauge(568) | color(Color::Red),
409 render_gauge(2222) | color(Color::RedLight),
410 render_gauge(220) | color(Color::Yellow),
411 render_gauge(348) | color(Color::YellowLight),
412 });
413 });
414
415 // ---------------------------------------------------------------------------
416 // 段落
417 // ---------------------------------------------------------------------------
418 auto make_box = [](size_t dimx, size_t dimy) {
419 std::string title = std::to_string(dimx) + "x" + std::to_string(dimy);
420 return window(text(title) | hcenter | bold,
421 text("content") | hcenter | dim) |
422 size(WIDTH, EQUAL, dimx) | size(HEIGHT, EQUAL, dimy);
423 };
424
425 auto paragraph_renderer_left = Renderer([&] {
426 std::string str =
427 "Lorem Ipsum is simply dummy text of the printing and typesetting "
428 "industry.\nLorem Ipsum has been the industry's standard dummy text "
429 "ever since the 1500s, when an unknown printer took a galley of type "
430 "and scrambled it to make a type specimen book.";
431 return vbox({
432 window(text("Align left:"), paragraphAlignLeft(str)),
433 window(text("Align center:"), paragraphAlignCenter(str)),
434 window(text("Align right:"), paragraphAlignRight(str)),
435 window(text("Align justify:"), paragraphAlignJustify(str)),
436 window(text("Side by side"), hbox({
437 paragraph(str),
438 separator(),
439 paragraph(str),
440 })),
441 window(text("Elements with different size:"),
442 flexbox({
443 make_box(10, 5),
444 make_box(9, 4),
445 make_box(8, 4),
446 make_box(6, 3),
447 make_box(10, 5),
448 make_box(9, 4),
449 make_box(8, 4),
450 make_box(6, 3),
451 make_box(10, 5),
452 make_box(9, 4),
453 make_box(8, 4),
454 make_box(6, 3),
455 })),
456 }) |
457 vscroll_indicator | yframe | flex;
458 });
459
460 auto paragraph_renderer_right = Renderer([] {
461 return paragraph("<--- This vertical bar is resizable using the mouse") |
462 center;
463 });
464
465 int paragraph_renderer_split_position = Terminal::Size().dimx / 2;
466 auto paragraph_renderer_group =
467 ResizableSplitLeft(paragraph_renderer_left, paragraph_renderer_right,
468 &paragraph_renderer_split_position);
469 auto paragraph_renderer_group_renderer =
470 Renderer(paragraph_renderer_group,
471 [&] { return paragraph_renderer_group->Render(); });
472
473 // ---------------------------------------------------------------------------
474 // 标签页
475 // ---------------------------------------------------------------------------
476
477 int tab_index = 0;
478 std::vector<std::string> tab_entries = {
479 "htop", "color", "spinner", "gauge", "compiler", "paragraph",
480 };
481 auto tab_selection =
482 Menu(&tab_entries, &tab_index, MenuOption::HorizontalAnimated());
483 auto tab_content = Container::Tab(
484 {
485 htop,
486 color_tab_renderer,
487 spinner_tab_renderer,
488 gauge_component,
489 compiler_renderer,
490 paragraph_renderer_group_renderer,
491 },
492 &tab_index);
493
494 auto exit_button =
495 Button("Exit", [&] { screen.Exit(); }, ButtonOption::Animated());
496
497 auto main_container = Container::Vertical({
498 Container::Horizontal({
499 tab_selection,
500 exit_button,
501 }),
502 tab_content,
503 });
504
505 auto main_renderer = Renderer(main_container, [&] {
506 return vbox({
507 text("FTXUI Demo") | bold | hcenter,
508 hbox({
509 tab_selection->Render() | flex,
510 exit_button->Render(),
511 }),
512 tab_content->Render() | flex,
513 });
514 });
515
516 Loop loop(&screen, main_renderer);
517 while (!loop.HasQuitted()) {
518 // 更新应用程序的状态。
519 shift++;
520
521 // 请求绘制新帧。
522 screen.RequestAnimationFrame();
523
524 // 执行事件,并绘制下一帧。
525 loop.RunOnce();
526
527 // 短暂休眠以控制帧率(60 FPS)。
528 std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 60));
529 }
530
531 return 0;
532}
std::vector< std::vector< ftxui::ColorInfo > > ColorInfoSorted2D()
Element make_box(int x, int y)
static ButtonOption Animated()
创建一个使用动画颜色的ButtonOption。
Element Render()
绘制组件。 构建一个 ftxui::Element,用于在表示此 ftxui::ComponentBase 的 ftxui::Screen 上绘制。 请覆盖 OnRender() 以修改渲染。
static ScreenInteractive Fullscreen()
static MenuOption HorizontalAnimated()
动画水平菜单的标准选项。 这对于实现选项卡栏非常有用。
Loop 是一个管理组件事件循环的类。
Component Menu(MenuOption options)
文本列表。選定的元素是焦點。
Component Radiobox(RadioboxOption options)
元素列表,其中只能选择一个。
Component Button(ButtonOption options)
绘制一个按钮。点击时执行一个函数。
Component Renderer(Component child, std::function< Element()>)
返回一个新组件,类似于 |child|,但使用 |render| 作为 Component::Render() 事件。
Component Input(InputOption options={})
用于编辑文本的输入框。
Component Checkbox(CheckboxOption options)
绘制可勾选元素。
Component ResizableSplitLeft(Component main, Component back, int *main_size)
两个组件之间的水平分割,可通过鼠标配置。
Input 组件的选项。
virtual void Render(Screen &screen)
在 ftxui::Screen 上显示元素。
FlexboxConfig & SetGap(int gap_x, int gap_y)
设置 flexbox flex direction。
Decorator bgcolor(Color)
使用背景色进行装饰。
Decorator size(WidthOrHeight, Constraint, int value)
对元素大小应用约束。
Element flex(Element)
使子元素按比例扩展以填充容器中剩余的空间。
Element paragraphAlignRight(const std::string &text)
返回一个在多行上绘制段落并右对齐的元素。
Element spinner(int charset_index, size_t image_index)
用于表示时间或事件的效果。这显示了一个 ASCII 艺术“视频”。
Element center(Element)
水平并垂直居中一个元素。
Element paragraphAlignCenter(const std::string &text)
返回一个在多行上绘制段落并居中对齐的元素。
Element text(std::wstring text)
显示一段Unicode文本。
Element flex_grow(Element)
如果可能,进行扩展。
Element paragraphAlignLeft(const std::string &text)
返回一个在多行上绘制段落并左对齐的元素。
Element separator()
在两个其他元素之间绘制垂直或水平分隔线。
Element filler()
一个元素,它将按比例扩展以填充容器中剩余的空间。
Element paragraphAlignJustify(const std::string &text)
返回一个在多行上绘制段落并使用两端对齐方式的元素。 居中对齐。
Decorator color(Color)
使用前景色进行装饰。
Element hcenter(Element)
水平居中一个元素。
Element vbox(Elements)
垂直一个接一个显示元素的容器。
FlexboxConfig 是一个配置结构体,定义了弹性盒子容器的布局属性。
static Color HSV(uint8_t hue, uint8_t saturation, uint8_t value)
从其 HSV 表示构建一个颜色。 https://en.wikipedia.org/wiki/HSL_and_HSV
Color 是一个表示终端用户界面中颜色的类。
int main()
#include "ftxui/component/component_base.hpp" // 用于 ComponentBase
Element flexbox(Elements, FlexboxConfig config=FlexboxConfig())
一个容器,用于在行/列中显示元素,并且在填满时能够换行到下一列/行。
Element hflow(Elements)
一个容器,用于从左到右在行中显示元素。当填满时,它会在下方开始新的一行。
Element hbox(Elements)
一个按水平顺序逐一显示元素的容器。
std::vector< Element > Elements
Element window(Element title, Element content, BorderStyle border=ROUNDED)
Elements paragraph(std::wstring text)
Element gauge(float progress)
绘制一个高清进度条。
Element graph(GraphFunction)
使用 GraphFunction 绘制图表。
std::shared_ptr< ComponentBase > Component