Skip to main content

kas_widgets/adapt/
with_label.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Wrapper adding a label
7
8use crate::AccessLabel;
9use kas::prelude::*;
10
11#[impl_self]
12mod WithLabel {
13    /// A wrapper widget with a label
14    ///
15    /// The label supports access keys; on usage the inner widget will receive
16    /// event `Event::Command(Command::Activate)`.
17    ///
18    /// Mouse/touch input on the label sends events to the inner widget.
19    #[autoimpl(Deref, DerefMut using self.inner)]
20    #[autoimpl(Viewport using self.inner where W: trait)]
21    #[widget]
22    #[layout(list![self.inner, self.label].with_direction(self.dir))]
23    pub struct WithLabel<W: Widget, D: Directional = Direction> {
24        core: widget_core!(),
25        dir: D,
26        #[widget]
27        inner: W,
28        #[widget(&())]
29        label: AccessLabel,
30    }
31
32    impl Self {
33        /// Construct a wrapper around `inner` placing a `label` in the given `direction`
34        pub fn new<T: Into<AccessString>>(inner: W, label: T) -> Self
35        where
36            D: Default,
37        {
38            Self::new_dir(inner, D::default(), label)
39        }
40    }
41    impl<W: Widget> WithLabel<W, kas::dir::Left> {
42        /// Construct from `inner` widget and `label`
43        pub fn left<T: Into<AccessString>>(inner: W, label: T) -> Self {
44            Self::new(inner, label)
45        }
46    }
47    impl<W: Widget> WithLabel<W, kas::dir::Right> {
48        /// Construct from `inner` widget and `label`
49        pub fn right<T: Into<AccessString>>(inner: W, label: T) -> Self {
50            Self::new(inner, label)
51        }
52    }
53
54    impl Self {
55        /// Construct a wrapper around `inner` placing a `label` in the given `direction`
56        #[inline]
57        pub fn new_dir<T: Into<AccessString>>(inner: W, direction: D, label: T) -> Self {
58            WithLabel {
59                core: Default::default(),
60                dir: direction,
61                inner,
62                label: AccessLabel::new(label.into()),
63            }
64        }
65
66        /// Get the direction
67        #[inline]
68        pub fn label_direction(&self) -> Direction {
69            self.dir.as_direction()
70        }
71
72        /// Take inner
73        #[inline]
74        pub fn take_inner(self) -> W {
75            self.inner
76        }
77
78        /// Get whether line-wrapping is enabled
79        #[inline]
80        pub fn label_wrap(&self) -> bool {
81            self.label.wrap()
82        }
83
84        /// Enable/disable line wrapping
85        ///
86        /// By default this is enabled.
87        #[inline]
88        pub fn set_label_wrap(&mut self, wrap: bool) {
89            self.label.set_wrap(wrap);
90        }
91
92        /// Enable/disable line wrapping (inline)
93        #[inline]
94        pub fn with_label_wrap(mut self, wrap: bool) -> Self {
95            self.label.set_wrap(wrap);
96            self
97        }
98
99        /// Set label text
100        ///
101        /// Note: this must not be called before fonts have been initialised
102        /// (usually done by the theme when the main loop starts).
103        pub fn set_label_text<T: Into<AccessString>>(&mut self, cx: &mut ConfigCx, text: T) {
104            self.label.set_text(cx, text.into());
105        }
106    }
107
108    impl Tile for Self {
109        fn role_child_properties(&self, cx: &mut dyn RoleCx, index: usize) {
110            if index == widget_index!(self.inner) {
111                cx.set_label(self.label.id());
112            }
113        }
114
115        fn nav_next(&self, _: bool, from: Option<usize>) -> Option<usize> {
116            from.xor(Some(widget_index!(self.inner)))
117        }
118    }
119
120    impl Events for Self {
121        type Data = W::Data;
122
123        fn probe(&self, _: Coord) -> Id {
124            self.inner.id()
125        }
126
127        fn post_configure(&mut self, _: &mut ConfigCx) {
128            self.label.set_target(self.inner.id());
129        }
130    }
131}
132
133#[impl_self]
134mod WithHiddenLabel {
135    /// A wrapper widget with a hidden label
136    ///
137    /// This label is not normally visible but may be read by accessibility
138    /// tools and tooltips.
139    #[autoimpl(Deref, DerefMut using self.inner)]
140    #[autoimpl(Clone where W: trait)]
141    #[autoimpl(Viewport using self.inner where W: trait)]
142    #[derive_widget]
143    pub struct WithHiddenLabel<W: Widget> {
144        #[widget]
145        inner: W,
146        label: String,
147    }
148
149    impl Self {
150        /// Wrap `inner`, adding a hidden `label`
151        #[inline]
152        pub fn new<T: ToString>(inner: W, label: T) -> Self {
153            WithHiddenLabel {
154                inner,
155                label: label.to_string(),
156            }
157        }
158
159        /// Take inner
160        #[inline]
161        pub fn take_inner(self) -> W {
162            self.inner
163        }
164
165        /// Set the label
166        pub fn set_label<T: ToString>(&mut self, text: T) {
167            self.label = text.to_string();
168        }
169    }
170
171    impl Tile for Self {
172        fn tooltip(&self) -> Option<&str> {
173            Some(&self.label)
174        }
175
176        fn role(&self, cx: &mut dyn RoleCx) -> Role<'_> {
177            cx.set_label(&self.label);
178            self.inner.role(cx)
179        }
180    }
181}