View::focus_view: replace () with zero-sized ViewNotFound

This commit is contained in:
Alexandre Bury 2020-12-20 10:58:57 -08:00
parent 759a7e8b49
commit c352e4c54a
15 changed files with 155 additions and 95 deletions

View File

@ -12,7 +12,7 @@ use crate::{
event::{Event, EventResult},
printer::Printer,
theme,
view::{self, Finder, IntoBoxedView, Position, View},
view::{self, Finder, IntoBoxedView, Position, View, ViewNotFound},
views::{self, LayerPosition},
Dump, Vec2,
};
@ -616,18 +616,21 @@ impl Cursive {
/// Moves the focus to the view identified by `name`.
///
/// Convenient method to call `focus` with a [`view::Selector::Name`].
pub fn focus_name(&mut self, name: &str) -> Result<(), ()> {
pub fn focus_name(&mut self, name: &str) -> Result<(), ViewNotFound> {
self.focus(&view::Selector::Name(name))
}
/// Same as [`focus_name`](Cursive::focus_name).
#[deprecated(note = "`focus_id` is being renamed to `focus_name`")]
pub fn focus_id(&mut self, id: &str) -> Result<(), ()> {
pub fn focus_id(&mut self, id: &str) -> Result<(), ViewNotFound> {
self.focus(&view::Selector::Name(id))
}
/// Moves the focus to the view identified by `sel`.
pub fn focus(&mut self, sel: &view::Selector<'_>) -> Result<(), ()> {
pub fn focus(
&mut self,
sel: &view::Selector<'_>,
) -> Result<(), ViewNotFound> {
self.root.focus_view(sel)
}

View File

@ -117,7 +117,7 @@ pub use self::scrollable::Scrollable;
pub use self::size_cache::SizeCache;
pub use self::size_constraint::SizeConstraint;
pub use self::view_path::ViewPath;
pub use self::view_trait::View;
pub use self::view_trait::{View, ViewNotFound};
pub use self::view_wrapper::ViewWrapper;
#[deprecated(note = "`Boxable` is being renamed to `Resizable`")]

View File

@ -6,7 +6,7 @@ use crate::{
printer::Printer,
rect::Rect,
theme::ColorStyle,
view::{ScrollStrategy, Selector, SizeCache},
view::{ScrollStrategy, Selector, SizeCache, ViewNotFound},
with::With,
Vec2, XY,
};
@ -282,9 +282,9 @@ impl Core {
&mut self,
selector: &Selector<'_>,
inner_focus_view: F,
) -> Result<(), ()>
) -> Result<(), ViewNotFound>
where
F: FnOnce(&Selector) -> Result<(), ()>,
F: FnOnce(&Selector) -> Result<(), ViewNotFound>,
{
inner_focus_view(selector)
}

View File

@ -6,6 +6,18 @@ use crate::Printer;
use crate::Vec2;
use std::any::Any;
/// Error indicating a view was not found.
#[derive(Debug)]
pub struct ViewNotFound;
impl std::fmt::Display for ViewNotFound {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "View could not be found")
}
}
impl std::error::Error for ViewNotFound {}
/// Main trait defining a view behaviour.
///
/// This is what you should implement to define a custom View.
@ -90,8 +102,8 @@ pub trait View: Any + AnyView {
/// Returns `Ok(())` if the view was found and selected.
///
/// Default implementation simply returns `Err(())`.
fn focus_view(&mut self, _: &Selector<'_>) -> Result<(), ()> {
Err(())
fn focus_view(&mut self, _: &Selector<'_>) -> Result<(), ViewNotFound> {
Err(ViewNotFound)
}
/// This view is offered focus. Will it take it?

View File

@ -1,9 +1,10 @@
use crate::direction::Direction;
use crate::event::{AnyCb, Event, EventResult};
use crate::rect::Rect;
use crate::view::{Selector, View};
use crate::Printer;
use crate::Vec2;
use crate::{
direction::Direction,
event::{AnyCb, Event, EventResult},
rect::Rect,
view::{Selector, View, ViewNotFound},
Printer, Vec2,
};
/// Generic wrapper around a view.
///
@ -84,9 +85,12 @@ pub trait ViewWrapper: 'static {
}
/// Wraps the `focus_view` method.
fn wrap_focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn wrap_focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
self.with_view_mut(|v| v.focus_view(selector))
.unwrap_or(Err(()))
.unwrap_or(Err(ViewNotFound))
}
/// Wraps the `needs_relayout` method.
@ -135,7 +139,10 @@ impl<T: ViewWrapper> View for T {
self.wrap_needs_relayout()
}
fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
self.wrap_focus_view(selector)
}

View File

@ -1,10 +1,10 @@
use crate::direction::Direction;
use crate::event::{AnyCb, Event, EventResult};
use crate::rect::Rect;
use crate::view::{Selector, View};
use crate::Printer;
use crate::Vec2;
use crate::With;
use crate::{
direction::Direction,
event::{AnyCb, Event, EventResult},
rect::Rect,
view::{Selector, View, ViewNotFound},
Printer, Vec2, With,
};
// Define this type separately to appease the Clippy god
type CallOnAny<T> = Box<dyn for<'a> FnMut(&mut T, &Selector, AnyCb<'a>)>;
@ -51,7 +51,7 @@ pub struct Canvas<T> {
layout: Box<dyn FnMut(&mut T, Vec2)>,
take_focus: Box<dyn FnMut(&mut T, Direction) -> bool>,
needs_relayout: Box<dyn Fn(&T) -> bool>,
focus_view: Box<dyn FnMut(&mut T, &Selector) -> Result<(), ()>>,
focus_view: Box<dyn FnMut(&mut T, &Selector) -> Result<(), ViewNotFound>>,
call_on_any: CallOnAny<T>,
important_area: Box<dyn Fn(&T, Vec2) -> Rect>,
}
@ -85,7 +85,7 @@ impl<T> Canvas<T> {
layout: Box::new(|_, _| ()),
take_focus: Box::new(|_, _| false),
needs_relayout: Box::new(|_| true),
focus_view: Box::new(|_, _| Err(())),
focus_view: Box::new(|_, _| Err(ViewNotFound)),
call_on_any: Box::new(|_, _, _| ()),
important_area: Box::new(|_, size| {
Rect::from_corners((0, 0), size)
@ -245,7 +245,7 @@ impl<T> Canvas<T> {
/// Sets the closure for `focus_view()`.
pub fn set_focus_view<F>(&mut self, f: F)
where
F: 'static + FnMut(&mut T, &Selector<'_>) -> Result<(), ()>,
F: 'static + FnMut(&mut T, &Selector<'_>) -> Result<(), ViewNotFound>,
{
self.focus_view = Box::new(f);
}
@ -255,7 +255,7 @@ impl<T> Canvas<T> {
/// Chainable variant.
pub fn with_focus_view<F>(self, f: F) -> Self
where
F: 'static + FnMut(&mut T, &Selector<'_>) -> Result<(), ()>,
F: 'static + FnMut(&mut T, &Selector<'_>) -> Result<(), ViewNotFound>,
{
self.with(|s| s.set_focus_view(f))
}
@ -286,7 +286,10 @@ impl<T: 'static> View for Canvas<T> {
(self.needs_relayout)(&self.state)
}
fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
(self.focus_view)(&mut self.state, selector)
}

View File

@ -1,14 +1,14 @@
use crate::align::*;
use crate::direction::{Absolute, Direction, Relative};
use crate::event::{AnyCb, Event, EventResult, Key};
use crate::rect::Rect;
use crate::theme::ColorStyle;
use crate::view::{IntoBoxedView, Margins, Selector, View};
use crate::views::{BoxedView, Button, DummyView, LastSizeView, TextView};
use crate::Cursive;
use crate::Printer;
use crate::Vec2;
use crate::{utils::markup::StyledString, With};
use crate::{
align::*,
direction::{Absolute, Direction, Relative},
event::{AnyCb, Event, EventResult, Key},
rect::Rect,
theme::ColorStyle,
utils::markup::StyledString,
view::{IntoBoxedView, Margins, Selector, View, ViewNotFound},
views::{BoxedView, Button, DummyView, LastSizeView, TextView},
Cursive, Printer, Vec2, With,
};
use std::cell::Cell;
use std::cmp::max;
use unicode_width::UnicodeWidthStr;
@ -764,7 +764,10 @@ impl View for Dialog {
self.content.call_on_any(selector, callback);
}
fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
self.content.focus_view(selector)
}

View File

@ -2,7 +2,7 @@ use crate::{
direction::{Absolute, Direction, Relative},
event::{AnyCb, Event, EventResult, Key},
rect::Rect,
view::{IntoBoxedView, Selector},
view::{IntoBoxedView, Selector, ViewNotFound},
{Printer, Vec2, View, With},
};
@ -72,7 +72,10 @@ impl FixedLayout {
///
/// Returns `Err(())` if `index >= self.len()`, or if the view at the
/// given index does not accept focus.
pub fn set_focus_index(&mut self, index: usize) -> Result<(), ()> {
pub fn set_focus_index(
&mut self,
index: usize,
) -> Result<(), ViewNotFound> {
if self
.children
.get_mut(index)
@ -82,7 +85,7 @@ impl FixedLayout {
self.focus = index;
Ok(())
} else {
Err(())
Err(ViewNotFound)
}
}
@ -352,7 +355,10 @@ impl View for FixedLayout {
}
}
fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
for (i, child) in self.children.iter_mut().enumerate() {
if child.view.focus_view(selector).is_ok() {
self.focus = i;
@ -360,6 +366,6 @@ impl View for FixedLayout {
}
}
Err(())
Err(ViewNotFound)
}
}

View File

@ -1,11 +1,10 @@
use crate::direction;
use crate::event::{AnyCb, Event, EventResult, Key};
use crate::rect::Rect;
use crate::view::{IntoBoxedView, Selector, SizeCache, View};
use crate::Printer;
use crate::Vec2;
use crate::With;
use crate::XY;
use crate::{
direction,
event::{AnyCb, Event, EventResult, Key},
rect::Rect,
view::{IntoBoxedView, Selector, SizeCache, View, ViewNotFound},
Printer, Vec2, With, XY,
};
use log::debug;
use std::cmp::min;
use std::ops::Deref;
@ -228,7 +227,10 @@ impl LinearLayout {
///
/// Returns `Err(())` if `index >= self.len()`, or if the view at the
/// given index does not accept focus.
pub fn set_focus_index(&mut self, index: usize) -> Result<(), ()> {
pub fn set_focus_index(
&mut self,
index: usize,
) -> Result<(), ViewNotFound> {
if self
.children
.get_mut(index)
@ -238,7 +240,7 @@ impl LinearLayout {
self.focus = index;
Ok(())
} else {
Err(())
Err(ViewNotFound)
}
}
@ -713,7 +715,10 @@ impl View for LinearLayout {
}
}
fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
for (i, child) in self.children.iter_mut().enumerate() {
if child.view.focus_view(selector).is_ok() {
self.focus = i;
@ -721,7 +726,7 @@ impl View for LinearLayout {
}
}
Err(())
Err(ViewNotFound)
}
fn important_area(&self, _: Vec2) -> Rect {

View File

@ -1,11 +1,10 @@
use crate::direction;
use crate::event::{AnyCb, Callback, Event, EventResult, Key};
use crate::rect::Rect;
use crate::view::{IntoBoxedView, Selector, View};
use crate::Cursive;
use crate::Printer;
use crate::Vec2;
use crate::With;
use crate::{
direction,
event::{AnyCb, Callback, Event, EventResult, Key},
rect::Rect,
view::{IntoBoxedView, Selector, View, ViewNotFound},
Cursive, Printer, Vec2, With,
};
use log::debug;
use std::rc::Rc;
use unicode_width::UnicodeWidthStr;
@ -435,7 +434,10 @@ impl View for ListView {
}
}
fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
if let Some(i) = self
.children
.iter_mut()
@ -447,7 +449,7 @@ impl View for ListView {
self.focus = i;
Ok(())
} else {
Err(())
Err(ViewNotFound)
}
}

View File

@ -1,5 +1,7 @@
use crate::event::AnyCb;
use crate::view::{Selector, View, ViewWrapper};
use crate::{
event::AnyCb,
view::{Selector, View, ViewNotFound, ViewWrapper},
};
use owning_ref::{OwningHandle, RcRef};
use std::cell::{RefCell, RefMut};
use std::ops::DerefMut;
@ -106,7 +108,10 @@ impl<T: View + 'static> ViewWrapper for NamedView<T> {
}
}
fn wrap_focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn wrap_focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
match selector {
#[allow(deprecated)]
&Selector::Name(name) | &Selector::Id(name)
@ -117,7 +122,7 @@ impl<T: View + 'static> ViewWrapper for NamedView<T> {
s => self
.view
.try_borrow_mut()
.map_err(|_| ())
.map_err(|_| ViewNotFound)
.and_then(|mut v| v.deref_mut().focus_view(s)),
}
}

View File

@ -1,7 +1,8 @@
use crate::event::AnyCb;
use crate::view::Selector;
use crate::views::BoxedView;
use crate::View;
use crate::{
event::AnyCb,
view::{Selector, View, ViewNotFound},
views::BoxedView,
};
/// Identifies a screen in the cursive root.
pub type ScreenId = usize;
@ -129,7 +130,10 @@ where
}
}
fn wrap_focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn wrap_focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
for (i, child) in self.screens.iter_mut().enumerate() {
if child.focus_view(selector).is_ok() {
self.active_screen = i;
@ -137,6 +141,6 @@ where
}
}
Err(())
Err(ViewNotFound)
}
}

View File

@ -1,7 +1,7 @@
use crate::{
direction::Direction,
event::{AnyCb, Event, EventResult},
view::{scroll, ScrollStrategy, Selector, View},
view::{scroll, ScrollStrategy, Selector, View, ViewNotFound},
Cursive, Printer, Rect, Vec2, With,
};
@ -361,7 +361,10 @@ where
self.inner.call_on_any(selector, cb)
}
fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
self.inner.focus_view(selector).map(|()| {
self.scroll_to_important_area();
})

View File

@ -1,13 +1,14 @@
use crate::direction::Direction;
use crate::event::{AnyCb, Event, EventResult};
use crate::theme::ColorStyle;
use crate::view::{
IntoBoxedView, Offset, Position, Selector, View, ViewWrapper,
use crate::{
direction::Direction,
event::{AnyCb, Event, EventResult},
theme::ColorStyle,
view::{
IntoBoxedView, Offset, Position, Selector, View, ViewNotFound,
ViewWrapper,
},
views::{BoxedView, CircularFocus, Layer, ShadowView},
Printer, Vec2, With,
};
use crate::views::{BoxedView, CircularFocus, Layer, ShadowView};
use crate::Printer;
use crate::Vec2;
use crate::With;
use std::cell;
use std::ops::Deref;
@ -189,7 +190,10 @@ impl<T: View> View for ChildWrapper<T> {
}
}
fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
match *self {
ChildWrapper::Shadow(ref mut v) => v.focus_view(selector),
ChildWrapper::Backfilled(ref mut v) => v.focus_view(selector),
@ -680,14 +684,17 @@ impl View for StackView {
}
}
fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
fn focus_view(
&mut self,
selector: &Selector<'_>,
) -> Result<(), ViewNotFound> {
for layer in &mut self.layers {
if layer.view.focus_view(selector).is_ok() {
return Ok(());
}
}
Err(())
Err(ViewNotFound)
}
}

View File

@ -203,7 +203,7 @@ impl Backend {
}
// Is it a UTF-8 starting point?
let event = if 32 <= ch && ch <= 255 && ch != 127 {
let event = if (32..=255).contains(&ch) && ch != 127 {
utf8::read_char(ch as u8, || Some(ncurses::getch() as u8))
.map(Event::Char)
.unwrap_or_else(|e| {