More rustfmt

This commit is contained in:
Alexandre Bury 2017-10-14 21:18:50 -07:00
parent 294a4102b4
commit f90621811c
18 changed files with 235 additions and 200 deletions

View File

@ -3,7 +3,7 @@ extern crate cursive;
use cursive::Cursive; use cursive::Cursive;
use cursive::align::HAlign; use cursive::align::HAlign;
use cursive::view::Boxable; use cursive::view::Boxable;
use cursive::views::{Dialog, TextView, Panel}; use cursive::views::{Dialog, Panel, TextView};
fn main() { fn main() {
// Read some long text from a file. // Read some long text from a file.

View File

@ -66,7 +66,7 @@ fn main() {
.leaf("About", .leaf("About",
|s| s.add_layer(Dialog::info("Cursive v0.0.0")))); |s| s.add_layer(Dialog::info("Cursive v0.0.0"))));
// When `autohide` is on (default), the menu only appears when it is active. // When `autohide` is on (default), the menu only appears when active.
// Turning it off will leave the menu always visible. // Turning it off will leave the menu always visible.
// siv.set_autohide_menu(false); // siv.set_autohide_menu(false);

View File

@ -7,17 +7,23 @@ use cursive::views::{Dialog, OnEventView, TextView};
fn show_popup(siv: &mut Cursive) { fn show_popup(siv: &mut Cursive) {
// Let's center the popup horizontally, but offset it down a few rows // Let's center the popup horizontally, but offset it down a few rows
siv.screen_mut() siv.screen_mut().add_layer_at(
.add_layer_at(Position::new(Offset::Center, Offset::Parent(3)), Position::new(Offset::Center, Offset::Parent(3)),
Dialog::around(TextView::new("Tak!")) Dialog::around(TextView::new("Tak!"))
.button("Change", |s| { .button("Change", |s| {
// Look for a view tagged "text". We _know_ it's there, so unwrap it. // Look for a view tagged "text".
s.call_on_id("text", |view: &mut TextView| { // We _know_ it's there, so unwrap it.
let content: String = view.get_content().chars().rev().collect(); s.call_on_id("text", |view: &mut TextView| {
view.set_content(content); let content = reverse(view.get_content());
}); view.set_content(content);
}) });
.dismiss_button("Ok")); })
.dismiss_button("Ok"),
);
}
fn reverse(text: &str) -> String {
text.chars().rev().collect()
} }
fn main() { fn main() {

View File

@ -30,7 +30,8 @@ fn main() {
let mut siv = Cursive::new(); let mut siv = Cursive::new();
// Let's add a BoxView to keep the list at a reasonable size - it can scroll anyway. // Let's add a BoxView to keep the list at a reasonable size
// (it can scroll anyway).
siv.add_layer( siv.add_layer(
Dialog::around(select.fixed_size((20, 10))) Dialog::around(select.fixed_size((20, 10)))
.title("Where are you from?"), .title("Where are you from?"),
@ -39,7 +40,8 @@ fn main() {
siv.run(); siv.run();
} }
// Let's put the callback in a separate function to keep it clean, but it's not required. // Let's put the callback in a separate function to keep it clean,
// but it's not required.
fn show_next_window(siv: &mut Cursive, city: &str) { fn show_next_window(siv: &mut Cursive, city: &str) {
siv.pop_layer(); siv.pop_layer();
let text = format!("{} is a great city!", city); let text = format!("{} is a great city!", city);

View File

@ -151,7 +151,8 @@ impl Concrete {
// Treat '\n' and the numpad Enter the same // Treat '\n' and the numpad Enter the same
10 | ncurses::KEY_ENTER => Event::Key(Key::Enter), 10 | ncurses::KEY_ENTER => Event::Key(Key::Enter),
// This is the escape key when pressed by itself. // This is the escape key when pressed by itself.
// When used for control sequences, it should have been caught earlier. // When used for control sequences,
// it should have been caught earlier.
27 => Event::Key(Key::Esc), 27 => Event::Key(Key::Esc),
// `Backspace` sends 127, but Ctrl-H sends `Backspace` // `Backspace` sends 127, but Ctrl-H sends `Backspace`
127 | ncurses::KEY_BACKSPACE => Event::Key(Key::Backspace), 127 | ncurses::KEY_BACKSPACE => Event::Key(Key::Backspace),
@ -267,7 +268,8 @@ impl Concrete {
impl backend::Backend for Concrete { impl backend::Backend for Concrete {
fn init() -> Self { fn init() -> Self {
// Change the locale. For some reasons it's mandatory to get some UTF-8 support. // Change the locale.
// For some reasons it's mandatory to get some UTF-8 support.
ncurses::setlocale(ncurses::LcCategory::all, ""); ncurses::setlocale(ncurses::LcCategory::all, "");
// The delay is the time ncurses wait after pressing ESC // The delay is the time ncurses wait after pressing ESC

View File

@ -260,16 +260,21 @@ impl Cursive {
/// # use cursive::{Cursive, views, view}; /// # use cursive::{Cursive, views, view};
/// # use cursive::traits::*; /// # use cursive::traits::*;
/// # fn main() { /// # fn main() {
/// let mut siv = Cursive::new(); /// fn main() {
/// let mut siv = Cursive::new();
/// ///
/// siv.add_layer(views::TextView::new("Text #1") /// siv.add_layer(views::TextView::new("Text #1").with_id("text"));
/// .with_id("text"));
/// ///
/// siv.add_global_callback('p', |s| { /// siv.add_global_callback('p', |s| {
/// s.call_on(&view::Selector::Id("text"), |view: &mut views::TextView| { /// s.call_on(
/// view.set_content("Text #2"); /// &view::Selector::Id("text"),
/// |view: &mut views::TextView| {
/// view.set_content("Text #2");
/// },
/// );
/// }); /// });
/// }); ///
/// }
/// # } /// # }
/// ``` /// ```
pub fn call_on<V, F, R>( pub fn call_on<V, F, R>(
@ -513,9 +518,7 @@ impl Cursive {
} }
if let Event::Mouse { if let Event::Mouse {
event, event, position, ..
position,
..
} = event } = event
{ {
if event.grabs_focus() && !self.menubar.autohide if event.grabs_focus() && !self.menubar.autohide

View File

@ -303,8 +303,8 @@ pub enum Event {
/// An unknown event was received. /// An unknown event was received.
Unknown(Vec<u8>), Unknown(Vec<u8>),
// Having a doc-hidden event prevents people from having exhaustive matches, // Having a doc-hidden event prevents people from having exhaustive
// allowing us to add events in the future. // matches, allowing us to add events in the future.
#[doc(hidden)] #[doc(hidden)]
/// The application is about to exit. /// The application is about to exit.
Exit, Exit,

View File

@ -10,22 +10,21 @@ pub use self::lines_iterator::{LinesIterator, Row};
pub use self::reader::ProgressReader; pub use self::reader::ProgressReader;
/// The length and width of a part of a string. /// The length and width of a part of a string.
pub struct Prefix { pub struct Span {
/// The length (in bytes) of the string. /// The length (in bytes) of the string.
pub length: usize, pub length: usize,
/// The unicode-width of the string. /// The unicode-width of the string.
pub width: usize, pub width: usize,
} }
/// Computes the length (number of bytes) and width of a prefix that fits in the given `width`. /// Computes a prefix that fits in the given `width`.
/// ///
/// Takes non-breakable elements from `iter`, while keeping the /// Takes non-breakable elements from `iter`, while keeping the string width
/// string width under `width` (and adding the length of `delimiter` /// under `width` (and adding `delimiter` between each element).
/// between each element).
/// ///
/// Given `total_text = iter.collect().join(delimiter)`, the result /// Given `total_text = iter.collect().join(delimiter)`, the result is the
/// is the length of the longest prefix of `width` or less cells, /// length of the longest prefix of `width` or less cells, without breaking
/// without breaking inside an element. /// inside an element.
/// ///
/// Example: /// Example:
/// ///
@ -42,9 +41,7 @@ pub struct Prefix {
/// prefix(my_text.graphemes(true), 5, ""); /// prefix(my_text.graphemes(true), 5, "");
/// # } /// # }
/// ``` /// ```
pub fn prefix<'a, I>( pub fn prefix<'a, I>(iter: I, available_width: usize, delimiter: &str) -> Span
iter: I, available_width: usize, delimiter: &str
) -> Prefix
where where
I: Iterator<Item = &'a str>, I: Iterator<Item = &'a str>,
{ {
@ -74,13 +71,13 @@ where
// `current_width` includes a delimiter after the last token // `current_width` includes a delimiter after the last token
debug_assert!(current_width <= available_width + delimiter_width); debug_assert!(current_width <= available_width + delimiter_width);
Prefix { Span {
length: length, length: length,
width: current_width, width: current_width,
} }
} }
/// Computes the length (number of bytes) and width of a suffix that fits in the given `width`. /// Computes the longest suffix that fits in the given `width`.
/// ///
/// Doesn't break inside elements returned by `iter`. /// Doesn't break inside elements returned by `iter`.
/// ///
@ -88,24 +85,24 @@ where
/// suffix from `text` that fits in `width`. /// suffix from `text` that fits in `width`.
/// ///
/// This is a shortcut for `prefix_length(iter.rev(), width, delimiter)` /// This is a shortcut for `prefix_length(iter.rev(), width, delimiter)`
pub fn suffix<'a, I>(iter: I, width: usize, delimiter: &str) -> Prefix pub fn suffix<'a, I>(iter: I, width: usize, delimiter: &str) -> Span
where where
I: DoubleEndedIterator<Item = &'a str>, I: DoubleEndedIterator<Item = &'a str>,
{ {
prefix(iter.rev(), width, delimiter) prefix(iter.rev(), width, delimiter)
} }
/// Computes a suffix that fits in the given `width`. /// Computes the longest suffix that fits in the given `width`.
/// ///
/// Breaks between any two graphemes. /// Breaks between any two graphemes.
pub fn simple_suffix(text: &str, width: usize) -> Prefix { pub fn simple_suffix(text: &str, width: usize) -> Span {
suffix(text.graphemes(true), width, "") suffix(text.graphemes(true), width, "")
} }
/// Computes the longest prefix of the given text that fits in the given width. /// Computes the longest prefix that fits in the given width.
/// ///
/// Breaks between any two graphemes. /// Breaks between any two graphemes.
pub fn simple_prefix(text: &str, width: usize) -> Prefix { pub fn simple_prefix(text: &str, width: usize) -> Span {
prefix(text.graphemes(true), width, "") prefix(text.graphemes(true), width, "")
} }

View File

@ -111,7 +111,8 @@ pub trait View {
/// Runs a closure on the view identified by the given selector. /// Runs a closure on the view identified by the given selector.
/// ///
/// See [`Finder::call_on`] for a nicer interface, implemented for all views. /// See [`Finder::call_on`] for a nicer interface, implemented for all
/// views.
/// ///
/// [`Finder::call_on`]: trait.Finder.html#method.call_on /// [`Finder::call_on`]: trait.Finder.html#method.call_on
/// ///

View File

@ -47,7 +47,8 @@ impl SizeCache {
/// A compatible request is one where, for each axis, either: /// A compatible request is one where, for each axis, either:
/// ///
/// * the request is equal to the cached size, or /// * the request is equal to the cached size, or
/// * the request is larger than the cached size and the cache is unconstrained /// * the request is larger than the cached size and the cache is
/// unconstrained
/// ///
/// Notes: /// Notes:
/// ///

View File

@ -12,21 +12,24 @@ use utils::{simple_prefix, simple_suffix};
use vec::Vec2; use vec::Vec2;
use view::View; use view::View;
/// closure type for callbacks when the content is modified. Arguments are the /// Closure type for callbacks when the content is modified.
/// `Cursive`, current content of the input and cursor position ///
/// Arguments are the `Cursive`, current content of the input and cursor
/// position
pub type OnEdit = Fn(&mut Cursive, &str, usize); pub type OnEdit = Fn(&mut Cursive, &str, usize);
/// closure type for callbacks when Enter is pressed. Arguments are the `Cursive` /// Closure type for callbacks when Enter is pressed.
/// and the content of the input. ///
/// Arguments are the `Cursive` and the content of the input.
pub type OnSubmit = Fn(&mut Cursive, &str); pub type OnSubmit = Fn(&mut Cursive, &str);
/// Input box where the user can enter and edit text. /// Input box where the user can enter and edit text.
/// ///
/// # Examples /// # Examples
/// ///
/// From the [edit example]. /// From the [edit example][1].
/// ///
/// [edit example]: https://github.com/gyscos/Cursive/blob/master/examples/edit.rs /// [1]: https://github.com/gyscos/Cursive/blob/master/examples/edit.rs
/// ///
/// ```no_run /// ```no_run
/// # extern crate cursive; /// # extern crate cursive;
@ -39,18 +42,24 @@ pub type OnSubmit = Fn(&mut Cursive, &str);
/// // Create a dialog with an edit text and a button. /// // Create a dialog with an edit text and a button.
/// // The user can either hit the <Ok> button, /// // The user can either hit the <Ok> button,
/// // or press Enter on the edit text. /// // or press Enter on the edit text.
/// siv.add_layer(Dialog::new() /// siv.add_layer(
/// .title("Enter your name") /// Dialog::new()
/// .padding((1, 1, 1, 0)) /// .title("Enter your name")
/// .content(EditView::new() /// .padding((1, 1, 1, 0))
/// .on_submit(show_popup) /// .content(
/// .with_id("name") /// EditView::new()
/// .fixed_width(20)) /// .on_submit(show_popup)
/// .button("Ok", |s| { /// .with_id("name")
/// let name = s.call_on_id("name", |view: &mut EditView| view.get_content()) /// .fixed_width(20),
/// .unwrap(); /// )
/// show_popup(s, &name); /// .button("Ok", |s| {
/// })); /// let name = s.call_on_id(
/// "name",
/// |view: &mut EditView| view.get_content(),
/// ).unwrap();
/// show_popup(s, &name);
/// }),
/// );
/// ///
/// fn show_popup(s: &mut Cursive, name: &str) { /// fn show_popup(s: &mut Cursive, name: &str) {
/// if name.is_empty() { /// if name.is_empty() {
@ -145,8 +154,7 @@ impl EditView {
/// ///
/// ```rust /// ```rust
/// # use cursive::views::EditView; /// # use cursive::views::EditView;
/// let edit = EditView::new() /// let edit = EditView::new().filler(" ");
/// .filler(" ");
/// ``` /// ```
pub fn filler<S: Into<String>>(self, filler: S) -> Self { pub fn filler<S: Into<String>>(self, filler: S) -> Self {
self.with(|s| s.set_filler(filler)) self.with(|s| s.set_filler(filler))

View File

@ -209,7 +209,12 @@ impl LinearLayout {
}; };
for (i, (offset, child)) in iterator.enumerate() { for (i, (offset, child)) in iterator.enumerate() {
let child_size = child.size.get(self.orientation); let child_size = child.size.get(self.orientation);
// eprintln!("Offset {:?}, size {:?}, position: {:?}", offset, child_size, position); // eprintln!(
// "Offset {:?}, size {:?}, position: {:?}",
// offset,
// child_size,
// position
// );
if (offset + child_size > position) if (offset + child_size > position)
&& child.view.take_focus(direction::Direction::none()) && child.view.take_focus(direction::Direction::none())
{ {

View File

@ -2,7 +2,7 @@ use Cursive;
use Printer; use Printer;
use With; use With;
use direction; use direction;
use event::{Callback, Event, EventResult, Key, MouseEvent, MouseButton}; use event::{Callback, Event, EventResult, Key, MouseButton, MouseEvent};
use std::any::Any; use std::any::Any;
use std::rc::Rc; use std::rc::Rc;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
@ -96,10 +96,8 @@ impl ListView {
/// Adds a view to the end of the list. /// Adds a view to the end of the list.
pub fn add_child<V: View + 'static>(&mut self, label: &str, mut view: V) { pub fn add_child<V: View + 'static>(&mut self, label: &str, mut view: V) {
view.take_focus(direction::Direction::none()); view.take_focus(direction::Direction::none());
self.children.push(ListChild::Row( self.children
label.to_string(), .push(ListChild::Row(label.to_string(), Box::new(view)));
Box::new(view),
));
} }
/// Removes all children from this view. /// Removes all children from this view.
@ -152,8 +150,9 @@ impl ListView {
self.focus self.focus
} }
fn iter_mut<'a>(&'a mut self, from_focus: bool, source: direction::Relative) fn iter_mut<'a>(
-> Box<Iterator<Item = (usize, &mut ListChild)> + 'a> { &'a mut self, from_focus: bool, source: direction::Relative
) -> Box<Iterator<Item = (usize, &mut ListChild)> + 'a> {
match source { match source {
direction::Relative::Front => { direction::Relative::Front => {
let start = if from_focus { self.focus } else { 0 }; let start = if from_focus { self.focus } else { 0 };
@ -171,8 +170,9 @@ impl ListView {
} }
} }
fn move_focus(&mut self, n: usize, source: direction::Direction) fn move_focus(
-> EventResult { &mut self, n: usize, source: direction::Direction
) -> EventResult {
let i = if let Some(i) = source let i = if let Some(i) = source
.relative(direction::Orientation::Vertical) .relative(direction::Orientation::Vertical)
.and_then(|rel| { .and_then(|rel| {
@ -183,8 +183,7 @@ impl ListView {
.filter_map(|p| try_focus(p, source)) .filter_map(|p| try_focus(p, source))
.take(n) .take(n)
.last() .last()
}) }) {
{
i i
} else { } else {
return EventResult::Ignored; return EventResult::Ignored;
@ -241,17 +240,16 @@ impl ListView {
} }
} }
fn try_focus((i, child): (usize, &mut ListChild), source: direction::Direction) fn try_focus(
-> Option<usize> { (i, child): (usize, &mut ListChild), source: direction::Direction
) -> Option<usize> {
match *child { match *child {
ListChild::Delimiter => None, ListChild::Delimiter => None,
ListChild::Row(_, ref mut view) => { ListChild::Row(_, ref mut view) => if view.take_focus(source) {
if view.take_focus(source) { Some(i)
Some(i) } else {
} else { None
None },
}
}
} }
} }
@ -264,16 +262,14 @@ impl View for ListView {
let offset = self.labels_width() + 1; let offset = self.labels_width() + 1;
debug!("Offset: {}", offset); debug!("Offset: {}", offset);
self.scrollbase.draw( self.scrollbase
printer, .draw(printer, |printer, i| match self.children[i] {
|printer, i| match self.children[i] {
ListChild::Row(ref label, ref view) => { ListChild::Row(ref label, ref view) => {
printer.print((0, 0), label); printer.print((0, 0), label);
view.draw(&printer.offset((offset, 0), i == self.focus)); view.draw(&printer.offset((offset, 0), i == self.focus));
} }
ListChild::Delimiter => (), ListChild::Delimiter => (),
}, });
);
} }
fn required_size(&mut self, req: Vec2) -> Vec2 { fn required_size(&mut self, req: Vec2) -> Vec2 {
@ -314,9 +310,8 @@ impl View for ListView {
let spacing = 1; let spacing = 1;
let scrollbar_width = if self.children.len() > size.y { 2 } else { 0 }; let scrollbar_width = if self.children.len() > size.y { 2 } else { 0 };
let available = size.x.saturating_sub( let available = size.x
label_width + spacing + scrollbar_width, .saturating_sub(label_width + spacing + scrollbar_width);
);
debug!("Available: {}", available); debug!("Available: {}", available);
@ -336,33 +331,35 @@ impl View for ListView {
event: MouseEvent::Press(MouseButton::Left), event: MouseEvent::Press(MouseButton::Left),
position, position,
offset, offset,
} } if position
if position .checked_sub(offset)
.checked_sub(offset) .map(|position| {
.map(|position| {
self.scrollbase.start_drag(position, self.last_size.x) self.scrollbase.start_drag(position, self.last_size.x)
}) })
.unwrap_or(false) => { .unwrap_or(false) =>
{
return EventResult::Consumed(None); return EventResult::Consumed(None);
} }
Event::Mouse { Event::Mouse {
event: MouseEvent::Hold(MouseButton::Left), event: MouseEvent::Hold(MouseButton::Left),
position, position,
offset, offset,
} if self.scrollbase.is_dragging() => { } if self.scrollbase.is_dragging() =>
position.checked_sub(offset).map(|position| { {
self.scrollbase.drag(position) position
}); .checked_sub(offset)
.map(|position| self.scrollbase.drag(position));
return EventResult::Consumed(None); return EventResult::Consumed(None);
} }
Event::Mouse { Event::Mouse {
event: MouseEvent::Release(MouseButton::Left), .. event: MouseEvent::Release(MouseButton::Left),
} if self.scrollbase.is_dragging() => { ..
} if self.scrollbase.is_dragging() =>
{
self.scrollbase.release_grab(); self.scrollbase.release_grab();
return EventResult::Consumed(None); return EventResult::Consumed(None);
} }
_ => (), _ => (),
} }
@ -394,15 +391,13 @@ impl View for ListView {
Event::Key(Key::PageDown) => { Event::Key(Key::PageDown) => {
self.move_focus(10, direction::Direction::up()) self.move_focus(10, direction::Direction::up())
} }
Event::Key(Key::Home) | Event::Key(Key::Home) | Event::Ctrl(Key::Home) => {
Event::Ctrl(Key::Home) => {
self.move_focus( self.move_focus(
usize::max_value(), usize::max_value(),
direction::Direction::back(), direction::Direction::back(),
) )
} }
Event::Key(Key::End) | Event::Key(Key::End) | Event::Ctrl(Key::End) => {
Event::Ctrl(Key::End) => {
self.move_focus( self.move_focus(
usize::max_value(), usize::max_value(),
direction::Direction::front(), direction::Direction::front(),
@ -414,13 +409,19 @@ impl View for ListView {
Event::Shift(Key::Tab) => { Event::Shift(Key::Tab) => {
self.move_focus(1, direction::Direction::back()) self.move_focus(1, direction::Direction::back())
} }
Event::Mouse { event: MouseEvent::WheelDown, .. } Event::Mouse {
if self.scrollbase.can_scroll_down() => { event: MouseEvent::WheelDown,
..
} if self.scrollbase.can_scroll_down() =>
{
self.scrollbase.scroll_down(5); self.scrollbase.scroll_down(5);
EventResult::Consumed(None) EventResult::Consumed(None)
} }
Event::Mouse { event: MouseEvent::WheelUp, .. } Event::Mouse {
if self.scrollbase.can_scroll_up() => { event: MouseEvent::WheelUp,
..
} if self.scrollbase.can_scroll_up() =>
{
self.scrollbase.scroll_up(5); self.scrollbase.scroll_up(5);
EventResult::Consumed(None) EventResult::Consumed(None)
} }
@ -430,24 +431,26 @@ impl View for ListView {
fn take_focus(&mut self, source: direction::Direction) -> bool { fn take_focus(&mut self, source: direction::Direction) -> bool {
let rel = source.relative(direction::Orientation::Vertical); let rel = source.relative(direction::Orientation::Vertical);
let i = let i = if let Some(i) = self.iter_mut(
if let Some(i) = self.iter_mut( rel.is_none(),
rel.is_none(), rel.unwrap_or(direction::Relative::Front),
rel.unwrap_or(direction::Relative::Front), ).filter_map(|p| try_focus(p, source))
).filter_map(|p| try_focus(p, source)) .next()
.next() {
{ i
i } else {
} else { // No one wants to be in focus
// No one wants to be in focus return false;
return false; };
};
self.focus = i; self.focus = i;
self.scrollbase.scroll_to(self.focus); self.scrollbase.scroll_to(self.focus);
true true
} }
fn call_on_any<'a>(&mut self, selector: &Selector, mut callback: Box<FnMut(&mut Any) + 'a>) { fn call_on_any<'a>(
&mut self, selector: &Selector,
mut callback: Box<FnMut(&mut Any) + 'a>,
) {
for view in self.children.iter_mut().filter_map(ListChild::view) { for view in self.children.iter_mut().filter_map(ListChild::view) {
view.call_on_any(selector, Box::new(|any| callback(any))); view.call_on_any(selector, Box::new(|any| callback(any)));
} }

View File

@ -81,8 +81,10 @@ impl<T: View> OnEventView<T> {
/// Registers a callback when the given event is received. /// Registers a callback when the given event is received.
/// ///
/// The given callback will be run before the child view sees the event. /// The given callback will be run before the child view sees the event.
/// If the result is `None`, then the child view is given the event as usual. /// * If the result is `None`, then the child view is given the event as
/// Otherwise, it bypasses the child view and directly processes the result. /// usual.
/// * Otherwise, it bypasses the child view and directly processes the
/// result.
/// ///
/// Chainable variant. /// Chainable variant.
pub fn on_pre_event_inner<F, E>(self, event: E, cb: F) -> Self pub fn on_pre_event_inner<F, E>(self, event: E, cb: F) -> Self
@ -139,8 +141,10 @@ impl<T: View> OnEventView<T> {
/// Registers a callback when the given event is received. /// Registers a callback when the given event is received.
/// ///
/// The given callback will be run before the child view sees the event. /// The given callback will be run before the child view sees the event.
/// If the result is `None`, then the child view is given the event as usual. /// * If the result is `None`, then the child view is given the event as
/// Otherwise, it bypasses the child view and directly processes the result. /// usual.
/// * Otherwise, it bypasses the child view and directly processes the
/// result.
pub fn set_on_pre_event_inner<F, E>(&mut self, event: E, cb: F) pub fn set_on_pre_event_inner<F, E>(&mut self, event: E, cb: F)
where where
E: Into<Event>, E: Into<Event>,

View File

@ -140,7 +140,7 @@ impl ProgressBar {
/// The default one shows a percentage progress: /// The default one shows a percentage progress:
/// ///
/// ``` /// ```
/// fn make_percentage(value: usize, (min, max): (usize, usize)) -> String { /// fn make_progress(value: usize, (min, max): (usize, usize)) -> String {
/// let percent = 101 * (value - min) / (1 + max - min); /// let percent = 101 * (value - min) / (1 + max - min);
/// format!("{} %", percent) /// format!("{} %", percent)
/// } /// }

View File

@ -339,13 +339,19 @@ impl<T: 'static> SelectView<T> {
Event::Key(Key::End) => { Event::Key(Key::End) => {
self.focus.set(self.items.len().saturating_sub(1)) self.focus.set(self.items.len().saturating_sub(1))
} }
Event::Mouse { event: MouseEvent::WheelDown, .. } Event::Mouse {
if self.scrollbase.can_scroll_down() => { event: MouseEvent::WheelDown,
..
} if self.scrollbase.can_scroll_down() =>
{
fix_scroll = false; fix_scroll = false;
self.scrollbase.scroll_down(5); self.scrollbase.scroll_down(5);
} }
Event::Mouse { event: MouseEvent::WheelUp, .. } Event::Mouse {
if self.scrollbase.can_scroll_up() => { event: MouseEvent::WheelUp,
..
} if self.scrollbase.can_scroll_up() =>
{
fix_scroll = false; fix_scroll = false;
self.scrollbase.scroll_up(5); self.scrollbase.scroll_up(5);
} }
@ -353,13 +359,13 @@ impl<T: 'static> SelectView<T> {
event: MouseEvent::Press(MouseButton::Left), event: MouseEvent::Press(MouseButton::Left),
position, position,
offset, offset,
} } if position
if position .checked_sub(offset)
.checked_sub(offset) .map(|position| {
.map(|position| {
self.scrollbase.start_drag(position, self.last_size.x) self.scrollbase.start_drag(position, self.last_size.x)
}) })
.unwrap_or(false) => { .unwrap_or(false) =>
{
fix_scroll = false; fix_scroll = false;
} }
Event::Mouse { Event::Mouse {
@ -369,31 +375,27 @@ impl<T: 'static> SelectView<T> {
} => { } => {
// If the mouse is dragged, we always consume the event. // If the mouse is dragged, we always consume the event.
fix_scroll = false; fix_scroll = false;
position.checked_sub(offset).map(|position| { position
self.scrollbase.drag(position) .checked_sub(offset)
}); .map(|position| self.scrollbase.drag(position));
} }
Event::Mouse { Event::Mouse {
event: MouseEvent::Press(_), event: MouseEvent::Press(_),
position, position,
offset, offset,
} => { } => if let Some(position) = position.checked_sub(offset) {
if let Some(position) = position.checked_sub(offset) { let scrollbar_size = if self.scrollbase.scrollable() {
let scrollbar_size = if self.scrollbase.scrollable() { (2, 0)
(2, 0) } else {
} else { (0, 0)
(0, 0) };
}; let clickable_size =
let clickable_size = self.last_size.saturating_sub(scrollbar_size);
self.last_size.saturating_sub(scrollbar_size); if position < clickable_size {
if position < clickable_size { fix_scroll = false;
fix_scroll = false; self.focus.set(position.y + self.scrollbase.start_line);
self.focus.set(
position.y + self.scrollbase.start_line,
);
}
} }
} },
Event::Mouse { Event::Mouse {
event: MouseEvent::Release(MouseButton::Left), event: MouseEvent::Release(MouseButton::Left),
position, position,
@ -410,9 +412,9 @@ impl<T: 'static> SelectView<T> {
}; };
let clickable_size = let clickable_size =
self.last_size.saturating_sub(scrollbar_size); self.last_size.saturating_sub(scrollbar_size);
if position < clickable_size && if position < clickable_size
(position.y + self.scrollbase.start_line) == && (position.y + self.scrollbase.start_line)
self.focus() == self.focus()
{ {
return self.submit(); return self.submit();
} }
@ -429,12 +431,9 @@ impl<T: 'static> SelectView<T> {
// the list when we reach the end. // the list when we reach the end.
// This is achieved by chaining twice the iterator // This is achieved by chaining twice the iterator
let iter = self.items.iter().chain(self.items.iter()); let iter = self.items.iter().chain(self.items.iter());
if let Some((i, _)) = if let Some((i, _)) = iter.enumerate()
iter.enumerate().skip(self.focus() + 1).find( .skip(self.focus() + 1)
|&(_, item)| { .find(|&(_, item)| item.label.starts_with(c))
item.label.starts_with(c)
},
)
{ {
// Apply modulo in case we have a hit // Apply modulo in case we have a hit
// from the chained iterator // from the chained iterator
@ -516,7 +515,8 @@ impl<T: 'static> SelectView<T> {
event: MouseEvent::Release(MouseButton::Left), event: MouseEvent::Release(MouseButton::Left),
position, position,
offset, offset,
} if position.fits_in_rect(offset, self.last_size) => { } if position.fits_in_rect(offset, self.last_size) =>
{
self.open_popup() self.open_popup()
} }
_ => EventResult::Ignored, _ => EventResult::Ignored,
@ -605,16 +605,15 @@ impl<T: 'static> View for SelectView<T> {
&printer.sub_printer(Vec2::new(0, offset), printer.size, true); &printer.sub_printer(Vec2::new(0, offset), printer.size, true);
self.scrollbase.draw(printer, |printer, i| { self.scrollbase.draw(printer, |printer, i| {
printer.with_selection( printer.with_selection(i == self.focus(), |printer| {
i == self.focus(), if i != self.focus() && !self.enabled {
|printer| if i != self.focus() && !self.enabled {
printer.with_color(ColorStyle::Secondary, |printer| { printer.with_color(ColorStyle::Secondary, |printer| {
self.draw_item(printer, i) self.draw_item(printer, i)
}); });
} else { } else {
self.draw_item(printer, i); self.draw_item(printer, i);
}, }
); });
}); });
} }
} }

View File

@ -1,8 +1,8 @@
use std::cmp::min;
use {Printer, With, XY}; use {Printer, With, XY};
use direction::Direction; use direction::Direction;
use event::{Event, EventResult, Key, MouseEvent, MouseButton}; use event::{Event, EventResult, Key, MouseButton, MouseEvent};
use odds::vec::VecExt; use odds::vec::VecExt;
use std::cmp::min;
use theme::{ColorStyle, Effect}; use theme::{ColorStyle, Effect};
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
@ -180,10 +180,11 @@ impl TextArea {
} }
} }
// If we are editing the text, we add a fake "space" character for the cursor to indicate // If we are editing the text, we add a fake "space" character for the
// where the next character will appear. // cursor to indicate where the next character will appear.
// If the current line is full, adding a character will overflow into the next line. To // If the current line is full, adding a character will overflow into the
// show that, we need to add a fake "ghost" row, just for the cursor. // next line. To show that, we need to add a fake "ghost" row, just for
// the cursor.
fn fix_ghost_row(&mut self) { fn fix_ghost_row(&mut self) {
if self.rows.is_empty() if self.rows.is_empty()
|| self.rows.last().unwrap().end != self.content.len() || self.rows.last().unwrap().end != self.content.len()
@ -198,7 +199,6 @@ impl TextArea {
} }
fn soft_compute_rows(&mut self, size: Vec2) { fn soft_compute_rows(&mut self, size: Vec2) {
if self.is_cache_valid(size) { if self.is_cache_valid(size) {
return; return;
} }
@ -297,7 +297,7 @@ impl TextArea {
/// The only damages are assumed to have occured around the cursor. /// The only damages are assumed to have occured around the cursor.
fn fix_damages(&mut self) { fn fix_damages(&mut self) {
if self.size_cache.is_none() { if self.size_cache.is_none() {
// If we don't know our size, it means we'll get a layout command soon. // If we don't know our size, we'll get a layout command soon.
// So no need to do that here. // So no need to do that here.
return; return;
} }
@ -470,14 +470,16 @@ impl View for TextArea {
Event::Mouse { Event::Mouse {
event: MouseEvent::WheelUp, event: MouseEvent::WheelUp,
.. ..
} if self.scrollbase.can_scroll_up() => { } if self.scrollbase.can_scroll_up() =>
{
fix_scroll = false; fix_scroll = false;
self.scrollbase.scroll_up(5); self.scrollbase.scroll_up(5);
} }
Event::Mouse { Event::Mouse {
event: MouseEvent::WheelDown, event: MouseEvent::WheelDown,
.. ..
} if self.scrollbase.can_scroll_down() => { } if self.scrollbase.can_scroll_down() =>
{
fix_scroll = false; fix_scroll = false;
self.scrollbase.scroll_down(5); self.scrollbase.scroll_down(5);
} }
@ -485,15 +487,19 @@ impl View for TextArea {
event: MouseEvent::Press(MouseButton::Left), event: MouseEvent::Press(MouseButton::Left),
position, position,
offset, offset,
} if position.checked_sub(offset).map(|position| { } if position
self.scrollbase.start_drag(position, self.last_size.x) .checked_sub(offset)
}).unwrap_or(false) => { .map(|position| {
self.scrollbase.start_drag(position, self.last_size.x)
})
.unwrap_or(false) =>
{
fix_scroll = false; fix_scroll = false;
} }
Event::Mouse { Event::Mouse {
event: MouseEvent::Hold(MouseButton::Left), event: MouseEvent::Hold(MouseButton::Left),
position, position,
offset offset,
} => { } => {
fix_scroll = false; fix_scroll = false;
position position
@ -504,10 +510,7 @@ impl View for TextArea {
event: MouseEvent::Press(_), event: MouseEvent::Press(_),
position, position,
offset, offset,
} if position.fits_in_rect( } if position.fits_in_rect(offset, self.last_size) =>
offset,
self.last_size,
) =>
{ {
position.checked_sub(offset).map(|position| { position.checked_sub(offset).map(|position| {
if self.rows.is_empty() { if self.rows.is_empty() {

View File

@ -205,7 +205,8 @@ impl TextView {
if self.rows.is_empty() && !self.content.is_empty() { if self.rows.is_empty() && !self.content.is_empty() {
// We have some content, we we didn't find any row for it? // We have some content, we we didn't find any row for it?
// This probably means we couldn't even make a single row // This probably means we couldn't even make a single row
// (for instance we only have 1 column and we have a wide character). // (for instance we only have 1 column and we have a wide
// character).
return; return;
} }
} }
@ -258,7 +259,7 @@ impl View for TextView {
return EventResult::Ignored; return EventResult::Ignored;
} }
// We know we are scrollable, otherwise the event would just be ignored. // We have a scrollbar, otherwise the event would just be ignored.
match event { match event {
Event::Key(Key::Home) => self.scrollbase.scroll_top(), Event::Key(Key::Home) => self.scrollbase.scroll_top(),
Event::Key(Key::End) => self.scrollbase.scroll_bottom(), Event::Key(Key::End) => self.scrollbase.scroll_bottom(),
@ -289,7 +290,7 @@ impl View for TextView {
} if position } if position
.checked_sub(offset) .checked_sub(offset)
.map(|position| { .map(|position| {
self.scrollbase.start_drag(position, self.last_size.x) self.scrollbase.start_drag(position, self.last_size.x)
}) })
.unwrap_or(false) => .unwrap_or(false) =>
{ {