Skip to main content

azul_layout/widgets/
divider.rs

1//! Divider (separator) widget — a thin rule line. A stateless single styled
2//! node with no callback, a near-clone of [`crate::widgets::label::Label`].
3//! Supports a horizontal (default) or vertical orientation.
4//!
5//! Key types: [`Divider`], [`DividerOrientation`].
6
7use azul_core::dom::{Dom, IdOrClass, IdOrClass::Class, IdOrClassVec};
8use azul_css::dynamic_selector::{CssPropertyWithConditions, CssPropertyWithConditionsVec};
9use azul_css::{
10    props::{
11        basic::ColorU,
12        layout::{LayoutDisplay, LayoutHeight, LayoutAlignSelf, LayoutFlexGrow, LayoutMarginTop, LayoutMarginBottom, LayoutWidth, LayoutMarginLeft, LayoutMarginRight},
13        property::{CssProperty, *},
14        style::{StyleBackgroundContent, StyleBackgroundContentVec},
15    },
16    AzString,
17};
18
19/// Orientation of a [`Divider`].
20#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
21#[repr(C)]
22pub enum DividerOrientation {
23    /// A full-width horizontal rule (1px tall) — the default.
24    #[default]
25    Horizontal,
26    /// A full-height vertical rule (1px wide).
27    Vertical,
28}
29
30/// A thin separator rule. Stateless; renders a single styled `div`.
31#[derive(Debug, Clone, PartialEq, Eq)]
32#[repr(C)]
33pub struct Divider {
34    pub orientation: DividerOrientation,
35    pub divider_style: CssPropertyWithConditionsVec,
36}
37
38/// Default rule colour (#dddddd), matching the frame widget's border colour.
39const DIVIDER_COLOR: ColorU = ColorU {
40    r: 221,
41    g: 221,
42    b: 221,
43    a: 255,
44};
45const DIVIDER_BG_ITEMS: &[StyleBackgroundContent] = &[StyleBackgroundContent::Color(DIVIDER_COLOR)];
46const DIVIDER_BG: StyleBackgroundContentVec =
47    StyleBackgroundContentVec::from_const_slice(DIVIDER_BG_ITEMS);
48
49static DIVIDER_STYLE_HORIZONTAL: &[CssPropertyWithConditions] = &[
50    CssPropertyWithConditions::simple(CssProperty::const_display(LayoutDisplay::Block)),
51    CssPropertyWithConditions::simple(CssProperty::const_height(LayoutHeight::const_px(1))),
52    // Stretch across the parent's cross axis so the rule spans the full width.
53    CssPropertyWithConditions::simple(CssProperty::align_self(LayoutAlignSelf::Stretch)),
54    CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
55    CssPropertyWithConditions::simple(CssProperty::const_margin_top(LayoutMarginTop::const_px(4))),
56    CssPropertyWithConditions::simple(CssProperty::const_margin_bottom(
57        LayoutMarginBottom::const_px(4),
58    )),
59    CssPropertyWithConditions::simple(CssProperty::const_background_content(DIVIDER_BG)),
60];
61
62static DIVIDER_STYLE_VERTICAL: &[CssPropertyWithConditions] = &[
63    CssPropertyWithConditions::simple(CssProperty::const_display(LayoutDisplay::Block)),
64    CssPropertyWithConditions::simple(CssProperty::const_width(LayoutWidth::const_px(1))),
65    // Stretch across the parent's cross axis so the rule spans the full height.
66    CssPropertyWithConditions::simple(CssProperty::align_self(LayoutAlignSelf::Stretch)),
67    CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
68    CssPropertyWithConditions::simple(CssProperty::const_margin_left(LayoutMarginLeft::const_px(4))),
69    CssPropertyWithConditions::simple(CssProperty::const_margin_right(
70        LayoutMarginRight::const_px(4),
71    )),
72    CssPropertyWithConditions::simple(CssProperty::const_background_content(DIVIDER_BG)),
73];
74
75impl Divider {
76    /// Creates a new horizontal divider with default styling.
77    #[inline]
78    #[must_use] pub fn create() -> Self {
79        Self::create_with_orientation(DividerOrientation::Horizontal)
80    }
81
82    /// Creates a new divider with the given orientation and default styling.
83    #[inline]
84    #[must_use] pub fn create_with_orientation(orientation: DividerOrientation) -> Self {
85        let divider_style = match orientation {
86            DividerOrientation::Horizontal => {
87                CssPropertyWithConditionsVec::from_const_slice(DIVIDER_STYLE_HORIZONTAL)
88            }
89            DividerOrientation::Vertical => {
90                CssPropertyWithConditionsVec::from_const_slice(DIVIDER_STYLE_VERTICAL)
91            }
92        };
93        Self {
94            orientation,
95            divider_style,
96        }
97    }
98
99    /// Sets the orientation, resetting the style to the matching default.
100    #[inline]
101    pub fn set_orientation(&mut self, orientation: DividerOrientation) {
102        *self = Self::create_with_orientation(orientation);
103    }
104
105    /// Builder-style setter for the orientation.
106    #[inline]
107    #[must_use] pub fn with_orientation(mut self, orientation: DividerOrientation) -> Self {
108        self.set_orientation(orientation);
109        self
110    }
111
112    /// Replaces `self` with a default horizontal divider and returns the original.
113    #[inline]
114    #[must_use] pub fn swap_with_default(&mut self) -> Self {
115        let mut s = Self::create();
116        core::mem::swap(&mut s, self);
117        s
118    }
119
120    /// Converts this divider into a DOM node with the `__azul-native-divider` class.
121    #[inline]
122    #[must_use] pub fn dom(self) -> Dom {
123        static DIVIDER_CLASS: &[IdOrClass] =
124            &[Class(AzString::from_const_str("__azul-native-divider"))];
125
126        Dom::create_div()
127            .with_ids_and_classes(IdOrClassVec::from_const_slice(DIVIDER_CLASS))
128            .with_css_props(self.divider_style)
129    }
130}
131
132impl Default for Divider {
133    fn default() -> Self {
134        Self::create()
135    }
136}
137
138impl From<Divider> for Dom {
139    fn from(d: Divider) -> Self {
140        d.dom()
141    }
142}