Skip to main content

kas_core/widgets/
adapt.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//! Adapter widgets (wrappers)
7
8#[allow(unused)] use crate::event::ConfigCx;
9use crate::geom::{Rect, Size};
10use crate::layout::{AlignHints, AxisInfo, SizeRules};
11use crate::theme::SizeCx;
12use crate::{Layout, Widget};
13use kas_macros::{autoimpl, impl_self};
14
15#[impl_self]
16mod MapAny {
17    /// Map any input data to `()`
18    ///
19    /// This is a generic data-mapping widget-wrapper with fixed `()` input
20    /// data type.
21    ///
22    /// This struct is a thin wrapper around the inner widget without its own
23    /// [`Id`](crate::Id). It supports [`Deref`](std::ops::Deref) and
24    /// [`DerefMut`](std::ops::DerefMut) to the inner widget.
25    #[autoimpl(Deref, DerefMut using self.inner)]
26    #[autoimpl(Clone, Default where W: trait)]
27    #[derive_widget]
28    pub struct MapAny<A, W: Widget<Data = ()>> {
29        _a: std::marker::PhantomData<A>,
30        /// The inner widget
31        #[widget = &()]
32        pub inner: W,
33    }
34
35    impl Widget for Self {
36        type Data = A;
37    }
38
39    impl Self {
40        /// Construct
41        pub fn new(inner: W) -> Self {
42            MapAny {
43                _a: std::marker::PhantomData,
44                inner,
45            }
46        }
47    }
48}
49
50#[impl_self]
51mod Align {
52    /// Apply an alignment hint
53    ///
54    /// The inner widget chooses how to apply (or ignore) this hint.
55    ///
56    /// Usually, this type will be constructed through one of the methods on
57    /// [`AdaptWidget`](https://docs.rs/kas/latest/kas/widgets/trait.AdaptWidget.html).
58    #[autoimpl(Deref, DerefMut using self.inner)]
59    #[autoimpl(Clone where W: trait)]
60    #[autoimpl(Viewport using self.inner where W: trait)]
61    #[derive_widget]
62    pub struct Align<W: Widget> {
63        #[widget]
64        pub inner: W,
65        /// Hints may be modified directly.
66        ///
67        /// Use [`ConfigCx::resize`] to apply changes.
68        pub hints: AlignHints,
69    }
70
71    impl Self {
72        /// Construct
73        #[inline]
74        pub fn new(inner: W, hints: AlignHints) -> Self {
75            Align { inner, hints }
76        }
77    }
78
79    impl Layout for Self {
80        fn set_rect(&mut self, cx: &mut SizeCx, rect: Rect, hints: AlignHints) {
81            self.inner.set_rect(cx, rect, self.hints.combine(hints));
82        }
83    }
84}
85
86#[impl_self]
87mod Pack {
88    /// Apply an alignment hint, squash and align the result
89    ///
90    /// The inner widget chooses how to apply (or ignore) this hint.
91    /// The widget is then prevented from stretching beyond its ideal size,
92    /// aligning within the available rect.
93    ///
94    /// Usually, this type will be constructed through one of the methods on
95    /// [`AdaptWidget`](https://docs.rs/kas/latest/kas/widgets/trait.AdaptWidget.html).
96    #[autoimpl(Deref, DerefMut using self.inner)]
97    #[autoimpl(Clone where W: trait)]
98    #[autoimpl(Viewport using self.inner where W: trait)]
99    #[derive_widget]
100    pub struct Pack<W: Widget> {
101        #[widget]
102        pub inner: W,
103        /// Hints may be modified directly.
104        ///
105        /// Use [`ConfigCx::resize`] to apply changes.
106        pub hints: AlignHints,
107        size: Size,
108    }
109
110    impl Self {
111        /// Construct
112        #[inline]
113        pub fn new(inner: W, hints: AlignHints) -> Self {
114            Pack {
115                inner,
116                hints,
117                size: Size::ZERO,
118            }
119        }
120    }
121
122    impl Layout for Self {
123        fn size_rules(&mut self, cx: &mut SizeCx, axis: AxisInfo) -> SizeRules {
124            let rules = self.inner.size_rules(cx, axis);
125            self.size.set_component(axis, rules.ideal_size());
126            rules
127        }
128
129        fn set_rect(&mut self, cx: &mut SizeCx, rect: Rect, hints: AlignHints) {
130            let align = self.hints.combine(hints).complete_default();
131            let rect = align.aligned_rect(self.size, rect);
132            self.inner.set_rect(cx, rect, hints);
133        }
134    }
135}