flux-tui 0.5.0

Fast and lightweight Terminal UI drawing library
Documentation
use crossterm::event::{Event, KeyCode};
use flux_tui::canvas::Canvas;
use flux_tui::common::*;
use flux_tui::components::*;
use flux_tui::tui::Tui;
use flux_tui::window::*;
use std::cell::RefCell;
use std::rc::Rc;
use vector2d::Vector2D;

fn main() {
	let control = Rc::new(RefCell::new(Control::default()));
	let mut tui = Tui::new(control.clone()).unwrap();
	tui.render().unwrap();
	while let Ok(()) = tui.handle_next_event() {
		if !control.borrow().running {
			return;
		}
		tui.render().unwrap();
	}
}

#[derive(Clone)]
struct ExampleRow {
	value_a: String,
	value_b: i32,
	value_c: bool,
	value_d: f32,
}

impl ExampleRow {
	fn new<S: ToString>(a: S, b: i32, c: bool, d: f32) -> Self {
		Self {
			value_a: a.to_string(),
			value_b: b,
			value_c: c,
			value_d: d,
		}
	}
}

impl DataRow for ExampleRow {
	fn get_data<'a>(&'a self, column: usize) -> Option<DataValue<'a>> {
		match column {
			0 => Some(DataValue::String(&self.value_a)),
			1 => Some(DataValue::Integer(self.value_b)),
			2 => Some(DataValue::Float(self.value_d)),
			3 => Some(DataValue::Boolean(self.value_c)),
			_ => None,
		}
	}
}

struct ExampleDataSource {
	rows: [ExampleRow; 12],
	defs: [ColumnDefiniton; 4],
}

impl Default for ExampleDataSource {
	fn default() -> Self {
		Self {
			rows: [
				ExampleRow::new("a", 1, true, 4.5),
				ExampleRow::new("bb", 31, false, 42.25),
				ExampleRow::new("ccc", 123, true, 4.265),
				ExampleRow::new("d", 1311, true, 24.125),
				ExampleRow::new("aa", 122, true, 4.5),
				ExampleRow::new("bbbb", 3281, false, 42.25),
				ExampleRow::new("cccc", 123, false, 4.265),
				ExampleRow::new("dd", 13, true, 34.125),
				ExampleRow::new("aaa", 19, false, 9.5),
				ExampleRow::new("bbb", 341, false, 11.25),
				ExampleRow::new("cccccc", 1223, true, 7.265),
				ExampleRow::new("ddd", 13111, true, 12.125),
			],
			defs: [
				ColumnDefiniton::new("A"),
				ColumnDefiniton::new("B"),
				ColumnDefiniton::new("C"),
				ColumnDefiniton::new("D"),
			],
		}
	}
}

impl DataSource for ExampleDataSource {
	fn column_definitions(&self) -> &[ColumnDefiniton] {
		&self.defs
	}

	fn rows(&self) -> usize {
		self.rows.len()
	}

	fn get_row(&self, row: usize) -> &dyn DataRow {
		&self.rows[row]
	}
}

struct Control {
	running: bool,
	uid: WindowUID,
	datagrid: Rc<RefCell<DataGrid>>,
}

impl Default for Control {
	fn default() -> Self {
		let datagrid = WindowFactory::create::<DataGrid>();
		{
			let mut brw = datagrid.borrow_mut();
			brw.set_data_source(Box::new(ExampleDataSource::default()));
			//brw.set_radix(Radix::Hexadecimal);
			brw.set_selection_color(Some(Color::Cyan));
		}

		Self {
			uid: WindowUID::new(),
			datagrid,
			running: true,
		}
	}
}

impl Window for Control {
	fn render(&self, _: &mut Canvas) {}

	fn handle_event(&mut self, event: &mut WindowEvent) {
		if let Event::Key(k) = event.raw() {
			if k.code == KeyCode::Esc {
				self.running = false;
			}
		}
	}

	fn children(&mut self, mut builder: SubWindowBuilder) -> SubWindows {
		builder.add_pair(self.datagrid.clone(), None).ok();
		builder.build().unwrap()
	}

	fn focus(&self) -> Option<WindowRef> {
		Some(self.datagrid.clone())
	}
}

impl HasWindowUID for Control {
	fn uid(&self) -> WindowUID {
		self.uid
	}
}

impl WindowLayout for Control {
	fn desired_size(&self, available_size: Vector2D<u16>) -> Vector2D<u16> {
		available_size / 2
	}
}