Skip to content

Allow specifying a custom Frame on each widget and container #7445

@emilk

Description

@emilk

Related

Description

It's very useful to be able to set an inner and outer margin on any one widget or container. For instance: add some inner margin to a ScrollArea, or an outer margin to a Button.

In the limit we would like to do so via some style engine plugin (#3284), but being able to just set a Frame on a ScrollArea etc explicitly or in a hard-coded Style would already be a very useful feature.

Making Frame and UiBuilder compose

Adding a UiBuilder::frame(…) would be very useful.

Example code (copied from #4019)

Add a min_size to Frame

/// A frame around some content, including margin and border colors.
/// 
/// The total (outer) size of a frame is
/// `content_size + inner_margin + border.stroke.width + outer_margin`.
/// 
/// Everything within the border stroke is filled with the border fill color (if any).
/// 
/// ```
/// +---------------^-------------------------------+
/// |               | outer_margin                  |
/// |   +-----------v----^-----------------------+  |
/// |   |                | border stroke width   |  |
/// |   |  +-------------v---^----------------+  |  |
/// |   |  |                 | inner_margin   |  |  |
/// |   |  |  +--------------v-------------+  |  |  |
/// |   |  |  |                            |  |  |  |
/// |   |  |  |                            |  |  |  |
/// |   |  |  | content rect               |  |  |  |
/// |   |  |  +----------------------------+  |  |  |
/// |   |  |                                  |  |  |
/// |   |  +----------------------------------+  |  |
/// |   |       widget rect                      |  |
/// |   +----------------------------------------+  |
/// |           outer rect                          |
/// +-----------------------------------------------+
/// ```
/// 
/// `widget rect` is the interactive part of the widget (what sense clicks etc),
/// and is what is returned by [`Response::rect`].
struct Frame {
    /// Inner spacing. Called `padding` in CSS.
    pub inner_margin: Margin,

    /// Stroke, fill color etc.
    ///
    /// The width of the border is counted as part of the size of the frame.
    pub border: Border,

    /// Optional drop-shadow.
    /// Does not affect margins or sizes.
    pub shadow: Shadow,

    /// Outer spacing. Called `margin` in CSS.
    /// 
    /// This does NOT do "Margin Collapse" like in CSS,
    /// i.e. when placing two frames next to each other,
    /// the distance between their borders is the SUM
    /// of their other margin.
    /// In CSS the distance would be the MAX of their outer margins.
    ///
    /// Supporting margin collapse is difficult, and would 
    /// requires complicating the already complicated egui layout code.
    /// 
    /// Consider using [`egui::Spacing::item_spacing`] instead
    /// for adding space between widgets.
    pub outer_margin:  Margin,

    /// The inner rectangle must be at least this size.
    pub min_size: Vec2,
}

/// Stroke, fill, rounding, etc.
/// 
/// Controls the look of widgets and [`RectShape`].
///
/// Similar to a CSS border.
struct Border {
    /// Fills the content and inner padding of a [`Frame`].
    ///
    /// In CSS this is called `background`.
    pub fill: Color32,

    pub stroke: Stroke,

    pub rounding: Rounding,

    // TODO: add texturing here eventually
}

struct RectShape {
    /// The rectangle on which edge the border stroke is painted.
    pub rect: Rect,

    pub border: Border,

    // TODO: consider moving these into `Border`.
    // Care must be taken so that `Border` and `Frame` doesn't become too huge in common cases,
    // i.e. when there is no texture, and the rounding is uniform.
    pub fill_texture_id: TextureId,
    pub uv: Rect,
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    eguistylevisuals and theming

    Projects

    Status

    Next up

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions