tuigui 0.1.0

An easy-to-use, highly extensible, and speedy TUI library.
Documentation

About

TuiGui is a very easy-to-use, highly extensible, and speedy TUI library. Unlike other TUI libraries, it also plays nicely with crates like owo-colors which allow you to color strings!

Examples

// Display the Ukrainian flag using owo-colors. (Why? Because that is my mom's country of origin.)
// Exits after 5 seconds.
// Oh, and it says "Hello, world!\nRust is great!" in the center.
use std::io;
use owo_colors::{
    OwoColorize,
    AnsiColors,
};
use tuigui::{
    Context,
    ContextConfig,
    Widget,
    WidgetInfo,
    WidgetSizeInfo,
    Canvas,
    Position,
    Size,
    backends,
    widgets::{ self, ColAnchor, RowAnchor },
};

// QUICK NOTE: CrosstermBackend is only available if you enable the 'backend_crossterm' feature.

const TIME_LIMIT: f64 = 5.0; // Exit after this amount of seconds.

struct ColorPaneWidget {
    color: AnsiColors,
}

impl ColorPaneWidget {
    pub fn new(color: AnsiColors) -> Self {
        Self {
            color,
        }
    }
}

impl Widget for ColorPaneWidget {
    fn draw(&mut self, canvas: &mut Canvas) {
        for row in 0..canvas.size.rows {
            for col in 0..canvas.size.cols {
                canvas.set_string(Position::new(col, row), "".color(self.color));
            }
        }
    }

    fn widget_info(&self) -> WidgetInfo {
        WidgetInfo {
            size_info: WidgetSizeInfo::Dynamic {
                min: None,
                max: None,
            },
        }
    }
}

fn main() -> Result<(), io::Error> {
    let flag = widgets::BoxContainer::new(
        widgets::Orientation::Vertical,
        vec![
            Box::new(ColorPaneWidget::new(AnsiColors::Blue)),
            Box::new(ColorPaneWidget::new(AnsiColors::Yellow)),
        ],
    );

    let text = widgets::AnchorContainer::new(
        widgets::Anchor::new(ColAnchor::Center, RowAnchor::Center),
        widgets::BoxContainer::new(
            widgets::Orientation::Vertical,
            vec![
                Box::new(widgets::Label::new("Hello, world!", false)),
                Box::new(widgets::Label::new("Rust is great!", false)),
            ],
        ),
        widgets::AnchorContainerWidgetSize::Fixed(Size::new(14, 2)),
    );

    let text_background = widgets::AnchorContainer::new(
        widgets::Anchor::new(ColAnchor::Center, RowAnchor::Center),
        widgets::ClearArea::new(),
        widgets::AnchorContainerWidgetSize::Fixed(Size::new(16, 4)),
    );

    let root = widgets::Layers::new(vec![
        Box::new(widgets::RootWidget::new(flag)),
        Box::new(widgets::RootWidget::new(text_background)),
        Box::new(widgets::RootWidget::new(text)),
    ]);

    let mut context = Context::new(
        ContextConfig::default(),
        backends::CrosstermBackend::new(),
        widgets::RootWidget::new(root),
    );

    // Set up the terminal.
    context.setup()?;

    // The time that the loop began.
    let start = std::time::Instant::now();

    // The loop.
    while std::time::Instant::now() - start < std::time::Duration::from_secs_f64(TIME_LIMIT) {
        context.draw()?;
    }

    // Clean up the terminal.
    context.cleanup()?;

    // Yay! Nothing went wrong!
    Ok(())
}