kas_widgets/frame.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//! A simple frame
7
8use kas::prelude::*;
9use kas::theme::{Background, FrameStyle};
10
11/// Make a [`Frame`] widget
12///
13/// # Syntax
14///
15/// ## Stand-alone usage
16///
17/// When called as a stand-alone macro, `frame!(inner)` is just syntactic sugar
18/// for `Frame::new(inner)`, and yes, this makes the macro pointless.
19///
20/// ## Usage within widget layout syntax
21///
22/// When called within [widget layout syntax], `frame!` may be evaluated as a
23/// recursive macro and the result does not have a specified type, except that
24/// methods [`map_any`], [`align`], [`pack`], [`with_stretch`] and [`with_style`] are
25/// supported via emulation.
26///
27/// # Example
28///
29/// ```
30/// let my_widget = kas_widgets::frame!(kas_widgets::Label::new("content"));
31/// ```
32///
33/// [widget layout syntax]: macro@kas::layout
34/// [`map_any`]: crate::AdaptWidgetAny::map_any
35/// [`align`]: crate::AdaptWidget::align
36/// [`pack`]: crate::AdaptWidget::pack
37/// [`with_stretch`]: crate::AdaptWidget::with_stretch
38/// [`with_style`]: Frame::with_style
39#[macro_export]
40macro_rules! frame {
41 ( $e:expr ) => {
42 $crate::Frame::new($e)
43 };
44}
45
46#[impl_self]
47mod Frame {
48 /// A frame around content
49 ///
50 /// This widget provides a simple abstraction: drawing a frame around its
51 /// contents.
52 //
53 // NOTE: this would use derive mode if that supported custom layout syntax,
54 // but it does not. This would allow us to implement Deref to self.inner.
55 #[derive(Default)]
56 #[widget]
57 #[layout(frame!(self.inner).with_style(self.style).with_background(self.bg))]
58 pub struct Frame<W: Widget> {
59 core: widget_core!(),
60 style: FrameStyle,
61 bg: Background,
62 /// The inner widget
63 #[widget]
64 pub inner: W,
65 }
66
67 impl Events for Self {
68 type Data = W::Data;
69 }
70
71 impl Self {
72 /// Construct a frame
73 #[inline]
74 pub fn new(inner: W) -> Self {
75 Frame {
76 core: Default::default(),
77 style: FrameStyle::Frame,
78 bg: Background::default(),
79 inner,
80 }
81 }
82
83 /// Set the frame style (inline)
84 ///
85 /// The default style is [`FrameStyle::Frame`].
86 ///
87 /// Note: using [`FrameStyle::NavFocus`] does not automatically make
88 /// this widget interactive.
89 #[inline]
90 #[must_use]
91 pub fn with_style(mut self, style: FrameStyle) -> Self {
92 self.style = style;
93 self
94 }
95
96 /// Set the frame background color (inline)
97 ///
98 /// Dependant on the [style](Self::with_style), this may not be used.
99 ///
100 /// The default background is [`Background::Default`].
101 #[inline]
102 #[must_use]
103 pub fn with_background(mut self, bg: Background) -> Self {
104 self.bg = bg;
105 self
106 }
107 }
108}