Add some documentation to the view::scroll module

This commit is contained in:
Alexandre Bury 2019-07-02 16:50:18 -07:00
parent 976cb99bdb
commit babc038e36
4 changed files with 118 additions and 36 deletions

View File

@ -12,6 +12,9 @@ repository = "https://github.com/gyscos/cursive"
version = "0.12.1-alpha.0"
edition = "2018"
[package.metadata.docs.rs]
features = ["unstable_scroll"]
[badges.travis-ci]
repository = "gyscos/cursive"

View File

@ -26,7 +26,11 @@ pub trait Scroller {
/// Core system for scrolling views.
///
/// See also [`ScrollView`](crate::views::ScrollView).
/// This is the lowest-level element handling scroll logic.
///
/// Higher-level abstractions are probably what you're after.
///
/// In particular, see also [`ScrollView`](crate::views::ScrollView).
#[derive(Debug)]
pub struct Core {
/// This is the size the child thinks we're giving him.
@ -93,7 +97,8 @@ impl Core {
/// Returns a sub-printer ready to draw the content.
pub fn sub_printer<'a, 'b>(
&self, printer: &Printer<'a, 'b>,
&self,
printer: &Printer<'a, 'b>,
) -> Printer<'a, 'b> {
// Draw scrollbar?
let scrolling = self.is_scrolling();
@ -180,7 +185,9 @@ impl Core {
/// Handle an event after processing by the content.
pub fn on_inner_event(
&mut self, event: Event, inner_result: EventResult,
&mut self,
event: Event,
inner_result: EventResult,
important_area: Rect,
) -> EventResult {
match inner_result {
@ -358,7 +365,9 @@ impl Core {
/// Performs `View::call_on_any()`
pub fn call_on_any<'a, F>(
&mut self, selector: &Selector<'_>, cb: AnyCb<'a>,
&mut self,
selector: &Selector<'_>,
cb: AnyCb<'a>,
inner_call_on_any: F,
) where
F: FnOnce(&Selector, AnyCb),
@ -368,7 +377,9 @@ impl Core {
/// Performs `View::focus_view()`
pub fn focus_view<F>(
&mut self, selector: &Selector<'_>, inner_focus_view: F,
&mut self,
selector: &Selector<'_>,
inner_focus_view: F,
) -> Result<(), ()>
where
F: FnOnce(&Selector) -> Result<(), ()>,
@ -402,7 +413,8 @@ impl Core {
/// Sets the padding between content and scrollbar.
pub fn set_scrollbar_padding<V: Into<Vec2>>(
&mut self, scrollbar_padding: V,
&mut self,
scrollbar_padding: V,
) {
self.scrollbar_padding = scrollbar_padding.into();
}
@ -411,7 +423,8 @@ impl Core {
///
/// Chainable variant.
pub fn scrollbar_padding<V: Into<Vec2>>(
self, scrollbar_padding: V,
self,
scrollbar_padding: V,
) -> Self {
self.with(|s| s.set_scrollbar_padding(scrollbar_padding))
}

View File

@ -1,8 +1,21 @@
//! Core mechanisms to implement scrolling.
//!
//! *This module is still unstable and may go through breaking changes.*
//! In addition, it is private unless you enable the `unstable_scroll` feature.
//!
//! This module defines [`Core`](crate::view::scroll::Core) and related traits.
//! This modules defines:
//!
//! * [`scroll::Core`](crate::view::scroll::Core): stores the state variables
//! required to handle scrolling. Any view that needs to implement scrolling
//! should embed a `scroll::Core`.
//! * [`scroll::Scroller`](crate::view::scroll::Scroller): a trait for
//! something that embeds a such a `scroll::Core`.
//! * Some free functions to help implement the usual `View` trait for a type
//! implementing `scroll::Scroller`.
//! Some methods, like `View::call_on_any`, are not affected by scrolling
//! and are not covered here.
//! * The functions defined here will usually take a reference to the
//! `Scroller` object, as well as closures to implement the "inner view".
//!
//! [`ScrollView`](crate::views::ScrollView) may be an easier way to add scrolling to an existing view.
@ -41,7 +54,9 @@ impl Default for ScrollStrategy {
/// }
/// ```
pub fn on_event<T, OnEvent, ImportantArea>(
scroller: &mut T, event: Event, on_event: OnEvent,
scroller: &mut T,
event: Event,
on_event: OnEvent,
important_area: ImportantArea,
) -> EventResult
where
@ -60,7 +75,9 @@ where
/// Performs `View::important_area` on a `scroll::Scroller`.
pub fn important_area<T, ImportantArea>(
scroller: &T, size: Vec2, mut important_area: ImportantArea,
scroller: &T,
size: Vec2,
mut important_area: ImportantArea,
) -> Rect
where
T: Scroller,
@ -79,7 +96,10 @@ where
/// Performs `View::layout` on a `scroll::Scroller`.
pub fn layout<T, Layout, RequiredSize>(
scroller: &mut T, size: Vec2, needs_relayout: bool, layout: Layout,
scroller: &mut T,
size: Vec2,
needs_relayout: bool,
layout: Layout,
required_size: RequiredSize,
) where
T: Scroller,
@ -98,7 +118,9 @@ pub fn layout<T, Layout, RequiredSize>(
/// Performs `View::required_size` on a `scroll::Scroller`.
pub fn required_size<T, RequiredSize>(
scroller: &mut T, size: Vec2, needs_relayout: bool,
scroller: &mut T,
size: Vec2,
needs_relayout: bool,
required_size: RequiredSize,
) -> Vec2
where
@ -127,7 +149,9 @@ where
///
/// This is an alternative to `scroll::draw()` when you just need to print individual lines.
pub fn draw_lines<T, LineDrawer>(
scroller: &T, printer: &Printer, mut line_drawer: LineDrawer,
scroller: &T,
printer: &Printer,
mut line_drawer: LineDrawer,
) where
T: Scroller,
LineDrawer: FnMut(&T, &Printer, usize),
@ -146,8 +170,11 @@ pub fn draw_lines<T, LineDrawer>(
///
/// `left_border` will be called for each row to draw the left border for the given line number.
pub fn draw_frame<T, LeftBorder, TopBorder, RightBorder, BottomBorder>(
scroller: &T, printer: &Printer, mut left_border: LeftBorder,
mut top_border: TopBorder, mut right_border: RightBorder,
scroller: &T,
printer: &Printer,
mut left_border: LeftBorder,
mut top_border: TopBorder,
mut right_border: RightBorder,
mut bottom_border: BottomBorder,
) where
T: Scroller,
@ -197,7 +224,9 @@ pub fn draw_frame<T, LeftBorder, TopBorder, RightBorder, BottomBorder>(
///
/// It will print a box with the appropriate `├`, `┤` and so on.
pub fn draw_box_frame<T, IsHDelim, IsVDelim>(
scroller: &T, printer: &Printer, is_h_delim: IsHDelim,
scroller: &T,
printer: &Printer,
is_h_delim: IsHDelim,
is_v_delim: IsVDelim,
) where
T: Scroller,

View File

@ -1,3 +1,7 @@
//! Low-level implementation of the `View` trait using a `scroll::Core`.
//!
//! Most functions take a generic `Model` class, and various closures to get
//! the required things from this model.
use crate::event::{Event, EventResult};
use crate::rect::Rect;
use crate::view::scroll;
@ -5,8 +9,11 @@ use crate::xy::XY;
use crate::Printer;
use crate::Vec2;
/// Implements `View::draw` over the `model`.
pub fn draw<Model, GetScroller, Draw>(
printer: &Printer, model: &Model, mut get_scroller: GetScroller,
printer: &Printer,
model: &Model,
mut get_scroller: GetScroller,
inner_draw: Draw,
) where
Model: ?Sized,
@ -17,9 +24,20 @@ pub fn draw<Model, GetScroller, Draw>(
inner_draw(model, &printer);
}
/// Intermediate method to get the size requirements of a view.
///
/// Assumes we are already scrolling on the axis designated by `scrolling`.
///
/// `strict` means the result will never be bigger than the constraint.
///
/// Returns (Inner size, Outer size, New scrolling)
fn sizes_when_scrolling<Model, GetScroller, RequiredSize>(
constraint: Vec2, scrollable: XY<bool>, strict: bool, model: &mut Model,
get_scroller: &mut GetScroller, required_size: &mut RequiredSize,
constraint: Vec2,
scrolling: XY<bool>,
strict: bool,
model: &mut Model,
get_scroller: &mut GetScroller,
required_size: &mut RequiredSize,
) -> (Vec2, Vec2, XY<bool>)
where
Model: ?Sized,
@ -27,7 +45,7 @@ where
RequiredSize: FnMut(&mut Model, Vec2) -> Vec2,
{
// This is the size taken by the scrollbars.
let scrollbar_size = scrollable.swap().select_or(
let scrollbar_size = scrolling.swap().select_or(
get_scroller(model).get_scrollbar_padding() + (1, 1),
Vec2::zero(),
);
@ -56,14 +74,21 @@ where
.is_enabled()
.select_or(inner_size, size.saturating_sub(scrollbar_size));
let new_scrollable = inner_size.zip_map(size, |i, s| i > s);
let new_scrolling = inner_size.zip_map(size, |i, s| i > s);
(inner_size, size, new_scrollable)
(inner_size, size, new_scrolling)
}
/// Returns the size requirement of the view.
///
/// Returns (Inner size, Outer size)
fn sizes<Model, GetScroller, RequiredSize>(
constraint: Vec2, strict: bool, needs_relayout: bool, model: &mut Model,
get_scroller: &mut GetScroller, required_size: &mut RequiredSize,
constraint: Vec2,
strict: bool,
needs_relayout: bool,
model: &mut Model,
get_scroller: &mut GetScroller,
required_size: &mut RequiredSize,
) -> (Vec2, Vec2)
where
Model: ?Sized,
@ -77,7 +102,7 @@ where
}
// Attempt 1: try without scrollbars
let (inner_size, size, scrollable) = sizes_when_scrolling(
let (inner_size, size, scrolling) = sizes_when_scrolling(
constraint,
XY::new(false, false),
strict,
@ -87,18 +112,18 @@ where
);
// If we need to add scrollbars, the available size will change.
if scrollable.any() && get_scroller(model).get_show_scrollbars() {
if scrolling.any() && get_scroller(model).get_show_scrollbars() {
// Attempt 2: he wants to scroll? Sure!
// Try again with some space for the scrollbar.
let (inner_size, size, new_scrollable) = sizes_when_scrolling(
let (inner_size, size, new_scrolling) = sizes_when_scrolling(
constraint,
scrollable,
scrolling,
strict,
model,
get_scroller,
required_size,
);
if scrollable == new_scrollable {
if scrolling == new_scrolling {
// Yup, scrolling did it. We're good to go now.
(inner_size, size)
} else {
@ -106,7 +131,7 @@ where
// There is no end to this!
let (inner_size, size, _) = sizes_when_scrolling(
constraint,
new_scrollable,
new_scrolling,
strict,
model,
get_scroller,
@ -124,9 +149,13 @@ where
}
}
/// Implements `View::layout` on the given model.
pub fn layout<Model, GetScroller, RequiredSize, Layout>(
size: Vec2, needs_relayout: bool, model: &mut Model,
mut get_scroller: GetScroller, mut required_size: RequiredSize,
size: Vec2,
needs_relayout: bool,
model: &mut Model,
mut get_scroller: GetScroller,
mut required_size: RequiredSize,
mut layout: Layout,
) where
Model: ?Sized,
@ -154,9 +183,13 @@ pub fn layout<Model, GetScroller, RequiredSize, Layout>(
get_scroller(model).update_offset();
}
/// Implements `View::required_size` on the given model.
pub fn required_size<Model, GetScroller, RequiredSize>(
constraint: Vec2, needs_relayout: bool, model: &mut Model,
mut get_scroller: GetScroller, mut required_size: RequiredSize,
constraint: Vec2,
needs_relayout: bool,
model: &mut Model,
mut get_scroller: GetScroller,
mut required_size: RequiredSize,
) -> Vec2
where
Model: ?Sized,
@ -175,9 +208,13 @@ where
size
}
/// Implements `View::on_event` on the given model.
pub fn on_event<Model, GetScroller, OnEvent, ImportantArea>(
event: Event, model: &mut Model, mut get_scroller: GetScroller,
mut on_event: OnEvent, mut important_area: ImportantArea,
event: Event,
model: &mut Model,
mut get_scroller: GetScroller,
mut on_event: OnEvent,
mut important_area: ImportantArea,
) -> EventResult
where
Model: ?Sized,