1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::event::AnyCb;
use crate::view::{Selector, View, ViewWrapper};
use owning_ref::{OwningHandle, RcRef};
use std::cell::{RefCell, RefMut};
use std::ops::DerefMut;
use std::rc::Rc;

/// Wrapper around a view to make it identifiable.
///
/// This lets other views refer to this one using a string identifier.
///
/// See [`Identifiable`](crate::view::Identifiable) for an easy way to wrap any view with it.
pub struct NamedView<V> {
    view: Rc<RefCell<V>>,
    name: String,
}

/// Mutable reference to a view.
///
/// This behaves like a [`RefMut`], but without being tied to a lifetime.
///
/// [`RefMut`]: std::cell::RefMut
pub type ViewRef<V> = OwningHandle<RcRef<RefCell<V>>, RefMut<'static, V>>;

impl<V> NamedView<V> {
    /// Wraps `view` in a new `NamedView`.
    pub fn new<S: Into<String>>(name: S, view: V) -> Self {
        NamedView {
            view: Rc::new(RefCell::new(view)),
            name: name.into(),
        }
    }

    /// 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> {
        let cell_ref = RcRef::new(Rc::clone(&self.view));

        OwningHandle::new_mut(cell_ref)
    }

    /// Returns the name attached to this view.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Changes the name attached to this view.
    pub fn set_name<S: Into<String>>(&mut self, name: S) {
        self.name = name.into();
    }
}

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

    fn with_view<F, R>(&self, f: F) -> Option<R>
    where
        F: FnOnce(&Self::V) -> R,
    {
        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,
    {
        self.view.try_borrow_mut().ok().map(|mut v| f(&mut *v))
    }

    fn into_inner(mut self) -> Result<Self::V, Self>
    where
        Self::V: Sized,
    {
        match Rc::try_unwrap(self.view) {
            Err(rc) => {
                // Whoops! Abort! Undo!
                self.view = rc;
                Err(self)
            }
            Ok(cell) => Ok(cell.into_inner()),
        }
    }

    fn wrap_call_on_any<'a>(
        &mut self,
        selector: &Selector<'_>,
        callback: AnyCb<'a>,
    ) {
        match selector {
            #[allow(deprecated)]
            &Selector::Name(name) | &Selector::Id(name)
                if name == self.name =>
            {
                callback(self)
            }
            s => {
                if let Ok(mut v) = self.view.try_borrow_mut() {
                    v.deref_mut().call_on_any(s, callback);
                }
            }
        }
    }

    fn wrap_focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
        match selector {
            #[allow(deprecated)]
            &Selector::Name(name) | &Selector::Id(name)
                if name == self.name =>
            {
                Ok(())
            }
            s => self
                .view
                .try_borrow_mut()
                .map_err(|_| ())
                .and_then(|mut v| v.deref_mut().focus_view(s)),
        }
    }
}