Skip to content

Commit

Permalink
IdView: skip view if borrowing fails.
Browse files Browse the repository at this point in the history
Fixes #144
  • Loading branch information
gyscos committed Jul 3, 2017
1 parent fb18ed8 commit 66af7fa
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 22 deletions.
8 changes: 5 additions & 3 deletions src/view/mod.rs
Expand Up @@ -114,22 +114,24 @@ 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<FnMut(&mut Any) + 'a>) {
// TODO: FnMut -> FnOnce once it works
}

/// 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(())
}
Expand Down
50 changes: 31 additions & 19 deletions src/views/id_view.rs
Expand Up @@ -30,50 +30,62 @@ impl<V: View> IdView<V> {
/// Gets mutable access to the inner view.
///
/// This returns a `ViewRef<V>`, which implement `DerefMut<Target = V>`.
///
/// # Panics
///
/// Panics if another reference for this view already exists.
pub fn get_mut(&mut self) -> ViewRef<V> {
// 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(),
)
}
}

impl<T: View + 'static> ViewWrapper for IdView<T> {
type V = T;

fn with_view<F, R>(&self, f: F) -> Option<R>
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<F, R>(&mut self, f: F) -> Option<R>
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<for<'b> FnMut(&'b mut Any) + 'a>) {
fn wrap_call_on_any<'a>(
&mut self, selector: &Selector,
mut callback: Box<for<'b> 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)
},
)
}
}
}
}

0 comments on commit 66af7fa

Please sign in to comment.