Make view::scroll public

This commit is contained in:
Alexandre Bury 2019-10-08 15:33:33 -07:00
parent 5bf6f952d1
commit 22886859dd
11 changed files with 116 additions and 35 deletions

View File

@ -87,6 +87,7 @@ pub mod logger;
pub mod menu; pub mod menu;
pub mod theme; pub mod theme;
pub mod vec; pub mod vec;
#[macro_use]
pub mod views; pub mod views;
// This probably doesn't need to be public? // This probably doesn't need to be public?

View File

@ -51,13 +51,9 @@ mod view_trait;
// Helper bases // Helper bases
mod boxable; mod boxable;
mod identifiable; mod identifiable;
#[cfg(feature = "unstable_scroll")] #[macro_use]
pub mod scroll; pub mod scroll;
#[cfg(not(feature = "unstable_scroll"))]
#[allow(dead_code)]
pub(crate) mod scroll;
mod scroll_base; mod scroll_base;
mod scrollable; mod scrollable;

View File

@ -24,6 +24,36 @@ pub trait Scroller {
fn get_scroller(&self) -> &Core; fn get_scroller(&self) -> &Core;
} }
/// Implements the `Scroller` trait for any type.
#[macro_export]
macro_rules! impl_scroller {
($class:ident :: $core:ident) => {
impl $crate::view::scroll::Scroller for $class {
fn get_scroller_mut(
&mut self,
) -> &mut $crate::view::scroll::Core {
&mut self.$core
}
fn get_scroller(&self) -> &$crate::view::scroll::Core {
&self.$core
}
}
};
($class:ident < $($args:tt),* > :: $core:ident) => {
impl <$( $args ),* > $crate::view::scroll::Scroller for $class<$($args),*> {
fn get_scroller_mut(
&mut self,
) -> &mut $crate::view::scroll::Core {
&mut self.$core
}
fn get_scroller(&self) -> &$crate::view::scroll::Core {
&self.$core
}
}
};
}
/// Core system for scrolling views. /// Core system for scrolling views.
/// ///
/// This is the lowest-level element handling scroll logic. /// This is the lowest-level element handling scroll logic.

View File

@ -19,6 +19,7 @@
//! //!
//! [`ScrollView`](crate::views::ScrollView) may be an easier way to add scrolling to an existing view. //! [`ScrollView`](crate::views::ScrollView) may be an easier way to add scrolling to an existing view.
#[macro_use]
mod core; mod core;
mod raw; mod raw;
@ -48,9 +49,32 @@ impl Default for ScrollStrategy {
/// ///
/// Example: /// Example:
/// ///
/// ```rust,ignore /// ```
/// fn on_event(&mut self, event: Event) -> EventResult { /// use cursive::{Printer, Vec2, Rect};
/// scroll::on_event(self, event, Self::inner_on_event, Self::inner_important_area) /// use cursive::event::{Event, EventResult};
/// use cursive::view::{View, scroll};
///
/// struct MyView {
/// core: scroll::Core,
/// }
///
/// cursive::impl_scroller!(MyView::core);
///
/// impl MyView {
/// fn inner_on_event(&mut self, event: Event) -> EventResult {
/// EventResult::Ignored
/// }
///
/// fn inner_important_area(&self, size: Vec2) -> Rect {
/// Rect::from_size((0,0), size)
/// }
/// }
///
/// impl View for MyView {
/// # fn draw(&self, printer: &Printer) {}
/// fn on_event(&mut self, event: Event) -> EventResult {
/// scroll::on_event(self, event, Self::inner_on_event, Self::inner_important_area)
/// }
/// } /// }
/// ``` /// ```
pub fn on_event<T, OnEvent, ImportantArea>( pub fn on_event<T, OnEvent, ImportantArea>(

View File

@ -23,12 +23,13 @@ impl SizeCache {
/// Returns `true` if `self` is still valid for the given `request`. /// Returns `true` if `self` is still valid for the given `request`.
pub fn accept(self, request: usize) -> bool { pub fn accept(self, request: usize) -> bool {
if request < self.value { match (request, self.value) {
false // Request a smaller size than last time? Hell no!
} else if request == self.value { (r, v) if r < v => false,
true // Request exactly what we had last time? Sure!
} else { (r, v) if r == v => true,
!self.constrained // Request more than we had last time? Maybe?
_ => !self.constrained,
} }
} }

View File

@ -1,6 +1,6 @@
use crate::event::{Event, EventResult}; use crate::event::{Event, EventResult};
use crate::view::{View, ViewWrapper}; use crate::view::{View, ViewWrapper};
use crate::{Printer, With}; use crate::Printer;
/// Wrapper around another view that can be enabled/disabled at will. /// Wrapper around another view that can be enabled/disabled at will.
/// ///

View File

@ -34,15 +34,7 @@ pub struct MenuPopup {
// The `scroll::Scroller` trait is used to weave the borrow phases. // The `scroll::Scroller` trait is used to weave the borrow phases.
// //
// TODO: use some macro to auto-generate this. // TODO: use some macro to auto-generate this.
impl scroll::Scroller for MenuPopup { impl_scroller!(MenuPopup::scroll_core);
fn get_scroller(&self) -> &scroll::Core {
&self.scroll_core
}
fn get_scroller_mut(&mut self) -> &mut scroll::Core {
&mut self.scroll_core
}
}
impl MenuPopup { impl MenuPopup {
/// Creates a new `MenuPopup` using the given menu tree. /// Creates a new `MenuPopup` using the given menu tree.

View File

@ -1,6 +1,22 @@
//! Various views to use when creating the layout. //! Various views to use when creating the layout.
/// A macro to help with creating toggleable views. /// A macro to help with creating toggleable views.
///
/// # Examples
///
/// ```
/// struct MyView {
/// enabled: bool,
/// }
///
/// impl MyView {
/// cursive::impl_enabled!(self.enabled);
/// }
///
/// let view = MyView { enabled: true };
/// assert!(view.is_enabled());
/// ```
#[macro_export]
macro_rules! impl_enabled { macro_rules! impl_enabled {
(self.$x:ident) => { (self.$x:ident) => {
@ -15,6 +31,7 @@ macro_rules! impl_enabled {
/// ///
/// Chainable variant. /// Chainable variant.
pub fn disabled(self) -> Self { pub fn disabled(self) -> Self {
use $crate::traits::With as _;
self.with(Self::disable) self.with(Self::disable)
} }

View File

@ -11,17 +11,7 @@ pub struct ScrollView<V> {
core: scroll::Core, core: scroll::Core,
} }
impl<V> scroll::Scroller for ScrollView<V> impl_scroller!(ScrollView<V>::core);
where
V: View,
{
fn get_scroller(&self) -> &scroll::Core {
&self.core
}
fn get_scroller_mut(&mut self) -> &mut scroll::Core {
&mut self.core
}
}
impl<V> ScrollView<V> impl<V> ScrollView<V>
where where

View File

@ -10,6 +10,21 @@ use crate::{Cursive, Printer};
use std::rc::Rc; use std::rc::Rc;
/// A horizontal or vertical slider. /// A horizontal or vertical slider.
///
/// # Examples
///
/// ```
/// use cursive::views::{Dialog, SliderView};
///
/// let slider_view = SliderView::horizontal(10)
/// .on_change(|s, n| if n == 5 {
/// s.add_layer(Dialog::info("5! Pick 5!"));
/// })
/// .on_enter(|s, n| match n {
/// 5 => s.add_layer(Dialog::info("You did it!")),
/// n => s.add_layer(Dialog::info(format!("Why {}? Why not 5?", n))),
/// });
/// ```
pub struct SliderView { pub struct SliderView {
orientation: Orientation, orientation: Orientation,
on_change: Option<Rc<dyn Fn(&mut Cursive, usize)>>, on_change: Option<Rc<dyn Fn(&mut Cursive, usize)>>,
@ -24,6 +39,8 @@ impl SliderView {
/// ///
/// The view will have a fixed length of `max_value`, /// The view will have a fixed length of `max_value`,
/// with one tick per block. /// with one tick per block.
///
/// The actual range of values for this slider is `[0, max_value - 1]`.
pub fn new(orientation: Orientation, max_value: usize) -> Self { pub fn new(orientation: Orientation, max_value: usize) -> Self {
SliderView { SliderView {
orientation, orientation,

View File

@ -16,6 +16,19 @@ use unicode_width::UnicodeWidthStr;
/// A `TextArea` will attempt to grow vertically and horizontally /// A `TextArea` will attempt to grow vertically and horizontally
/// dependent on the content. Wrap it in a `BoxView` to /// dependent on the content. Wrap it in a `BoxView` to
/// constrain its size. /// constrain its size.
///
/// # Examples
///
/// ```
/// use cursive::traits::{Boxable, Identifiable};
/// use cursive::views::TextArea;
///
/// let text_area = TextArea::new()
/// .content("Write description here...")
/// .with_id("text_area")
/// .fixed_width(30)
/// .min_height(5);
/// ```
pub struct TextArea { pub struct TextArea {
// TODO: use a smarter data structure (rope?) // TODO: use a smarter data structure (rope?)
content: String, content: String,