ring.rs

 1use gpui::{
 2    AnyElement, IntoElement, ParentElement, Pixels, RenderOnce, Styled, px, transparent_black,
 3};
 4use smallvec::SmallVec;
 5use theme::ActiveTheme;
 6
 7use crate::{h_flex, utils::CornerSolver};
 8
 9/// A ring is a stylistic focus indicator that draws a ring around
10/// an element with some space between the element and ring.
11#[derive(IntoElement)]
12pub struct Ring {
13    corner_radius: Pixels,
14    border_width: Pixels,
15    padding: Pixels,
16    focused: bool,
17    active: bool,
18    children: SmallVec<[AnyElement; 2]>,
19}
20
21impl Ring {
22    pub fn new(child_corner_radius: Pixels, focused: bool) -> Self {
23        let border_width = px(1.);
24        let padding = px(2.);
25        let corner_radius =
26            CornerSolver::parent_radius(child_corner_radius, border_width, padding, px(0.));
27        Self {
28            corner_radius,
29            border_width,
30            padding,
31            focused,
32            active: false,
33            children: SmallVec::new(),
34        }
35    }
36
37    pub fn active(mut self, active: bool) -> Self {
38        self.active = active;
39        self
40    }
41}
42
43impl RenderOnce for Ring {
44    fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
45        let border_color = if self.focused && self.active {
46            cx.theme().colors().border_focused.opacity(0.48)
47        } else if self.focused {
48            cx.theme().colors().border_variant
49        } else {
50            transparent_black()
51        };
52
53        h_flex()
54            .border(self.border_width)
55            .border_color(border_color)
56            .rounded(self.corner_radius)
57            .p(self.padding)
58            .children(self.children)
59    }
60}
61
62impl ParentElement for Ring {
63    fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
64        self.children.extend(elements)
65    }
66}