//! The separator: a hairline rule between sibling content. use std::rc::Rc; use gpui::prelude::FluentBuilder as _; use gpui::{App, InteractiveElement as _, IntoElement, RenderOnce, Styled as _, Window, div, px}; use gpui_native_theme::ActiveTheme as _; /// Which axis the rule runs along. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub enum SeparatorOrientation { /// A horizontal rule between stacked content. #[default] Horizontal, /// A vertical rule between side-by-side content. Vertical, } type DebugSelector = Rc String>; /// A hairline rule that divides sibling content. #[derive(IntoElement)] pub struct Separator { orientation: SeparatorOrientation, debug_selector: Option, } impl Separator { /// Creates a horizontal rule. pub fn horizontal() -> Self { Self { orientation: SeparatorOrientation::Horizontal, debug_selector: None, } } /// Creates a vertical rule. pub fn vertical() -> Self { Self { orientation: SeparatorOrientation::Vertical, debug_selector: None, } } /// Sets which axis the rule runs along. pub fn orientation(mut self, orientation: SeparatorOrientation) -> Self { self.orientation = orientation; self } /// Sets the debug-bounds selector, for headless tests. pub fn debug_selector(mut self, selector: F) -> Self where F: Fn() -> String + 'static, { self.debug_selector = Some(Rc::new(selector)); self } } impl RenderOnce for Separator { fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement { let border = cx.theme().colors.border; div() .flex_none() .bg(border) .when_some(self.debug_selector, |rule, selector| { rule.debug_selector(move || selector()) }) .map(|rule| match self.orientation { SeparatorOrientation::Horizontal => rule.w_full().h(px(1.)), SeparatorOrientation::Vertical => rule.self_stretch().w(px(1.)), }) } }