rat_widget/clipper/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//!
//! An alternative view widget.
//!
//! > The extra requirement for this one is that you can create
//! > a Layout that defines the bounds of all widgets that can
//! > be rendered.
//!
//! It works in 4 phases:
//!
//! ```rust no_run
//!     # use rat_widget::clipper::{Clipper, ClipperState};
//!     # use rat_widget::checkbox::{Checkbox, CheckboxState};
//!     # use ratatui::prelude::*;
//! use rat_focus::FocusFlag;
//! use rat_widget::layout::GenericLayout;
//!     #
//!     # let l2 = [Rect::ZERO, Rect::ZERO];
//!     # struct State {
//!     #      check_states: Vec<CheckboxState>,
//!     #      clipper: ClipperState<FocusFlag>
//!     #  }
//!     # let mut state = State {
//!     #      clipper: Default::default(),
//!     #      check_states: Vec::default()
//!     #  };
//!     # let mut buf = Buffer::default();
//!     ///
//!     /// Create the layout. The layout can be stored long-term
//!     /// and needs to be rebuilt only if your widget layout changes.
//!     ///
//!     ///> __Note__: add() returns a handle for the area. Can be used later
//!     ///> to refer to the stored area.
//!
//!     if state.clipper.layout.is_empty() {
//!         let mut cl = GenericLayout::new();
//!         for i in 0..100 {
//!             cl.add(state.check_states[i].focus.clone(),
//!                 Rect::new(10, i as u16 *11, 15, 10),
//!                 None,
//!                 Rect::default()
//!             );
//!         }
//!     }
//!
//!     /// The given area plus the current scroll offset define the
//!     /// view area. With the view area a temporary buffer is created
//!     /// that is big enough to fit all widgets that are at least
//!     /// partially visible.
//!
//!     let clipper = Clipper::new();
//!
//!     let mut clip_buf = clipper
//!         .into_buffer(l2[1], &mut state.clipper);
//!
//!     ///
//!     /// The widgets are rendered to that buffer.
//!     ///
//!     for i in 0..100 {
//!         // refer by handle
//!         clip_buf.render(
//!             state.check_states[i].focus.clone(),
//!             || {
//!                 Checkbox::new()
//!                 .text(format!("{:?}", i))
//!             },
//!             &mut state.check_states[i],
//!         );
//!     }
//!
//!     ///
//!     /// The last step clips and copies the buffer to the frame buffer.
//!     ///
//!
//!     clip_buf
//!         .into_widget()
//!         .render(l2[1], &mut buf, &mut state.clipper);
//!
//! ```
//!
//! __StatefulWidget__
//!
//! For this to work with StatefulWidgets they must cooperate
//! by implementing the [RelocatableState](crate::reloc::RelocatableState)
//! trait. With this trait the widget can clip/hide all areas that
//! it stores in its state.
//!
//! __See__
//!
//! [example](https://github.com/thscharler/rat-widget/blob/master/examples/clipper1.rs)
//!

#[allow(clippy::module_inception)]
mod clipper;
mod clipper_style;

pub use clipper::*;
pub use clipper_style::*;