FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
homescreen.cpp
Go to the documentation of this file.
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("頻率 [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("使用率 [%]") | 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("記憶體 [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 // Compiler
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_option);
181
182 std::string executable_content_ = "";
183 Component executable_ = Input(&executable_content_, "可執行檔");
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 // flags
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 // Executable
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 // Input
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("編譯器"),
234 compiler->Render() | vscroll_indicator | frame);
235 auto flags_win =
236 window(text("旗標"), flags->Render() | vscroll_indicator | frame);
237 auto executable_win = window(text("可執行檔:"), executable_->Render());
238 auto input_win =
239 window(text("輸入"), hbox({
240 vbox({
241 hbox({
242 text("新增: "),
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 // Spinner
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 // Colors
281 // ---------------------------------------------------------------------------
282 auto color_tab_renderer = Renderer([] {
283 auto basic_color_display =
284 vbox({
285 text("16 色調色盤:"),
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 色調色盤:");
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 // True color display.
351 auto true_color_display = text("真彩色: 24位元:");
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 // Gauges
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 // Paragraph
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("內容") | 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 只是印刷和排版行業的虛擬文字。\nLorem Ipsum 自 1500 年代以來一直是該行業的標準虛擬文字,當時一位不知名的印刷商取了一塊活字,並將其打亂製成了一本字體樣本。";
428 return vbox({
429 window(text("靠左對齊:"), paragraphAlignLeft(str)),
430 window(text("置中對齊:"), paragraphAlignCenter(str)),
431 window(text("靠右對齊:"), paragraphAlignRight(str)),
432 window(text("左右對齊:"), paragraphAlignJustify(str)),
433 window(text("並排顯示"), hbox({
434 paragraph(str),
435 separator(),
436 paragraph(str),
437 })),
438 window(text("不同大小的元素:"),
439 flexbox({
440 make_box(10, 5),
441 make_box(9, 4),
442 make_box(8, 4),
443 make_box(6, 3),
444 make_box(10, 5),
445 make_box(9, 4),
446 make_box(8, 4),
447 make_box(6, 3),
448 make_box(10, 5),
449 make_box(9, 4),
450 make_box(8, 4),
451 make_box(6, 3),
452 })),
453 }) |
454 vscroll_indicator | yframe | flex;
455 });
456
457 auto paragraph_renderer_right = Renderer([] {
458 return paragraph("<--- 這個垂直條可以使用滑鼠調整大小") |
459 center;
460 });
461
462 int paragraph_renderer_split_position = Terminal::Size().dimx / 2;
463 auto paragraph_renderer_group =
464 ResizableSplitLeft(paragraph_renderer_left, paragraph_renderer_right,
465 &paragraph_renderer_split_position);
466 auto paragraph_renderer_group_renderer =
467 Renderer(paragraph_renderer_group,
468 [&] { return paragraph_renderer_group->Render(); });
469
470 // ---------------------------------------------------------------------------
471 // Tabs
472 // ---------------------------------------------------------------------------
473
474 int tab_index = 0;
475 std::vector<std::string> tab_entries = {
476 "htop", "顏色", "旋轉", "量表", "編譯器", "段落",
477 };
478 auto tab_selection =
479 Menu(&tab_entries, &tab_index, MenuOption::HorizontalAnimated());
480 auto tab_content = Container::Tab(
481 {
482 htop,
483 color_tab_renderer,
484 spinner_tab_renderer,
485 gauge_component,
486 compiler_renderer,
487 paragraph_renderer_group_renderer,
488 },
489 &tab_index);
490
491 auto exit_button =
492 Button("離開", [&] { screen.Exit(); }, ButtonOption::Animated());
493
494 auto main_container = Container::Vertical({
495 Container::Horizontal({
496 tab_selection,
497 exit_button,
498 }),
499 tab_content,
500 });
501
502 auto main_renderer = Renderer(main_container, [&] {
503 return vbox({
504 text("FTXUI 示範") | bold | hcenter,
505 hbox({
506 tab_selection->Render() | flex,
507 exit_button->Render(),
508 }),
509 tab_content->Render() | flex,
510 });
511 });
512
513 Loop loop(&screen, main_renderer);
514 while (!loop.HasQuitted()) {
515 // 更新應用程式狀態。
516 shift++;
517
518 // 請求繪製新畫面。
519 screen.RequestAnimationFrame();
520
521 // Execute events, and draw the next frame.
522 loop.RunOnce();
523
524 // 短暫睡眠以控制幀率 (60 FPS)。
525 std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 60));
526 }
527
528 return 0;
529}
Loop 是一個用於管理元件事件循環的類別。
Definition loop.hpp:56
std::vector< std::vector< ftxui::ColorInfo > > ColorInfoSorted2D()
Element make_box(int x, int y)
auto input
Definition gallery.cpp:78
static ButtonOption Animated()
創建一個 ButtonOption,使用動畫顏色。
Element Render()
繪製組件。 建構一個 ftxui::Element,用於在表示此 ftxui::ComponentBase 的 ftxui::Screen 上繪製。請覆寫 OnRender() 以修改渲染。
static ScreenInteractive Fullscreen()
static MenuOption HorizontalAnimated()
動畫水平選單的標準選項。 這對於實現一個標籤頁列很有用。
Component Checkbox(CheckboxOption options)
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 ResizableSplitLeft(Component main, Component back, int *main_size)
兩個元件之間的水平分割,可透過滑鼠設定。
Input 元件的選項。
virtual void Render(Screen &screen)
FlexboxConfig & SetGap(int gap_x, int gap_y)
設定 flexbox 彈性方向。
Decorator bgcolor(Color)
使用背景顏色進行裝飾。
Element window(Element title, Element content, BorderStyle border=ROUNDED)
繪製帶有標題和邊框的視窗。
Decorator size(WidthOrHeight, Constraint, int value)
限制元素的大小。
Element flex(Element)
使子元素按比例擴展以佔據容器中剩餘的空間。
Definition flex.cpp:140
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 文字。
Definition text.cpp:160
Element flex_grow(Element)
盡可能擴展。
Definition flex.cpp:158
Element paragraphAlignLeft(const std::string &text)
回傳一個在多行上繪製段落並靠左對齊的元素。
Element separator()
在兩個元素之間繪製垂直或水平分隔線。
Element filler()
一個元素,它會按比例擴展以佔據容器中剩餘的空間。
Definition flex.cpp:97
Element gauge(float progress)
繪製一個高解析度進度條。
Element paragraphAlignJustify(const std::string &text)
回傳一個在多行上繪製段落並使用左右對齊的元素。
Decorator color(Color)
使用前景顏色進行裝飾。
Element hcenter(Element)
水平置中一個元素。
Element vbox(Elements)
一個垂直一個接一個顯示元素的容器。
Definition vbox.cpp:95
FlexboxConfig 是一個配置結構,用於定義彈性盒容器的佈局屬性。
static Color HSV(uint8_t hue, uint8_t saturation, uint8_t value)
從 HSV 表示建立一個顏色。 https://en.wikipedia.org/wiki/HSL_and_HSV
Color 是一個在終端使用者介面中表示顏色的類別。
Definition color.hpp:20
int main()
FTXUI 的 ftxui:: 命名空間
Definition animation.hpp:10
Element flexbox(Elements, FlexboxConfig config=FlexboxConfig())
一個容器,用於在行/列中顯示元素,並在滿時能夠換行到下一列/行。
Definition flexbox.cpp:249
Element hflow(Elements)
一個容器,用於從左到右在行中顯示元素。當填滿時,它會在下方的新行開始。
Definition flexbox.cpp:266
Element hbox(Elements)
一個逐一水平顯示元素的容器。
Definition hbox.cpp:94
std::vector< Element > Elements
Definition elements.hpp:23
Elements paragraph(std::wstring text)
@ LESS_THAN
Definition elements.hpp:159
@ GREATER_THAN
Definition elements.hpp:159
Element graph(GraphFunction)
使用 GraphFunction 繪製圖形。
std::shared_ptr< ComponentBase > Component