Skip to main content

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}