wgui: interactable components, rename TextLabel -> WidgetLabel
This commit is contained in:
@@ -3,15 +3,15 @@ use taffy::{AlignItems, JustifyContent, prelude::length};
|
||||
|
||||
use crate::{
|
||||
animation::{Animation, AnimationEasing},
|
||||
components::{Component, InitData},
|
||||
components::{Component, ComponentTrait, InitData},
|
||||
drawing::{self, Color},
|
||||
event::{EventAlterables, EventListenerCollection, EventListenerKind, ListenerHandleVec},
|
||||
i18n::Translation,
|
||||
layout::{Layout, LayoutState, WidgetID},
|
||||
renderer_vk::text::{FontWeight, TextStyle},
|
||||
widget::{
|
||||
rectangle::{Rectangle, RectangleParams},
|
||||
text::{TextLabel, TextParams},
|
||||
label::{WidgetLabel, WidgetLabelParams},
|
||||
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||
util::WLength,
|
||||
},
|
||||
};
|
||||
@@ -38,9 +38,16 @@ impl Default for Params {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ButtonClickEvent<'a> {
|
||||
pub state: &'a LayoutState,
|
||||
pub alterables: &'a mut EventAlterables,
|
||||
}
|
||||
pub type ButtonClickCallback = Box<dyn Fn(ButtonClickEvent)>;
|
||||
|
||||
struct State {
|
||||
hovered: bool,
|
||||
down: bool,
|
||||
on_click: Option<ButtonClickCallback>,
|
||||
}
|
||||
|
||||
struct Data {
|
||||
@@ -59,27 +66,30 @@ pub struct ComponentButton {
|
||||
listener_handles: ListenerHandleVec,
|
||||
}
|
||||
|
||||
impl Component for ComponentButton {
|
||||
impl ComponentTrait for ComponentButton {
|
||||
fn init(&self, _data: &mut InitData) {}
|
||||
}
|
||||
|
||||
impl ComponentButton {
|
||||
pub fn set_text(&self, state: &mut LayoutState, text: Translation) {
|
||||
pub fn set_text(&self, state: &LayoutState, alterables: &mut EventAlterables, text: Translation) {
|
||||
let globals = state.globals.clone();
|
||||
|
||||
state
|
||||
.widgets
|
||||
.call(self.data.text_id, |label: &mut TextLabel| {
|
||||
.call(self.data.text_id, |label: &mut WidgetLabel| {
|
||||
label.set_text(&mut globals.i18n(), text);
|
||||
});
|
||||
|
||||
let mut alterables = EventAlterables::default();
|
||||
alterables.mark_redraw();
|
||||
alterables.mark_dirty(self.data.text_node);
|
||||
}
|
||||
|
||||
pub fn on_click(&self, func: ButtonClickCallback) {
|
||||
self.state.borrow_mut().on_click = Some(func);
|
||||
}
|
||||
}
|
||||
|
||||
fn anim_hover(rect: &mut Rectangle, data: &Data, pos: f32) {
|
||||
fn anim_hover(rect: &mut WidgetRectangle, data: &Data, pos: f32) {
|
||||
let brightness = pos * 0.5;
|
||||
let border_brightness = pos;
|
||||
rect.params.color.r = data.initial_color.r + brightness;
|
||||
@@ -97,7 +107,7 @@ fn anim_hover_in(data: Rc<Data>, widget_id: WidgetID) -> Animation {
|
||||
5,
|
||||
AnimationEasing::OutQuad,
|
||||
Box::new(move |common, anim_data| {
|
||||
let rect = anim_data.obj.get_as_mut::<Rectangle>();
|
||||
let rect = anim_data.obj.get_as_mut::<WidgetRectangle>();
|
||||
anim_hover(rect, &data, anim_data.pos);
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
@@ -110,7 +120,7 @@ fn anim_hover_out(data: Rc<Data>, widget_id: WidgetID) -> Animation {
|
||||
8,
|
||||
AnimationEasing::OutQuad,
|
||||
Box::new(move |common, anim_data| {
|
||||
let rect = anim_data.obj.get_as_mut::<Rectangle>();
|
||||
let rect = anim_data.obj.get_as_mut::<WidgetRectangle>();
|
||||
anim_hover(rect, &data, 1.0 - anim_data.pos);
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
@@ -167,7 +177,7 @@ fn register_event_mouse_press<U1, U2>(
|
||||
listener_handles,
|
||||
data.rect_id,
|
||||
EventListenerKind::MousePress,
|
||||
Box::new(move |common, event_data, _, _| {
|
||||
Box::new(move |common, _event_data, _, _| {
|
||||
common.alterables.trigger_haptics();
|
||||
let mut state = state.borrow_mut();
|
||||
|
||||
@@ -196,7 +206,12 @@ fn register_event_mouse_release<U1, U2>(
|
||||
state.down = false;
|
||||
|
||||
if state.hovered {
|
||||
//TODO: click event
|
||||
if let Some(on_click) = &state.on_click {
|
||||
on_click(ButtonClickEvent {
|
||||
state: common.state,
|
||||
alterables: &mut common.alterables,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
@@ -220,7 +235,7 @@ pub fn construct<U1, U2>(
|
||||
|
||||
let (rect_id, _) = layout.add_child(
|
||||
parent,
|
||||
Rectangle::create(RectangleParams {
|
||||
WidgetRectangle::create(WidgetRectangleParams {
|
||||
color: params.color,
|
||||
color2: params
|
||||
.color
|
||||
@@ -237,9 +252,9 @@ pub fn construct<U1, U2>(
|
||||
|
||||
let (text_id, text_node) = layout.add_child(
|
||||
rect_id,
|
||||
TextLabel::create(
|
||||
WidgetLabel::create(
|
||||
&mut globals.i18n(),
|
||||
TextParams {
|
||||
WidgetLabelParams {
|
||||
content: params.text,
|
||||
style: TextStyle {
|
||||
weight: Some(FontWeight::Bold),
|
||||
@@ -268,6 +283,7 @@ pub fn construct<U1, U2>(
|
||||
let state = Rc::new(RefCell::new(State {
|
||||
down: false,
|
||||
hovered: false,
|
||||
on_click: None,
|
||||
}));
|
||||
|
||||
let mut lhandles = ListenerHandleVec::default();
|
||||
@@ -283,6 +299,6 @@ pub fn construct<U1, U2>(
|
||||
listener_handles: lhandles,
|
||||
});
|
||||
|
||||
layout.defer_component_init(button.clone());
|
||||
layout.defer_component_init(Component(button.clone()));
|
||||
Ok(button)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::{any::AnyTrait, event::EventAlterables, layout::LayoutState};
|
||||
|
||||
pub mod button;
|
||||
@@ -8,6 +10,26 @@ pub struct InitData<'a> {
|
||||
pub alterables: &'a mut EventAlterables,
|
||||
}
|
||||
|
||||
pub trait Component: AnyTrait {
|
||||
pub trait ComponentTrait: AnyTrait {
|
||||
fn init(&self, data: &mut InitData);
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Component(pub Rc<dyn ComponentTrait>);
|
||||
|
||||
pub type ComponentWeak = std::rc::Weak<dyn ComponentTrait>;
|
||||
|
||||
impl Component {
|
||||
pub fn weak(&self) -> ComponentWeak {
|
||||
Rc::downgrade(&self.0)
|
||||
}
|
||||
|
||||
pub fn try_cast<T: 'static>(&self) -> anyhow::Result<Rc<T>> {
|
||||
if !(*self.0).as_any().is::<T>() {
|
||||
anyhow::bail!("try_cast: type not matching");
|
||||
}
|
||||
|
||||
// safety: we already checked it above, should be safe to directly cast it
|
||||
unsafe { Ok(Rc::from_raw(Rc::into_raw(self.0.clone()) as _)) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use taffy::prelude::{length, percent};
|
||||
|
||||
use crate::{
|
||||
animation::{Animation, AnimationEasing},
|
||||
components::{Component, InitData},
|
||||
components::{Component, ComponentTrait, InitData},
|
||||
drawing::{self},
|
||||
event::{
|
||||
self, CallbackDataCommon, EventAlterables, EventListenerCollection, EventListenerKind,
|
||||
@@ -18,9 +18,9 @@ use crate::{
|
||||
util,
|
||||
},
|
||||
widget::{
|
||||
div::Div,
|
||||
rectangle::{Rectangle, RectangleParams},
|
||||
text::{TextLabel, TextParams},
|
||||
div::WidgetDiv,
|
||||
label::{WidgetLabel, WidgetLabelParams},
|
||||
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||
util::WLength,
|
||||
},
|
||||
};
|
||||
@@ -70,7 +70,7 @@ pub struct ComponentSlider {
|
||||
listener_handles: ListenerHandleVec,
|
||||
}
|
||||
|
||||
impl Component for ComponentSlider {
|
||||
impl ComponentTrait for ComponentSlider {
|
||||
fn init(&self, init_data: &mut InitData) {
|
||||
let mut state = self.state.borrow_mut();
|
||||
let value = state.values.value;
|
||||
@@ -129,7 +129,7 @@ impl State {
|
||||
self.set_value(common.state, data, common.alterables, val);
|
||||
}
|
||||
|
||||
fn update_text(&self, i18n: &mut I18n, text: &mut TextLabel, value: f32) {
|
||||
fn update_text(&self, i18n: &mut I18n, text: &mut WidgetLabel, value: f32) {
|
||||
// round displayed value, should be sufficient for now
|
||||
text.set_text(
|
||||
i18n,
|
||||
@@ -153,7 +153,7 @@ impl State {
|
||||
alterables.set_style(data.slider_handle_node, style);
|
||||
state
|
||||
.widgets
|
||||
.call(data.slider_text_id, |label: &mut TextLabel| {
|
||||
.call(data.slider_text_id, |label: &mut WidgetLabel| {
|
||||
self.update_text(&mut state.globals.i18n(), label, value);
|
||||
});
|
||||
}
|
||||
@@ -174,7 +174,7 @@ fn get_anim_transform(pos: f32, widget_size: Vec2) -> Mat4 {
|
||||
)
|
||||
}
|
||||
|
||||
fn anim_rect(rect: &mut Rectangle, pos: f32) {
|
||||
fn anim_rect(rect: &mut WidgetRectangle, pos: f32) {
|
||||
rect.params.color = drawing::Color::lerp(&HANDLE_COLOR, &HANDLE_COLOR_HOVERED, pos);
|
||||
rect.params.border_color =
|
||||
drawing::Color::lerp(&HANDLE_BORDER_COLOR, &HANDLE_BORDER_COLOR_HOVERED, pos);
|
||||
@@ -186,7 +186,7 @@ fn on_enter_anim(common: &mut event::CallbackDataCommon, handle_id: WidgetID) {
|
||||
20,
|
||||
AnimationEasing::OutBack,
|
||||
Box::new(move |common, data| {
|
||||
let rect = data.obj.get_as_mut::<Rectangle>();
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>();
|
||||
data.data.transform = get_anim_transform(data.pos, data.widget_size);
|
||||
anim_rect(rect, data.pos);
|
||||
common.alterables.mark_redraw();
|
||||
@@ -200,7 +200,7 @@ fn on_leave_anim(common: &mut event::CallbackDataCommon, handle_id: WidgetID) {
|
||||
10,
|
||||
AnimationEasing::OutQuad,
|
||||
Box::new(move |common, data| {
|
||||
let rect = data.obj.get_as_mut::<Rectangle>();
|
||||
let rect = data.obj.get_as_mut::<WidgetRectangle>();
|
||||
data.data.transform = get_anim_transform(1.0 - data.pos, data.widget_size);
|
||||
anim_rect(rect, 1.0 - data.pos);
|
||||
common.alterables.mark_redraw();
|
||||
@@ -318,11 +318,11 @@ pub fn construct<U1, U2>(
|
||||
style.min_size = style.size;
|
||||
style.max_size = style.size;
|
||||
|
||||
let (body_id, slider_body_node) = layout.add_child(parent, Div::create()?, style)?;
|
||||
let (body_id, slider_body_node) = layout.add_child(parent, WidgetDiv::create()?, style)?;
|
||||
|
||||
let (_background_id, _) = layout.add_child(
|
||||
body_id,
|
||||
Rectangle::create(RectangleParams {
|
||||
WidgetRectangle::create(WidgetRectangleParams {
|
||||
color: BODY_COLOR,
|
||||
round: WLength::Percent(1.0),
|
||||
border_color: BODY_BORDER_COLOR,
|
||||
@@ -361,11 +361,11 @@ pub fn construct<U1, U2>(
|
||||
|
||||
// invisible outer handle body
|
||||
let (slider_handle_id, slider_handle_node) =
|
||||
layout.add_child(body_id, Div::create()?, slider_handle_style)?;
|
||||
layout.add_child(body_id, WidgetDiv::create()?, slider_handle_style)?;
|
||||
|
||||
let (slider_handle_rect_id, _) = layout.add_child(
|
||||
slider_handle_id,
|
||||
Rectangle::create(RectangleParams {
|
||||
WidgetRectangle::create(WidgetRectangleParams {
|
||||
color: HANDLE_COLOR,
|
||||
border_color: HANDLE_BORDER_COLOR,
|
||||
border: 2.0,
|
||||
@@ -393,9 +393,9 @@ pub fn construct<U1, U2>(
|
||||
|
||||
let (slider_text_id, _) = layout.add_child(
|
||||
slider_handle_id,
|
||||
TextLabel::create(
|
||||
WidgetLabel::create(
|
||||
&mut i18n,
|
||||
TextParams {
|
||||
WidgetLabelParams {
|
||||
content: Translation::default(),
|
||||
style: TextStyle {
|
||||
weight: Some(FontWeight::Bold),
|
||||
@@ -432,6 +432,6 @@ pub fn construct<U1, U2>(
|
||||
listener_handles: lhandles,
|
||||
});
|
||||
|
||||
layout.defer_component_init(slider.clone());
|
||||
layout.defer_component_init(Component(slider.clone()));
|
||||
Ok(slider)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user