cursive_extras/views/
lazy_view.rs

1use cursive_core::{
2    View, Printer, Vec2,
3    event::{Event, EventResult, AnyCb},
4    direction::Direction,
5    view::{
6        CannotFocus,
7        Selector,
8        ViewNotFound
9    },
10    Rect
11};
12
13/// A view that lazily renders its contents
14pub struct LazyView<V: View> {
15    view_thunk: Option<Box<dyn FnOnce() -> V + Send + Sync>>,
16    final_view: Option<V>,
17    auto_init: bool
18}
19
20impl<V: View> LazyView<V> {
21    /// Create a new `LazyView` with function to generate the inner view
22    pub fn new<F: FnOnce() -> V + Send + Sync + 'static>(view_thunk: F) -> Self {
23        LazyView {
24            view_thunk: Some(Box::new(view_thunk)),
25            final_view: None,
26            auto_init: true
27        }
28    }
29
30    /// Manually initialize the inner view
31    pub fn initialize(&mut self) {
32        if self.final_view.is_none() {
33            let view_thunk = self.view_thunk.take().unwrap();
34            self.final_view = Some(view_thunk());
35        }
36    }
37
38    /// Is the view initialized?
39    pub fn is_initialized(&self) -> bool {
40        self.get_view().is_some()
41    }
42
43    /// Get access to the inner view
44    /// 
45    /// Returns `None` if the inner view isn't initialized yet
46    pub fn get_view(&self) -> Option<&V> {
47        self.final_view.as_ref()
48    }
49
50    /// Get mutable access to the inner view
51    /// 
52    /// Also initializes the inner view if it hasn't been done yet
53    pub fn get_view_mut(&mut self) -> Option<&mut V> {
54        self.initialize();
55        self.final_view.as_mut()
56    }
57
58    /// Should the view be automatically initialized?
59    pub fn set_auto_init(&mut self, auto_init: bool) {
60        self.auto_init = auto_init;
61    }
62
63    /// Should the view be automatically initialized?
64    ///
65    /// Chainable version
66    pub fn auto_init(mut self, auto_init: bool) -> Self {
67        self.set_auto_init(auto_init);
68        self
69    }
70}
71
72impl<V: View> View for LazyView<V> {
73    fn draw(&self, printer: &Printer) {
74        if let Some(ref view) = self.final_view {
75            view.draw(printer);
76        }
77    }
78
79    fn layout(&mut self, size: Vec2) {
80        if let Some(ref mut view) = self.final_view {
81            view.layout(size);
82        }
83        else if self.auto_init {
84            self.initialize();
85        }
86    }
87
88    fn required_size(&mut self, constraint: Vec2) -> Vec2 {
89        if let Some(ref mut view) = self.final_view {
90            view.required_size(constraint)
91        }
92        else { Vec2::new(0, 0) }
93    }
94
95    fn on_event(&mut self, event: Event) -> EventResult {
96        if let Some(ref mut view) = self.final_view {
97            view.on_event(event)
98        }
99        else { EventResult::Ignored }
100    }
101
102    fn take_focus(&mut self, dir: Direction) -> Result<EventResult, CannotFocus> {
103        if let Some(ref mut view) = self.final_view {
104            view.take_focus(dir)
105        }
106        else {
107            Err(CannotFocus)
108        }
109    }
110
111    fn call_on_any(&mut self, sel: &Selector, cb: AnyCb) {
112        if let Some(ref mut view) = self.final_view {
113            view.call_on_any(sel, cb);
114        }
115    }
116
117    fn focus_view(&mut self, sel: &Selector) -> Result<EventResult, ViewNotFound> {
118        if let Some(ref mut view) = self.final_view {
119            view.focus_view(sel)
120        }
121        else { Err(ViewNotFound) }
122    }
123
124    fn needs_relayout(&self) -> bool {
125        if let Some(ref view) = self.final_view {
126            view.needs_relayout()
127        }
128        else { true }
129    }
130
131    fn important_area(&self, size: Vec2) -> Rect {
132        if let Some(ref view) = self.final_view {
133            view.important_area(size)
134        }
135        else { Rect::from_point((1, 1)) }
136    }
137}