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::*;