child labels+sprites to inherit on-color from button

This commit is contained in:
galister 2026-07-12 22:56:03 +09:00
parent fb71975019
commit b3e4e37992
9 changed files with 154 additions and 60 deletions

View File

@ -666,13 +666,12 @@ impl View {
let mut com = layout.common(); let mut com = layout.common();
let mut perform = |btn_num: u8, btn: &Rc<ComponentButton>| { let mut perform = |btn_num: u8, btn: &Rc<ComponentButton>| {
let (color, label_color) = if num == btn_num { let color = if num == btn_num {
(WguiColorName::Primary, WguiColorName::OnPrimary) WguiColorName::Primary
} else { } else {
(WguiColorName::BackgroundVariant, WguiColorName::OnBackgroundVariant) WguiColorName::BackgroundVariant
}; };
btn.set_color(&mut com, color.into()); btn.set_color(&mut com, color.into());
btn.set_label_color(&mut com, label_color.into());
}; };
perform(0, &self.btn_sinks); perform(0, &self.btn_sinks);

View File

@ -95,7 +95,8 @@
</template> </template>
<macro name="button_style" border="2" round="6" <macro name="button_style" border="2" round="6"
align_items="center" justify_content="center" padding="6" width="60" height="60" overflow="visible"/> align_items="center" justify_content="center" padding="6" width="60" height="60" overflow="visible"
sticky_color="primary" sticky_border_color="primary(rgb-mult-0.5)" hover_color="tertiary" hover_border_color="tertiary(rgb-mult-0.5)" />
<macro name="bg_rect" width="100%" color="background_contrast" round="10" border="2" border_color="primary" /> <macro name="bg_rect" width="100%" color="background_contrast" round="10" border="2" border_color="primary" />
@ -198,9 +199,9 @@
<template name="Clock"> <template name="Clock">
<div flex_direction="column" gap="3" align_items="center"> <div flex_direction="column" gap="3" align_items="center">
<label text="23:59" _source="clock" _display="time" size="21" weight="bold" /> <label text="23:59" _source="clock" _display="time" size="21" weight="bold" color="primary" />
<label text="Tuesday" _source="clock" _display="dow" size="15" /> <label text="Tuesday" _source="clock" _display="dow" size="15" color="on_background_variant" />
<label text="22/2/2022" _source="clock" _display="date" size="15" /> <label text="22/2/2022" _source="clock" _display="date" size="15" color="on_background_variant" />
</div> </div>
</template> </template>

View File

@ -11,7 +11,8 @@
padding="8" color="background" padding="8" color="background"
border="2" border_color="outline" round="8" /> border="2" border_color="outline" round="8" />
<macro name="button_style" padding="8" border="2" round="8" align_items="center" justify_content="center" sticky_color="primary" sticky_border_color="primary(rgb-mult-0.5)" hover_color="tertiary" hover_border_color="tertiary(rgb-mult-0.5)" /> <macro name="button_style" padding="8" border="2" round="8" align_items="center" justify_content="center"
sticky_color="primary" sticky_border_color="primary(rgb-mult-0.5)" hover_color="tertiary" hover_border_color="tertiary(rgb-mult-0.5)" />
<template name="Device"> <template name="Device">
<rectangle macro="decorative_rect" padding_top="4" padding_bottom="4" align_items="center" gap="8"> <rectangle macro="decorative_rect" padding_top="4" padding_bottom="4" align_items="center" gap="8">
@ -74,8 +75,8 @@
<div flex_direction="column" > <div flex_direction="column" >
<label text="11:22 PM" _source="clock" _display="time" color="on_background" size="~clock0_size" weight="bold" align="center" /> <label text="11:22 PM" _source="clock" _display="time" color="on_background" size="~clock0_size" weight="bold" align="center" />
<div padding_left="2" gap="16" flex_direction="row" justify_content="center"> <div padding_left="2" gap="16" flex_direction="row" justify_content="center">
<label text="Tue" _source="clock" _display="dow_short" color="on_background" size="~clock0_dow_size" weight="bold" /> <label text="Tue" _source="clock" _display="dow_short" color="on_background_variant" size="~clock0_dow_size" weight="bold" />
<label text="22/2/2022" _source="clock" _display="date" color="on_background" size="~clock0_date_size" weight="bold" /> <label text="22/2/2022" _source="clock" _display="date" color="on_background_variant" size="~clock0_date_size" weight="bold" />
</div> </div>
</div> </div>
<div flex_direction="row" gap="8" justify_content="space_around"> <div flex_direction="row" gap="8" justify_content="space_around">

View File

@ -1,6 +1,7 @@
<layout> <layout>
<macro name="button_style" border="2" round="6" <macro name="button_style" border="2" round="6"
align_items="center" justify_content="center" padding="6" width="60" height="60" overflow="visible"/> align_items="center" justify_content="center" padding="6" width="60" height="60" overflow="visible"
sticky_color="primary" sticky_border_color="primary(rgb-mult-0.5)" hover_color="tertiary" hover_border_color="tertiary(rgb-mult-0.5)" />
<macro name="bg_rect" width="100%" color="background" border_color="outline" round="10" border="2" /> <macro name="bg_rect" width="100%" color="background" border_color="outline" round="10" border="2" />

View File

@ -118,9 +118,30 @@ impl WguiColor {
c1.lerp(&c2, val).into() c1.lerp(&c2, val).into()
} }
} }
pub fn on_color(&self) -> Option<Self> {
if let Self::Named(name) = self {
name.name.on_color().map(|x| x.into())
} else {
None
}
}
} }
impl WguiColorName { impl WguiColorName {
pub fn on_color(&self) -> Option<Self> {
match self {
Self::Primary => Some(Self::OnPrimary),
Self::Secondary => Some(Self::OnSecondary),
Self::Tertiary => Some(Self::OnTertiary),
Self::Danger => Some(Self::OnDanger),
Self::Background => Some(Self::OnBackground),
Self::BackgroundVariant => Some(Self::OnBackgroundVariant),
Self::BackgroundContrast => Some(Self::OnBackgroundContrast),
_ => None,
}
}
pub const fn to_wgui_color(&self) -> WguiColor { pub const fn to_wgui_color(&self) -> WguiColor {
WguiColor::Named(WguiNamedColor { WguiColor::Named(WguiNamedColor {
name: *self, name: *self,

View File

@ -3,35 +3,34 @@ use crate::{
assets::AssetPath, assets::AssetPath,
color::{WguiColor, WguiColorName}, color::{WguiColor, WguiColorName},
components::{ components::{
self, self, Component, ComponentBase, ComponentTrait, RefreshData,
tooltip::{ComponentTooltip, TooltipTrait}, tooltip::{ComponentTooltip, TooltipTrait},
Component, ComponentBase, ComponentTrait, RefreshData,
}, },
drawing::{self, Boundary}, drawing::{self, Boundary},
event::{CallbackDataCommon, EventListenerCollection, EventListenerID, EventListenerKind}, event::{CallbackDataCommon, EventListenerCollection, EventListenerID, EventListenerKind},
i18n::Translation, i18n::Translation,
layout::{WidgetID, WidgetPair}, layout::{WidgetID, WidgetPair},
renderer_vk::{ renderer_vk::{
text::{custom_glyph::CustomGlyphData, FontWeight, TextStyle}, text::{FontWeight, TextStyle, custom_glyph::CustomGlyphData},
util::centered_matrix, util::centered_matrix,
}, },
sound::WguiSoundType, sound::WguiSoundType,
widget::{ widget::{
self, self, ConstructEssentials, EventResult, WidgetData,
label::{WidgetLabel, WidgetLabelParams}, label::{WidgetLabel, WidgetLabelParams},
rectangle::{WidgetRectangle, WidgetRectangleParams}, rectangle::{WidgetRectangle, WidgetRectangleParams},
sprite::{WidgetSprite, WidgetSpriteParams}, sprite::{WidgetSprite, WidgetSpriteParams},
util::WLength, util::WLength,
ConstructEssentials, EventResult, WidgetData,
}, },
}; };
use glam::{Mat4, Vec2, Vec3}; use glam::{Mat4, Vec2, Vec3};
use slotmap::Key;
use std::{ use std::{
cell::RefCell, cell::RefCell,
rc::Rc, rc::Rc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use taffy::{prelude::length, AlignItems, JustifyContent}; use taffy::{AlignItems, JustifyContent, prelude::length};
pub struct Params<'a> { pub struct Params<'a> {
pub text: Option<Translation>, // if unset, label will not be populated pub text: Option<Translation>, // if unset, label will not be populated
@ -102,6 +101,9 @@ struct State {
active_tooltip: Option<Rc<ComponentTooltip>>, active_tooltip: Option<Rc<ComponentTooltip>>,
colors: Colors, colors: Colors,
last_pressed: Instant, last_pressed: Instant,
id_label: WidgetID, // Label
id_sprite: WidgetID, // Sprite
children_discovered: bool,
} }
impl TooltipTrait for State { impl TooltipTrait for State {
@ -111,8 +113,7 @@ impl TooltipTrait for State {
} }
struct Data { struct Data {
id_label: WidgetID, // Label id_rect: WidgetID, // Rectangle
id_rect: WidgetID, // Rectangle
sticky: bool, sticky: bool,
} }
@ -134,6 +135,44 @@ impl ComponentTrait for ComponentButton {
fn refresh(&self, data: &mut RefreshData) { fn refresh(&self, data: &mut RefreshData) {
let mut state = self.state.borrow_mut(); let mut state = self.state.borrow_mut();
if !state.children_discovered {
state.children_discovered = true;
let mut children = vec![];
data
.layout
.collect_children_ids_recursive(self.data.id_rect, &mut children);
for (child, _) in children {
if let Some(mut widget) = data.layout.state.widgets.get_as::<WidgetSprite>(child) {
if !state.id_sprite.is_null() {
log::error!("Button with more than one sprite!");
}
// apply initial color from button
if let Some(on_color) = state.colors.color.on_color() {
let common = &mut CallbackDataCommon {
state: &data.layout.state,
alterables: &mut data.layout.alterables,
};
widget.set_color(common, on_color);
}
state.id_sprite = child;
} else if let Some(mut widget) = data.layout.state.widgets.get_as::<WidgetLabel>(child) {
if !state.id_label.is_null() {
log::error!("Button with more than one label!");
}
if let Some(on_color) = state.colors.color.on_color() {
let common = &mut CallbackDataCommon {
state: &data.layout.state,
alterables: &mut data.layout.alterables,
};
widget.set_color(common, on_color, true);
}
state.id_label = child;
}
}
}
if state.active_tooltip.is_some() { if state.active_tooltip.is_some() {
let l_state = &data.layout.state; let l_state = &data.layout.state;
if let Some(node_id) = l_state.nodes.get(self.base.get_id()) { if let Some(node_id) = l_state.nodes.get(self.base.get_id()) {
@ -152,16 +191,13 @@ fn get_color2(color: &WguiColor, gradient_intensity: f32) -> WguiColor {
} }
impl ComponentButton { impl ComponentButton {
pub fn get_label(&self) -> WidgetID {
self.data.id_label
}
pub fn get_rect(&self) -> WidgetID { pub fn get_rect(&self) -> WidgetID {
self.data.id_rect self.data.id_rect
} }
pub fn set_text(&self, common: &mut CallbackDataCommon, text: Translation) { pub fn set_text(&self, common: &mut CallbackDataCommon, text: Translation) {
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(self.data.id_label) else { let state = self.state.borrow();
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(state.id_label) else {
return; return;
}; };
@ -179,13 +215,15 @@ impl ComponentButton {
let mut state = self.state.borrow_mut(); let mut state = self.state.borrow_mut();
state.colors.color = color; state.colors.color = color;
}
pub fn set_label_color(&self, common: &mut CallbackDataCommon, color: WguiColor) { if let Some(on_color) = color.on_color() {
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(self.data.id_label) else { if let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(state.id_label) {
return; label.set_color(common, on_color, true);
}; }
label.set_color(common, color, true); if let Some(mut sprite) = common.state.widgets.get_as::<WidgetSprite>(state.id_sprite) {
sprite.set_color(common, on_color);
}
}
} }
pub fn get_time_since_last_pressed(&self) -> Duration { pub fn get_time_since_last_pressed(&self) -> Duration {
@ -234,19 +272,32 @@ impl ComponentButton {
let state = state.borrow(); let state = state.borrow();
let colors = &state.colors; let colors = &state.colors;
let (alt_color, alt_border_color) = if sticky_down {
(&colors.sticky_color, &colors.sticky_border_color)
} else {
(&colors.hover_color, &colors.hover_border_color)
};
{ {
let bgcolor = if sticky_down { let bgcolor = colors.color.lerp(&common.globals().palette, alt_color, mult);
colors.color.lerp(&common.globals().palette, &colors.sticky_color, mult)
} else { rect.params.color = bgcolor;
colors.color.lerp(&common.globals().palette, &colors.hover_color, mult * 0.5) rect.params.color2 = get_color2(&bgcolor, gradient_intensity);
}; rect.params.border_color = colors
rect.params.color = bgcolor; .border_color
rect.params.color2 = get_color2(&bgcolor, gradient_intensity); .lerp(&common.globals().palette, alt_border_color, mult);
rect.params.border_color = if sticky_down {
colors.border_color.lerp(&common.globals().palette, &colors.sticky_border_color, mult) if let Some(on_color0) = colors.color.on_color()
} else { && let Some(on_color1) = alt_color.on_color()
colors.border_color.lerp(&common.globals().palette, &colors.hover_border_color, mult) {
}; let on_color = on_color0.lerp(&common.globals().palette, &on_color1, mult);
if let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(state.id_label) {
label.set_color(common, on_color, true);
}
if let Some(mut sprite) = common.state.widgets.get_as::<WidgetSprite>(state.id_sprite) {
sprite.set_color(common, on_color);
}
}
} }
common.alterables.mark_redraw(); common.alterables.mark_redraw();
}), }),
@ -260,6 +311,8 @@ impl ComponentButton {
fn anim_hover( fn anim_hover(
common: &mut CallbackDataCommon, common: &mut CallbackDataCommon,
rect: &mut WidgetRectangle, rect: &mut WidgetRectangle,
label: WidgetID,
sprite: WidgetID,
widget_data: &mut WidgetData, widget_data: &mut WidgetData,
colors: &Colors, colors: &Colors,
widget_boundary: Boundary, widget_boundary: Boundary,
@ -269,17 +322,26 @@ fn anim_hover(
) { ) {
let mult = pos * if pressed { 1.5 } else { 1.0 }; let mult = pos * if pressed { 1.5 } else { 1.0 };
let globals = common.globals();
let (init_border_color, init_color) = if sticky_down { let (init_border_color, init_color) = if sticky_down {
( (colors.sticky_border_color, colors.sticky_color)
colors.sticky_border_color,
colors.sticky_color,
)
} else { } else {
(colors.border_color, colors.color) (colors.border_color, colors.color)
}; };
if let Some(on_color0) = init_color.on_color()
&& let Some(on_color1) = colors.hover_color.on_color()
{
let on_color = on_color0.lerp(&common.globals().palette, &on_color1, mult);
if let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(label) {
label.set_color(common, on_color, true);
}
if let Some(mut sprite) = common.state.widgets.get_as::<WidgetSprite>(sprite) {
sprite.set_color(common, on_color);
}
}
let globals = common.globals();
let bgcolor = init_color.lerp(&globals.palette, &colors.hover_color, mult); let bgcolor = init_color.lerp(&globals.palette, &colors.hover_color, mult);
let gradient_intensity = common.state.theme.gradient_intensity; let gradient_intensity = common.state.theme.gradient_intensity;
@ -306,6 +368,8 @@ fn anim_hover_create(state: Rc<RefCell<State>>, widget_id: WidgetID, fade_in: bo
anim_hover( anim_hover(
common, common,
rect, rect,
state.id_label,
state.id_sprite,
anim_data.data, anim_data.data,
&state.colors, &state.colors,
anim_data.widget_boundary, anim_data.widget_boundary,
@ -385,6 +449,8 @@ fn register_event_mouse_press(state: Rc<RefCell<State>>, listeners: &mut EventLi
anim_hover( anim_hover(
common, common,
rect, rect,
state.id_label,
state.id_sprite,
event_data.widget_data, event_data.widget_data,
&state.colors, &state.colors,
common.state.get_node_boundary(event_data.node_id), common.state.get_node_boundary(event_data.node_id),
@ -434,6 +500,8 @@ fn register_event_mouse_release(
anim_hover( anim_hover(
common, common,
rect, rect,
state.id_label,
state.id_sprite,
event_data.widget_data, event_data.widget_data,
&state.colors, &state.colors,
common.state.get_node_boundary(event_data.node_id), common.state.get_node_boundary(event_data.node_id),
@ -526,13 +594,13 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
right: length(4.0), right: length(4.0),
}; };
if let Some(sprite_path) = params.sprite_src { let id_sprite = if let Some(sprite_path) = params.sprite_src {
let sprite = WidgetSprite::create(WidgetSpriteParams { let sprite = WidgetSprite::create(WidgetSpriteParams {
glyph_data: Some(CustomGlyphData::from_assets(&ess.layout.state.globals, sprite_path)?), glyph_data: Some(CustomGlyphData::from_assets(&ess.layout.state.globals, sprite_path)?),
color: Some(params.sprite_color.unwrap_or(WguiColorName::OnBackground.into())), color: Some(params.sprite_color.unwrap_or(WguiColorName::OnBackground.into())),
}); });
ess.layout.add_child( let (sprite_pair, _) = ess.layout.add_child(
root.id, root.id,
sprite, sprite,
taffy::Style { taffy::Style {
@ -544,7 +612,11 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
..Default::default() ..Default::default()
}, },
)?; )?;
}
sprite_pair.id
} else {
WidgetID::default()
};
let id_label = if let Some(content) = params.text { let id_label = if let Some(content) = params.text {
let widget_label = WidgetLabel::create( let widget_label = WidgetLabel::create(
@ -573,7 +645,6 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
}; };
let data = Rc::new(Data { let data = Rc::new(Data {
id_label,
id_rect, id_rect,
sticky: params.sticky, sticky: params.sticky,
}); });
@ -593,6 +664,9 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
sticky_color, sticky_color,
sticky_border_color, sticky_border_color,
}, },
id_label,
id_sprite,
children_discovered: false,
})); }));
let base = ComponentBase { let base = ComponentBase {

View File

@ -68,10 +68,8 @@ impl ComponentTrait for ComponentTabs {
fn set_button_selected(common: &mut CallbackDataCommon, button: &Rc<ComponentButton>, selected: bool) { fn set_button_selected(common: &mut CallbackDataCommon, button: &Rc<ComponentButton>, selected: bool) {
if selected { if selected {
button.set_color(common, WguiColorName::Primary.into()); button.set_color(common, WguiColorName::Primary.into());
button.set_label_color(common, WguiColorName::OnPrimary.into());
} else { } else {
button.set_color(common, WguiColorName::Background.into()); button.set_color(common, WguiColorName::Background.into());
button.set_label_color(common, WguiColorName::OnBackground.into());
} }
} }

View File

@ -282,7 +282,7 @@ impl Layout {
}) })
} }
fn collect_children_ids_recursive(&self, widget_id: WidgetID, out: &mut Vec<(WidgetID, taffy::NodeId)>) { pub(crate) fn collect_children_ids_recursive(&self, widget_id: WidgetID, out: &mut Vec<(WidgetID, taffy::NodeId)>) {
let Some(node_id) = self.state.nodes.get(widget_id) else { let Some(node_id) = self.state.nodes.get(widget_id) else {
return; return;
}; };

View File

@ -1,15 +1,14 @@
use crate::{ use crate::{
assets::AssetPath, assets::AssetPath,
color::WguiColor, color::WguiColor,
components::{button, Component}, components::{Component, button},
i18n::Translation, i18n::Translation,
layout::WidgetID, layout::WidgetID,
parser::{ parser::{
get_asset_path_from_kv, AttribPair, ParserContext, ParserFile, get_asset_path_from_kv,
helpers::{parse_attrib_tooltip, TooltipAttribs}, helpers::{TooltipAttribs, parse_attrib_tooltip},
parse_children, parse_f32, process_component, parse_children, parse_f32, process_component,
style::{parse_color_opt, parse_round, parse_style, parse_text_style}, style::{parse_color_opt, parse_round, parse_style, parse_text_style},
AttribPair, ParserContext, ParserFile,
}, },
widget::util::WLength, widget::util::WLength,
}; };