mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
More rustfmt
This commit is contained in:
parent
294a4102b4
commit
f90621811c
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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".
|
||||||
|
// We _know_ it's there, so unwrap it.
|
||||||
s.call_on_id("text", |view: &mut TextView| {
|
s.call_on_id("text", |view: &mut TextView| {
|
||||||
let content: String = view.get_content().chars().rev().collect();
|
let content = reverse(view.get_content());
|
||||||
view.set_content(content);
|
view.set_content(content);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.dismiss_button("Ok"));
|
.dismiss_button("Ok"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reverse(text: &str) -> String {
|
||||||
|
text.chars().rev().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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() {
|
||||||
|
/// fn main() {
|
||||||
/// let mut siv = Cursive::new();
|
/// 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::Selector::Id("text"),
|
||||||
|
/// |view: &mut views::TextView| {
|
||||||
/// view.set_content("Text #2");
|
/// 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
|
||||||
|
@ -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,
|
||||||
|
@ -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, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
///
|
///
|
||||||
|
@ -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:
|
||||||
///
|
///
|
||||||
|
@ -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(
|
||||||
|
/// Dialog::new()
|
||||||
/// .title("Enter your name")
|
/// .title("Enter your name")
|
||||||
/// .padding((1, 1, 1, 0))
|
/// .padding((1, 1, 1, 0))
|
||||||
/// .content(EditView::new()
|
/// .content(
|
||||||
|
/// EditView::new()
|
||||||
/// .on_submit(show_popup)
|
/// .on_submit(show_popup)
|
||||||
/// .with_id("name")
|
/// .with_id("name")
|
||||||
/// .fixed_width(20))
|
/// .fixed_width(20),
|
||||||
|
/// )
|
||||||
/// .button("Ok", |s| {
|
/// .button("Ok", |s| {
|
||||||
/// let name = s.call_on_id("name", |view: &mut EditView| view.get_content())
|
/// let name = s.call_on_id(
|
||||||
/// .unwrap();
|
/// "name",
|
||||||
|
/// |view: &mut EditView| view.get_content(),
|
||||||
|
/// ).unwrap();
|
||||||
/// show_popup(s, &name);
|
/// 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))
|
||||||
|
@ -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())
|
||||||
{
|
{
|
||||||
|
@ -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,8 +431,7 @@ 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))
|
||||||
@ -447,7 +447,10 @@ impl View for ListView {
|
|||||||
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)));
|
||||||
}
|
}
|
||||||
|
@ -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>,
|
||||||
|
@ -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)
|
||||||
/// }
|
/// }
|
||||||
|
@ -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,16 +375,15 @@ 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 {
|
||||||
@ -388,12 +393,9 @@ impl<T: 'static> SelectView<T> {
|
|||||||
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(
|
self.focus.set(position.y + self.scrollbase.start_line);
|
||||||
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);
|
||||||
},
|
}
|
||||||
);
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
.checked_sub(offset)
|
||||||
|
.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 {
|
||||||
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() {
|
||||||
|
@ -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(),
|
||||||
|
Loading…
Reference in New Issue
Block a user