Skip to content

Commit 66af7fa

Browse files
committed
IdView: skip view if borrowing fails.
Fixes #144
1 parent fb18ed8 commit 66af7fa

2 files changed

Lines changed: 36 additions & 22 deletions

File tree

src/view/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,22 +114,24 @@ pub trait View {
114114
/// Draws the view with the given printer (includes bounds) and focus.
115115
fn draw(&self, printer: &Printer);
116116

117-
/// Finds the view identified by the given selector.
117+
/// Runs a closure on the view identified by the given selector.
118118
///
119119
/// See [`Finder::call_on`] for a nicer interface, implemented for all views.
120120
///
121121
/// [`Finder::call_on`]: trait.Finder.html#method.call_on
122122
///
123-
/// Returns None if the path doesn't lead to a view.
123+
/// If the selector doesn't find a match, the closure will not be run.
124124
///
125-
/// Default implementation always return `None`.
125+
/// Default implementation is a no-op.
126126
fn call_on_any<'a>(&mut self, _: &Selector, _: Box<FnMut(&mut Any) + 'a>) {
127127
// TODO: FnMut -> FnOnce once it works
128128
}
129129

130130
/// Moves the focus to the view identified by the given selector.
131131
///
132132
/// Returns `Ok(())` if the view was found and selected.
133+
///
134+
/// Default implementation simply returns `Err(())`.
133135
fn focus_view(&mut self, &Selector) -> Result<(), ()> {
134136
Err(())
135137
}

src/views/id_view.rs

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,50 +30,62 @@ impl<V: View> IdView<V> {
3030
/// Gets mutable access to the inner view.
3131
///
3232
/// This returns a `ViewRef<V>`, which implement `DerefMut<Target = V>`.
33+
///
34+
/// # Panics
35+
///
36+
/// Panics if another reference for this view already exists.
3337
pub fn get_mut(&mut self) -> ViewRef<V> {
34-
// TODO: return a standalone item (not tied to our lifetime)
35-
// that bundles `self.view.clone()` and allow mutable reference to
36-
// the inner view.
3738
let cell_ref = RcRef::new(self.view.clone());
3839

39-
OwningHandle::new(cell_ref,
40-
|x| unsafe { x.as_ref() }.unwrap().borrow_mut())
40+
// The unsafe part here is tied to OwningHandle's limitation.
41+
OwningHandle::new(
42+
cell_ref,
43+
|x| unsafe { x.as_ref() }.unwrap().borrow_mut(),
44+
)
4145
}
4246
}
4347

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

4751
fn with_view<F, R>(&self, f: F) -> Option<R>
48-
where F: FnOnce(&Self::V) -> R
52+
where
53+
F: FnOnce(&Self::V) -> R,
4954
{
50-
self.view
51-
.try_borrow()
52-
.ok()
53-
.map(|v| f(&*v))
55+
self.view.try_borrow().ok().map(|v| f(&*v))
5456
}
5557

5658
fn with_view_mut<F, R>(&mut self, f: F) -> Option<R>
57-
where F: FnOnce(&mut Self::V) -> R
59+
where
60+
F: FnOnce(&mut Self::V) -> R,
5861
{
59-
self.view
60-
.try_borrow_mut()
61-
.ok()
62-
.map(|mut v| f(&mut *v))
62+
self.view.try_borrow_mut().ok().map(|mut v| f(&mut *v))
6363
}
6464

65-
fn wrap_call_on_any<'a>(&mut self, selector: &Selector,
66-
mut callback: Box<for<'b> FnMut(&'b mut Any) + 'a>) {
65+
fn wrap_call_on_any<'a>(
66+
&mut self, selector: &Selector,
67+
mut callback: Box<for<'b> FnMut(&'b mut Any) + 'a>
68+
) {
6769
match selector {
6870
&Selector::Id(id) if id == self.id => callback(self),
69-
s => self.view.borrow_mut().call_on_any(s, callback),
71+
s => {
72+
self.view.try_borrow_mut().ok().map(|mut v| {
73+
v.call_on_any(s, callback)
74+
});
75+
}
7076
}
7177
}
7278

7379
fn wrap_focus_view(&mut self, selector: &Selector) -> Result<(), ()> {
7480
match selector {
7581
&Selector::Id(id) if id == self.id => Ok(()),
76-
s => self.view.borrow_mut().focus_view(s),
82+
s => {
83+
self.view.try_borrow_mut().map_err(|_| ()).and_then(
84+
|mut v| {
85+
v.focus_view(s)
86+
},
87+
)
88+
}
7789
}
7890
}
7991
}

0 commit comments

Comments
 (0)