component_base.hpp
ComponentBase 类
界说组件基类。
- class ComponentBase {
- public:
- // 必须显式构造。
- explicit ComponentBase(Components children)
- : children_(std::move(children)) {}
- virtual ~ComponentBase();
- ComponentBase() = default;
- // 组件不可复制/移动。
- ComponentBase(const ComponentBase&) = delete;
- ComponentBase(ComponentBase&&) = delete;
- ComponentBase& operator=(const ComponentBase&) = delete;
- ComponentBase& operator=(ComponentBase&&) = delete;
- // ------------- Component 层级关系 -----------------------
- // 获取当前的父级Component组件
- ComponentBase* Parent() const;
- // 获取第 i 个子级Component组件
- Component& ChildAt(size_t i);
- // 获取子级Component组件的数量
- size_t ChildCount() const;
- // 返回当前组件在其父级Component中的索引。如果没有父级,则返回 -1。
- int Index() const;
- // 添加子级Component组件
- void Add(Component children);
- // 将当前组件从父级Component中分离
- void Detach();
- // 将所有子级Component分离
- void DetachAllChildren();
- // 渲染组件。
- Element Render();
- // 重写此函数,完成“Render”绘制功能
- virtual Element OnRender();
- // 处理事件。
- // 默认情况下,减少具有懒惰 OR 的子级Component。
- // 返回该事件是否已经被处理。
- virtual bool OnEvent(Event);
- // 处理动画步骤。
- virtual void OnAnimation(animation::Params& params);
- // ------------------- 焦点管理 ----------------------------------------------------------
- // 如果此组件包含子组件,则这指示哪一个是活动的,如果没有活动,则为 nullptr。
- //
- // 如果根组件的 ActiveChild() 链包含该对象,我们就说该元素具有焦点。
- virtual Component ActiveChild();
- // 当组件包含可聚焦元素时返回 true。
- // 使用键盘导航时,无法聚焦的组件将被跳过。
- virtual bool Focusable() const;
- // 判断当前组件是否在其父级的子组件列表中处于Active状态
- bool Active() const;
- // 判断所有祖先是否都处于Active状态。
- bool Focused() const;
- // 让 |child| 成为“Active”的一个。
- virtual void SetActiveChild(ComponentBase* child);
- // 设置指定的子级Component为Active状态。
- void SetActiveChild(Component child);
- // Configure all the ancestors to give focus to this component.
- // 配置所有祖先将焦点放在当前该组件上。
- void TakeFocus();
- protected:
- CapturedMouse CaptureMouse(const Event& event);
- Components children_;
- private:
- ComponentBase* parent_ = nullptr;
- bool in_render = false;
- };
复制代码 receiver.hpp
界说了消息变乱循环的基本功能,包罗消息发送和吸取吸取的两个类。
SenderImpl类 和 ReceiverImpl 类
SenderImpl类实例用于实现发送消息功能。
ReceiverImpl类实例用于实现吸取消息功能。
- template <class T>
- class SenderImpl {
- public:
- SenderImpl(const SenderImpl&) = delete;
- SenderImpl(SenderImpl&&) = delete;
- SenderImpl& operator=(const SenderImpl&) = delete;
- SenderImpl& operator=(SenderImpl&&) = delete;
- void Send(T t) { receiver_->Receive(std::move(t)); }
- ~SenderImpl() { receiver_->ReleaseSender(); }
- Sender<T> Clone() { return receiver_->MakeSender(); }
- private:
- friend class ReceiverImpl<T>;
- explicit SenderImpl(ReceiverImpl<T>* consumer) : receiver_(consumer) {}
- ReceiverImpl<T>* receiver_;
- };
复制代码- template <class T>
- class ReceiverImpl {
- public:
- Sender<T> MakeSender() {
- std::unique_lock<std::mutex> lock(mutex_);
- senders_++;
- return std::unique_ptr<SenderImpl<T>>(new SenderImpl<T>(this));
- }
- ReceiverImpl() = default;
- bool Receive(T* t) {
- while (senders_ || !queue_.empty()) {
- std::unique_lock<std::mutex> lock(mutex_);
- if (queue_.empty()) {
- notifier_.wait(lock);
- }
- if (queue_.empty()) {
- continue;
- }
- *t = std::move(queue_.front());
- queue_.pop();
- return true;
- }
- return false;
- }
- bool ReceiveNonBlocking(T* t) {
- std::unique_lock<std::mutex> lock(mutex_);
- if (queue_.empty()) {
- return false;
- }
- *t = queue_.front();
- queue_.pop();
- return true;
- }
- bool HasPending() {
- std::unique_lock<std::mutex> lock(mutex_);
- return !queue_.empty();
- }
- bool HasQuitted() {
- std::unique_lock<std::mutex> lock(mutex_);
- return queue_.empty() && !senders_;
- }
- private:
- friend class SenderImpl<T>;
- void Receive(T t) {
- {
- std::unique_lock<std::mutex> lock(mutex_);
- queue_.push(std::move(t));
- }
- notifier_.notify_one();
- }
- void ReleaseSender() {
- senders_--;
- notifier_.notify_one();
- }
- std::mutex mutex_;
- std::queue<T> queue_;
- std::condition_variable notifier_;
- std::atomic<int> senders_{0};
- };
复制代码 创建消息收发的组件实例。
- template <class T>
- Receiver<T> MakeReceiver() {
- return std::make_unique<ReceiverImpl<T>>();
- }
复制代码 使用示例:
初始化消息收发的组件实例
- // 实例化 std::string 类型的消息组件。
- auto receiver = MakeReceiver<std:string>();
- // 通过接收对象创建两个发送对象,发送对象可以在其他线程执行消息发送操作。
- auto sender_1= receiver->MakeSender();
- auto sender_2 = receiver->MakeSender();
复制代码- // (线程1)发送模块
- sender_1->Send("hello");
- // (线程2)发送模块
- sender_2->Send("world");
复制代码- // (线程3)接收模块
- //只要存在Sender且存在消息队列有消息,则Receive函数返回 true。
- std::string data;
- while(receiver->Receive(&data)) {
- printf("recv: %s\n", data.c_str());
- }
复制代码 mouse.hpp
界说鼠标类
Mouse 类
界说鼠标的基本信息。
- // 定义鼠标按键类型
- struct Mouse {
- enum Button {
- Left = 0,
- Middle = 1,
- Right = 2,
- None = 3,
- WheelUp = 4,
- WheelDown = 5,
- WheelLeft = 6, /// 仅支持终端。
- WheelRight = 7, /// 仅支持终端。
- };
- // 定义鼠标按键动作
- enum Motion {
- Released = 0,
- Pressed = 1,
- Moved = 2,
- };
- // Button 默认鼠标按键
- Button button = Button::None;
- // Motion 默认鼠标动作
- Motion motion = Motion::Pressed;
- // Modifiers: 修饰符信息
- bool shift = false;
- bool meta = false;
- bool control = false;
- // Coordinates: 坐标信息
- int x = 0;
- int y = 0;
- };
复制代码 event.hpp
界说变乱。
Event 类
界说变乱的基本信息。
- struct Event {
- // -------- 构造函数部分 ----------------------------------------------
- // 与给定键入字符串对应的事件。用户输入的字符。
- static Event Character(std::string);
- // 与给定键入字符对应的事件。用户输入的字符。
- static Event Character(char);
- // 与给定键入宽字符对应的事件。用户输入的字符。
- static Event Character(wchar_t);
- // 自定义事件,其含义由库的用户定义。开发人员定义的任意字符序列。
- static Event Special(std::string);
- // 与给定键入字符串对应的事件。终端发送的字符序列。鼠标状态。
- static Event Mouse(std::string, Mouse mouse);
- // 与给定键入字符串对应的事件。终端发送的字符序列。终端焦点位置。
- static Event CursorPosition(std::string, int x, int y); // Internal
- // 与终端 DCS(设备控制字符串)对应的事件。终端发送的字符序列。终端焦点形状
- static Event CursorShape(std::string, int shape); // Internal
- // --- 键盘的方向按键 ---
- static const Event ArrowLeft;
- static const Event ArrowRight;
- static const Event ArrowUp;
- static const Event ArrowDown;
- // 键盘的控制+方向按键
- static const Event ArrowLeftCtrl;
- static const Event ArrowRightCtrl;
- static const Event ArrowUpCtrl;
- static const Event ArrowDownCtrl;
- // --- 键盘的其他按键 ---
- static const Event Backspace;
- static const Event Delete;
- static const Event Return;
- static const Event Escape;
- static const Event Tab;
- static const Event TabReverse;
- // --- 键盘的导航按键 ---
- static const Event Insert;
- static const Event Home;
- static const Event End;
- static const Event PageUp;
- static const Event PageDown;
- // --- 键盘的功能按键 ---
- static const Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12;
- // --- 键盘的控制+字母按键 ---
- static const Event a, A, CtrlA, AltA, CtrlAltA;
- static const Event b, B, CtrlB, AltB, CtrlAltB;
- static const Event c, C, CtrlC, AltC, CtrlAltC;
- static const Event d, D, CtrlD, AltD, CtrlAltD;
- static const Event e, E, CtrlE, AltE, CtrlAltE;
- static const Event f, F, CtrlF, AltF, CtrlAltF;
- static const Event g, G, CtrlG, AltG, CtrlAltG;
- static const Event h, H, CtrlH, AltH, CtrlAltH;
- static const Event i, I, CtrlI, AltI, CtrlAltI;
- static const Event j, J, CtrlJ, AltJ, CtrlAltJ;
- static const Event k, K, CtrlK, AltK, CtrlAltK;
- static const Event l, L, CtrlL, AltL, CtrlAltL;
- static const Event m, M, CtrlM, AltM, CtrlAltM;
- static const Event n, N, CtrlN, AltN, CtrlAltN;
- static const Event o, O, CtrlO, AltO, CtrlAltO;
- static const Event p, P, CtrlP, AltP, CtrlAltP;
- static const Event q, Q, CtrlQ, AltQ, CtrlAltQ;
- static const Event r, R, CtrlR, AltR, CtrlAltR;
- static const Event s, S, CtrlS, AltS, CtrlAltS;
- static const Event t, T, CtrlT, AltT, CtrlAltT;
- static const Event u, U, CtrlU, AltU, CtrlAltU;
- static const Event v, V, CtrlV, AltV, CtrlAltV;
- static const Event w, W, CtrlW, AltW, CtrlAltW;
- static const Event x, X, CtrlX, AltX, CtrlAltX;
- static const Event y, Y, CtrlY, AltY, CtrlAltY;
- static const Event z, Z, CtrlZ, AltZ, CtrlAltZ;
- // --- 自定义按键 ---
- static const Event Custom;
- //--- 比较按键事件相关的函数 ---------------------------------------------------------
- bool operator==(const Event& other) const { return input_ == other.input_; }
- bool operator!=(const Event& other) const { return !operator==(other); }
- bool operator<(const Event& other) const { return input_ < other.input_; }
- // 获取事件的字符串内容
- const std::string& input() const { return input_; }
- // 判断事件是否为键盘按键触发类型
- bool is_character() const { return type_ == Type::Character; }
- // 获取事件的字符串内容
- std::string character() const { return input_; }
- // 判断事件是否为鼠标触发类型
- bool is_mouse() const { return type_ == Type::Mouse; }
- // 获取事件的鼠标信息
- struct Mouse& mouse() { return data_.mouse; }
- // --- 判断事件是否存在焦点信息 -----------------------------------------------
- bool is_cursor_position() const { return type_ == Type::CursorPosition; }
- // 获取事件的焦点坐标
- int cursor_x() const { return data_.cursor.x; }
- int cursor_y() const { return data_.cursor.y; }
-
- // 判断事件是否存在焦点形状
- bool is_cursor_shape() const { return type_ == Type::CursorShape; }
- // 获取事件的焦点形状
- int cursor_shape() const { return data_.cursor_shape; }
- // 获取Debug字符串内容
- std::string DebugString() const;
- //--- 交互界面句柄 ----------------------------------------------------------
- ScreenInteractive* screen_ = nullptr;
- private:
- friend ComponentBase;
- friend ScreenInteractive;
- enum class Type {
- Unknown,
- Character, // 键盘字符信息
- Mouse, // 鼠标信息
- CursorPosition, // 焦点位置
- CursorShape, // 焦点形状
- };
- Type type_ = Type::Unknown; // 存储事件的类型
- struct Cursor {
- int x = 0;
- int y = 0;
- };//定义焦点坐标
- union {
- struct Mouse mouse;
- struct Cursor cursor;
- int cursor_shape;
- } data_ = {}; // 存储事件的信息
- std::string input_; // 存储事件对应字符串内容
- };
复制代码 screen_interactive.hpp
界说终端界面交互的底子功能
ScreenInteractive 类
该类继承了Screen类,提供了终端界面渲染和交互的基本功能。
- class ScreenInteractive : public Screen {
- public:
- // 创建占用完整Component大小的终端界面交互。
- static ScreenInteractive FitComponent();
-
- // 创建占用Screen终端宽度的终端界面交互(终端界面的高度取决于Component高度)。
- static ScreenInteractive TerminalOutput();
- // 创建指定大小区域的终端界面交互
- static ScreenInteractive FixedSize(int dimx, int dimy);
-
- // 创建占用完整Screen终端大小的终端界面交互。(默认使用双缓冲机制)
- static ScreenInteractive Fullscreen();
- //创建占用完整Screen终端大小的终端界面交互。主屏幕缓冲区正在被占用。
- // (不使用双缓冲)这意味着如果调整终端大小,先前的内容可能会与终端内容混淆。
- static ScreenInteractive FullscreenPrimaryScreen();
-
- //创建占用完整Screen终端大小的终端界面交互。
- // (双缓冲机制)这将使用备用屏幕缓冲区来避免干扰终端内容。
- static ScreenInteractive FullscreenAlternateScreen();
- // 可选. 必须在执行Loop()前调用。该函数作用用于控制是否进行跟踪鼠标控制。
- void TrackMouse(bool enable = true);
- // 返回当前活动屏幕,如果没有则返回 nullptr。
- static ScreenInteractive* Active();
- // 创建Loop循环,并启动主循环进行Component组件交互。
- void Loop(Component);
- // 停止主循环。
- void Exit();
- // 返回停止主循环的回调函数。
- Closure ExitLoopClosure();
- // 发布要由主循环执行的任务。
- void Post(Task task);
- // 发布要由主循环执行的事件(按键事件、鼠标事件)。
- void PostEvent(Event event);
- // 发布要由主循环执行的动画。
- void RequestAnimationFrame();
-
- // 尝试获取能够捕获鼠标的独特锁。如果鼠标尚未被捕获,则为唯一锁,否则为空。
- CapturedMouse CaptureMouse();
- // 装饰一个函数。输出的函数将以与输入函数类似的方式执行,但当前活动的屏幕终端钩子会被暂时卸载。
- Closure WithRestoredIO(Closure);
- // FTXUI 实现了 Ctrl-C 和 Ctrl-Z 的处理程序。
- // 默认情况下,即使组件捕获了事件,这些处理程序也会执行。
- // 这避免了用户处理每个事件时被应用程序捕获。但是在某些情况下,应用程序可能希望自行处理这些事件。
- // 在这种情况下,应用程序可以通过调用以下函数并设置 force=true 来强制 FTXUI 不处理这些事件。
- void ForceHandleCtrlC(bool force);
- void ForceHandleCtrlZ(bool force);
- // 选中功能
- std::string GetSelection();
- void SelectionChange(std::function<void()> callback);
- private:
- void ExitNow();
- void Install();
- void Uninstall();
- void PreMain();
- void PostMain();
- bool HasQuitted();
- void RunOnce(Component component);
- void RunOnceBlocking(Component component);
- void HandleTask(Component component, Task& task);
- bool HandleSelection(bool handled, Event event);
- void RefreshSelection();
- void Draw(Component component);
- void ResetCursorPosition();
- void Signal(int signal);
- ScreenInteractive* suspended_screen_ = nullptr;
- enum class Dimension {
- FitComponent,
- Fixed,
- Fullscreen,
- TerminalOutput,
- };
- Dimension dimension_ = Dimension::Fixed;
- bool use_alternative_screen_ = false;
- ScreenInteractive(int dimx,
- int dimy,
- Dimension dimension,
- bool use_alternative_screen);
- bool track_mouse_ = true;
- Sender<Task> task_sender_;
- Receiver<Task> task_receiver_;
- std::string set_cursor_position;
- std::string reset_cursor_position;
- std::atomic<bool> quit_{false};
- std::thread event_listener_;
- std::thread animation_listener_;
- bool animation_requested_ = false;
- animation::TimePoint previous_animation_time_;
- int cursor_x_ = 1;
- int cursor_y_ = 1;
- bool mouse_captured = false;
- bool previous_frame_resized_ = false;
- bool frame_valid_ = false;
- bool force_handle_ctrl_c_ = true;
- bool force_handle_ctrl_z_ = true;
- // The style of the cursor to restore on exit.
- int cursor_reset_shape_ = 1;
- // Selection API:
- CapturedMouse selection_pending_;
- struct SelectionData {
- int start_x = -1;
- int start_y = -1;
- int end_x = -2;
- int end_y = -2;
- bool empty = true;
- bool operator==(const SelectionData& other) const;
- bool operator!=(const SelectionData& other) const;
- };
- SelectionData selection_data_;
- SelectionData selection_data_previous_;
- std::unique_ptr<Selection> selection_;
- std::function<void()> selection_on_change_;
- friend class Loop;
- public:
- class Private {
- public:
- static void Signal(ScreenInteractive& s, int signal) { s.Signal(signal); }
- };
- friend Private;
- };
复制代码 loop.hpp
Loop 类
界说Loop变乱循环。
- class Loop {
- public:
- Loop(ScreenInteractive* screen, Component component);
- ~Loop();
- // 此类不可复制/移动。
- Loop(const Loop&) = default;
- Loop(Loop&&) = delete;
- Loop& operator=(Loop&&) = delete;
- Loop(const ScreenInteractive&) = delete;
- Loop& operator=(const Loop&) = delete;
-
- // 判断循环是否已经退出
- bool HasQuitted();
- // 执行循环。使“组件”处理每个待处理的任务/事件。如果前一帧无效,则可能会绘制新的一帧。
- void RunOnce();
- // 等待至少一个事件被处理并执行Loop::RunOnce()
- void RunOnceBlocking();
- // 执行循环,阻塞当前线程,直到循环退出。
- void Run();
-
- private:
- ScreenInteractive* screen_;// 存储当前循环的终端交互界面
- Component component_;//存储当前事件循环的组件。
- };
复制代码 animation.hpp
界说动画显示的功能以及算法。
- // 获取当前激活的ScreenInteractive界面,执行动画显示。
- void RequestAnimationFrame();
复制代码- using Clock = std::chrono::steady_clock;
- using TimePoint = std::chrono::time_point<Clock>;
- using Duration = std::chrono::duration<float>;
- // 定义时长参数
- class Params {
- public:
- explicit Params(Duration duration) : duration_(duration) {}
- /// The duration this animation step represents.
- Duration duration() const { return duration_; }
- private:
- Duration duration_;
- };
复制代码- // 定义动画的算法库
- namespace easing {
- using Function = std::function<float(float)>;
- // Linear interpolation (no easing)
- float Linear(float p);
- // Quadratic easing; p^2
- float QuadraticIn(float p);
- float QuadraticOut(float p);
- float QuadraticInOut(float p);
- // Cubic easing; p^3
- float CubicIn(float p);
- float CubicOut(float p);
- float CubicInOut(float p);
- // Quartic easing; p^4
- float QuarticIn(float p);
- float QuarticOut(float p);
- float QuarticInOut(float p);
- // Quintic easing; p^5
- float QuinticIn(float p);
- float QuinticOut(float p);
- float QuinticInOut(float p);
- // Sine wave easing; sin(p * PI/2)
- float SineIn(float p);
- float SineOut(float p);
- float SineInOut(float p);
- // Circular easing; sqrt(1 - p^2)
- float CircularIn(float p);
- float CircularOut(float p);
- float CircularInOut(float p);
- // Exponential easing, base 2
- float ExponentialIn(float p);
- float ExponentialOut(float p);
- float ExponentialInOut(float p);
- // Exponentially-damped sine wave easing
- float ElasticIn(float p);
- float ElasticOut(float p);
- float ElasticInOut(float p);
- // Overshooting cubic easing;
- float BackIn(float p);
- float BackOut(float p);
- float BackInOut(float p);
- // Exponentially-decaying bounce easing
- float BounceIn(float p);
- float BounceOut(float p);
- float BounceInOut(float p);
- } // namespace easing
复制代码- // 定义动画显示参数
- class Animator {
- public:
- explicit Animator(float* from,
- float to = 0.f,
- Duration duration = std::chrono::milliseconds(250),
- easing::Function easing_function = easing::Linear,
- Duration delay = std::chrono::milliseconds(0));
- void OnAnimation(Params&);
- float to() const { return to_; }
- private:
- float* value_;
- float from_;
- float to_;
- Duration duration_;
- easing::Function easing_function_;
- Duration current_;
- };
复制代码 component_options.hpp
界说component的options配置信息。
EntryState 类
界说组件的状态、激活、焦点状态配置信息。
- struct EntryState {
- std::string label; ///< 要显示的标签。
- bool state; ///< 按钮/复选框/单选框的状态
- bool active; ///< 该条目是否为活动条目。
- bool focused; ///< 该条目是否是用户关注的条目。
- int index; ///< 适用时条目的索引或 -1。
- };
复制代码 UnderlineOption 类
界说下划线的配置项
- struct UnderlineOption {
- bool enabled = false; // 是否使能下划线配置
- Color color_active = Color::White; // Active状态下的颜色
- Color color_inactive = Color::GrayDark; // 非Active状态下的颜色
- animation::easing::Function leader_function =
- animation::easing::QuadraticInOut;
- animation::easing::Function follower_function =
- animation::easing::QuadraticInOut;
- animation::Duration leader_duration = std::chrono::milliseconds(250);
- animation::Duration leader_delay = std::chrono::milliseconds(0);
- animation::Duration follower_duration = std::chrono::milliseconds(250);
- animation::Duration follower_delay = std::chrono::milliseconds(0);
- void SetAnimation(animation::Duration d, animation::easing::Function f);
- void SetAnimationDuration(animation::Duration d);
- void SetAnimationFunction(animation::easing::Function f);
- void SetAnimationFunction(animation::easing::Function f_leader,
- animation::easing::Function f_follower);
- };
复制代码 AnimatedColorOption 类
关于潜在动画颜色的选项。
- struct AnimatedColorOption {
- void Set(
- Color inactive,
- Color active,
- animation::Duration duration = std::chrono::milliseconds(250),
- animation::easing::Function function = animation::easing::QuadraticInOut);
- bool enabled = false;
- Color inactive;
- Color active;
- animation::Duration duration = std::chrono::milliseconds(250);
- animation::easing::Function function = animation::easing::QuadraticInOut;
- };
- struct AnimatedColorsOption {
- AnimatedColorOption background;
- AnimatedColorOption foreground;
- };
复制代码 MenuEntryOption 类
MenuEntry 组件的选项。
- struct MenuEntryOption {
- ConstStringRef label = "MenuEntry";
- std::function<Element(const EntryState& state)> transform;
- AnimatedColorsOption animated_colors;
- };
复制代码 MenuOption 类
菜单组件的选项。
- struct MenuOption {
- // 标准构造函数:
- static MenuOption Horizontal();
- static MenuOption HorizontalAnimated();
- static MenuOption Vertical();
- static MenuOption VerticalAnimated();
- static MenuOption Toggle();
- ConstStringListRef entries; ///> 条目列表。
- Ref<int> selected = 0; ///> 选定条目的索引。
- // 样式风格:
- UnderlineOption underline;
- MenuEntryOption entries_option;
- Direction direction = Direction::Down;
- std::function<Element()> elements_prefix;
- std::function<Element()> elements_infix;
- std::function<Element()> elements_postfix;
- // 监听器:
- std::function<void()> on_change; ///> Called when the selected entry changes.
- std::function<void()> on_enter; ///> Called when the user presses enter.
- Ref<int> focused_entry = 0;
- };
复制代码 ButtonOption 类
AnimatedButton 组件的选项。
- struct ButtonOption {
- // 标准构造函数
- static ButtonOption Ascii();
- static ButtonOption Simple();
- static ButtonOption Border();
- static ButtonOption Animated();
- static ButtonOption Animated(Color color);
- static ButtonOption Animated(Color background, Color foreground);
- static ButtonOption Animated(Color background,
- Color foreground,
- Color background_active,
- Color foreground_active);
- ConstStringRef label = "Button";
- std::function<void()> on_click = [] {};
- // 样式风格
- std::function<Element(const EntryState&)> transform;
- AnimatedColorsOption animated_colors;
- };
复制代码 CheckboxOption 类
复选框组件的选项。
- struct CheckboxOption {
- // 标准构造函数
- static CheckboxOption Simple();
- ConstStringRef label = "Checkbox";
- Ref<bool> checked = false;
- // 样式风格:
- std::function<Element(const EntryState&)> transform;
- // 监听器:
- /// Called when the user change the state.
- std::function<void()> on_change = [] {};
- };
复制代码 InputState 类
用于界说输入组件的样式。
- struct InputState {
- Element element;
- bool hovered; ///< 输入是否被鼠标悬停。
- bool focused; ///< 输入是否受到用户的关注。
- bool is_placeholder; ///< 输入是否为空,显示占位符。
- };
复制代码 InputOption 类
输入组件的选项。
- struct InputOption {
- // 一组预定义的样式:
- // 创建默认输入样式风格
- static InputOption Default();
- // 黑底白字样式,边距较高:
- static InputOption Spacious();
- /// 输入的内容。
- StringRef content = "";
- /// 当输入为空时的内容。
- StringRef placeholder = "";
- // 样式风格:
- std::function<Element(InputState)> transform;
- Ref<bool> password = false; ///< 使用‘*’隐藏输入内容。
- Ref<bool> multiline = true; ///< 输入是否可以是多行。
- Ref<bool> insert = true; ///< 插入或改写字符模式。
- /// 当内容改变时调用。
- std::function<void()> on_change = [] {};
- /// 当用户按下回车键时调用。
- std::function<void()> on_enter = [] {};
- // 光标的字符位置:
- Ref<int> cursor_position = 0;
- };
复制代码 RadioboxOption 类
Radiobox 组件的选项。
- struct RadioboxOption {
- // 标准构造函数
- static RadioboxOption Simple();
- // 内容:
- ConstStringListRef entries;
- Ref<int> selected = 0;
- // 样式风格:
- std::function<Element(const EntryState&)> transform;
- // 监听器:
- /// 当选定的条目发生改变时调用。
- std::function<void()> on_change = [] {};
- Ref<int> focused_entry = 0;
- };
复制代码 ResizableSplitOption 类
界说可以缩放的配置。
- struct ResizableSplitOption {
- Component main; // 主组件
- Component back; // 备用组件
- Ref<Direction> direction = Direction::Left;
- Ref<int> main_size =
- (direction() == Direction::Left || direction() == Direction::Right) ? 20
- : 10;
- std::function<Element()> separator_func = [] { return ::ftxui::separator(); };
- };
复制代码 SliderOption 类
Slider 组件的选项。
- template <typename T>
- struct SliderOption {
- Ref<T> value;
- ConstRef<T> min = T(0);
- ConstRef<T> max = T(100);
- ConstRef<T> increment = (max() - min()) / 20;
- Direction direction = Direction::Right;
- Color color_active = Color::White;
- Color color_inactive = Color::GrayDark;
- std::function<void()> on_change; ///> 当“值”更新时调用。
- };
复制代码 WindowRenderState 类
WindowOptions::render 使用的参数包。
- struct WindowRenderState {
- Element inner; ///< 该元素包裹在该窗口内。
- const std::string& title; ///< 窗口的标题。
- bool active = false; ///< 窗口是否为活动窗口。
- bool drag = false; ///< 窗口是否正在被拖动。
- bool resize = false; ///< 窗口是否正在调整大小。
- bool hover_left = false; ///< 可调整大小的左侧是否处于悬停状态。
- bool hover_right = false; ///< 可调整大小的右侧是否处于悬停状态。
- bool hover_top = false; ///< 可调整大小的顶部是否处于悬停状态。
- bool hover_down = false; ///< 可调整大小的下方是否处于悬停状态。
- };
复制代码 WindowOptions 类
“窗口”组件的选项。
- struct WindowOptions {
- Component inner; ///< 该窗口包裹的组件。
- ConstStringRef title = ""; ///< 此窗口显示的标题。
- Ref<int> left = 0; ///< 窗口左侧的位置。
- Ref<int> top = 0; ///< 窗口顶部的位置。
- Ref<int> width = 20; ///< 窗口的宽度。
- Ref<int> height = 10; ///< 窗口的高度。
- Ref<bool> resize_left = true; ///< 左侧可以调整大小吗?
- Ref<bool> resize_right = true; ///< 右侧可以调整大小吗?
- Ref<bool> resize_top = true; ///< 顶部可以调整大小吗?
- Ref<bool> resize_down = true; ///< 下方可以调整大小吗?
- /// 用于自定义窗口外观的可选函数:
- std::function<Element(const WindowRenderState&)> render;
- };
复制代码 DropdownOption 类
下拉组件的选项。
- struct DropdownOption {
- /// 下拉菜单是否打开或关闭:
- Ref<bool> open = false;
- // 复选框的选项:
- CheckboxOption checkbox;
- // 单选框的选项:
- RadioboxOption radiobox;
- // 变换函数:
- std::function<Element(bool open, Element checkbox, Element radiobox)>
- transform;
- };
复制代码 component.hpp
该文件界说了常用的Component基本组件。
- // 定义模版,用于创建特定的组件实例
- template <class T, class... Args>
- std::shared_ptr<T> Make(Args&&... args) {
- return std::make_shared<T>(std::forward<Args>(args)...);
- }
- // 管道运算符来装饰组件
- using ComponentDecorator = std::function<Component(Component)>;
- using ElementDecorator = std::function<Element(Element)>;
- Component operator|(Component component, ComponentDecorator decorator);
- Component operator|(Component component, ElementDecorator decorator);
- Component& operator|=(Component& component, ComponentDecorator decorator);
- Component& operator|=(Component& component, ElementDecorator decorator);
复制代码 Container 组件容器
- // 定义组件容器
- namespace Container {
- Component Vertical(Components children);
- Component Vertical(Components children, int* selector);
- Component Horizontal(Components children);
- Component Horizontal(Components children, int* selector);
- Component Tab(Components children, int* selector);
- Component Stacked(Components children);
- } // namespace Container
复制代码 Vertical 垂直布局容器
组件列表,垂直逐一绘制,并使用上/下箭头键或“j”/“k”键垂直导航。
Horizontal 水平布局容器
一系列组件,逐一水平绘制,并使用左/右箭头键或“h”/“l”键水平导航。
Tab 选项卡布局容器
一个组件列表,一次只绘制一个组件并与之交互。selector给出所选组件的索引。这对于实现选项卡很有效。同Toggle、Menu组件一起使用可实现选项卡切换。
Stacked
堆叠的组件列表。变乱会通报到第一个组件,如果未处置惩罚则通报到第二个组件,以此类推。组件的绘制顺序与传入顺序相反。当某个组件获得焦点时,它会被置于最前面,而不会改变其他元素的相对顺序。此组件应与 Window 组件一起使用。
Button 按钮组件
- // 定义按钮组件
- Component Button(ButtonOption options);
- Component Button(ConstStringRef label,
- std::function<void()> on_click,
- ButtonOption options = ButtonOption::Simple());
复制代码 使用示例:
- ftxui::ButtonOption buttonOption = ftxui::ButtonOption::Animated( // 按钮的样式
- ftxui::Color::Black, ftxui::Color::White,
- ftxui::Color::Black, ftxui::Color::Yellow);
- std::function<void()> on_click = [](){ // 点击按钮时被调用
- spdlog::trace("on_click");
- };
- ftxui::Component button_layout = ftxui::Button("Button1", on_click, buttonOption);
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(button_layout);
复制代码
Checkbox 复选框组件
- // 定义复选框组件
- Component Checkbox(CheckboxOption options);
- Component Checkbox(ConstStringRef label,
- bool* checked,
- CheckboxOption options = CheckboxOption::Simple());
复制代码 使用示例:
- bool is_checked = false;// 存储复选框状态
- ftxui::CheckboxOption checkboxOption = ftxui::CheckboxOption::Simple();
- checkboxOption.on_change = [&is_checked](){ // 复选框状态变化时被调用
- spdlog::trace("on_change: {}", is_checked);
- };
- ftxui::Component checkbox_layout = ftxui::Checkbox("Item1", &is_checked, checkboxOption);
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(checkbox_layout);
复制代码
Input 输入框组件
- // 定义输入框组件
- Component Input(InputOption options = {});
- Component Input(StringRef content, InputOption options = {});
- Component Input(StringRef content,
- StringRef placeholder,
- InputOption options = {});
复制代码 使用示例:
- std::string input_data;//存储从输入框获取的内容
- std::string placeholder = "please input data";// 输入框的提示内容
- ftxui::InputOption inputOption = ftxui::InputOption::Spacious(); // 输入框配置选项
- inputOption.password = false;// 非密码模式
- inputOption.multiline = false;// 非多行模式
- inputOption.insert = false; // 非插入模式
- inputOption.on_change = [&input_data](){ // 输入内容变化时被调用
- spdlog::trace("on_change: {}", input_data);
- };
- inputOption.on_enter = [&input_data](){ // 输入回车时被调用
- spdlog::trace("on_enter: {}", input_data);
- };
- ftxui::Component input_layout = ftxui::Input(&input_data, "please input data", inputOption);
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(input_layout);
复制代码
Menu 菜单组件
- // 定义菜单组件
- Component Menu(MenuOption options);
- Component Menu(ConstStringListRef entries,
- int* selected_,
- MenuOption options = MenuOption::Vertical());
复制代码 使用示例:
- std::vector<std::string> menu = { // 设置要显示的菜单列表
- "menu_item1",
- "menu_item2",
- "menu_item3",
- };
- int selected_index = 0; // 存储选择的菜单选项索引
- ftxui::MenuOption menuOption = ftxui::MenuOption::Vertical();//
- menuOption.on_change = [&selected_index](){ // 选择项改变时被调用
- spdlog::trace("on_change: {}", selected_index);
- };
- menuOption.on_enter = [&selected_index](){ // 输入回车按键时被调用
- spdlog::trace("on_enter: {}", selected_index);
- };
- ftxui::Component menu_layout = ftxui::Menu(menu, &selected_index, menuOption);
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(menu_layout);
复制代码
MenuEntry 菜单选择组件(垂直显示)
- // 定义菜单选项
- Component MenuEntry(MenuEntryOption options);
- Component MenuEntry(ConstStringRef label, MenuEntryOption options = {});
复制代码 使用示例:
- int selected = 0;
- auto menu_layout = ftxui::Container::Vertical({
- ftxui::MenuEntry("menu_entry 1"),
- ftxui::MenuEntry("menu_entry 2"),
- ftxui::MenuEntry("menu_entry 3"),
- }, &selected);
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(menu_layout);
复制代码
Toggle 菜单选择组件(水平显示)
- // 定义水平方向的菜单选项
- Component Toggle(ConstStringListRef entries, int* selected);
复制代码 使用示例:
- std::vector<std::string> menu = { // 设置要显示的菜单列表
- "menu_item1",
- "menu_item2",
- "menu_item3",
- };
- int selected_index = 0; // 存储选择的菜单选项索引
- ftxui::Component toggle_layout = ftxui::Toggle(menu, &selected_index);
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(toggle_layout);
复制代码
Radiobox 单选框组件
- // 定义单选框组件
- Component Radiobox(RadioboxOption options);
- Component Radiobox(ConstStringListRef entries,
- int* selected_,
- RadioboxOption options = {});
复制代码 使用示例:
- std::vector<std::string> radio_list = { // 设置要显示的单选列表
- "radio_item1",
- "radio_item2",
- "radio_item3",
- };
- int selected_index = 0; // 存储选择的菜单选项索引
- ftxui::RadioboxOption radioboxOption = ftxui::RadioboxOption::Simple();// 单选框配置项
- radioboxOption.on_change = [&selected_index](){
- spdlog::trace("on_change: {}", selected_index);
- };
- ftxui::Component radio_layout = ftxui::Radiobox(radio_list, &selected_index, radioboxOption);
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(radio_layout);
复制代码
Dropdown 下拉框组件
- // 定义下拉框组件
- Component Dropdown(ConstStringListRef entries, int* selected);
- Component Dropdown(DropdownOption options);
复制代码 使用示例:
- std::vector<std::string> dropdown_list = { // 设置要显示的下拉菜单列表
- "dropdown_item1",
- "dropdown_item2",
- "dropdown_item3",
- };
- int selected_index = 0; // 存储选择的菜单选项索引
- ftxui::Component dropdown_layout = ftxui::Dropdown(dropdown_list, &selected_index);
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(dropdown_layout);
复制代码
Slider 滑块组件
- // 定义通用Slider滑块组件
- template <typename T>
- Component Slider(SliderOption<T> options);
- // 不使用 `SliderOption` 构造函数的简写
- Component Slider(ConstStringRef label,
- Ref<int> value,
- ConstRef<int> min = 0,
- ConstRef<int> max = 100,
- ConstRef<int> increment = 5);
- Component Slider(ConstStringRef label,
- Ref<float> value,
- ConstRef<float> min = 0.f,
- ConstRef<float> max = 100.f,
- ConstRef<float> increment = 5.f);
- Component Slider(ConstStringRef label,
- Ref<long> value,
- ConstRef<long> min = 0L,
- ConstRef<long> max = 100L,
- ConstRef<long> increment = 5L);
复制代码 使用示例:
- int progress = 0;// 存储当前进度值
- int slider_min = 0; // 配置进度最小值
- int slider_max = 100; // 配置进度最大值
- int slider_increment = 1; // 配置进度单步长度
- ftxui::Component slider_layout = ftxui::Slider("slider_progress", &progress, slider_min, slider_max, slider_increment);
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(slider_layout);
复制代码
ResizableSplit 缩放和分割组件
- // 定义可缩放的分割组件
- Component ResizableSplit(ResizableSplitOption options);
- Component ResizableSplitLeft(Component main, Component back, int* main_size);
- Component ResizableSplitRight(Component main, Component back, int* main_size);
- Component ResizableSplitTop(Component main, Component back, int* main_size);
- Component ResizableSplitBottom(Component main, Component back, int* main_size);
复制代码 使用示例:
- ftxui::ResizableSplitOption resizableSplitOption;
- // 主Component
- resizableSplitOption.main = ftxui::Renderer([]{ return ftxui::paragraph("this is long long long right text..."); });
- // 副Component
- resizableSplitOption.back = ftxui::Renderer([]{ return ftxui::paragraph("this is long long long left..."); });
- // 设置偏移方向: 从上向下
- resizableSplitOption.direction = ftxui::Direction::Up;
- // 设置主Component的分割的大小: 2个单位
- resizableSplitOption.main_size = 2;
- // 设置自定义分割线样式: 虚线
- resizableSplitOption.separator_func = []{ return ftxui::separatorStyled(ftxui::BorderStyle::DASHED); };
- ftxui::Component resizableSplit_layout = ftxui::ResizableSplit(resizableSplitOption);
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(resizableSplit_layout);
复制代码
Renderer 渲染Element转为组件
- // 渲染Element元素,转为组件
- Component Renderer(Component child, std::function<Element()>);
- Component Renderer(std::function<Element()>);
- Component Renderer(std::function<Element(bool /* focused */)>);
- ComponentDecorator Renderer(ElementDecorator);
复制代码 使用示例:
- std::string text = "this is content..."; // 文本内容
- // 将 Element 元素 转为 Component 组件。
- ftxui::Component layout = ftxui::Renderer([&text](){
- return ftxui::text(text);
- });
- auto screen = ftxui::ScreenInteractive::TerminalOutput();
- screen.Loop(layout);
复制代码
CatchEvent 变乱捕获
- // 捕获组件的事件
- Component CatchEvent(Component child, std::function<bool(Event)>);
- ComponentDecorator CatchEvent(std::function<bool(Event)> on_event);
复制代码 使用示例:
根据screen_interactive.cpp源码可以确定,需要处置惩罚Ctrl+C的Event变乱并将force_handle_ctrl_c设为false才可以屏蔽FTXUI触发应用退出。
- std::string paragraph_text = "This is paragraph text...";
- auto paragraph_view = ftxui::Renderer([¶graph_text](){
- return ftxui::paragraph(paragraph_text) | ftxui::border;
- });
-
- auto screen = ftxui::ScreenInteractive::Fullscreen();
- screen.ForceHandleCtrlC(false);// 设置false强制FTXUI不处理Ctrl+C信号
- screen.ForceHandleCtrlZ(false);// 设置false强制FTXUI不处理Ctrl+Z信号
- auto component = CatchEvent(paragraph_view, [&](ftxui::Event event) {
- if (event == ftxui::Event::CtrlC) {
- spdlog::trace("CtrlC");
- screen.ExitLoopClosure()();
- return true;// 返回true表示已经处理 Ctrl+C 事件,不让FTXUI触发ABORT退出信号
- }
- if (event == ftxui::Event::CtrlZ) {
- spdlog::trace("CtrlZ");
- screen.ExitLoopClosure()();
- return true;// 返回true表示已经处理 Ctrl+Z 事件,不让FTXUI触发ABORT退出信号
- }
- return false;
- });
- screen.Loop(component);
复制代码
Maybe 可隐蔽组件
- // 隐藏一个组件。仅当 show=true 时才显示被隐藏的组件
- Component Maybe(Component, const bool* show);
- Component Maybe(Component, std::function<bool()>);
- ComponentDecorator Maybe(const bool* show);
- ComponentDecorator Maybe(std::function<bool()>);
复制代码 使用示例:
- bool show_status = true; // 控制paragraph_layout显示/隐藏
- auto button_show = ftxui::Button("Show", [&show_status](){
- show_status = true;
- }, ftxui::ButtonOption::Border());
- auto button_hidden = ftxui::Button("Hidden", [&show_status](){
- show_status = false;
- }, ftxui::ButtonOption::Border());
- auto button_layout = ftxui::Container::Horizontal({
- button_show,
- button_hidden,
- });
- std::string paragraph_text = "This is paragraph text...";
- auto paragraph_layout = ftxui::Renderer([¶graph_text](){
- return ftxui::paragraph(paragraph_text) | ftxui::border;
- });
- auto layout = ftxui::Container::Vertical({
- button_layout,
- ftxui::Maybe(paragraph_layout, &show_status),// 根据show_status变量状态控制是否隐藏paragraph_layout
- });
- auto screen = ftxui::ScreenInteractive::Fullscreen();
- screen.ForceHandleCtrlC(false);
- screen.ForceHandleCtrlZ(false);
- auto component = CatchEvent(layout, [&](ftxui::Event event) {
- if (event == ftxui::Event::CtrlC) {
- spdlog::trace("CtrlC");
- screen.ExitLoopClosure()();
- return true;
- }
- if (event == ftxui::Event::CtrlZ) {
- spdlog::trace("CtrlZ");
- screen.ExitLoopClosure()();
- return true;
- }
- return false;
- });
- screen.Loop(component);
复制代码

Modal 叠加组件
- // 叠加一个组件。在main组件的外层叠加显示一个modal组件,仅当 show_modal=true 时才会叠加显示。
- Component Modal(Component main, Component modal, const bool* show_modal);
- ComponentDecorator Modal(Component modal, const bool* show_modal);
复制代码 使用示例:
- bool show_status = true; // 控制是否叠加model_layout
- auto button_show = ftxui::Button("Show", [&show_status](){
- show_status = true;
- }, ftxui::ButtonOption::Border());
- auto button_hidden = ftxui::Button("Hidden", [&show_status](){
- show_status = false;
- }, ftxui::ButtonOption::Border());
- auto button_layout = ftxui::Container::Horizontal({
- button_show,
- button_hidden,
- });
- std::string paragraph_text = "This is paragraph text...";
- auto paragraph_layout = ftxui::Renderer([¶graph_text](){
- return ftxui::paragraph(paragraph_text) | ftxui::border;
- });
- std::string model_text = "This is model_text text...";
- auto model_layout = ftxui::Renderer([&model_text](){
- return ftxui::paragraph(model_text) | ftxui::border;
- });
- auto layout = ftxui::Container::Vertical({
- button_layout,
- ftxui::Modal(paragraph_layout, model_layout, &show_status),// 根据show_status变量状态控制是否将model_layout叠加到paragraph_layout外层
- });
- auto screen = ftxui::ScreenInteractive::Fullscreen();
- screen.ForceHandleCtrlC(false);
- screen.ForceHandleCtrlZ(false);
- auto component = CatchEvent(layout, [&](ftxui::Event event) {
- if (event == ftxui::Event::CtrlC) {
- spdlog::trace("CtrlC");
- screen.ExitLoopClosure()();
- return true;
- }
- if (event == ftxui::Event::CtrlZ) {
- spdlog::trace("CtrlZ");
- screen.ExitLoopClosure()();
- return true;
- }
- return false;
- });
- screen.Loop(component);
复制代码

Collapsible 可折叠组件
- // 可折叠组件。它显示一个带箭头的复选框。一旦激活,子项就会显示出来。
- Component Collapsible(ConstStringRef label,
- Component child,
- Ref<bool> show = false);
复制代码 使用示例:
- bool show_status = true; // 控制paragraph_layout显示/折叠
- auto button_show = ftxui::Button("Show", [&show_status](){
- show_status = true;
- }, ftxui::ButtonOption::Border());
- auto button_hidden = ftxui::Button("Hidden", [&show_status](){
- show_status = false;
- }, ftxui::ButtonOption::Border());
- auto button_layout = ftxui::Container::Horizontal({
- button_show,
- button_hidden,
- });
- std::string paragraph_text = "This is paragraph text...";
- auto paragraph_layout = ftxui::Renderer([¶graph_text](){
- return ftxui::paragraph(paragraph_text) | ftxui::border;
- });
- auto layout = ftxui::Container::Vertical({
- button_layout,
- ftxui::Collapsible("paragraph", paragraph_layout, &show_status),// 根据show_status变量状态控制是否折叠paragraph_layout
- });
- auto screen = ftxui::ScreenInteractive::Fullscreen();
- screen.ForceHandleCtrlC(false);
- screen.ForceHandleCtrlZ(false);
- auto component = CatchEvent(layout, [&](ftxui::Event event) {
- if (event == ftxui::Event::CtrlC) {
- spdlog::trace("CtrlC");
- screen.ExitLoopClosure()();
- return true;
- }
- if (event == ftxui::Event::CtrlZ) {
- spdlog::trace("CtrlZ");
- screen.ExitLoopClosure()();
- return true;
- }
- return false;
- });
- screen.Loop(component);
复制代码

Hoverable 可包裹组件
- // 包裹一个组件。使其能够知道鼠标是否悬停在组件上。
- Component Hoverable(Component component, bool* hover);
- Component Hoverable(Component component,
- std::function<void()> on_enter,
- std::function<void()> on_leave);
- Component Hoverable(Component component, //
- std::function<void(bool)> on_change);
- ComponentDecorator Hoverable(bool* hover);
- ComponentDecorator Hoverable(std::function<void()> on_enter,
- std::function<void()> on_leave);
- ComponentDecorator Hoverable(std::function<void(bool)> on_change);
复制代码 使用示例:
- std::string paragraph_text = "This is paragraph text...";
- auto paragraph_layout = ftxui::Renderer([¶graph_text](){
- return ftxui::paragraph(paragraph_text) | ftxui::border;
- });
- auto layout = ftxui::Container::Vertical({
- ftxui::Hoverable(paragraph_layout,
- [](){ spdlog::trace("on_enter"); }, // 当鼠标进入paragraph_layout区域时被调用
- [](){ spdlog::trace("on_leave"); }), // 当鼠标离开paragraph_layout区域时被调用
- });
- auto screen = ftxui::ScreenInteractive::Fullscreen();
- screen.ForceHandleCtrlC(false);
- screen.ForceHandleCtrlZ(false);
- auto component = CatchEvent(layout, [&](ftxui::Event event) {
- if (event == ftxui::Event::CtrlC) {
- spdlog::trace("CtrlC");
- screen.ExitLoopClosure()();
- return true;
- }
- if (event == ftxui::Event::CtrlZ) {
- spdlog::trace("CtrlZ");
- screen.ExitLoopClosure()();
- return true;
- }
- return false;
- });
- screen.Loop(component);
复制代码
Window 可拖动窗口
- // 可拖动/可调整大小的窗口。
- // 要使用多个窗口,必须使用 `Container::Stacked({...})` 组件将它们堆叠起来;
- Component Window(WindowOptions option);
复制代码 使用示例:
- std::string paragraph_text = "This is paragraph text...";
- auto paragraph_layout = ftxui::Renderer([¶graph_text](){
- return ftxui::paragraph(paragraph_text) | ftxui::border;
- });
- ftxui::WindowOptions windowOptions;
- windowOptions.inner = paragraph_layout;
- windowOptions.title = "paragraph";
- auto layout = ftxui::Window(windowOptions);
- auto screen = ftxui::ScreenInteractive::Fullscreen();
- screen.ForceHandleCtrlC(false);
- screen.ForceHandleCtrlZ(false);
- auto component = CatchEvent(layout, [&](ftxui::Event event) {
- if (event == ftxui::Event::CtrlC) {
- spdlog::trace("CtrlC");
- screen.ExitLoopClosure()();
- return true;
- }
- if (event == ftxui::Event::CtrlZ) {
- spdlog::trace("CtrlZ");
- screen.ExitLoopClosure()();
- return true;
- }
- return false;
- });
- screen.Loop(component);
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|