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
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License in the LICENSE-APACHE file or at:
//     https://www.apache.org/licenses/LICENSE-2.0

//! Wrapper adding a label

use crate::AccessLabel;
use kas::{layout, prelude::*};

impl_scope! {
    /// A wrapper widget with a label
    ///
    /// The label supports access keys, which activate `self.inner` on
    /// usage.
    ///
    /// Mouse/touch input on the label sends events to the inner widget.
    #[autoimpl(Deref, DerefMut using self.inner)]
    #[derive(Clone, Default)]
    #[widget {
        Data = W::Data;
        layout = list! 'row (self.dir, [self.inner, non_navigable!(self.label)]);
    }]
    pub struct WithLabel<W: Widget, D: Directional = Direction> {
        core: widget_core!(),
        dir: D,
        #[widget]
        inner: W,
        #[widget(&())]
        label: AccessLabel,
    }

    impl Self {
        /// Construct a wrapper around `inner` placing a `label` in the given `direction`
        pub fn new<T: Into<AccessString>>(inner: W, label: T) -> Self where D: Default {
            Self::new_dir(inner, D::default(), label)
        }
    }
    impl<W: Widget> WithLabel<W, kas::dir::Left> {
        /// Construct from `inner` widget and `label`
        pub fn left<T: Into<AccessString>>(inner: W, label: T) -> Self {
            Self::new(inner, label)
        }
    }
    impl<W: Widget> WithLabel<W, kas::dir::Right> {
        /// Construct from `inner` widget and `label`
        pub fn right<T: Into<AccessString>>(inner: W, label: T) -> Self {
            Self::new(inner, label)
        }
    }

    impl Self {
        /// Construct a wrapper around `inner` placing a `label` in the given `direction`
        #[inline]
        pub fn new_dir<T: Into<AccessString>>(inner: W, direction: D, label: T) -> Self {
            WithLabel {
                core: Default::default(),
                dir: direction,
                inner,
                label: AccessLabel::new(label.into()),
            }
        }

        /// Get the direction
        #[inline]
        pub fn direction(&self) -> Direction {
            self.dir.as_direction()
        }

        /// Take inner
        #[inline]
        pub fn take_inner(self) -> W {
            self.inner
        }

        /// Access layout storage
        ///
        /// The number of columns/rows is fixed at two: the `inner` widget, and
        /// the `label` (in this order, regardless of direction).
        #[inline]
        pub fn layout_storage(&mut self) -> &mut impl layout::RowStorage {
            &mut self.core.row
        }

        /// Get whether line-wrapping is enabled
        #[inline]
        pub fn wrap(&self) -> bool {
            self.label.wrap()
        }

        /// Enable/disable line wrapping
        ///
        /// By default this is enabled.
        #[inline]
        pub fn set_wrap(&mut self, wrap: bool) {
            self.label.set_wrap(wrap);
        }

        /// Enable/disable line wrapping (inline)
        #[inline]
        pub fn with_wrap(mut self, wrap: bool) -> Self {
            self.label.set_wrap(wrap);
            self
        }

        /// Set text
        ///
        /// Note: this must not be called before fonts have been initialised
        /// (usually done by the theme when the main loop starts).
        pub fn set_text<T: Into<AccessString>>(&mut self, text: T) -> Action {
            self.label.set_text(text.into())
        }
    }

    impl Layout for Self {
        fn find_id(&mut self, coord: Coord) -> Option<Id> {
            self.rect().contains(coord).then(|| self.inner.id())
        }
    }
}