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
125
126
127
128
use crate::event::AnyCb;
use crate::view::{Selector, View, ViewWrapper};
use crate::Vec2;
use crate::With;

/// Wrapper around another view that can be hidden at will.
///
/// By default, it simply forwards all calls to the inner view.
///
/// When hidden (with `HideableView::hide()`), it will appear as a zero-sized
/// invisible view, will not take focus and will not accept input.
///
/// It can be made visible again with `HideableView::unhide()`.
pub struct HideableView<V> {
    view: V,
    visible: bool,
    invalidated: bool,
}

new_default!(HideableView<V: Default>);

impl<V> HideableView<V> {
    /// Creates a new HideableView around `view`.
    ///
    /// It will be visible by default.
    pub fn new(view: V) -> Self {
        HideableView {
            view,
            visible: true,
            invalidated: true,
        }
    }

    /// Sets the visibility for this view.
    pub fn set_visible(&mut self, visible: bool) {
        self.visible = visible;
        self.invalidate();
    }

    /// Sets the visibility for this view to `false`.
    pub fn hide(&mut self) {
        self.set_visible(false);
    }

    /// Sets the visibility for this view to `true`.
    pub fn unhide(&mut self) {
        self.set_visible(true);
    }

    /// Sets the visibility for this view to `false`.
    ///
    /// Chainable variant.
    #[must_use]
    pub fn hidden(self) -> Self {
        self.with(Self::hide)
    }

    /// Sets the visibility for this view to flag value.
    /// Useful when creating views needs to be decided at runtime.
    /// Chainable variant.
    #[must_use]
    pub fn visible(self, flag: bool) -> Self {
        self.with(|s| s.set_visible(flag))
    }

    /// Returns `true` if the wrapped view is going to be visible.
    pub fn is_visible(&self) -> bool {
        self.visible
    }

    fn invalidate(&mut self) {
        self.invalidated = true;
    }

    inner_getters!(self.view: V);
}

impl<V: View> ViewWrapper for HideableView<V> {
    type V = V;

    fn with_view<F, R>(&self, f: F) -> Option<R>
    where
        F: FnOnce(&Self::V) -> R,
    {
        if self.visible {
            Some(f(&self.view))
        } else {
            None
        }
    }

    fn with_view_mut<F, R>(&mut self, f: F) -> Option<R>
    where
        F: FnOnce(&mut Self::V) -> R,
    {
        if self.visible {
            Some(f(&mut self.view))
        } else {
            None
        }
    }

    fn wrap_call_on_any<'a>(
        &mut self,
        selector: &Selector<'_>,
        callback: AnyCb<'a>,
    ) {
        // We always run callbacks, even when invisible.
        self.view.call_on_any(selector, callback)
    }

    fn into_inner(self) -> Result<Self::V, Self>
    where
        Self: Sized,
        Self::V: Sized,
    {
        Ok(self.view)
    }

    fn wrap_layout(&mut self, size: Vec2) {
        self.invalidated = false;
        self.with_view_mut(|v| v.layout(size));
    }

    fn wrap_needs_relayout(&self) -> bool {
        self.invalidated || (self.visible && self.view.needs_relayout())
    }
}