From 66af7fab7cf87adc5a1d1e074c6443d6d6071a54 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Mon, 3 Jul 2017 01:27:55 -0700 Subject: [PATCH] IdView: skip view if borrowing fails. Fixes #144 --- src/view/mod.rs | 8 ++++--- src/views/id_view.rs | 50 +++++++++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/view/mod.rs b/src/view/mod.rs index f0d91d2b8..8cbed6f23 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -114,15 +114,15 @@ pub trait View { /// Draws the view with the given printer (includes bounds) and focus. fn draw(&self, printer: &Printer); - /// Finds 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. /// /// [`Finder::call_on`]: trait.Finder.html#method.call_on /// - /// Returns None if the path doesn't lead to a view. + /// If the selector doesn't find a match, the closure will not be run. /// - /// Default implementation always return `None`. + /// Default implementation is a no-op. fn call_on_any<'a>(&mut self, _: &Selector, _: Box) { // TODO: FnMut -> FnOnce once it works } @@ -130,6 +130,8 @@ pub trait View { /// Moves the focus to the view identified by the given selector. /// /// Returns `Ok(())` if the view was found and selected. + /// + /// Default implementation simply returns `Err(())`. fn focus_view(&mut self, &Selector) -> Result<(), ()> { Err(()) } diff --git a/src/views/id_view.rs b/src/views/id_view.rs index 3ef6c5e24..05dc8cf8e 100644 --- a/src/views/id_view.rs +++ b/src/views/id_view.rs @@ -30,14 +30,18 @@ impl IdView { /// Gets mutable access to the inner view. /// /// This returns a `ViewRef`, which implement `DerefMut`. + /// + /// # Panics + /// + /// Panics if another reference for this view already exists. pub fn get_mut(&mut self) -> ViewRef { - // TODO: return a standalone item (not tied to our lifetime) - // that bundles `self.view.clone()` and allow mutable reference to - // the inner view. let cell_ref = RcRef::new(self.view.clone()); - OwningHandle::new(cell_ref, - |x| unsafe { x.as_ref() }.unwrap().borrow_mut()) + // The unsafe part here is tied to OwningHandle's limitation. + OwningHandle::new( + cell_ref, + |x| unsafe { x.as_ref() }.unwrap().borrow_mut(), + ) } } @@ -45,35 +49,43 @@ impl ViewWrapper for IdView { type V = T; fn with_view(&self, f: F) -> Option - where F: FnOnce(&Self::V) -> R + where + F: FnOnce(&Self::V) -> R, { - self.view - .try_borrow() - .ok() - .map(|v| f(&*v)) + self.view.try_borrow().ok().map(|v| f(&*v)) } fn with_view_mut(&mut self, f: F) -> Option - where F: FnOnce(&mut Self::V) -> R + where + F: FnOnce(&mut Self::V) -> R, { - self.view - .try_borrow_mut() - .ok() - .map(|mut v| f(&mut *v)) + self.view.try_borrow_mut().ok().map(|mut v| f(&mut *v)) } - fn wrap_call_on_any<'a>(&mut self, selector: &Selector, - mut callback: Box FnMut(&'b mut Any) + 'a>) { + fn wrap_call_on_any<'a>( + &mut self, selector: &Selector, + mut callback: Box FnMut(&'b mut Any) + 'a> + ) { match selector { &Selector::Id(id) if id == self.id => callback(self), - s => self.view.borrow_mut().call_on_any(s, callback), + s => { + self.view.try_borrow_mut().ok().map(|mut v| { + v.call_on_any(s, callback) + }); + } } } fn wrap_focus_view(&mut self, selector: &Selector) -> Result<(), ()> { match selector { &Selector::Id(id) if id == self.id => Ok(()), - s => self.view.borrow_mut().focus_view(s), + s => { + self.view.try_borrow_mut().map_err(|_| ()).and_then( + |mut v| { + v.focus_view(s) + }, + ) + } } } }