WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Better styling: per-widget styles #7586

@emilk

Description

@emilk

As a step towards better stylling I want to introduce per-widget styling options.

Code (outline)

/// For generic widgets, that dont have/need their own style struct.
/// Also used by 3rd party widgets.
pub struct WidgetStyle {
    /// Background color, stroke, margin, and shadow.
    pub frame: Frame,

    /// How text looks like
    pub text: TextVisuals,

    /// Color and width of e.g. checkbox checkmark.
    pub stroke: Stroke
}

pub struct ButtonStyle {
    pub frame: Frame,
    pub text: TextVisuals,
}

pub struct CheckboxStyle {
    // frame/margin around checkbox and text
    pub frame: Frame,

    pub text: TextVisuals,

    pub checkbox_width: f32,

    /// How the box is painted
    pub checkbox_frame: Frame,

    /// How the check is painted
    pub stroke: Stroke,
}

pub struct SeparatorSyle {
    /// How much space it allocated
    pub size: f32,

    /// How to paint it
    pub stroke: Stroke,
}

…etc.

I'm referencing a new struct TextVisuals here:

struct TextVisuals {
    pub font_id: FontId,
    pub color: Color32,
    // In the future we can expand this to be more like `epaint::TextFormat`.
}

Let's also introduce a new enum:

pub enum WidgetState {
    /// This type of widget cannot be interacted with
    Noninteractive,

    /// An interactive widget that is not being interacted with
    Inactive,

    /// An interactive widget that is being hovered
    Hovered,
    
    /// An interactive widget that is being clicked or dragged
    Active,   
}

We then change e.g. checkbox.rs to query egui::Style about its CheckboxStyle:

let id = ui.next_auto_id(); // so we can read the interact state before the interaction
let response: OptionResponse = ui.ctx().read_response(id);
let state: WidgetState = response.map(|r| r.widget_state()).unwrap_or(WidgetState::Inactive);
let style: CheckboxStyle = ui.style().checkbox_style(state);
// format text according to `style.text`
// allocate space according to size of galley, and all the margins in `style`
// paint everything

This is an important change from how styles are currently computed!
Instead of having a fixed size and then only having different colors based on the response, we can now (theoretically) support widgets that grow when hovered.

However, as a start we can just hardcode checkbox_style:

impl Style {
    pub fn widget_style(&self, state: WidgetState) -> WidgetStyle {
        // … hard-coded based on WidgetVisuals. We will trait-ify this later!
     }

    fn checkbox_style(&self, state: WidgetState)  -> CheckboxStyle {
        let ws = self.widget_style(state);
        // use the above as a basis, and fill in the rest of CheckboxStyle
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    stylevisuals and theming

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions