cursive-extras 0.13.4

Extra views for the Cursive TUI library as well some helper functions and macros
Documentation
use cursive_core::{
    View, Printer, Vec2,
    event::{Event, EventResult, AnyCb},
    direction::Direction,
    view::{
        CannotFocus,
        Selector,
        ViewNotFound
    },
    Rect
};

/// A view that lazily renders its contents
pub struct LazyView<V: View> {
    view_thunk: Option<Box<dyn FnOnce() -> V + Send + Sync>>,
    final_view: Option<V>,
    auto_init: bool
}

impl<V: View> LazyView<V> {
    /// Create a new `LazyView` with function to generate the inner view
    pub fn new<F: FnOnce() -> V + Send + Sync + 'static>(view_thunk: F) -> Self {
        LazyView {
            view_thunk: Some(Box::new(view_thunk)),
            final_view: None,
            auto_init: true
        }
    }

    /// Manually initialize the inner view
    pub fn initialize(&mut self) {
        if self.final_view.is_none() {
            let view_thunk = self.view_thunk.take().unwrap();
            self.final_view = Some(view_thunk());
        }
    }

    /// Is the view initialized?
    pub fn is_initialized(&self) -> bool {
        self.get_view().is_some()
    }

    /// Get access to the inner view
    /// 
    /// Returns `None` if the inner view isn't initialized yet
    pub fn get_view(&self) -> Option<&V> {
        self.final_view.as_ref()
    }

    /// Get mutable access to the inner view
    /// 
    /// Also initializes the inner view if it hasn't been done yet
    pub fn get_view_mut(&mut self) -> Option<&mut V> {
        self.initialize();
        self.final_view.as_mut()
    }

    /// Should the view be automatically initialized?
    pub fn set_auto_init(&mut self, auto_init: bool) {
        self.auto_init = auto_init;
    }

    /// Should the view be automatically initialized?
    ///
    /// Chainable version
    pub fn auto_init(mut self, auto_init: bool) -> Self {
        self.set_auto_init(auto_init);
        self
    }
}

impl<V: View> View for LazyView<V> {
    fn draw(&self, printer: &Printer) {
        if let Some(ref view) = self.final_view {
            view.draw(printer);
        }
    }

    fn layout(&mut self, size: Vec2) {
        if let Some(ref mut view) = self.final_view {
            view.layout(size);
        }
        else if self.auto_init {
            self.initialize();
        }
    }

    fn required_size(&mut self, constraint: Vec2) -> Vec2 {
        if let Some(ref mut view) = self.final_view {
            view.required_size(constraint)
        }
        else { Vec2::new(0, 0) }
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        if let Some(ref mut view) = self.final_view {
            view.on_event(event)
        }
        else { EventResult::Ignored }
    }

    fn take_focus(&mut self, dir: Direction) -> Result<EventResult, CannotFocus> {
        if let Some(ref mut view) = self.final_view {
            view.take_focus(dir)
        }
        else {
            Err(CannotFocus)
        }
    }

    fn call_on_any(&mut self, sel: &Selector, cb: AnyCb) {
        if let Some(ref mut view) = self.final_view {
            view.call_on_any(sel, cb);
        }
    }

    fn focus_view(&mut self, sel: &Selector) -> Result<EventResult, ViewNotFound> {
        if let Some(ref mut view) = self.final_view {
            view.focus_view(sel)
        }
        else { Err(ViewNotFound) }
    }

    fn needs_relayout(&self) -> bool {
        if let Some(ref view) = self.final_view {
            view.needs_relayout()
        }
        else { true }
    }

    fn important_area(&self, size: Vec2) -> Rect {
        if let Some(ref view) = self.final_view {
            view.important_area(size)
        }
        else { Rect::from_point((1, 1)) }
    }
}