add: more TUI stuff
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
use tui_realm_stdlib::Label;
|
||||
use tuirealm::{event::{Key, KeyEvent, KeyModifiers}, props::{Alignment, Color, TextModifiers}, Component, Event, MockComponent, NoUserEvent};
|
||||
|
||||
use crate::Msg;
|
||||
|
||||
#[derive(MockComponent)]
|
||||
pub struct HelloLabel {
|
||||
component: Label,
|
||||
}
|
||||
|
||||
impl Default for HelloLabel {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
component: Label::default()
|
||||
.alignment(Alignment::Center)
|
||||
.foreground(Color::Green)
|
||||
.modifiers(TextModifiers::BOLD)
|
||||
.text("This is a label"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for HelloLabel {
|
||||
fn on(&mut self, ev: tuirealm::Event<NoUserEvent>) -> Option<Msg> {
|
||||
match ev {
|
||||
Event::Keyboard(KeyEvent{
|
||||
code: Key::Esc,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
}) => Some(Msg::AppClose),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
mod model;
|
||||
mod hellolabel;
|
||||
|
||||
pub use model::*;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Msg {
|
||||
AppClose,
|
||||
}
|
||||
|
||||
// Let's define the component ids for our application
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
|
||||
pub enum Id {
|
||||
Label,
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
use tui_tea::*;
|
||||
use tuirealm::Update;
|
||||
|
||||
fn main() {
|
||||
let mut model = Model::default();
|
||||
// Enter alternate screen
|
||||
let _ = model.terminal.enter_alternate_screen();
|
||||
let _ = model.terminal.enable_raw_mode();
|
||||
|
||||
// main loop
|
||||
while !model.quit {
|
||||
match model.app.tick(tuirealm::PollStrategy::Once) {
|
||||
Err(_) => break,
|
||||
Ok(messages) => {
|
||||
for msg in messages.into_iter() {
|
||||
let mut msg = Some(msg);
|
||||
while msg.is_some() {
|
||||
model.redraw = true;
|
||||
msg = model.update(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if model.redraw {
|
||||
model.view();
|
||||
model.redraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate terminal
|
||||
let _ = model.terminal.leave_alternate_screen();
|
||||
let _ = model.terminal.disable_raw_mode();
|
||||
let _ = model.terminal.clear_screen();
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use tuirealm::{terminal::{CrosstermTerminalAdapter, TerminalAdapter, TerminalBridge}, Application, EventListenerCfg, NoUserEvent, Update};
|
||||
|
||||
use crate::Id;
|
||||
|
||||
pub struct Model<T>
|
||||
where T: TerminalAdapter {
|
||||
pub app: Application<super::Id, super::Msg, NoUserEvent>,
|
||||
pub terminal: TerminalBridge<T>,
|
||||
pub quit: bool,
|
||||
pub redraw: bool,
|
||||
}
|
||||
|
||||
impl Default for Model<CrosstermTerminalAdapter> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
app: Self::init_app(),
|
||||
terminal: TerminalBridge::init_crossterm().expect("failed to init terminal"),
|
||||
quit: false,
|
||||
redraw: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Model<T>
|
||||
where T: TerminalAdapter {
|
||||
pub fn view(&mut self) {
|
||||
self.terminal.draw(|f| {
|
||||
self.app.view(&super::Id::Label, f, f.area());
|
||||
}).expect("failed to render view");
|
||||
}
|
||||
|
||||
fn init_app() -> Application<super::Id, super::Msg, NoUserEvent> {
|
||||
// Setup application
|
||||
// NOTE: NoUserEvent is a shorthand to tell tui-realm we're not going to use any custom user event
|
||||
// NOTE: the event listener is configured to use the default crossterm input listener and to raise a Tick event each second
|
||||
// which we will use to update the clock
|
||||
|
||||
let mut app = Application::init(
|
||||
EventListenerCfg::default()
|
||||
.crossterm_input_listener(Duration::from_millis(20), 3)
|
||||
.poll_timeout(Duration::from_millis(10))
|
||||
.tick_interval(Duration::from_secs(1)),
|
||||
);
|
||||
app.mount(super::Id::Label, Box::new(
|
||||
super::hellolabel::HelloLabel::default()
|
||||
), Vec::default()).expect("failed to create label");
|
||||
app.active(&Id::Label).unwrap();
|
||||
app
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Update<super::Msg> for Model<T>
|
||||
where T: TerminalAdapter {
|
||||
fn update(&mut self, msg: Option<super::Msg>) -> Option<super::Msg> {
|
||||
if msg.is_none() {
|
||||
return None;
|
||||
}
|
||||
self.redraw = true;
|
||||
match msg.unwrap() {
|
||||
super::Msg::AppClose => {
|
||||
self.quit = true;
|
||||
None
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user