FTXUI 条记(五)——基本交互组件

打印 上一主题 下一主题

主题 1893|帖子 1893|积分 5679

component_base.hpp

ComponentBase 类

界说组件基类。
  1. class ComponentBase {
  2. public:
  3.   // 必须显式构造。
  4.   explicit ComponentBase(Components children)
  5.       : children_(std::move(children)) {}
  6.   virtual ~ComponentBase();
  7.   ComponentBase() = default;
  8.   // 组件不可复制/移动。
  9.   ComponentBase(const ComponentBase&) = delete;
  10.   ComponentBase(ComponentBase&&) = delete;
  11.   ComponentBase& operator=(const ComponentBase&) = delete;
  12.   ComponentBase& operator=(ComponentBase&&) = delete;
  13.   // ------------- Component 层级关系 -----------------------
  14.   // 获取当前的父级Component组件
  15.   ComponentBase* Parent() const;
  16.   // 获取第 i 个子级Component组件
  17.   Component& ChildAt(size_t i);
  18.   // 获取子级Component组件的数量
  19.   size_t ChildCount() const;
  20.   // 返回当前组件在其父级Component中的索引。如果没有父级,则返回 -1。
  21.   int Index() const;
  22.   // 添加子级Component组件
  23.   void Add(Component children);
  24.   // 将当前组件从父级Component中分离
  25.   void Detach();
  26.   // 将所有子级Component分离
  27.   void DetachAllChildren();
  28.   // 渲染组件。
  29.   Element Render();
  30.   // 重写此函数,完成“Render”绘制功能
  31.   virtual Element OnRender();
  32.   // 处理事件。
  33.   // 默认情况下,减少具有懒惰 OR 的子级Component。
  34.   // 返回该事件是否已经被处理。
  35.   virtual bool OnEvent(Event);
  36.   // 处理动画步骤。
  37.   virtual void OnAnimation(animation::Params& params);
  38.   // ------------------- 焦点管理 ----------------------------------------------------------
  39.   // 如果此组件包含子组件,则这指示哪一个是活动的,如果没有活动,则为 nullptr。
  40.   //
  41.   // 如果根组件的 ActiveChild() 链包含该对象,我们就说该元素具有焦点。
  42.   virtual Component ActiveChild();
  43.   // 当组件包含可聚焦元素时返回 true。
  44.   // 使用键盘导航时,无法聚焦的组件将被跳过。
  45.   virtual bool Focusable() const;
  46.   // 判断当前组件是否在其父级的子组件列表中处于Active状态
  47.   bool Active() const;
  48.   // 判断所有祖先是否都处于Active状态。
  49.   bool Focused() const;
  50.   // 让 |child| 成为“Active”的一个。
  51.   virtual void SetActiveChild(ComponentBase* child);
  52.   // 设置指定的子级Component为Active状态。
  53.   void SetActiveChild(Component child);
  54.   // Configure all the ancestors to give focus to this component.
  55.   // 配置所有祖先将焦点放在当前该组件上。
  56.   void TakeFocus();
  57. protected:
  58.   CapturedMouse CaptureMouse(const Event& event);
  59.   Components children_;
  60. private:
  61.   ComponentBase* parent_ = nullptr;
  62.   bool in_render = false;
  63. };
复制代码
receiver.hpp

界说了消息变乱循环的基本功能,包罗消息发送和吸取吸取的两个类。
SenderImpl类 和 ReceiverImpl 类

SenderImpl类实例用于实现发送消息功能。
ReceiverImpl类实例用于实现吸取消息功能。
  1. template <class T>
  2. class SenderImpl {
  3. public:
  4.   SenderImpl(const SenderImpl&) = delete;
  5.   SenderImpl(SenderImpl&&) = delete;
  6.   SenderImpl& operator=(const SenderImpl&) = delete;
  7.   SenderImpl& operator=(SenderImpl&&) = delete;
  8.   void Send(T t) { receiver_->Receive(std::move(t)); }
  9.   ~SenderImpl() { receiver_->ReleaseSender(); }
  10.   Sender<T> Clone() { return receiver_->MakeSender(); }
  11. private:
  12.   friend class ReceiverImpl<T>;
  13.   explicit SenderImpl(ReceiverImpl<T>* consumer) : receiver_(consumer) {}
  14.   ReceiverImpl<T>* receiver_;
  15. };
复制代码
  1. template <class T>
  2. class ReceiverImpl {
  3. public:
  4.   Sender<T> MakeSender() {
  5.     std::unique_lock<std::mutex> lock(mutex_);
  6.     senders_++;
  7.     return std::unique_ptr<SenderImpl<T>>(new SenderImpl<T>(this));
  8.   }
  9.   ReceiverImpl() = default;
  10.   bool Receive(T* t) {
  11.     while (senders_ || !queue_.empty()) {
  12.       std::unique_lock<std::mutex> lock(mutex_);
  13.       if (queue_.empty()) {
  14.         notifier_.wait(lock);
  15.       }
  16.       if (queue_.empty()) {
  17.         continue;
  18.       }
  19.       *t = std::move(queue_.front());
  20.       queue_.pop();
  21.       return true;
  22.     }
  23.     return false;
  24.   }
  25.   bool ReceiveNonBlocking(T* t) {
  26.     std::unique_lock<std::mutex> lock(mutex_);
  27.     if (queue_.empty()) {
  28.       return false;
  29.     }
  30.     *t = queue_.front();
  31.     queue_.pop();
  32.     return true;
  33.   }
  34.   bool HasPending() {
  35.     std::unique_lock<std::mutex> lock(mutex_);
  36.     return !queue_.empty();
  37.   }
  38.   bool HasQuitted() {
  39.     std::unique_lock<std::mutex> lock(mutex_);
  40.     return queue_.empty() && !senders_;
  41.   }
  42. private:
  43.   friend class SenderImpl<T>;
  44.   void Receive(T t) {
  45.     {
  46.       std::unique_lock<std::mutex> lock(mutex_);
  47.       queue_.push(std::move(t));
  48.     }
  49.     notifier_.notify_one();
  50.   }
  51.   void ReleaseSender() {
  52.     senders_--;
  53.     notifier_.notify_one();
  54.   }
  55.   std::mutex mutex_;
  56.   std::queue<T> queue_;
  57.   std::condition_variable notifier_;
  58.   std::atomic<int> senders_{0};
  59. };
复制代码
创建消息收发的组件实例。
  1. template <class T>
  2. Receiver<T> MakeReceiver() {
  3.   return std::make_unique<ReceiverImpl<T>>();
  4. }
复制代码
使用示例
初始化消息收发的组件实例
  1. // 实例化 std::string 类型的消息组件。
  2. auto receiver = MakeReceiver<std:string>();
  3. // 通过接收对象创建两个发送对象,发送对象可以在其他线程执行消息发送操作。
  4. auto sender_1= receiver->MakeSender();
  5. auto sender_2 = receiver->MakeSender();
复制代码
  1. // (线程1)发送模块
  2. sender_1->Send("hello");
  3. // (线程2)发送模块
  4. sender_2->Send("world");
复制代码
  1. // (线程3)接收模块
  2. //只要存在Sender且存在消息队列有消息,则Receive函数返回 true。
  3. std::string data;
  4. while(receiver->Receive(&data)) {
  5.    printf("recv: %s\n", data.c_str());
  6. }
复制代码
mouse.hpp

界说鼠标类
Mouse 类

界说鼠标的基本信息。
  1. // 定义鼠标按键类型
  2. struct Mouse {
  3.   enum Button {
  4.     Left = 0,
  5.     Middle = 1,
  6.     Right = 2,
  7.     None = 3,
  8.     WheelUp = 4,
  9.     WheelDown = 5,
  10.     WheelLeft = 6,   /// 仅支持终端。
  11.     WheelRight = 7,  /// 仅支持终端。
  12.   };
  13.   // 定义鼠标按键动作
  14.   enum Motion {
  15.     Released = 0,
  16.     Pressed = 1,
  17.     Moved = 2,
  18.   };
  19.   // Button 默认鼠标按键
  20.   Button button = Button::None;
  21.   // Motion 默认鼠标动作
  22.   Motion motion = Motion::Pressed;
  23.   // Modifiers: 修饰符信息
  24.   bool shift = false;
  25.   bool meta = false;
  26.   bool control = false;
  27.   // Coordinates: 坐标信息
  28.   int x = 0;
  29.   int y = 0;
  30. };
复制代码
event.hpp

界说变乱。
Event 类

界说变乱的基本信息。
  1. struct Event {
  2.   // -------- 构造函数部分 ----------------------------------------------
  3.   // 与给定键入字符串对应的事件。用户输入的字符。
  4.   static Event Character(std::string);
  5.   // 与给定键入字符对应的事件。用户输入的字符。
  6.   static Event Character(char);
  7.   // 与给定键入宽字符对应的事件。用户输入的字符。
  8.   static Event Character(wchar_t);
  9.   // 自定义事件,其含义由库的用户定义。开发人员定义的任意字符序列。
  10.   static Event Special(std::string);
  11.   // 与给定键入字符串对应的事件。终端发送的字符序列。鼠标状态。
  12.   static Event Mouse(std::string, Mouse mouse);
  13.   // 与给定键入字符串对应的事件。终端发送的字符序列。终端焦点位置。
  14.   static Event CursorPosition(std::string, int x, int y);  // Internal
  15.   // 与终端 DCS(设备控制字符串)对应的事件。终端发送的字符序列。终端焦点形状
  16.   static Event CursorShape(std::string, int shape);     // Internal
  17.   // --- 键盘的方向按键 ---
  18.   static const Event ArrowLeft;
  19.   static const Event ArrowRight;
  20.   static const Event ArrowUp;
  21.   static const Event ArrowDown;
  22.   // 键盘的控制+方向按键
  23.   static const Event ArrowLeftCtrl;
  24.   static const Event ArrowRightCtrl;
  25.   static const Event ArrowUpCtrl;
  26.   static const Event ArrowDownCtrl;
  27.   // --- 键盘的其他按键 ---
  28.   static const Event Backspace;
  29.   static const Event Delete;
  30.   static const Event Return;
  31.   static const Event Escape;
  32.   static const Event Tab;
  33.   static const Event TabReverse;
  34.   // --- 键盘的导航按键 ---
  35.   static const Event Insert;
  36.   static const Event Home;
  37.   static const Event End;
  38.   static const Event PageUp;
  39.   static const Event PageDown;
  40.   // --- 键盘的功能按键 ---
  41.   static const Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12;
  42.   // --- 键盘的控制+字母按键 ---
  43.   static const Event a, A, CtrlA, AltA, CtrlAltA;
  44.   static const Event b, B, CtrlB, AltB, CtrlAltB;
  45.   static const Event c, C, CtrlC, AltC, CtrlAltC;
  46.   static const Event d, D, CtrlD, AltD, CtrlAltD;
  47.   static const Event e, E, CtrlE, AltE, CtrlAltE;
  48.   static const Event f, F, CtrlF, AltF, CtrlAltF;
  49.   static const Event g, G, CtrlG, AltG, CtrlAltG;
  50.   static const Event h, H, CtrlH, AltH, CtrlAltH;
  51.   static const Event i, I, CtrlI, AltI, CtrlAltI;
  52.   static const Event j, J, CtrlJ, AltJ, CtrlAltJ;
  53.   static const Event k, K, CtrlK, AltK, CtrlAltK;
  54.   static const Event l, L, CtrlL, AltL, CtrlAltL;
  55.   static const Event m, M, CtrlM, AltM, CtrlAltM;
  56.   static const Event n, N, CtrlN, AltN, CtrlAltN;
  57.   static const Event o, O, CtrlO, AltO, CtrlAltO;
  58.   static const Event p, P, CtrlP, AltP, CtrlAltP;
  59.   static const Event q, Q, CtrlQ, AltQ, CtrlAltQ;
  60.   static const Event r, R, CtrlR, AltR, CtrlAltR;
  61.   static const Event s, S, CtrlS, AltS, CtrlAltS;
  62.   static const Event t, T, CtrlT, AltT, CtrlAltT;
  63.   static const Event u, U, CtrlU, AltU, CtrlAltU;
  64.   static const Event v, V, CtrlV, AltV, CtrlAltV;
  65.   static const Event w, W, CtrlW, AltW, CtrlAltW;
  66.   static const Event x, X, CtrlX, AltX, CtrlAltX;
  67.   static const Event y, Y, CtrlY, AltY, CtrlAltY;
  68.   static const Event z, Z, CtrlZ, AltZ, CtrlAltZ;
  69.   // --- 自定义按键 ---
  70.   static const Event Custom;
  71.   //--- 比较按键事件相关的函数 ---------------------------------------------------------
  72.   bool operator==(const Event& other) const { return input_ == other.input_; }
  73.   bool operator!=(const Event& other) const { return !operator==(other); }
  74.   bool operator<(const Event& other) const { return input_ < other.input_; }
  75.   // 获取事件的字符串内容
  76.   const std::string& input() const { return input_; }
  77.   // 判断事件是否为键盘按键触发类型
  78.   bool is_character() const { return type_ == Type::Character; }
  79.   // 获取事件的字符串内容
  80.   std::string character() const { return input_; }
  81.   // 判断事件是否为鼠标触发类型
  82.   bool is_mouse() const { return type_ == Type::Mouse; }
  83.   // 获取事件的鼠标信息
  84.   struct Mouse& mouse() { return data_.mouse; }
  85.   // --- 判断事件是否存在焦点信息 -----------------------------------------------
  86.   bool is_cursor_position() const { return type_ == Type::CursorPosition; }
  87.   // 获取事件的焦点坐标
  88.   int cursor_x() const { return data_.cursor.x; }
  89.   int cursor_y() const { return data_.cursor.y; }
  90.   // 判断事件是否存在焦点形状
  91.   bool is_cursor_shape() const { return type_ == Type::CursorShape; }
  92.   // 获取事件的焦点形状
  93.   int cursor_shape() const { return data_.cursor_shape; }
  94.   // 获取Debug字符串内容
  95.   std::string DebugString() const;
  96.   //--- 交互界面句柄 ----------------------------------------------------------
  97.   ScreenInteractive* screen_ = nullptr;
  98. private:
  99.   friend ComponentBase;
  100.   friend ScreenInteractive;
  101.   enum class Type {
  102.     Unknown,
  103.     Character,           // 键盘字符信息
  104.     Mouse,                // 鼠标信息
  105.     CursorPosition,   // 焦点位置
  106.     CursorShape,     // 焦点形状
  107.   };
  108.   Type type_ = Type::Unknown; // 存储事件的类型
  109.   struct Cursor {
  110.     int x = 0;
  111.     int y = 0;
  112.   };//定义焦点坐标
  113.   union {
  114.     struct Mouse mouse;
  115.     struct Cursor cursor;
  116.     int cursor_shape;
  117.   } data_ = {}; // 存储事件的信息
  118.   std::string input_; // 存储事件对应字符串内容
  119. };
复制代码
screen_interactive.hpp

界说终端界面交互的底子功能
ScreenInteractive 类

该类继承了Screen类,提供了终端界面渲染和交互的基本功能。
  1. class ScreenInteractive : public Screen {
  2. public:
  3.   // 创建占用完整Component大小的终端界面交互。
  4.   static ScreenInteractive FitComponent();
  5.   
  6.   // 创建占用Screen终端宽度的终端界面交互(终端界面的高度取决于Component高度)。
  7.   static ScreenInteractive TerminalOutput();
  8.   // 创建指定大小区域的终端界面交互
  9.   static ScreenInteractive FixedSize(int dimx, int dimy);
  10.   
  11.   // 创建占用完整Screen终端大小的终端界面交互。(默认使用双缓冲机制)
  12.   static ScreenInteractive Fullscreen();
  13.   //创建占用完整Screen终端大小的终端界面交互。主屏幕缓冲区正在被占用。
  14.   // (不使用双缓冲)这意味着如果调整终端大小,先前的内容可能会与终端内容混淆。
  15.   static ScreenInteractive FullscreenPrimaryScreen();
  16.   
  17.   //创建占用完整Screen终端大小的终端界面交互。
  18.   // (双缓冲机制)这将使用备用屏幕缓冲区来避免干扰终端内容。
  19.   static ScreenInteractive FullscreenAlternateScreen();
  20.   // 可选. 必须在执行Loop()前调用。该函数作用用于控制是否进行跟踪鼠标控制。
  21.   void TrackMouse(bool enable = true);
  22.   // 返回当前活动屏幕,如果没有则返回 nullptr。
  23.   static ScreenInteractive* Active();
  24.   // 创建Loop循环,并启动主循环进行Component组件交互。
  25.   void Loop(Component);
  26.   // 停止主循环。
  27.   void Exit();
  28.   // 返回停止主循环的回调函数。
  29.   Closure ExitLoopClosure();
  30.   // 发布要由主循环执行的任务。
  31.   void Post(Task task);
  32.   // 发布要由主循环执行的事件(按键事件、鼠标事件)。
  33.   void PostEvent(Event event);
  34.   // 发布要由主循环执行的动画。
  35.   void RequestAnimationFrame();
  36.   
  37.   // 尝试获取能够捕获鼠标的独特锁。如果鼠标尚未被捕获,则为唯一锁,否则为空。
  38.   CapturedMouse CaptureMouse();
  39.   // 装饰一个函数。输出的函数将以与输入函数类似的方式执行,但当前活动的屏幕终端钩子会被暂时卸载。
  40.   Closure WithRestoredIO(Closure);
  41.   // FTXUI 实现了 Ctrl-C 和 Ctrl-Z 的处理程序。
  42.   // 默认情况下,即使组件捕获了事件,这些处理程序也会执行。
  43.   // 这避免了用户处理每个事件时被应用程序捕获。但是在某些情况下,应用程序可能希望自行处理这些事件。
  44.   // 在这种情况下,应用程序可以通过调用以下函数并设置 force=true 来强制 FTXUI 不处理这些事件。
  45.   void ForceHandleCtrlC(bool force);
  46.   void ForceHandleCtrlZ(bool force);
  47.   // 选中功能
  48.   std::string GetSelection();
  49.   void SelectionChange(std::function<void()> callback);
  50. private:
  51.   void ExitNow();
  52.   void Install();
  53.   void Uninstall();
  54.   void PreMain();
  55.   void PostMain();
  56.   bool HasQuitted();
  57.   void RunOnce(Component component);
  58.   void RunOnceBlocking(Component component);
  59.   void HandleTask(Component component, Task& task);
  60.   bool HandleSelection(bool handled, Event event);
  61.   void RefreshSelection();
  62.   void Draw(Component component);
  63.   void ResetCursorPosition();
  64.   void Signal(int signal);
  65.   ScreenInteractive* suspended_screen_ = nullptr;
  66.   enum class Dimension {
  67.     FitComponent,
  68.     Fixed,
  69.     Fullscreen,
  70.     TerminalOutput,
  71.   };
  72.   Dimension dimension_ = Dimension::Fixed;
  73.   bool use_alternative_screen_ = false;
  74.   ScreenInteractive(int dimx,
  75.                     int dimy,
  76.                     Dimension dimension,
  77.                     bool use_alternative_screen);
  78.   bool track_mouse_ = true;
  79.   Sender<Task> task_sender_;
  80.   Receiver<Task> task_receiver_;
  81.   std::string set_cursor_position;
  82.   std::string reset_cursor_position;
  83.   std::atomic<bool> quit_{false};
  84.   std::thread event_listener_;
  85.   std::thread animation_listener_;
  86.   bool animation_requested_ = false;
  87.   animation::TimePoint previous_animation_time_;
  88.   int cursor_x_ = 1;
  89.   int cursor_y_ = 1;
  90.   bool mouse_captured = false;
  91.   bool previous_frame_resized_ = false;
  92.   bool frame_valid_ = false;
  93.   bool force_handle_ctrl_c_ = true;
  94.   bool force_handle_ctrl_z_ = true;
  95.   // The style of the cursor to restore on exit.
  96.   int cursor_reset_shape_ = 1;
  97.   // Selection API:
  98.   CapturedMouse selection_pending_;
  99.   struct SelectionData {
  100.     int start_x = -1;
  101.     int start_y = -1;
  102.     int end_x = -2;
  103.     int end_y = -2;
  104.     bool empty = true;
  105.     bool operator==(const SelectionData& other) const;
  106.     bool operator!=(const SelectionData& other) const;
  107.   };
  108.   SelectionData selection_data_;
  109.   SelectionData selection_data_previous_;
  110.   std::unique_ptr<Selection> selection_;
  111.   std::function<void()> selection_on_change_;
  112.   friend class Loop;
  113. public:
  114.   class Private {
  115.    public:
  116.     static void Signal(ScreenInteractive& s, int signal) { s.Signal(signal); }
  117.   };
  118.   friend Private;
  119. };
复制代码
loop.hpp

Loop 类

界说Loop变乱循环。
  1. class Loop {
  2. public:
  3.   Loop(ScreenInteractive* screen, Component component);
  4.   ~Loop();
  5.     // 此类不可复制/移动。
  6.   Loop(const Loop&) = default;
  7.   Loop(Loop&&) = delete;
  8.   Loop& operator=(Loop&&) = delete;
  9.   Loop(const ScreenInteractive&) = delete;
  10.   Loop& operator=(const Loop&) = delete;
  11.   
  12.   // 判断循环是否已经退出
  13.   bool HasQuitted();
  14.   // 执行循环。使“组件”处理每个待处理的任务/事件。如果前一帧无效,则可能会绘制新的一帧。
  15.   void RunOnce();
  16.   // 等待至少一个事件被处理并执行Loop::RunOnce()
  17.   void RunOnceBlocking();
  18.   // 执行循环,阻塞当前线程,直到循环退出。
  19.   void Run();
  20.   
  21. private:
  22.   ScreenInteractive* screen_;// 存储当前循环的终端交互界面
  23.   Component component_;//存储当前事件循环的组件。
  24. };
复制代码
animation.hpp

界说动画显示的功能以及算法。
  1. // 获取当前激活的ScreenInteractive界面,执行动画显示。
  2. void RequestAnimationFrame();
复制代码
  1. using Clock = std::chrono::steady_clock;
  2. using TimePoint = std::chrono::time_point<Clock>;
  3. using Duration = std::chrono::duration<float>;
  4. // 定义时长参数
  5. class Params {
  6. public:
  7.   explicit Params(Duration duration) : duration_(duration) {}
  8.   /// The duration this animation step represents.
  9.   Duration duration() const { return duration_; }
  10. private:
  11.   Duration duration_;
  12. };
复制代码
  1. // 定义动画的算法库
  2. namespace easing {
  3. using Function = std::function<float(float)>;
  4. // Linear interpolation (no easing)
  5. float Linear(float p);
  6. // Quadratic easing; p^2
  7. float QuadraticIn(float p);
  8. float QuadraticOut(float p);
  9. float QuadraticInOut(float p);
  10. // Cubic easing; p^3
  11. float CubicIn(float p);
  12. float CubicOut(float p);
  13. float CubicInOut(float p);
  14. // Quartic easing; p^4
  15. float QuarticIn(float p);
  16. float QuarticOut(float p);
  17. float QuarticInOut(float p);
  18. // Quintic easing; p^5
  19. float QuinticIn(float p);
  20. float QuinticOut(float p);
  21. float QuinticInOut(float p);
  22. // Sine wave easing; sin(p * PI/2)
  23. float SineIn(float p);
  24. float SineOut(float p);
  25. float SineInOut(float p);
  26. // Circular easing; sqrt(1 - p^2)
  27. float CircularIn(float p);
  28. float CircularOut(float p);
  29. float CircularInOut(float p);
  30. // Exponential easing, base 2
  31. float ExponentialIn(float p);
  32. float ExponentialOut(float p);
  33. float ExponentialInOut(float p);
  34. // Exponentially-damped sine wave easing
  35. float ElasticIn(float p);
  36. float ElasticOut(float p);
  37. float ElasticInOut(float p);
  38. // Overshooting cubic easing;
  39. float BackIn(float p);
  40. float BackOut(float p);
  41. float BackInOut(float p);
  42. // Exponentially-decaying bounce easing
  43. float BounceIn(float p);
  44. float BounceOut(float p);
  45. float BounceInOut(float p);
  46. }  // namespace easing
复制代码
  1. // 定义动画显示参数
  2. class Animator {
  3. public:
  4.   explicit Animator(float* from,
  5.                     float to = 0.f,
  6.                     Duration duration = std::chrono::milliseconds(250),
  7.                     easing::Function easing_function = easing::Linear,
  8.                     Duration delay = std::chrono::milliseconds(0));
  9.   void OnAnimation(Params&);
  10.   float to() const { return to_; }
  11. private:
  12.   float* value_;
  13.   float from_;
  14.   float to_;
  15.   Duration duration_;
  16.   easing::Function easing_function_;
  17.   Duration current_;
  18. };
复制代码
component_options.hpp

界说component的options配置信息。
EntryState 类

界说组件的状态、激活、焦点状态配置信息。
  1. struct EntryState {
  2.   std::string label;  ///< 要显示的标签。
  3.   bool state;         ///< 按钮/复选框/单选框的状态
  4.   bool active;        ///< 该条目是否为活动条目。
  5.   bool focused;       ///< 该条目是否是用户关注的条目。
  6.   int index;          ///< 适用时条目的索引或 -1。
  7. };
复制代码
UnderlineOption 类

界说下划线的配置项
  1. struct UnderlineOption {
  2.   bool enabled = false;  // 是否使能下划线配置
  3.   Color color_active = Color::White; // Active状态下的颜色
  4.   Color color_inactive = Color::GrayDark; // 非Active状态下的颜色
  5.   animation::easing::Function leader_function =
  6.       animation::easing::QuadraticInOut;
  7.   animation::easing::Function follower_function =
  8.       animation::easing::QuadraticInOut;
  9.   animation::Duration leader_duration = std::chrono::milliseconds(250);
  10.   animation::Duration leader_delay = std::chrono::milliseconds(0);
  11.   animation::Duration follower_duration = std::chrono::milliseconds(250);
  12.   animation::Duration follower_delay = std::chrono::milliseconds(0);
  13.   void SetAnimation(animation::Duration d, animation::easing::Function f);
  14.   void SetAnimationDuration(animation::Duration d);
  15.   void SetAnimationFunction(animation::easing::Function f);
  16.   void SetAnimationFunction(animation::easing::Function f_leader,
  17.                             animation::easing::Function f_follower);
  18. };
复制代码
AnimatedColorOption 类

关于潜在动画颜色的选项。
  1. struct AnimatedColorOption {
  2.   void Set(
  3.       Color inactive,
  4.       Color active,
  5.       animation::Duration duration = std::chrono::milliseconds(250),
  6.       animation::easing::Function function = animation::easing::QuadraticInOut);
  7.   bool enabled = false;
  8.   Color inactive;
  9.   Color active;
  10.   animation::Duration duration = std::chrono::milliseconds(250);
  11.   animation::easing::Function function = animation::easing::QuadraticInOut;
  12. };
  13. struct AnimatedColorsOption {
  14.   AnimatedColorOption background;
  15.   AnimatedColorOption foreground;
  16. };
复制代码
MenuEntryOption 类

MenuEntry 组件的选项。
  1. struct MenuEntryOption {
  2.   ConstStringRef label = "MenuEntry";
  3.   std::function<Element(const EntryState& state)> transform;
  4.   AnimatedColorsOption animated_colors;
  5. };
复制代码
MenuOption 类

菜单组件的选项。
  1. struct MenuOption {
  2.   // 标准构造函数:
  3.   static MenuOption Horizontal();
  4.   static MenuOption HorizontalAnimated();
  5.   static MenuOption Vertical();
  6.   static MenuOption VerticalAnimated();
  7.   static MenuOption Toggle();
  8.   ConstStringListRef entries;  ///> 条目列表。
  9.   Ref<int> selected = 0;       ///> 选定条目的索引。
  10.   // 样式风格:
  11.   UnderlineOption underline;
  12.   MenuEntryOption entries_option;
  13.   Direction direction = Direction::Down;
  14.   std::function<Element()> elements_prefix;
  15.   std::function<Element()> elements_infix;
  16.   std::function<Element()> elements_postfix;
  17.   // 监听器:
  18.   std::function<void()> on_change;  ///> Called when the selected entry changes.
  19.   std::function<void()> on_enter;   ///> Called when the user presses enter.
  20.   Ref<int> focused_entry = 0;
  21. };
复制代码
ButtonOption 类

AnimatedButton 组件的选项。
  1. struct ButtonOption {
  2.   // 标准构造函数
  3.   static ButtonOption Ascii();
  4.   static ButtonOption Simple();
  5.   static ButtonOption Border();
  6.   static ButtonOption Animated();
  7.   static ButtonOption Animated(Color color);
  8.   static ButtonOption Animated(Color background, Color foreground);
  9.   static ButtonOption Animated(Color background,
  10.                                Color foreground,
  11.                                Color background_active,
  12.                                Color foreground_active);
  13.   ConstStringRef label = "Button";
  14.   std::function<void()> on_click = [] {};
  15.   // 样式风格
  16.   std::function<Element(const EntryState&)> transform;
  17.   AnimatedColorsOption animated_colors;
  18. };
复制代码
CheckboxOption 类

复选框组件的选项。
  1. struct CheckboxOption {
  2.   // 标准构造函数
  3.   static CheckboxOption Simple();
  4.   ConstStringRef label = "Checkbox";
  5.   Ref<bool> checked = false;
  6.   // 样式风格:
  7.   std::function<Element(const EntryState&)> transform;
  8.   // 监听器:
  9.   /// Called when the user change the state.
  10.   std::function<void()> on_change = [] {};
  11. };
复制代码
InputState 类

用于界说输入组件的样式。
  1. struct InputState {
  2.   Element element;
  3.   bool hovered;         ///< 输入是否被鼠标悬停。
  4.   bool focused;         ///< 输入是否受到用户的关注。
  5.   bool is_placeholder;  ///< 输入是否为空,显示占位符。
  6. };
复制代码
InputOption 类

输入组件的选项。
  1. struct InputOption {
  2.   // 一组预定义的样式:
  3.   // 创建默认输入样式风格
  4.   static InputOption Default();
  5.   // 黑底白字样式,边距较高:
  6.   static InputOption Spacious();
  7.   /// 输入的内容。
  8.   StringRef content = "";
  9.   /// 当输入为空时的内容。
  10.   StringRef placeholder = "";
  11.   // 样式风格:
  12.   std::function<Element(InputState)> transform;
  13.   Ref<bool> password = false;  ///< 使用‘*’隐藏输入内容。
  14.   Ref<bool> multiline = true;  ///< 输入是否可以是多行。
  15.   Ref<bool> insert = true;     ///< 插入或改写字符模式。
  16.   /// 当内容改变时调用。
  17.   std::function<void()> on_change = [] {};
  18.   /// 当用户按下回车键时调用。
  19.   std::function<void()> on_enter = [] {};
  20.   // 光标的字符位置:
  21.   Ref<int> cursor_position = 0;
  22. };
复制代码
RadioboxOption 类

Radiobox 组件的选项。
  1. struct RadioboxOption {
  2.   // 标准构造函数
  3.   static RadioboxOption Simple();
  4.   // 内容:
  5.   ConstStringListRef entries;
  6.   Ref<int> selected = 0;
  7.   // 样式风格:
  8.   std::function<Element(const EntryState&)> transform;
  9.   // 监听器:
  10.   /// 当选定的条目发生改变时调用。
  11.   std::function<void()> on_change = [] {};
  12.   Ref<int> focused_entry = 0;
  13. };
复制代码
ResizableSplitOption 类

界说可以缩放的配置。
  1. struct ResizableSplitOption {
  2.   Component main;  // 主组件
  3.   Component back;  // 备用组件
  4.   Ref<Direction> direction = Direction::Left;
  5.   Ref<int> main_size =
  6.       (direction() == Direction::Left || direction() == Direction::Right) ? 20
  7.                                                                           : 10;
  8.   std::function<Element()> separator_func = [] { return ::ftxui::separator(); };
  9. };
复制代码
SliderOption 类

Slider 组件的选项。
  1. template <typename T>
  2. struct SliderOption {
  3.   Ref<T> value;
  4.   ConstRef<T> min = T(0);
  5.   ConstRef<T> max = T(100);
  6.   ConstRef<T> increment = (max() - min()) / 20;
  7.   Direction direction = Direction::Right;
  8.   Color color_active = Color::White;
  9.   Color color_inactive = Color::GrayDark;
  10.   std::function<void()> on_change;  ///> 当“值”更新时调用。
  11. };
复制代码
WindowRenderState 类

WindowOptions::render 使用的参数包。
  1. struct WindowRenderState {
  2.   Element inner;             ///< 该元素包裹在该窗口内。
  3.   const std::string& title;  ///< 窗口的标题。
  4.   bool active = false;       ///< 窗口是否为活动窗口。
  5.   bool drag = false;         ///< 窗口是否正在被拖动。
  6.   bool resize = false;       ///< 窗口是否正在调整大小。
  7.   bool hover_left = false;   ///< 可调整大小的左侧是否处于悬停状态。
  8.   bool hover_right = false;  ///< 可调整大小的右侧是否处于悬停状态。
  9.   bool hover_top = false;    ///< 可调整大小的顶部是否处于悬停状态。
  10.   bool hover_down = false;   ///< 可调整大小的下方是否处于悬停状态。
  11. };
复制代码
WindowOptions 类

“窗口”组件的选项。
  1. struct WindowOptions {
  2.   Component inner;            ///< 该窗口包裹的组件。
  3.   ConstStringRef title = "";  ///< 此窗口显示的标题。
  4.   Ref<int> left = 0;     ///< 窗口左侧的位置。
  5.   Ref<int> top = 0;      ///< 窗口顶部的位置。
  6.   Ref<int> width = 20;   ///< 窗口的宽度。
  7.   Ref<int> height = 10;  ///< 窗口的高度。
  8.   Ref<bool> resize_left = true;   ///< 左侧可以调整大小吗?
  9.   Ref<bool> resize_right = true;  ///< 右侧可以调整大小吗?
  10.   Ref<bool> resize_top = true;    ///< 顶部可以调整大小吗?
  11.   Ref<bool> resize_down = true;   ///< 下方可以调整大小吗?
  12.   /// 用于自定义窗口外观的可选函数:
  13.   std::function<Element(const WindowRenderState&)> render;
  14. };
复制代码
DropdownOption 类

下拉组件的选项。
  1. struct DropdownOption {
  2.   /// 下拉菜单是否打开或关闭:
  3.   Ref<bool> open = false;
  4.   // 复选框的选项:
  5.   CheckboxOption checkbox;
  6.   // 单选框的选项:
  7.   RadioboxOption radiobox;
  8.   // 变换函数:
  9.   std::function<Element(bool open, Element checkbox, Element radiobox)>
  10.       transform;
  11. };
复制代码
component.hpp

该文件界说了常用的Component基本组件。
  1. // 定义模版,用于创建特定的组件实例
  2. template <class T, class... Args>
  3. std::shared_ptr<T> Make(Args&&... args) {
  4.   return std::make_shared<T>(std::forward<Args>(args)...);
  5. }
  6. //  管道运算符来装饰组件
  7. using ComponentDecorator = std::function<Component(Component)>;
  8. using ElementDecorator = std::function<Element(Element)>;
  9. Component operator|(Component component, ComponentDecorator decorator);
  10. Component operator|(Component component, ElementDecorator decorator);
  11. Component& operator|=(Component& component, ComponentDecorator decorator);
  12. Component& operator|=(Component& component, ElementDecorator decorator);
复制代码
Container 组件容器

  1. // 定义组件容器
  2. namespace Container {
  3. Component Vertical(Components children);
  4. Component Vertical(Components children, int* selector);
  5. Component Horizontal(Components children);
  6. Component Horizontal(Components children, int* selector);
  7. Component Tab(Components children, int* selector);
  8. Component Stacked(Components children);
  9. }  // namespace Container
复制代码
Vertical 垂直布局容器

组件列表,垂直逐一绘制,并使用上/下箭头键或“j”/“k”键垂直导航。
Horizontal 水平布局容器

一系列组件,逐一水平绘制,并使用左/右箭头键或“h”/“l”键水平导航。
Tab 选项卡布局容器

一个组件列表,一次只绘制一个组件并与之交互。selector给出所选组件的索引。这对于实现选项卡很有效。同Toggle、Menu组件一起使用可实现选项卡切换。
Stacked

堆叠的组件列表。变乱会通报到第一个组件,如果未处置惩罚则通报到第二个组件,以此类推。组件的绘制顺序与传入顺序相反。当某个组件获得焦点时,它会被置于最前面,而不会改变其他元素的相对顺序。此组件应与 Window 组件一起使用。
Button 按钮组件

  1. // 定义按钮组件
  2. Component Button(ButtonOption options);
  3. Component Button(ConstStringRef label,
  4.                  std::function<void()> on_click,
  5.                  ButtonOption options = ButtonOption::Simple());
复制代码
使用示例
  1.     ftxui::ButtonOption buttonOption = ftxui::ButtonOption::Animated(    // 按钮的样式
  2.             ftxui::Color::Black, ftxui::Color::White,
  3.             ftxui::Color::Black, ftxui::Color::Yellow);
  4.     std::function<void()> on_click = [](){    // 点击按钮时被调用
  5.         spdlog::trace("on_click");
  6.     };
  7.     ftxui::Component button_layout = ftxui::Button("Button1", on_click, buttonOption);
  8.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  9.     screen.Loop(button_layout);
复制代码

Checkbox 复选框组件

  1. // 定义复选框组件
  2. Component Checkbox(CheckboxOption options);
  3. Component Checkbox(ConstStringRef label,
  4.                    bool* checked,
  5.                    CheckboxOption options = CheckboxOption::Simple());
复制代码
使用示例
  1.     bool is_checked = false;// 存储复选框状态
  2.     ftxui::CheckboxOption checkboxOption = ftxui::CheckboxOption::Simple();
  3.     checkboxOption.on_change = [&is_checked](){        // 复选框状态变化时被调用
  4.         spdlog::trace("on_change: {}", is_checked);
  5.     };
  6.     ftxui::Component checkbox_layout = ftxui::Checkbox("Item1", &is_checked, checkboxOption);
  7.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  8.     screen.Loop(checkbox_layout);
复制代码

Input 输入框组件

  1. // 定义输入框组件
  2. Component Input(InputOption options = {});
  3. Component Input(StringRef content, InputOption options = {});
  4. Component Input(StringRef content,
  5.                 StringRef placeholder,
  6.                 InputOption options = {});
复制代码
使用示例
  1.     std::string input_data;//存储从输入框获取的内容
  2.     std::string placeholder = "please input data";// 输入框的提示内容
  3.     ftxui::InputOption inputOption = ftxui::InputOption::Spacious(); // 输入框配置选项
  4.     inputOption.password = false;// 非密码模式
  5.     inputOption.multiline = false;// 非多行模式
  6.     inputOption.insert = false; // 非插入模式
  7.     inputOption.on_change = [&input_data](){        // 输入内容变化时被调用
  8.         spdlog::trace("on_change: {}", input_data);
  9.     };
  10.     inputOption.on_enter = [&input_data](){        // 输入回车时被调用
  11.         spdlog::trace("on_enter: {}", input_data);
  12.     };
  13.     ftxui::Component input_layout = ftxui::Input(&input_data, "please input data", inputOption);
  14.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  15.     screen.Loop(input_layout);
复制代码

Menu 菜单组件

  1. // 定义菜单组件
  2. Component Menu(MenuOption options);
  3. Component Menu(ConstStringListRef entries,
  4.                int* selected_,
  5.                MenuOption options = MenuOption::Vertical());
复制代码
使用示例
  1.     std::vector<std::string> menu = { // 设置要显示的菜单列表
  2.             "menu_item1",
  3.             "menu_item2",
  4.             "menu_item3",
  5.     };
  6.     int selected_index = 0; // 存储选择的菜单选项索引
  7.     ftxui::MenuOption menuOption = ftxui::MenuOption::Vertical();//
  8.     menuOption.on_change = [&selected_index](){    // 选择项改变时被调用
  9.         spdlog::trace("on_change: {}", selected_index);
  10.     };
  11.     menuOption.on_enter = [&selected_index](){    // 输入回车按键时被调用
  12.         spdlog::trace("on_enter: {}", selected_index);
  13.     };
  14.     ftxui::Component menu_layout = ftxui::Menu(menu, &selected_index, menuOption);
  15.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  16.     screen.Loop(menu_layout);
复制代码

MenuEntry 菜单选择组件(垂直显示)

  1. // 定义菜单选项
  2. Component MenuEntry(MenuEntryOption options);
  3. Component MenuEntry(ConstStringRef label, MenuEntryOption options = {});
复制代码
使用示例
  1.     int selected = 0;
  2.     auto menu_layout = ftxui::Container::Vertical({
  3.         ftxui::MenuEntry("menu_entry 1"),
  4.         ftxui::MenuEntry("menu_entry 2"),
  5.         ftxui::MenuEntry("menu_entry 3"),
  6.      }, &selected);
  7.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  8.     screen.Loop(menu_layout);
复制代码

Toggle 菜单选择组件(水平显示)

  1. // 定义水平方向的菜单选项
  2. Component Toggle(ConstStringListRef entries, int* selected);
复制代码
使用示例
  1.     std::vector<std::string> menu = { // 设置要显示的菜单列表
  2.             "menu_item1",
  3.             "menu_item2",
  4.             "menu_item3",
  5.     };
  6.     int selected_index = 0; // 存储选择的菜单选项索引
  7.     ftxui::Component toggle_layout = ftxui::Toggle(menu, &selected_index);
  8.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  9.     screen.Loop(toggle_layout);
复制代码

Radiobox 单选框组件

  1. // 定义单选框组件
  2. Component Radiobox(RadioboxOption options);
  3. Component Radiobox(ConstStringListRef entries,
  4.                    int* selected_,
  5.                    RadioboxOption options = {});
复制代码
使用示例
  1.     std::vector<std::string> radio_list = { // 设置要显示的单选列表
  2.             "radio_item1",
  3.             "radio_item2",
  4.             "radio_item3",
  5.     };
  6.     int selected_index = 0; // 存储选择的菜单选项索引
  7.     ftxui::RadioboxOption radioboxOption = ftxui::RadioboxOption::Simple();// 单选框配置项
  8.     radioboxOption.on_change = [&selected_index](){
  9.         spdlog::trace("on_change: {}", selected_index);
  10.     };
  11.     ftxui::Component radio_layout = ftxui::Radiobox(radio_list, &selected_index, radioboxOption);
  12.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  13.     screen.Loop(radio_layout);
复制代码

Dropdown 下拉框组件

  1. // 定义下拉框组件
  2. Component Dropdown(ConstStringListRef entries, int* selected);
  3. Component Dropdown(DropdownOption options);
复制代码
使用示例
  1.     std::vector<std::string> dropdown_list = { // 设置要显示的下拉菜单列表
  2.             "dropdown_item1",
  3.             "dropdown_item2",
  4.             "dropdown_item3",
  5.     };
  6.     int selected_index = 0; // 存储选择的菜单选项索引
  7.     ftxui::Component dropdown_layout = ftxui::Dropdown(dropdown_list, &selected_index);
  8.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  9.     screen.Loop(dropdown_layout);
复制代码

Slider 滑块组件

  1. // 定义通用Slider滑块组件
  2. template <typename T>
  3. Component Slider(SliderOption<T> options);
  4. // 不使用 `SliderOption` 构造函数的简写
  5. Component Slider(ConstStringRef label,
  6.                  Ref<int> value,
  7.                  ConstRef<int> min = 0,
  8.                  ConstRef<int> max = 100,
  9.                  ConstRef<int> increment = 5);
  10. Component Slider(ConstStringRef label,
  11.                  Ref<float> value,
  12.                  ConstRef<float> min = 0.f,
  13.                  ConstRef<float> max = 100.f,
  14.                  ConstRef<float> increment = 5.f);
  15. Component Slider(ConstStringRef label,
  16.                  Ref<long> value,
  17.                  ConstRef<long> min = 0L,
  18.                  ConstRef<long> max = 100L,
  19.                  ConstRef<long> increment = 5L);
复制代码
使用示例
  1.     int progress = 0;// 存储当前进度值
  2.     int slider_min = 0;        // 配置进度最小值
  3.     int slider_max = 100;      // 配置进度最大值
  4.     int slider_increment = 1;  // 配置进度单步长度
  5.     ftxui::Component slider_layout = ftxui::Slider("slider_progress", &progress, slider_min, slider_max, slider_increment);
  6.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  7.     screen.Loop(slider_layout);
复制代码

ResizableSplit 缩放和分割组件

  1. // 定义可缩放的分割组件
  2. Component ResizableSplit(ResizableSplitOption options);
  3. Component ResizableSplitLeft(Component main, Component back, int* main_size);
  4. Component ResizableSplitRight(Component main, Component back, int* main_size);
  5. Component ResizableSplitTop(Component main, Component back, int* main_size);
  6. Component ResizableSplitBottom(Component main, Component back, int* main_size);
复制代码
使用示例
  1.     ftxui::ResizableSplitOption resizableSplitOption;
  2.     // 主Component
  3.     resizableSplitOption.main = ftxui::Renderer([]{ return ftxui::paragraph("this is long long long right text..."); });
  4.     // 副Component
  5.     resizableSplitOption.back = ftxui::Renderer([]{ return ftxui::paragraph("this is long long long left..."); });
  6.     // 设置偏移方向: 从上向下
  7.     resizableSplitOption.direction = ftxui::Direction::Up;
  8.     // 设置主Component的分割的大小: 2个单位
  9.     resizableSplitOption.main_size = 2;
  10.     // 设置自定义分割线样式: 虚线
  11.     resizableSplitOption.separator_func = []{ return ftxui::separatorStyled(ftxui::BorderStyle::DASHED); };
  12.     ftxui::Component resizableSplit_layout = ftxui::ResizableSplit(resizableSplitOption);
  13.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  14.     screen.Loop(resizableSplit_layout);
复制代码

Renderer 渲染Element转为组件

  1. // 渲染Element元素,转为组件
  2. Component Renderer(Component child, std::function<Element()>);
  3. Component Renderer(std::function<Element()>);
  4. Component Renderer(std::function<Element(bool /* focused */)>);
  5. ComponentDecorator Renderer(ElementDecorator);
复制代码
使用示例
  1.     std::string text = "this is content..."; // 文本内容
  2.     // 将 Element 元素 转为 Component 组件。
  3.     ftxui::Component layout = ftxui::Renderer([&text](){
  4.         return ftxui::text(text);
  5.     });
  6.     auto screen = ftxui::ScreenInteractive::TerminalOutput();
  7.     screen.Loop(layout);
复制代码

CatchEvent 变乱捕获

  1. // 捕获组件的事件
  2. Component CatchEvent(Component child, std::function<bool(Event)>);
  3. ComponentDecorator CatchEvent(std::function<bool(Event)> on_event);
复制代码
使用示例

根据screen_interactive.cpp源码可以确定,需要处置惩罚Ctrl+C的Event变乱并将force_handle_ctrl_c设为false才可以屏蔽FTXUI触发应用退出。
  1.     std::string paragraph_text = "This is paragraph text...";
  2.     auto paragraph_view = ftxui::Renderer([&paragraph_text](){
  3.         return ftxui::paragraph(paragraph_text) | ftxui::border;
  4.     });
  5.    
  6.     auto screen = ftxui::ScreenInteractive::Fullscreen();
  7.     screen.ForceHandleCtrlC(false);// 设置false强制FTXUI不处理Ctrl+C信号
  8.     screen.ForceHandleCtrlZ(false);// 设置false强制FTXUI不处理Ctrl+Z信号
  9.     auto component = CatchEvent(paragraph_view, [&](ftxui::Event event) {
  10.         if (event == ftxui::Event::CtrlC) {
  11.             spdlog::trace("CtrlC");
  12.             screen.ExitLoopClosure()();
  13.             return true;// 返回true表示已经处理 Ctrl+C 事件,不让FTXUI触发ABORT退出信号
  14.         }
  15.         if (event == ftxui::Event::CtrlZ) {
  16.             spdlog::trace("CtrlZ");
  17.             screen.ExitLoopClosure()();
  18.             return true;// 返回true表示已经处理 Ctrl+Z 事件,不让FTXUI触发ABORT退出信号
  19.         }
  20.         return false;
  21.     });
  22.     screen.Loop(component);
复制代码

Maybe 可隐蔽组件

  1. // 隐藏一个组件。仅当 show=true 时才显示被隐藏的组件
  2. Component Maybe(Component, const bool* show);
  3. Component Maybe(Component, std::function<bool()>);
  4. ComponentDecorator Maybe(const bool* show);
  5. ComponentDecorator Maybe(std::function<bool()>);
复制代码
使用示例
  1.     bool show_status = true; // 控制paragraph_layout显示/隐藏
  2.     auto button_show = ftxui::Button("Show", [&show_status](){
  3.         show_status = true;
  4.     }, ftxui::ButtonOption::Border());
  5.     auto button_hidden = ftxui::Button("Hidden", [&show_status](){
  6.         show_status = false;
  7.     }, ftxui::ButtonOption::Border());
  8.     auto button_layout = ftxui::Container::Horizontal({
  9.         button_show,
  10.         button_hidden,
  11.     });
  12.     std::string paragraph_text = "This is paragraph text...";
  13.     auto paragraph_layout = ftxui::Renderer([&paragraph_text](){
  14.         return ftxui::paragraph(paragraph_text) | ftxui::border;
  15.     });
  16.     auto layout = ftxui::Container::Vertical({
  17.         button_layout,
  18.         ftxui::Maybe(paragraph_layout, &show_status),// 根据show_status变量状态控制是否隐藏paragraph_layout
  19.     });
  20.     auto screen = ftxui::ScreenInteractive::Fullscreen();
  21.     screen.ForceHandleCtrlC(false);
  22.     screen.ForceHandleCtrlZ(false);
  23.     auto component = CatchEvent(layout, [&](ftxui::Event event) {
  24.         if (event == ftxui::Event::CtrlC) {
  25.             spdlog::trace("CtrlC");
  26.             screen.ExitLoopClosure()();
  27.             return true;
  28.         }
  29.         if (event == ftxui::Event::CtrlZ) {
  30.             spdlog::trace("CtrlZ");
  31.             screen.ExitLoopClosure()();
  32.             return true;
  33.         }
  34.         return false;
  35.     });
  36.     screen.Loop(component);
复制代码


Modal 叠加组件

  1. // 叠加一个组件。在main组件的外层叠加显示一个modal组件,仅当 show_modal=true 时才​会叠加显示。
  2. Component Modal(Component main, Component modal, const bool* show_modal);
  3. ComponentDecorator Modal(Component modal, const bool* show_modal);
复制代码
使用示例
  1.     bool show_status = true; // 控制是否叠加model_layout
  2.     auto button_show = ftxui::Button("Show", [&show_status](){
  3.         show_status = true;
  4.     }, ftxui::ButtonOption::Border());
  5.     auto button_hidden = ftxui::Button("Hidden", [&show_status](){
  6.         show_status = false;
  7.     }, ftxui::ButtonOption::Border());
  8.     auto button_layout = ftxui::Container::Horizontal({
  9.         button_show,
  10.         button_hidden,
  11.     });
  12.     std::string paragraph_text = "This is paragraph text...";
  13.     auto paragraph_layout = ftxui::Renderer([&paragraph_text](){
  14.         return ftxui::paragraph(paragraph_text) | ftxui::border;
  15.     });
  16.     std::string model_text = "This is model_text text...";
  17.     auto model_layout = ftxui::Renderer([&model_text](){
  18.         return ftxui::paragraph(model_text) | ftxui::border;
  19.     });
  20.     auto layout = ftxui::Container::Vertical({
  21.         button_layout,
  22.         ftxui::Modal(paragraph_layout, model_layout, &show_status),// 根据show_status变量状态控制是否将model_layout叠加到paragraph_layout外层
  23.     });
  24.     auto screen = ftxui::ScreenInteractive::Fullscreen();
  25.     screen.ForceHandleCtrlC(false);
  26.     screen.ForceHandleCtrlZ(false);
  27.     auto component = CatchEvent(layout, [&](ftxui::Event event) {
  28.         if (event == ftxui::Event::CtrlC) {
  29.             spdlog::trace("CtrlC");
  30.             screen.ExitLoopClosure()();
  31.             return true;
  32.         }
  33.         if (event == ftxui::Event::CtrlZ) {
  34.             spdlog::trace("CtrlZ");
  35.             screen.ExitLoopClosure()();
  36.             return true;
  37.         }
  38.         return false;
  39.     });
  40.     screen.Loop(component);
复制代码


Collapsible 可折叠组件

  1. // 可折叠组件。它显示一个带箭头的复选框。一旦激活,子项就会显示出来。
  2. Component Collapsible(ConstStringRef label,
  3.                       Component child,
  4.                       Ref<bool> show = false);
复制代码
使用示例
  1.     bool show_status = true; // 控制paragraph_layout显示/折叠
  2.     auto button_show = ftxui::Button("Show", [&show_status](){
  3.         show_status = true;
  4.     }, ftxui::ButtonOption::Border());
  5.     auto button_hidden = ftxui::Button("Hidden", [&show_status](){
  6.         show_status = false;
  7.     }, ftxui::ButtonOption::Border());
  8.     auto button_layout = ftxui::Container::Horizontal({
  9.         button_show,
  10.         button_hidden,
  11.     });
  12.     std::string paragraph_text = "This is paragraph text...";
  13.     auto paragraph_layout = ftxui::Renderer([&paragraph_text](){
  14.         return ftxui::paragraph(paragraph_text) | ftxui::border;
  15.     });
  16.     auto layout = ftxui::Container::Vertical({
  17.         button_layout,
  18.         ftxui::Collapsible("paragraph", paragraph_layout, &show_status),// 根据show_status变量状态控制是否折叠paragraph_layout
  19.     });
  20.     auto screen = ftxui::ScreenInteractive::Fullscreen();
  21.     screen.ForceHandleCtrlC(false);
  22.     screen.ForceHandleCtrlZ(false);
  23.     auto component = CatchEvent(layout, [&](ftxui::Event event) {
  24.         if (event == ftxui::Event::CtrlC) {
  25.             spdlog::trace("CtrlC");
  26.             screen.ExitLoopClosure()();
  27.             return true;
  28.         }
  29.         if (event == ftxui::Event::CtrlZ) {
  30.             spdlog::trace("CtrlZ");
  31.             screen.ExitLoopClosure()();
  32.             return true;
  33.         }
  34.         return false;
  35.     });
  36.     screen.Loop(component);
复制代码


Hoverable 可包裹组件

  1. // 包裹一个组件。使其能够知道鼠标是否悬停在组件上。
  2. Component Hoverable(Component component, bool* hover);
  3. Component Hoverable(Component component,
  4.                     std::function<void()> on_enter,
  5.                     std::function<void()> on_leave);
  6. Component Hoverable(Component component,  //
  7.                     std::function<void(bool)> on_change);
  8. ComponentDecorator Hoverable(bool* hover);
  9. ComponentDecorator Hoverable(std::function<void()> on_enter,
  10.                              std::function<void()> on_leave);
  11. ComponentDecorator Hoverable(std::function<void(bool)> on_change);
复制代码
使用示例
  1.     std::string paragraph_text = "This is paragraph text...";
  2.     auto paragraph_layout = ftxui::Renderer([&paragraph_text](){
  3.         return ftxui::paragraph(paragraph_text) | ftxui::border;
  4.     });
  5.     auto layout = ftxui::Container::Vertical({
  6.         ftxui::Hoverable(paragraph_layout,
  7.                          [](){ spdlog::trace("on_enter"); },    // 当鼠标进入paragraph_layout区域时被调用
  8.                          [](){ spdlog::trace("on_leave"); }),  // 当鼠标离开paragraph_layout区域时被调用
  9.     });
  10.     auto screen = ftxui::ScreenInteractive::Fullscreen();
  11.     screen.ForceHandleCtrlC(false);
  12.     screen.ForceHandleCtrlZ(false);
  13.     auto component = CatchEvent(layout, [&](ftxui::Event event) {
  14.         if (event == ftxui::Event::CtrlC) {
  15.             spdlog::trace("CtrlC");
  16.             screen.ExitLoopClosure()();
  17.             return true;
  18.         }
  19.         if (event == ftxui::Event::CtrlZ) {
  20.             spdlog::trace("CtrlZ");
  21.             screen.ExitLoopClosure()();
  22.             return true;
  23.         }
  24.         return false;
  25.     });
  26.     screen.Loop(component);
复制代码

Window 可拖动窗口

  1. // 可拖动/可调整大小的窗口。
  2. // 要使用多个窗口,必须使用 `Container::Stacked({...})` 组件将它们堆叠起来;
  3. Component Window(WindowOptions option);
复制代码
使用示例
  1.     std::string paragraph_text = "This is paragraph text...";
  2.     auto paragraph_layout = ftxui::Renderer([&paragraph_text](){
  3.         return ftxui::paragraph(paragraph_text) | ftxui::border;
  4.     });
  5.     ftxui::WindowOptions windowOptions;
  6.     windowOptions.inner = paragraph_layout;
  7.     windowOptions.title = "paragraph";
  8.     auto layout = ftxui::Window(windowOptions);
  9.     auto screen = ftxui::ScreenInteractive::Fullscreen();
  10.     screen.ForceHandleCtrlC(false);
  11.     screen.ForceHandleCtrlZ(false);
  12.     auto component = CatchEvent(layout, [&](ftxui::Event event) {
  13.         if (event == ftxui::Event::CtrlC) {
  14.             spdlog::trace("CtrlC");
  15.             screen.ExitLoopClosure()();
  16.             return true;
  17.         }
  18.         if (event == ftxui::Event::CtrlZ) {
  19.             spdlog::trace("CtrlZ");
  20.             screen.ExitLoopClosure()();
  21.             return true;
  22.         }
  23.         return false;
  24.     });
  25.     screen.Loop(component);
复制代码



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

徐锦洪

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表