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