252 lines · 8.0 KB · Rust
RawDownload
use gpui::{Hsla, IntoElement, PathBuilder, canvas, point}; use crate::prelude::*; pub fn divider() -> Divider {    Divider {        style: DividerStyle::Solid,        direction: DividerDirection::Horizontal,        color: DividerColor::default(),        inset: false,    }} pub fn vertical_divider() -> Divider {    Divider {        style: DividerStyle::Solid,        direction: DividerDirection::Vertical,        color: DividerColor::default(),        inset: false,    }} #[derive(Clone, Copy, PartialEq)]enum DividerStyle {    Solid,    Dashed,} #[derive(Clone, Copy, PartialEq)]enum DividerDirection {    Horizontal,    Vertical,} /// The color of a [`Divider`].#[derive(Default)]pub enum DividerColor {    Border,    BorderFaded,    #[default]    BorderVariant,} impl DividerColor {    pub fn hsla(self, cx: &mut App) -> Hsla {        match self {            DividerColor::Border => cx.theme().colors().border,            DividerColor::BorderFaded => cx.theme().colors().border.opacity(0.6),            DividerColor::BorderVariant => cx.theme().colors().border_variant,        }    }} #[derive(IntoElement, RegisterComponent)]pub struct Divider {    style: DividerStyle,    direction: DividerDirection,    color: DividerColor,    inset: bool,} impl Divider {    pub fn horizontal() -> Self {        Self {            style: DividerStyle::Solid,            direction: DividerDirection::Horizontal,            color: DividerColor::default(),            inset: false,        }    }     pub fn vertical() -> Self {        Self {            style: DividerStyle::Solid,            direction: DividerDirection::Vertical,            color: DividerColor::default(),            inset: false,        }    }     pub fn horizontal_dashed() -> Self {        Self {            style: DividerStyle::Dashed,            direction: DividerDirection::Horizontal,            color: DividerColor::default(),            inset: false,        }    }     pub fn vertical_dashed() -> Self {        Self {            style: DividerStyle::Dashed,            direction: DividerDirection::Vertical,            color: DividerColor::default(),            inset: false,        }    }     pub fn inset(mut self) -> Self {        self.inset = true;        self    }     pub fn color(mut self, color: DividerColor) -> Self {        self.color = color;        self    }     pub fn render_solid(self, base: Div, cx: &mut App) -> impl IntoElement {        base.bg(self.color.hsla(cx))    }     pub fn render_dashed(self, base: Div) -> impl IntoElement {        base.relative().child(            canvas(                |_, _, _| {},                move |bounds, _, window, cx| {                    let mut builder = PathBuilder::stroke(px(1.)).dash_array(&[px(4.), px(2.)]);                    let (start, end) = match self.direction {                        DividerDirection::Horizontal => {                            let x = bounds.origin.x;                            let y = bounds.origin.y + px(0.5);                            (point(x, y), point(x + bounds.size.width, y))                        }                        DividerDirection::Vertical => {                            let x = bounds.origin.x + px(0.5);                            let y = bounds.origin.y;                            (point(x, y), point(x, y + bounds.size.height))                        }                    };                    builder.move_to(start);                    builder.line_to(end);                    if let Ok(line) = builder.build() {                        window.paint_path(line, self.color.hsla(cx));                    }                },            )            .absolute()            .size_full(),        )    }} impl RenderOnce for Divider {    fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {        let base = match self.direction {            DividerDirection::Horizontal => div()                .min_w_0()                .h_px()                .w_full()                .when(self.inset, |this| this.mx_1p5()),            DividerDirection::Vertical => div()                .min_w_0()                .w_px()                .h_full()                .when(self.inset, |this| this.my_1p5()),        };         match self.style {            DividerStyle::Solid => self.render_solid(base, cx).into_any_element(),            DividerStyle::Dashed => self.render_dashed(base).into_any_element(),        }    }} impl Component for Divider {    fn scope() -> ComponentScope {        ComponentScope::Layout    }     fn description() -> Option<&'static str> {        Some(            "Visual separator used to create divisions between groups of content or sections in a layout.",        )    }     fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {        Some(            v_flex()                .gap_6()                .children(vec![                    example_group_with_title(                        "Horizontal Dividers",                        vec![                            single_example("Default", Divider::horizontal().into_any_element()),                            single_example(                                "Border Color",                                Divider::horizontal()                                    .color(DividerColor::Border)                                    .into_any_element(),                            ),                            single_example(                                "Inset",                                Divider::horizontal().inset().into_any_element(),                            ),                            single_example(                                "Dashed",                                Divider::horizontal_dashed().into_any_element(),                            ),                        ],                    ),                    example_group_with_title(                        "Vertical Dividers",                        vec![                            single_example(                                "Default",                                div().h_16().child(Divider::vertical()).into_any_element(),                            ),                            single_example(                                "Border Color",                                div()                                    .h_16()                                    .child(Divider::vertical().color(DividerColor::Border))                                    .into_any_element(),                            ),                            single_example(                                "Inset",                                div()                                    .h_16()                                    .child(Divider::vertical().inset())                                    .into_any_element(),                            ),                            single_example(                                "Dashed",                                div()                                    .h_16()                                    .child(Divider::vertical_dashed())                                    .into_any_element(),                            ),                        ],                    ),                    example_group_with_title(                        "Example Usage",                        vec![single_example(                            "Between Content",                            v_flex()                                .w_full()                                .gap_4()                                .px_4()                                .child(Label::new("Section One"))                                .child(Divider::horizontal())                                .child(Label::new("Section Two"))                                .child(Divider::horizontal_dashed())                                .child(Label::new("Section Three"))                                .into_any_element(),                        )],                    ),                ])                .into_any_element(),        )    }}