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}