rat_widget/pager/
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//!
//! If you are tired of scrolling, try paging :)
//!
//! If you have a lot of widgets to display, splitting
//! them into pages is an alternative to scrolling.
//!
//! ```rust no_run
//!     # use std::rc::Rc;
//!     # use rat_widget::pager::{SinglePager, SinglePagerState};
//!     # use rat_widget::checkbox::{Checkbox, CheckboxState};
//!     # use ratatui::prelude::*;
//!     # use rat_focus::FocusFlag;
//!     # use rat_widget::layout::{GenericLayout, LayoutForm};
//!     #
//!     # let l2 = [Rect::ZERO, Rect::ZERO];
//!     # struct State {
//!     #      check_states: Vec<CheckboxState>,
//!     #      pager: SinglePagerState<FocusFlag>
//!     #  }
//!     # let mut state = State {
//!     #      check_states: Vec::default(),
//!     #      pager: Default::default(),
//!     #  };
//!     # let mut buf = Buffer::default();
//!
//!     /// Single pager shows the widgets in one column, and
//!     /// can page through the list.
//!     let pager = SinglePager::new();
//!     let size = pager.layout_size(l2[1]);
//!
//!     if !state.pager.valid_layout(size) {
//!           // GenericLayout is very basic.
//!           // Try LayoutForm or layout_edit() instead.
//!           let mut pl = GenericLayout::new();
//!           for i in 0..100 {
//!               pl.add(
//!                     state.check_states[i].focus.clone(), // widget-key
//!                     Rect::new(10, 10+i as u16, 15, 10), // widget area
//!                     None, // label text
//!                     Rect::default() // label area
//!               );
//!           }
//!           state.pager.set_layout(pl);
//!       }
//!
//!       ///
//!       /// Use [SinglePager] or [DualPager] to calculate the page breaks.
//!       ///
//!       let mut pg_buf = pager
//!             .into_buffer(l2[1], &mut buf, &mut state.pager);
//!
//!       ///
//!       /// Render your widgets with the help of [SinglePagerBuffer]/[DualPagerBuffer]
//!       ///
//!       for i in 0..100 {
//!           pg_buf.render(
//!               state.check_states[i].focus.clone(),
//!               || {
//!                 Checkbox::new().text(format!("{:?}", i).to_string())
//!               },
//!               &mut state.check_states[i],
//!           );
//!       }
//!
//! ```

mod dual_pager;
#[allow(clippy::module_inception)]
mod pager;
mod pager_nav;
mod pager_style;
mod single_pager;

pub use dual_pager::*;
pub use pager::{Pager, PagerBuffer};
pub use pager_nav::{PageNavigation, PageNavigationState};
pub use pager_style::*;
pub use single_pager::*;

pub(crate) mod event {
    use rat_event::{ConsumedEvent, Outcome};

    /// Result of event handling.
    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
    pub enum PagerOutcome {
        /// The given event has not been used at all.
        Continue,
        /// The event has been recognized, but the result was nil.
        /// Further processing for this event may stop.
        Unchanged,
        /// The event has been recognized and there is some change
        /// due to it.
        /// Further processing for this event may stop.
        /// Rendering the ui is advised.
        Changed,
        /// Displayed page changed.
        Page(usize),
    }

    impl ConsumedEvent for PagerOutcome {
        fn is_consumed(&self) -> bool {
            *self != PagerOutcome::Continue
        }
    }

    // Useful for converting most navigation/edit results.
    impl From<bool> for PagerOutcome {
        fn from(value: bool) -> Self {
            if value {
                PagerOutcome::Changed
            } else {
                PagerOutcome::Unchanged
            }
        }
    }

    impl From<Outcome> for PagerOutcome {
        fn from(value: Outcome) -> Self {
            match value {
                Outcome::Continue => PagerOutcome::Continue,
                Outcome::Unchanged => PagerOutcome::Unchanged,
                Outcome::Changed => PagerOutcome::Changed,
            }
        }
    }

    impl From<PagerOutcome> for Outcome {
        fn from(value: PagerOutcome) -> Self {
            match value {
                PagerOutcome::Continue => Outcome::Continue,
                PagerOutcome::Unchanged => Outcome::Unchanged,
                PagerOutcome::Changed => Outcome::Changed,
                PagerOutcome::Page(_) => Outcome::Changed,
            }
        }
    }
}