rat-dialog 0.4.0

stacked dialog windows
Documentation

alpha 2 crates.io Documentation License License

unstable

This crate is a part of rat-salsa.

Rat Dialog

This crates provides a DialogStack that can be used with rat-salsa apps. It can stack and render any number of dialog-windows on top of the main application.

It uses the rat-salsa traits for AppWidget/AppState for rendering and event handling.


# use std::path::PathBuf;
use anyhow::Error;
use rat_dialog::DialogStackState;
use crate::rat_dialog::DialogWidget;
use rat_dialog::widgets::{FileDialog, FileDialogState};
# use rat_salsa::{AppState, Control};
# use rat_theme2::DarkTheme;
# use rat_widget::event::FileOutcome;
# struct GlobalState { dialogs: DialogStackState<GlobalState, MyEvent, Error>, theme: DarkTheme }
# enum MyEvent { Event(crossterm::event::Event), Status(u16, String) }
# impl TryFrom<&MyEvent> for &crossterm::event::Event {
#   type Error = ();
#   fn try_from(value: &MyEvent) -> Result<Self, Self::Error> {
#       match self {
#           MyEvent::Event(event) => Ok(event),
#           _ => Err(())    
#       }
#   }
# }
# struct MyAppState {}

impl AppState<GlobalState, MyEvent, Error> for MyAppState {
    fn event(
        &mut self,
        event: &MyEvent,
        ctx: &mut rat_salsa::AppContext<'_, GlobalState, MyEvent, Error>,
    ) -> Result<Control<MyEvent>, Error> {
        if matches!(event, MyEvent::Event(event)) {
            let mut state = FileDialogState::new();
            state.save_dialog_ext(PathBuf::from("."), "", "pas")?;
            state.map_outcome(|r| match r {
                FileOutcome::Ok(f) => {
                    Control::Event(MyEvent::Status(0, format!("New file {:?}", f)))
                }
                r => r.into(),
            });
            
            ctx.g.dialogs.push_dialog(
                |area, buf, state, ctx| {
                    FileDialog::new()
                        .styles(ctx.g.theme.file_dialog_style())
                        .render(area, buf, state, ctx)
                },
                state                    
            );
            
            Ok(Control::Changed)
        } else {
            Ok(Control::Continue)
        }
    }
}

During rendering of the application:

# use anyhow::Error;
# use ratatui::buffer::Buffer;
# use ratatui::layout::Rect;
use rat_dialog::{DialogStack, DialogStackState};
# use rat_salsa::{AppWidget,AppState, RenderContext};
# use rat_theme2::DarkTheme;
# struct MainApp;
# struct GlobalState { dialogs: DialogStackState<GlobalState, MyEvent, Error>, theme: DarkTheme }
# enum MyEvent { Event(crossterm::event::Event), Status(u16, String) }
# struct MainAppState {}
# impl AppState<GlobalState, MyEvent, Error> for MainAppState {}


impl AppWidget<GlobalState, MyEvent, Error> for MainApp {
    type State = MainAppState;

    fn render(
            &self,
            area: Rect,
            buf: &mut Buffer,
            state: &mut Self::State,
            ctx: &mut RenderContext<'_, GlobalState>,
    ) -> Result<(), Error> {

        // ... do all the rendering ...

        DialogStack.render(area, buf, &mut ctx.g.dialogs.clone(), ctx)?;

        Ok(())
   }
}