#tui #user-interface #widgets #cross-platform #text #ensure #text-input

simple_tui

SimpleTUI 是一个轻量级且跨平台的文本用户界面(TUI)库

2 个版本

0.1.1 2023 年 12 月 12 日
0.1.0 2023 年 12 月 12 日

#459 in GUI

MIT 许可证

34KB
676

SimpleTUI

SimpleTUI 是一个轻量级且跨平台的文本用户界面(TUI)库,专为简洁性和易用性设计。通过利用强大的 crossterm 后端进行输入处理,SimpleTUI 确保了无缝的跨平台体验,使其成为寻求构建 TUI 应用程序的简单解决方案的开发者的理想选择。

演示

OS: Windows 10 Pro

demo-gif

特性

  • 以小部件为中心的设计:使用以小部件为中心的方法构建您的 TUI 应用程序,其中每个组件都是一个小部件。这使得库直观且易于开发者使用。

  • 自定义小部件:您可以轻松制作自定义小部件。

  • 跨平台兼容性:通过利用 crossterm 后端,simple_tui 确保了在不同平台(包括 Windows、macOS 和 Linux)上的一致 TUI 行为。

  • 使用 on_click 支持回调:通过使用 on_click 回调轻松处理用户交互,使开发者能够创建响应性和动态的 UI。



超级小部件

超级小部件是实现 EventHandler 特性的小部件;它将赋予它们特殊的功能

  1. 启动应用程序(在屏幕上绘制)
  2. 渲染其他小部件
  3. 处理鼠标、键盘和调整大小事件

这种方法可能会在未来发生变化。但到目前为止,这将保持一切简单;P

小部件

小部件 描述 状态
vbox (sw) 垂直布局 可用
hbox (sw) 水平布局 可用
label 文本显示 可用
button 带有 on_click 的按钮 可用
input 用户文本输入 待办事项
paragraph 带标题的段落 待办事项
... 更多 ... ...

(sw) 超级小部件


入门指南

use simple_tui::functions::*;

fn main() {
    hbox(    // Construct new Horizontal Layout `Super Widget`.

        // Macro: Vector of Widgets (implement AsWidget trait)
        widgets![ 
            label("مرحباََ")                      // Construct new lable widget with `ََمرحبا` text.
                .align(Alignment::Center)     // Center text.
                .wrap()                       // wrap around
        ]

    ).start(); // Calling start method to start the app.
}

添加您的自定义小部件

要添加自定义小部件,您需要执行一些步骤

  1. 将您的小部件添加到 enum Widget

    enum Widget{
      ....
    MyWidget(MyWidgetStruct)
    }
    
  2. 为您的小部件实现 AsWidget

    impl AsWidget for MyWidgetStruct {
        fn as_widget(self) -> Option<Widget>{
            Some(Widget::MyWidget(self))
        };
    }
    
  3. 您的小部件必须具有这些方法和字段

    struct CustomWidget{
        console: Console,
        rect: Rect
    }
    
      fn render(&mut self, rect: Rect) {
          // draw your Widget using the rect.
    
           // self.console.draw((rect.x, rect.y), "My custom widget!!!")
           // ...
    
          // after drawing you need to move rect to self.rect .
          // self.rect = rect
    }
    
      fn shape(&self) -> Rect { self.rect }
    

将来

  • 步骤 1 和 2 将是动态的。
  • 步骤 3 您将为自定义小部件实现 CustomWidget 特性。


示例用法

使用 on_click 的回调

use simple_tui::functions::*;

fn add_one(w: &mut Widget) -> &mut Widget {
    if let Widget::Lable(l) = w {
        let n = &l.text["Counter: ".len()..].parse::<usize>().unwrap();
        l.text = "Counter: ".to_string() + &(n + 1).to_string();
    }
    w
}

fn main() {
    vbox(widgets![
        lable("Counter: 0")
            .set_id(1337)
            .align(Alignment::Center)
            .wrap(),
        button("Click me!")
            .set_rid(1337)
            .on_click(|w| add_one(w))
    ])
    .start();
}

水平布局

use simple_tui::functions::*;

fn main() {
    hbox(
        widgets![
            label("Hello 1").align(Alignment::Left),
            label("Hello 2").align(Alignment::Center),
            label("Hello 3").align(Alignment::Right),
            label("Hello 4").align(Alignment::Left).wrap(),
            label("Hello 5").align(Alignment::Center).wrap(),
            label("Hello 6").align(Alignment::Right).wrap()
        ]
    )
    .start();
}

垂直布局

use simple_tui::functions::*;

fn main() {
    vbox(
        widgets![
            label("Hello 1").align(Alignment::Left),
            label("Hello 2").align(Alignment::Center),
            label("Hello 3").align(Alignment::Right),
            label("Hello 4").align(Alignment::Right).wrap(),
            label("Hello 5").align(Alignment::Center).wrap(),
            label("Hello 6").align(Alignment::Left).wrap()
        ]
    )
    .start();
}

创建网格

use simple_tui::functions::*;

fn main() {
    vbox(widgets![
        hbox(widgets![
            label("Hello 1").align(Alignment::Right).wrap(),
            label("Hello 2").align(Alignment::Right).wrap(),
            label("Hello 3").align(Alignment::Left).wrap()
        ]),
        hbox(widgets![
            label("Hello 4").align(Alignment::Left).wrap(),
            label("Hello 5").align(Alignment::Center).wrap(),
            label("Hello 6").align(Alignment::Right).wrap()
        ]),
        hbox(widgets![
            label("Hello 7").align(Alignment::Right).wrap(),
            label("Hello 8").align(Alignment::Left).wrap(),
            label("Hello 9").align(Alignment::Left).wrap()
        ])
    ])
    .start();
}

依赖项

~0.8–6MB
~20K SLoC