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
use super::internal;
use crate::prelude::*;

/// Modifiers for changing the abilities of a view.
pub trait AbilityModifiers: internal::Modifiable {
    /// Sets whether the view can be hovered by the mouse and receive mouse events.
    ///
    /// Accepts a bool or a lens to some boolean state.
    /// Views which cannot be hovered will not receive mouse input events unless
    /// the view has captured the mouse input, see [`cx.capture()`](crate::prelude::EventContext::capture).
    ///
    /// # Example
    /// ```
    /// # use vizia_core::prelude::*;
    /// # let cx = &mut Context::default();
    /// Label::new(cx, "Hello Vizia")
    ///     .hoverable(false);
    /// ```
    fn hoverable<U: Into<bool>>(mut self, state: impl Res<U>) -> Self {
        let entity = self.entity();
        let current = self.entity();
        self.context().with_current(current, move |cx| {
            state.set_or_bind(cx, entity, move |cx, v| {
                let val = v.get(cx).into();
                if let Some(abilities) = cx.style.abilities.get_mut(entity) {
                    abilities.set(Abilities::HOVERABLE, val);
                    cx.needs_restyle(entity);
                }
            });
        });

        self
    }

    /// Sets whether the view can be focused to receive keyboard input events.
    ///
    /// Accepts a bool or a lens to some boolean state.
    /// # Example
    /// ```
    /// # use vizia_core::prelude::*;
    /// # let cx = &mut Context::default();
    /// Label::new(cx, "Hello Vizia")
    ///     .focusable(false);
    /// ```
    fn focusable<U: Into<bool>>(mut self, state: impl Res<U>) -> Self {
        let entity = self.entity();
        let current = self.current();
        self.context().with_current(current, move |cx| {
            state.set_or_bind(cx, entity, move |cx, v| {
                let state = v.get(cx).into();
                if let Some(abilities) = cx.style.abilities.get_mut(entity) {
                    abilities.set(Abilities::FOCUSABLE, state);

                    // If an element is not focusable then it can't be keyboard navigable.
                    if !state {
                        abilities.set(Abilities::NAVIGABLE, false);
                    }

                    cx.needs_restyle(entity);
                }
            });
        });

        self
    }

    /// Sets whether the view can be checked.
    ///
    /// Accepts a bool or a lens to some boolean state.
    /// # Example
    /// ```
    /// # use vizia_core::prelude::*;
    /// # let cx = &mut Context::default();
    /// Label::new(cx, "Hello Vizia")
    ///     .checkable(false);
    /// ```
    fn checkable<U: Into<bool>>(mut self, state: impl Res<U>) -> Self {
        let entity = self.entity();
        let current = self.current();
        self.context().with_current(current, move |cx| {
            state.set_or_bind(cx, entity, move |cx, v| {
                let state = v.get(cx).into();
                if let Some(abilities) = cx.style.abilities.get_mut(cx.current) {
                    abilities.set(Abilities::CHECKABLE, state);

                    cx.needs_restyle(entity);
                }
            });
        });

        self
    }

    /// Sets whether the view can be navigated to, i.e. focused, by the keyboard.
    ///
    /// Accepts a bool or a lens to some boolean state.
    /// Navigating to a view with the keyboard gives the view keyboard focus and is typically done with `tab` and `shift + tab` key combinations.
    /// # Example
    /// ```
    /// # use vizia_core::prelude::*;
    /// # let cx = &mut Context::default();
    /// Label::new(cx, "Hello Vizia")
    ///     .checkable(false);
    /// ```
    fn navigable<U: Into<bool>>(mut self, state: impl Res<U>) -> Self {
        let entity = self.entity();
        let current = self.current();
        self.context().with_current(current, move |cx| {
            state.set_or_bind(cx, entity, move |cx, v| {
                let val = v.get(cx).into();
                if let Some(abilities) = cx.style.abilities.get_mut(entity) {
                    abilities.set(Abilities::NAVIGABLE, val);
                    cx.needs_restyle(entity);
                }
            });
        });

        self
    }
}

impl<'a, V> AbilityModifiers for Handle<'a, V> {}