Skip to main content

azul_layout/widgets/
frame.rs

1//! Frame widget — a titled border container similar to an HTML `<fieldset>`
2//! or a Windows group box.
3//!
4//! Renders a header with a centered title flanked by horizontal border lines,
5//! and a bordered content area below.
6
7use azul_core::dom::{Dom, DomVec, IdOrClass, IdOrClass::Class, IdOrClassVec};
8#[allow(clippy::wildcard_imports)] // widget/render module pulls in the css property/value types it builds with
9use azul_css::{
10    dynamic_selector::{CssPropertyWithConditions, CssPropertyWithConditionsVec},
11    props::{
12        basic::*,
13        layout::*,
14        property::{CssProperty, *},
15        style::*,
16    },
17    *,
18};
19
20const BORDER_COLOR: ColorU = ColorU {
21    r: 221,
22    g: 221,
23    b: 221,
24    a: 255,
25};
26
27const STRING_16146701490593874959: AzString = AzString::from_const_str("system:ui");
28const STYLE_FONT_FAMILY_8122988506401935406_ITEMS: &[StyleFontFamily] =
29    &[StyleFontFamily::System(STRING_16146701490593874959)];
30
31const CSS_MATCH_15775557796860201720_PROPERTIES: &[CssPropertyWithConditions] = &[
32    // .__azul-native-frame .__azul-native-frame-header .__azul-native-frame-header-before div
33    CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
34        LayoutHeight::Px(PixelValue::const_px(8)),
35    ))),
36    CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
37        LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
38            inner: PixelValue::const_px(1),
39        }),
40    )),
41    CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
42        StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
43            inner: BorderStyle::Solid,
44        }),
45    )),
46    CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
47        StyleBorderTopColorValue::Exact(StyleBorderTopColor {
48            inner: BORDER_COLOR,
49        }),
50    )),
51    CssPropertyWithConditions::simple(CssProperty::BorderLeftWidth(
52        LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
53            inner: PixelValue::const_px(1),
54        }),
55    )),
56    CssPropertyWithConditions::simple(CssProperty::BorderLeftStyle(
57        StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
58            inner: BorderStyle::Solid,
59        }),
60    )),
61    CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
62        StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
63            inner: BORDER_COLOR,
64        }),
65    )),
66    // .__azul-native-frame .__azul-native-frame-header .__azul-native-frame-header-before
67    CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
68        LayoutWidth::Px(PixelValue::const_px(5)),
69    ))),
70    CssPropertyWithConditions::simple(CssProperty::MarginTop(LayoutMarginTopValue::Exact(
71        LayoutMarginTop {
72            inner: PixelValue::const_px(6),
73        },
74    ))),
75    CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
76        LayoutFlexGrow {
77            inner: FloatValue::const_new(1),
78        },
79    ))),
80    CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
81        LayoutFlexDirection::Column,
82    ))),
83];
84const CSS_MATCH_15775557796860201720: CssPropertyWithConditionsVec =
85    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_15775557796860201720_PROPERTIES);
86
87const CSS_MATCH_16739370686243728873_PROPERTIES: &[CssPropertyWithConditions] = &[
88    // .__azul-native-frame .__azul-native-frame-header
89    CssPropertyWithConditions::simple(CssProperty::FontSize(StyleFontSizeValue::Exact(
90        StyleFontSize {
91            inner: PixelValue::const_px(11),
92        },
93    ))),
94    CssPropertyWithConditions::simple(CssProperty::FontFamily(StyleFontFamilyVecValue::Exact(
95        StyleFontFamilyVec::from_const_slice(STYLE_FONT_FAMILY_8122988506401935406_ITEMS),
96    ))),
97    CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
98        LayoutFlexDirection::Row,
99    ))),
100    CssPropertyWithConditions::simple(CssProperty::AlignItems(LayoutAlignItemsValue::Exact(
101        LayoutAlignItems::End,
102    ))),
103];
104const CSS_MATCH_16739370686243728873: CssPropertyWithConditionsVec =
105    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_16739370686243728873_PROPERTIES);
106
107const CSS_MATCH_4236783900531286611_PROPERTIES: &[CssPropertyWithConditions] = &[
108    // .__azul-native-frame .__azul-native-frame-header p
109    CssPropertyWithConditions::simple(CssProperty::TextAlign(StyleTextAlignValue::Exact(
110        StyleTextAlign::Center,
111    ))),
112    CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
113        LayoutPaddingLeft {
114            inner: PixelValue::const_px(3),
115        },
116    ))),
117    CssPropertyWithConditions::simple(CssProperty::PaddingRight(LayoutPaddingRightValue::Exact(
118        LayoutPaddingRight {
119            inner: PixelValue::const_px(1),
120        },
121    ))),
122    CssPropertyWithConditions::simple(CssProperty::PaddingBottom(LayoutPaddingBottomValue::Exact(
123        LayoutPaddingBottom {
124            inner: PixelValue::const_px(0),
125        },
126    ))),
127    CssPropertyWithConditions::simple(CssProperty::PaddingTop(LayoutPaddingTopValue::Exact(
128        LayoutPaddingTop {
129            inner: PixelValue::const_px(0),
130        },
131    ))),
132];
133const CSS_MATCH_4236783900531286611: CssPropertyWithConditionsVec =
134    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_4236783900531286611_PROPERTIES);
135
136const CSS_MATCH_8602559445190067154_PROPERTIES: &[CssPropertyWithConditions] = &[
137    // .__azul-native-frame
138    CssPropertyWithConditions::simple(CssProperty::PaddingRight(LayoutPaddingRightValue::Exact(
139        LayoutPaddingRight {
140            inner: PixelValue::const_px(5),
141        },
142    ))),
143    CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
144        LayoutPaddingLeft {
145            inner: PixelValue::const_px(5),
146        },
147    ))),
148    CssPropertyWithConditions::simple(CssProperty::PaddingBottom(LayoutPaddingBottomValue::Exact(
149        LayoutPaddingBottom {
150            inner: PixelValue::const_px(3),
151        },
152    ))),
153    CssPropertyWithConditions::simple(CssProperty::PaddingTop(LayoutPaddingTopValue::Exact(
154        LayoutPaddingTop {
155            inner: PixelValue::const_px(3),
156        },
157    ))),
158];
159const CSS_MATCH_8602559445190067154: CssPropertyWithConditionsVec =
160    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_8602559445190067154_PROPERTIES);
161
162const CSS_MATCH_9156589477016488419_PROPERTIES: &[CssPropertyWithConditions] = &[
163    // .__azul-native-frame .__azul-native-frame-header .__azul-native-frame-header-after div
164    CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
165        LayoutHeight::Px(PixelValue::const_px(8)),
166    ))),
167    CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
168        LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
169            inner: PixelValue::const_px(1),
170        }),
171    )),
172    CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
173        StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
174            inner: BorderStyle::Solid,
175        }),
176    )),
177    CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
178        StyleBorderTopColorValue::Exact(StyleBorderTopColor {
179            inner: BORDER_COLOR,
180        }),
181    )),
182    CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
183        LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
184            inner: PixelValue::const_px(1),
185        }),
186    )),
187    CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
188        StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
189            inner: BorderStyle::Solid,
190        }),
191    )),
192    CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
193        StyleBorderRightColorValue::Exact(StyleBorderRightColor {
194            inner: BORDER_COLOR,
195        }),
196    )),
197    // .__azul-native-frame .__azul-native-frame-header .__azul-native-frame-header-after
198    CssPropertyWithConditions::simple(CssProperty::MarginTop(LayoutMarginTopValue::Exact(
199        LayoutMarginTop {
200            inner: PixelValue::const_px(6),
201        },
202    ))),
203    CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
204        LayoutFlexGrow {
205            inner: FloatValue::const_new(1),
206        },
207    ))),
208    CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
209        LayoutFlexDirection::Column,
210    ))),
211];
212const CSS_MATCH_9156589477016488419: CssPropertyWithConditionsVec =
213    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_9156589477016488419_PROPERTIES);
214
215const CSS_MATCH_CONTENT_AREA_PROPERTIES: &[CssPropertyWithConditions] = &[
216    // .__azul-native-frame .__azul-native-frame-content (static properties)
217    CssPropertyWithConditions::simple(CssProperty::PaddingRight(
218        LayoutPaddingRightValue::Exact(LayoutPaddingRight {
219            inner: PixelValue::const_px(5),
220        }),
221    )),
222    CssPropertyWithConditions::simple(CssProperty::PaddingLeft(
223        LayoutPaddingLeftValue::Exact(LayoutPaddingLeft {
224            inner: PixelValue::const_px(5),
225        }),
226    )),
227    CssPropertyWithConditions::simple(CssProperty::PaddingBottom(
228        LayoutPaddingBottomValue::Exact(LayoutPaddingBottom {
229            inner: PixelValue::const_px(5),
230        }),
231    )),
232    CssPropertyWithConditions::simple(CssProperty::PaddingTop(
233        LayoutPaddingTopValue::Exact(LayoutPaddingTop {
234            inner: PixelValue::const_px(5),
235        }),
236    )),
237    CssPropertyWithConditions::simple(CssProperty::FontSize(
238        StyleFontSizeValue::Exact(StyleFontSize {
239            inner: PixelValue::const_px(11),
240        }),
241    )),
242    CssPropertyWithConditions::simple(CssProperty::FontFamily(
243        StyleFontFamilyVecValue::Exact(StyleFontFamilyVec::from_const_slice(
244            STYLE_FONT_FAMILY_8122988506401935406_ITEMS,
245        )),
246    )),
247    CssPropertyWithConditions::simple(CssProperty::BorderBottomWidth(
248        LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
249            inner: PixelValue::const_px(1),
250        }),
251    )),
252    CssPropertyWithConditions::simple(CssProperty::BorderLeftWidth(
253        LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
254            inner: PixelValue::const_px(1),
255        }),
256    )),
257    CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
258        LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
259            inner: PixelValue::const_px(1),
260        }),
261    )),
262    CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
263        LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
264            inner: PixelValue::const_px(1),
265        }),
266    )),
267    CssPropertyWithConditions::simple(CssProperty::BorderBottomStyle(
268        StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
269            inner: BorderStyle::Solid,
270        }),
271    )),
272    CssPropertyWithConditions::simple(CssProperty::BorderLeftStyle(
273        StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
274            inner: BorderStyle::Solid,
275        }),
276    )),
277    CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
278        StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
279            inner: BorderStyle::Solid,
280        }),
281    )),
282    CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
283        StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
284            inner: BorderStyle::Solid,
285        }),
286    )),
287    CssPropertyWithConditions::simple(CssProperty::BorderBottomColor(
288        StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
289            inner: BORDER_COLOR,
290        }),
291    )),
292    CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
293        StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
294            inner: BORDER_COLOR,
295        }),
296    )),
297    CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
298        StyleBorderRightColorValue::Exact(StyleBorderRightColor {
299            inner: BORDER_COLOR,
300        }),
301    )),
302    CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
303        StyleBorderTopColorValue::Exact(StyleBorderTopColor {
304            inner: BORDER_COLOR,
305        }),
306    )),
307];
308
309/// A titled border container widget, similar to an HTML `<fieldset>` or
310/// a Windows group box. Displays a header with a centered title and a
311/// bordered content area below.
312#[derive(Debug, Clone)]
313#[repr(C)]
314pub struct Frame {
315    pub title: AzString,
316    pub flex_grow: f32,
317    pub content: Dom,
318}
319
320impl Frame {
321    /// Creates a new `Frame` with the given title and content DOM.
322    #[must_use] pub const fn create(title: AzString, content: Dom) -> Self {
323        Self {
324            title,
325            content,
326            flex_grow: 0.0,
327        }
328    }
329
330    /// Replaces `self` with a default frame and returns the original.
331    #[must_use]
332    pub const fn swap_with_default(&mut self) -> Self {
333        let mut s = Self::create(AzString::from_const_str(""), Dom::create_div());
334        core::mem::swap(&mut s, self);
335        s
336    }
337
338    /// Sets the flex-grow factor for the content area.
339    pub const fn set_flex_grow(&mut self, flex_grow: f32) {
340        self.flex_grow = flex_grow;
341    }
342
343    /// Builder-style setter for the flex-grow factor.
344    #[must_use] pub const fn with_flex_grow(mut self, flex_grow: f32) -> Self {
345        self.set_flex_grow(flex_grow);
346        self
347    }
348
349    #[must_use] pub fn dom(self) -> Dom {
350        Dom::create_div()
351            .with_css_props(CSS_MATCH_8602559445190067154)
352            .with_ids_and_classes({
353                const IDS_AND_CLASSES_14615537625743340639: &[IdOrClass] =
354                    &[Class(AzString::from_const_str("__azul-native-frame"))];
355                IdOrClassVec::from_const_slice(IDS_AND_CLASSES_14615537625743340639)
356            })
357            .with_children(DomVec::from_vec(vec![
358                Dom::create_div()
359                    .with_css_props(CSS_MATCH_16739370686243728873)
360                    .with_ids_and_classes({
361                        const IDS_AND_CLASSES_17776797146874875377: &[IdOrClass] = &[Class(
362                            AzString::from_const_str("__azul-native-frame-header"),
363                        )];
364                        IdOrClassVec::from_const_slice(IDS_AND_CLASSES_17776797146874875377)
365                    })
366                    .with_children(DomVec::from_vec(vec![
367                        Dom::create_div()
368                            .with_css_props(CSS_MATCH_15775557796860201720)
369                            .with_ids_and_classes({
370                                const IDS_AND_CLASSES_15264202958442287530: &[IdOrClass] =
371                                    &[Class(AzString::from_const_str(
372                                        "__azul-native-frame-header-before",
373                                    ))];
374                                IdOrClassVec::from_const_slice(IDS_AND_CLASSES_15264202958442287530)
375                            })
376                            .with_children(DomVec::from_vec(vec![Dom::create_div()])),
377                        Dom::create_text(self.title).with_css_props(CSS_MATCH_4236783900531286611),
378                        Dom::create_div()
379                            .with_css_props(CSS_MATCH_9156589477016488419)
380                            .with_ids_and_classes({
381                                const IDS_AND_CLASSES_5689091102265932280: &[IdOrClass] = &[Class(
382                                    AzString::from_const_str("__azul-native-frame-header-after"),
383                                )];
384                                IdOrClassVec::from_const_slice(IDS_AND_CLASSES_5689091102265932280)
385                            })
386                            .with_children(DomVec::from_vec(vec![Dom::create_div()])),
387                    ])),
388                Dom::create_div()
389                    .with_css_props({
390                        let mut props = vec![
391                            CssPropertyWithConditions::simple(CssProperty::FlexGrow(
392                                LayoutFlexGrowValue::Exact(LayoutFlexGrow {
393                                    inner: FloatValue::new(self.flex_grow),
394                                }),
395                            )),
396                        ];
397                        props.extend_from_slice(CSS_MATCH_CONTENT_AREA_PROPERTIES);
398                        CssPropertyWithConditionsVec::from_vec(props)
399                    })
400                    .with_ids_and_classes({
401                        const IDS_AND_CLASSES_9898887665724137124: &[IdOrClass] = &[Class(
402                            AzString::from_const_str("__azul-native-frame-content"),
403                        )];
404                        IdOrClassVec::from_const_slice(IDS_AND_CLASSES_9898887665724137124)
405                    })
406                    .with_children(vec![self.content].into()),
407            ]))
408    }
409}