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
129
130
131
132
/// What sort of interaction is a widget sensitive to?
#[derive(Clone, Copy, Eq, PartialEq)]
// #[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Sense {
    /// Buttons, sliders, windows, …
    pub click: bool,

    /// Sliders, windows, scroll bars, scroll areas, …
    pub drag: bool,

    /// This widget wants focus.
    ///
    /// Anything interactive + labels that can be focused
    /// for the benefit of screen readers.
    pub focusable: bool,
}

impl std::fmt::Debug for Sense {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let Self {
            click,
            drag,
            focusable,
        } = self;

        write!(f, "Sense {{")?;
        if *click {
            write!(f, " click")?;
        }
        if *drag {
            write!(f, " drag")?;
        }
        if *focusable {
            write!(f, " focusable")?;
        }
        write!(f, " }}")
    }
}

impl Sense {
    /// Senses no clicks or drags. Only senses mouse hover.
    #[doc(alias = "none")]
    #[inline]
    pub fn hover() -> Self {
        Self {
            click: false,
            drag: false,
            focusable: false,
        }
    }

    /// Senses no clicks or drags, but can be focused with the keyboard.
    /// Used for labels that can be focused for the benefit of screen readers.
    #[inline]
    pub fn focusable_noninteractive() -> Self {
        Self {
            click: false,
            drag: false,
            focusable: true,
        }
    }

    /// Sense clicks and hover, but not drags.
    #[inline]
    pub fn click() -> Self {
        Self {
            click: true,
            drag: false,
            focusable: true,
        }
    }

    /// Sense drags and hover, but not clicks.
    #[inline]
    pub fn drag() -> Self {
        Self {
            click: false,
            drag: true,
            focusable: true,
        }
    }

    /// Sense both clicks, drags and hover (e.g. a slider or window).
    ///
    /// Note that this will introduce a latency when dragging,
    /// because when the user starts a press egui can't know if this is the start
    /// of a click or a drag, and it won't know until the cursor has
    /// either moved a certain distance, or the user has released the mouse button.
    ///
    /// See [`crate::PointerState::is_decidedly_dragging`] for details.
    #[inline]
    pub fn click_and_drag() -> Self {
        Self {
            click: true,
            drag: true,
            focusable: true,
        }
    }

    /// The logical "or" of two [`Sense`]s.
    #[must_use]
    #[inline]
    pub fn union(self, other: Self) -> Self {
        Self {
            click: self.click | other.click,
            drag: self.drag | other.drag,
            focusable: self.focusable | other.focusable,
        }
    }

    /// Returns true if we sense either clicks or drags.
    #[inline]
    pub fn interactive(&self) -> bool {
        self.click || self.drag
    }
}

impl std::ops::BitOr for Sense {
    type Output = Self;

    #[inline]
    fn bitor(self, rhs: Self) -> Self {
        self.union(rhs)
    }
}

impl std::ops::BitOrAssign for Sense {
    #[inline]
    fn bitor_assign(&mut self, rhs: Self) {
        *self = self.union(rhs);
    }
}