implement listeners for Button component back

This commit is contained in:
Aleksander
2025-06-28 18:30:38 +02:00
parent 2420e8007c
commit 28d58fef59
6 changed files with 65 additions and 26 deletions

View File

@@ -2,10 +2,10 @@ use std::sync::Arc;
use taffy::{AlignItems, JustifyContent, prelude::length};
use crate::{
animation::{Animation, AnimationEasing},
animation::{self, Animation, AnimationEasing},
components::Component,
drawing::{self, Color},
event::WidgetCallback,
event::{EventListenerCollection, EventListenerKind, WidgetCallback},
layout::{Layout, WidgetID},
renderer_vk::text::{FontWeight, TextStyle},
widget::{
@@ -38,7 +38,8 @@ impl Default for Params<'_> {
}
pub struct Button {
pub color: drawing::Color,
initial_color: drawing::Color,
initial_border_color: drawing::Color,
pub body: WidgetID, // Rectangle
pub text_id: WidgetID, // Text
text_node: taffy::NodeId,
@@ -59,6 +60,18 @@ impl Button {
}
}
fn anim_hover(rect: &mut Rectangle, button: &Button, pos: f32) {
let brightness = pos * 0.5;
let border_brightness = pos;
rect.params.color.r = button.initial_color.r + brightness;
rect.params.color.g = button.initial_color.g + brightness;
rect.params.color.b = button.initial_color.b + brightness;
rect.params.border_color.r = button.initial_border_color.r + border_brightness;
rect.params.border_color.g = button.initial_border_color.g + border_brightness;
rect.params.border_color.b = button.initial_border_color.b + border_brightness;
rect.params.border = 3.0;
}
fn anim_hover_in(button: Arc<Button>, widget_id: WidgetID) -> Animation {
Animation::new(
widget_id,
@@ -66,12 +79,7 @@ fn anim_hover_in(button: Arc<Button>, widget_id: WidgetID) -> Animation {
AnimationEasing::OutQuad,
Box::new(move |data| {
let rect = data.obj.get_as_mut::<Rectangle>();
let brightness = data.pos * 0.5;
rect.params.color.r = button.color.r + brightness;
rect.params.color.g = button.color.g + brightness;
rect.params.color.b = button.color.b + brightness;
rect.params.border_color = Color::new(1.0, 1.0, 1.0, 1.0);
rect.params.border = 1.0 + data.pos;
anim_hover(rect, &button, data.pos);
data.needs_redraw = true;
}),
)
@@ -84,12 +92,7 @@ fn anim_hover_out(button: Arc<Button>, widget_id: WidgetID) -> Animation {
AnimationEasing::OutQuad,
Box::new(move |data| {
let rect = data.obj.get_as_mut::<Rectangle>();
let brightness = (1.0 - data.pos) * 0.5;
rect.params.color.r = button.color.r + brightness;
rect.params.color.g = button.color.g + brightness;
rect.params.color.b = button.color.b + brightness;
rect.params.border_color = Color::new(1.0, 1.0, 1.0, 1.0);
rect.params.border = 1.0 + (1.0 - data.pos) * 2.0;
anim_hover(rect, &button, 1.0 - data.pos);
data.needs_redraw = true;
}),
)
@@ -97,6 +100,7 @@ fn anim_hover_out(button: Arc<Button>, widget_id: WidgetID) -> Animation {
pub fn construct(
layout: &mut Layout,
listeners: &mut EventListenerCollection<(), ()>,
parent: WidgetID,
params: Params,
) -> anyhow::Result<Arc<Button>> {
@@ -142,14 +146,35 @@ pub fn construct(
let button = Arc::new(Button {
body: rect_id,
color: params.color,
text_id,
text_node,
initial_color: params.color,
initial_border_color: params.border_color,
});
//TODO: Highlight background on mouse enter
//let mut widget = layout.widget_map.get(rect_id).unwrap().lock().unwrap();
//TODO: Bring back old color on mouse leave
let _button = button.clone();
listeners.add(
rect_id,
EventListenerKind::MouseEnter,
Box::new(move |data, _, _| {
data
.animations
.push(anim_hover_in(_button.clone(), data.widget_id));
}),
);
let _button = button.clone();
listeners.add(
rect_id,
EventListenerKind::MouseLeave,
Box::new(move |data, _, _| {
data
.animations
.push(anim_hover_out(_button.clone(), data.widget_id));
}),
);
Ok(button)
}

View File

@@ -45,6 +45,7 @@ pub fn parse_component_button<'a>(
let button = button::construct(
ctx.layout,
ctx.listeners,
parent_id,
button::Params {
color,

View File

@@ -8,6 +8,7 @@ mod widget_sprite;
use crate::{
assets::AssetProvider,
drawing::{self},
event::EventListenerCollection,
layout::{Layout, WidgetID},
parser::{
component_button::parse_component_button, widget_div::parse_widget_div,
@@ -62,6 +63,7 @@ impl ParserResult {
&mut self,
template_name: &str,
layout: &mut Layout,
listeners: &mut EventListenerCollection<(), ()>,
widget_id: WidgetID,
template_parameters: HashMap<Rc<str>, Rc<str>>,
) -> anyhow::Result<()> {
@@ -71,6 +73,7 @@ impl ParserResult {
let mut ctx = ParserContext {
layout,
listeners,
ids: Default::default(),
macro_attribs: self.macro_attribs.clone(), // FIXME: prevent copying
var_map: self.var_map.clone(), // FIXME: prevent copying
@@ -107,6 +110,7 @@ struct MacroAttribs {
struct ParserContext<'a> {
layout: &'a mut Layout,
listeners: &'a mut EventListenerCollection<(), ()>,
var_map: HashMap<Rc<str>, Rc<str>>,
macro_attribs: HashMap<Rc<str>, MacroAttribs>,
ids: HashMap<Rc<str>, WidgetID>,
@@ -557,9 +561,13 @@ fn parse_children<'a>(
Ok(())
}
fn create_default_context(layout: &mut Layout) -> ParserContext<'_> {
fn create_default_context<'a>(
layout: &'a mut Layout,
listeners: &'a mut EventListenerCollection<(), ()>,
) -> ParserContext<'a> {
ParserContext {
layout,
listeners,
ids: Default::default(),
var_map: Default::default(),
templates: Default::default(),
@@ -569,12 +577,13 @@ fn create_default_context(layout: &mut Layout) -> ParserContext<'_> {
pub fn parse_from_assets(
layout: &mut Layout,
listeners: &mut EventListenerCollection<(), ()>,
parent_id: WidgetID,
path: &str,
) -> anyhow::Result<ParserResult> {
let path = PathBuf::from(path);
let mut ctx = create_default_context(layout);
let mut ctx = create_default_context(layout, listeners);
let (file, node_layout) = get_doc_from_path(&mut ctx, &path)?;
parse_document_root(file, &mut ctx, parent_id, node_layout)?;
@@ -595,11 +604,12 @@ pub fn parse_from_assets(
pub fn new_layout_from_assets(
assets: Box<dyn AssetProvider>,
listeners: &mut EventListenerCollection<(), ()>,
path: &str,
) -> anyhow::Result<(Layout, ParserResult)> {
let mut layout = Layout::new(assets)?;
let widget = layout.root_widget;
let state = parse_from_assets(&mut layout, widget, path)?;
let state = parse_from_assets(&mut layout, listeners, widget, path)?;
Ok((layout, state))
}