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`] and [`with_style`] are supported
25/// 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_style`]: Frame::with_style
38#[macro_export]
39macro_rules! frame {
40 ( $e:expr ) => {
41 $crate::Frame::new($e)
42 };
43}
44
45#[impl_self]
46mod Frame {
47 /// A frame around content
48 ///
49 /// This widget provides a simple abstraction: drawing a frame around its
50 /// contents.
51 //
52 // NOTE: this would use derive mode if that supported custom layout syntax,
53 // but it does not. This would allow us to implement Deref to self.inner.
54 #[derive(Clone, Default)]
55 #[widget]
56 #[layout(frame!(self.inner).with_style(self.style))]
57 pub struct Frame<W: Widget> {
58 core: widget_core!(),
59 style: FrameStyle,
60 bg: Background,
61 /// The inner widget
62 #[widget]
63 pub inner: W,
64 }
65
66 impl Events for Self {
67 type Data = W::Data;
68 }
69
70 impl Self {
71 /// Construct a frame
72 #[inline]
73 pub fn new(inner: W) -> Self {
74 Frame {
75 core: Default::default(),
76 style: FrameStyle::Frame,
77 bg: Background::default(),
78 inner,
79 }
80 }
81
82 /// Set the frame style (inline)
83 ///
84 /// The default style is [`FrameStyle::Frame`].
85 ///
86 /// Note: using [`FrameStyle::NavFocus`] does not automatically make
87 /// this widget interactive.
88 #[inline]
89 #[must_use]
90 pub fn with_style(mut self, style: FrameStyle) -> Self {
91 self.style = style;
92 self
93 }
94
95 /// Set the frame background color (inline)
96 ///
97 /// The default background is [`Background::Default`].
98 #[inline]
99 #[must_use]
100 pub fn with_background(mut self, bg: Background) -> Self {
101 self.bg = bg;
102 self
103 }
104 }
105}