当前位置: 首页 > news >正文

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

文章目录

  • component_base.hpp
    • ComponentBase 类
  • receiver.hpp
    • SenderImpl类 和 ReceiverImpl 类
  • mouse.hpp
    • Mouse 类
  • event.hpp
    • Event 类
  • screen_interactive.hpp
    • ScreenInteractive 类
  • loop.hpp
    • Loop 类
  • animation.hpp
  • component_options.hpp
    • EntryState 类
    • UnderlineOption 类
    • AnimatedColorOption 类
    • MenuEntryOption 类
    • MenuOption 类
    • ButtonOption 类
    • CheckboxOption 类
    • InputState 类
    • InputOption 类
    • RadioboxOption 类
    • ResizableSplitOption 类
    • SliderOption 类
    • WindowRenderState 类
    • WindowOptions 类
    • DropdownOption 类
  • component.hpp
    • Container 组件容器
    • Button 按钮组件
    • Checkbox 复选框组件
    • Input 输入框组件
    • Menu 菜单组件
    • MenuEntry 菜单选择组件(垂直显示)
    • Toggle 菜单选择组件(水平显示)
    • Radiobox 单选框组件
    • Dropdown 下拉框组件
    • Slider 滑块组件
    • ResizableSplit 缩放和分割组件
    • Renderer 渲染Element转为组件
    • CatchEvent 事件捕获
    • Maybe 可隐藏组件
    • Modal 叠加组件
    • Collapsible 可折叠组件
    • Hoverable 可包裹组件
    • Window 可拖动窗口

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:// 创建指定大小区域的终端界面交互static ScreenInteractive FixedSize(int dimx, int dimy);//创建一个占用完整Screen终端大小的终端界面交互。这将使用备用屏幕缓冲区来避免干扰终端内容。static ScreenInteractive Fullscreen();//创建一个占用完整Screen终端大小的终端界面交互。主屏幕缓冲区正在被占用。这意味着如果调整终端大小,先前的内容可能会与终端内容混淆。static ScreenInteractive FullscreenPrimaryScreen();//创建一个占用完整Screen终端大小的终端界面交互。这将使用备用屏幕缓冲区来避免干扰终端内容。static ScreenInteractive FullscreenAlternateScreen();//创建一个占用完整Component大小的终端界面交互。static ScreenInteractive FitComponent();//创建一个占用Screen终端宽度的终端界面交互(终端界面的高度取决于Component高度)。static ScreenInteractive TerminalOutput();// 可选. 必须在执行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

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;// 主ComponentresizableSplitOption.main = ftxui::Renderer([]{ return ftxui::paragraph("this is long long long right text..."); });// 副ComponentresizableSplitOption.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);

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()>);

Modal 叠加组件

// 叠加一个组件。在main组件的外层叠加显示一个modal组件,仅当 show_modal=true 时才​会叠加显示。
Component Modal(Component main, Component modal, const bool* show_modal);
ComponentDecorator Modal(Component modal, const bool* show_modal);

Collapsible 可折叠组件

// 可折叠组件。它显示一个带箭头的复选框。一旦激活,子项就会显示出来。
Component Collapsible(ConstStringRef label,Component child,Ref<bool> show = false);

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);

Window 可拖动窗口

// 可拖动/可调整大小的窗口。
// 要使用多个窗口,必须使用 `Container::Stacked({...})` 组件将它们堆叠起来;
Component Window(WindowOptions option);

http://www.mrgr.cn/news/98212.html

相关文章:

  • Java—— 文字版格斗游戏
  • 一种基于学习的多尺度方法及其在非弹性碰撞问题中的应用
  • 【Linux实践系列】:匿名管道收尾+完善shell外壳程序
  • # Shell脚本参数设计规范(DeepSeek指导)
  • 大模型到底是怎么产生的?一文揭秘大模型诞生全过程
  • Redis之缓存更新策略
  • Ubuntu系统美化
  • 回顾CSA,CSA复习
  • SpringAi 会话记忆功能
  • C++ 入门六:多态 —— 同一接口的多种实现之道
  • Spring Boot集成Nacos
  • 【BEPU V1物理】BEPUphysics v1 入门指南 汉化笔记#1
  • 哈希表-算法小结
  • 02_通过调用硅基流动平台deepseekapi按输入的标题生成文章
  • C. Robin Hood in Town思考与理解
  • 【前端】webpack一本通
  • 【Linux】单例模式及其在线程池中的应用
  • C++ STL及Python中等效实现
  • Linux 内核知识体系
  • 【SQL Server 2017】封闭网络下,数据调研所有数据表实战(提效400%)