wgui: interactable components, rename TextLabel -> WidgetLabel
This commit is contained in:
@@ -8,12 +8,16 @@
|
|||||||
<label text="Raw text" color="#FFFFFF" />
|
<label text="Raw text" color="#FFFFFF" />
|
||||||
<label translation="TESTBED.HELLO_WORLD" color="#FFFFFF" />
|
<label translation="TESTBED.HELLO_WORLD" color="#FFFFFF" />
|
||||||
|
|
||||||
|
<div margin_left="16" gap="8" flex_direction="column">
|
||||||
|
<label id="label_current_option" text="Click any of these buttons" size="20" weight="bold" />
|
||||||
|
<div>
|
||||||
|
<button id="button_red" text="Red button" width="220" height="32" color="#FF0000" />
|
||||||
|
<button id="button_aqua" text="Aqua button" width="220" height="32" color="#00FFFF" />
|
||||||
|
<button id="button_yellow" text="Yellow button" width="220" height="32" color="#FFFF00" />
|
||||||
|
</div>
|
||||||
|
<button id="button_click_me" text="Click me" width="128" height="24" color="#FFFFFF" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<label id="label_current_option" />
|
|
||||||
|
|
||||||
<button margin_left="16" id="button_red" text="Red button" width="128" height="32" color="#FF0000" />
|
|
||||||
<button margin_left="16" id="button_aqua" text="Aqua button" width="128" height="32" color="#00FFFF" />
|
|
||||||
<button margin_left="16" id="button_yellow" text="Yellow button" width="128" height="32" color="#FFFF00" />
|
|
||||||
|
|
||||||
<div flex_direction="row" gap="16">
|
<div flex_direction="row" gap="16">
|
||||||
<div flex_direction="column" gap="8">
|
<div flex_direction="column" gap="8">
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
render_context.update_viewport(&mut shared_context, swapchain_size, scale)?;
|
render_context.update_viewport(&mut shared_context, swapchain_size, scale)?;
|
||||||
println!("new swapchain_size: {swapchain_size:?}");
|
println!("new swapchain_size: {swapchain_size:?}");
|
||||||
|
|
||||||
let mut profiler = profiler::Profiler::new(100);
|
let mut profiler = profiler::Profiler::new(1000);
|
||||||
let mut frame_index: u64 = 0;
|
let mut frame_index: u64 = 0;
|
||||||
|
|
||||||
let mut timestep = Timestep::new();
|
let mut timestep = Timestep::new();
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::{assets, testbed::Testbed};
|
use crate::{assets, testbed::Testbed};
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use wgui::{
|
use wgui::{
|
||||||
components::button::ComponentButton, event::EventListenerCollection, globals::WguiGlobals,
|
components::{
|
||||||
i18n::Translation, layout::Layout, parser::ParserState,
|
Component,
|
||||||
|
button::{ButtonClickCallback, ComponentButton},
|
||||||
|
},
|
||||||
|
event::EventListenerCollection,
|
||||||
|
globals::WguiGlobals,
|
||||||
|
i18n::Translation,
|
||||||
|
layout::{Layout, Widget},
|
||||||
|
parser::ParserState,
|
||||||
|
widget::label::WidgetLabel,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct TestbedGeneric {
|
pub struct TestbedGeneric {
|
||||||
@@ -12,24 +22,63 @@ pub struct TestbedGeneric {
|
|||||||
state: ParserState,
|
state: ParserState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn button_click_callback(
|
||||||
|
button: Component,
|
||||||
|
label: Widget,
|
||||||
|
text: &'static str,
|
||||||
|
) -> ButtonClickCallback {
|
||||||
|
Box::new(move |e| {
|
||||||
|
label.get_as_mut::<WidgetLabel>().set_text(
|
||||||
|
&mut e.state.globals.i18n(),
|
||||||
|
Translation::from_raw_text(text),
|
||||||
|
);
|
||||||
|
|
||||||
|
// FIXME: remove unwrap
|
||||||
|
button.try_cast::<ComponentButton>().unwrap().set_text(
|
||||||
|
e.state,
|
||||||
|
e.alterables,
|
||||||
|
Translation::from_raw_text("this button has been clicked"),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_button_click(button: Rc<ComponentButton>, label: Widget, text: &'static str) {
|
||||||
|
button.on_click(button_click_callback(
|
||||||
|
Component(button.clone()),
|
||||||
|
label,
|
||||||
|
text,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
impl TestbedGeneric {
|
impl TestbedGeneric {
|
||||||
pub fn new(listeners: &mut EventListenerCollection<(), ()>) -> anyhow::Result<Self> {
|
pub fn new(listeners: &mut EventListenerCollection<(), ()>) -> anyhow::Result<Self> {
|
||||||
const XML_PATH: &str = "gui/various_widgets.xml";
|
const XML_PATH: &str = "gui/various_widgets.xml";
|
||||||
|
|
||||||
let globals = WguiGlobals::new(Box::new(assets::Asset {}))?;
|
let globals = WguiGlobals::new(Box::new(assets::Asset {}))?;
|
||||||
|
|
||||||
let (mut layout, state) =
|
let (layout, state) =
|
||||||
wgui::parser::new_layout_from_assets(globals, listeners, XML_PATH, false)?;
|
wgui::parser::new_layout_from_assets(globals, listeners, XML_PATH, false)?;
|
||||||
|
|
||||||
let label_current_option = state.fetch_widget("label_current_option")?;
|
let label_cur_option =
|
||||||
let b1 = state.fetch_component_as::<ComponentButton>("button_red")?;
|
state.fetch_widget::<WidgetLabel>(&layout.state, "label_current_option")?;
|
||||||
let b2 = state.fetch_component_as::<ComponentButton>("button_aqua")?;
|
|
||||||
let b3 = state.fetch_component_as::<ComponentButton>("button_yellow")?;
|
|
||||||
|
|
||||||
b1.set_text(
|
let button_click_me = state.fetch_component_as::<ComponentButton>("button_click_me")?;
|
||||||
&mut layout.state,
|
let button = button_click_me.clone();
|
||||||
Translation::from_raw_text("hello, world!"),
|
button_click_me.on_click(Box::new(move |e| {
|
||||||
|
button.set_text(
|
||||||
|
e.state,
|
||||||
|
e.alterables,
|
||||||
|
Translation::from_raw_text("congrats!"),
|
||||||
);
|
);
|
||||||
|
}));
|
||||||
|
|
||||||
|
let button_red = state.fetch_component_as::<ComponentButton>("button_red")?;
|
||||||
|
let button_aqua = state.fetch_component_as::<ComponentButton>("button_aqua")?;
|
||||||
|
let button_yellow = state.fetch_component_as::<ComponentButton>("button_yellow")?;
|
||||||
|
|
||||||
|
handle_button_click(button_red, label_cur_option.clone(), "Clicked red");
|
||||||
|
handle_button_click(button_aqua, label_cur_option.clone(), "Clicked aqua");
|
||||||
|
handle_button_click(button_yellow, label_cur_option.clone(), "Clicked yellow");
|
||||||
|
|
||||||
Ok(Self { layout, state })
|
Ok(Self { layout, state })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,9 +97,8 @@ impl Animation {
|
|||||||
let widget_node = *state.nodes.get(self.target_widget).unwrap();
|
let widget_node = *state.nodes.get(self.target_widget).unwrap();
|
||||||
let layout = state.tree.layout(widget_node).unwrap(); // should always succeed
|
let layout = state.tree.layout(widget_node).unwrap(); // should always succeed
|
||||||
|
|
||||||
let mut widget = widget.lock();
|
let mut widget_state = widget.state();
|
||||||
|
let (data, obj) = widget_state.get_data_obj_mut();
|
||||||
let (data, obj) = widget.get_data_obj_mut();
|
|
||||||
|
|
||||||
let data = &mut CallbackData {
|
let data = &mut CallbackData {
|
||||||
widget_id: self.target_widget,
|
widget_id: self.target_widget,
|
||||||
|
|||||||
@@ -3,15 +3,15 @@ use taffy::{AlignItems, JustifyContent, prelude::length};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
animation::{Animation, AnimationEasing},
|
animation::{Animation, AnimationEasing},
|
||||||
components::{Component, InitData},
|
components::{Component, ComponentTrait, InitData},
|
||||||
drawing::{self, Color},
|
drawing::{self, Color},
|
||||||
event::{EventAlterables, EventListenerCollection, EventListenerKind, ListenerHandleVec},
|
event::{EventAlterables, EventListenerCollection, EventListenerKind, ListenerHandleVec},
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, LayoutState, WidgetID},
|
layout::{Layout, LayoutState, WidgetID},
|
||||||
renderer_vk::text::{FontWeight, TextStyle},
|
renderer_vk::text::{FontWeight, TextStyle},
|
||||||
widget::{
|
widget::{
|
||||||
rectangle::{Rectangle, RectangleParams},
|
label::{WidgetLabel, WidgetLabelParams},
|
||||||
text::{TextLabel, TextParams},
|
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||||
util::WLength,
|
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 {
|
struct State {
|
||||||
hovered: bool,
|
hovered: bool,
|
||||||
down: bool,
|
down: bool,
|
||||||
|
on_click: Option<ButtonClickCallback>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
@@ -59,27 +66,30 @@ pub struct ComponentButton {
|
|||||||
listener_handles: ListenerHandleVec,
|
listener_handles: ListenerHandleVec,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for ComponentButton {
|
impl ComponentTrait for ComponentButton {
|
||||||
fn init(&self, _data: &mut InitData) {}
|
fn init(&self, _data: &mut InitData) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComponentButton {
|
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();
|
let globals = state.globals.clone();
|
||||||
|
|
||||||
state
|
state
|
||||||
.widgets
|
.widgets
|
||||||
.call(self.data.text_id, |label: &mut TextLabel| {
|
.call(self.data.text_id, |label: &mut WidgetLabel| {
|
||||||
label.set_text(&mut globals.i18n(), text);
|
label.set_text(&mut globals.i18n(), text);
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut alterables = EventAlterables::default();
|
|
||||||
alterables.mark_redraw();
|
alterables.mark_redraw();
|
||||||
alterables.mark_dirty(self.data.text_node);
|
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 brightness = pos * 0.5;
|
||||||
let border_brightness = pos;
|
let border_brightness = pos;
|
||||||
rect.params.color.r = data.initial_color.r + brightness;
|
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,
|
5,
|
||||||
AnimationEasing::OutQuad,
|
AnimationEasing::OutQuad,
|
||||||
Box::new(move |common, anim_data| {
|
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);
|
anim_hover(rect, &data, anim_data.pos);
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
}),
|
}),
|
||||||
@@ -110,7 +120,7 @@ fn anim_hover_out(data: Rc<Data>, widget_id: WidgetID) -> Animation {
|
|||||||
8,
|
8,
|
||||||
AnimationEasing::OutQuad,
|
AnimationEasing::OutQuad,
|
||||||
Box::new(move |common, anim_data| {
|
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);
|
anim_hover(rect, &data, 1.0 - anim_data.pos);
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
}),
|
}),
|
||||||
@@ -167,7 +177,7 @@ fn register_event_mouse_press<U1, U2>(
|
|||||||
listener_handles,
|
listener_handles,
|
||||||
data.rect_id,
|
data.rect_id,
|
||||||
EventListenerKind::MousePress,
|
EventListenerKind::MousePress,
|
||||||
Box::new(move |common, event_data, _, _| {
|
Box::new(move |common, _event_data, _, _| {
|
||||||
common.alterables.trigger_haptics();
|
common.alterables.trigger_haptics();
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
|
|
||||||
@@ -196,7 +206,12 @@ fn register_event_mouse_release<U1, U2>(
|
|||||||
state.down = false;
|
state.down = false;
|
||||||
|
|
||||||
if state.hovered {
|
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(
|
let (rect_id, _) = layout.add_child(
|
||||||
parent,
|
parent,
|
||||||
Rectangle::create(RectangleParams {
|
WidgetRectangle::create(WidgetRectangleParams {
|
||||||
color: params.color,
|
color: params.color,
|
||||||
color2: params
|
color2: params
|
||||||
.color
|
.color
|
||||||
@@ -237,9 +252,9 @@ pub fn construct<U1, U2>(
|
|||||||
|
|
||||||
let (text_id, text_node) = layout.add_child(
|
let (text_id, text_node) = layout.add_child(
|
||||||
rect_id,
|
rect_id,
|
||||||
TextLabel::create(
|
WidgetLabel::create(
|
||||||
&mut globals.i18n(),
|
&mut globals.i18n(),
|
||||||
TextParams {
|
WidgetLabelParams {
|
||||||
content: params.text,
|
content: params.text,
|
||||||
style: TextStyle {
|
style: TextStyle {
|
||||||
weight: Some(FontWeight::Bold),
|
weight: Some(FontWeight::Bold),
|
||||||
@@ -268,6 +283,7 @@ pub fn construct<U1, U2>(
|
|||||||
let state = Rc::new(RefCell::new(State {
|
let state = Rc::new(RefCell::new(State {
|
||||||
down: false,
|
down: false,
|
||||||
hovered: false,
|
hovered: false,
|
||||||
|
on_click: None,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let mut lhandles = ListenerHandleVec::default();
|
let mut lhandles = ListenerHandleVec::default();
|
||||||
@@ -283,6 +299,6 @@ pub fn construct<U1, U2>(
|
|||||||
listener_handles: lhandles,
|
listener_handles: lhandles,
|
||||||
});
|
});
|
||||||
|
|
||||||
layout.defer_component_init(button.clone());
|
layout.defer_component_init(Component(button.clone()));
|
||||||
Ok(button)
|
Ok(button)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::{any::AnyTrait, event::EventAlterables, layout::LayoutState};
|
use crate::{any::AnyTrait, event::EventAlterables, layout::LayoutState};
|
||||||
|
|
||||||
pub mod button;
|
pub mod button;
|
||||||
@@ -8,6 +10,26 @@ pub struct InitData<'a> {
|
|||||||
pub alterables: &'a mut EventAlterables,
|
pub alterables: &'a mut EventAlterables,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Component: AnyTrait {
|
pub trait ComponentTrait: AnyTrait {
|
||||||
fn init(&self, data: &mut InitData);
|
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::{
|
use crate::{
|
||||||
animation::{Animation, AnimationEasing},
|
animation::{Animation, AnimationEasing},
|
||||||
components::{Component, InitData},
|
components::{Component, ComponentTrait, InitData},
|
||||||
drawing::{self},
|
drawing::{self},
|
||||||
event::{
|
event::{
|
||||||
self, CallbackDataCommon, EventAlterables, EventListenerCollection, EventListenerKind,
|
self, CallbackDataCommon, EventAlterables, EventListenerCollection, EventListenerKind,
|
||||||
@@ -18,9 +18,9 @@ use crate::{
|
|||||||
util,
|
util,
|
||||||
},
|
},
|
||||||
widget::{
|
widget::{
|
||||||
div::Div,
|
div::WidgetDiv,
|
||||||
rectangle::{Rectangle, RectangleParams},
|
label::{WidgetLabel, WidgetLabelParams},
|
||||||
text::{TextLabel, TextParams},
|
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||||
util::WLength,
|
util::WLength,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -70,7 +70,7 @@ pub struct ComponentSlider {
|
|||||||
listener_handles: ListenerHandleVec,
|
listener_handles: ListenerHandleVec,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for ComponentSlider {
|
impl ComponentTrait for ComponentSlider {
|
||||||
fn init(&self, init_data: &mut InitData) {
|
fn init(&self, init_data: &mut InitData) {
|
||||||
let mut state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
let value = state.values.value;
|
let value = state.values.value;
|
||||||
@@ -129,7 +129,7 @@ impl State {
|
|||||||
self.set_value(common.state, data, common.alterables, val);
|
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
|
// round displayed value, should be sufficient for now
|
||||||
text.set_text(
|
text.set_text(
|
||||||
i18n,
|
i18n,
|
||||||
@@ -153,7 +153,7 @@ impl State {
|
|||||||
alterables.set_style(data.slider_handle_node, style);
|
alterables.set_style(data.slider_handle_node, style);
|
||||||
state
|
state
|
||||||
.widgets
|
.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);
|
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.color = drawing::Color::lerp(&HANDLE_COLOR, &HANDLE_COLOR_HOVERED, pos);
|
||||||
rect.params.border_color =
|
rect.params.border_color =
|
||||||
drawing::Color::lerp(&HANDLE_BORDER_COLOR, &HANDLE_BORDER_COLOR_HOVERED, pos);
|
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,
|
20,
|
||||||
AnimationEasing::OutBack,
|
AnimationEasing::OutBack,
|
||||||
Box::new(move |common, data| {
|
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);
|
data.data.transform = get_anim_transform(data.pos, data.widget_size);
|
||||||
anim_rect(rect, data.pos);
|
anim_rect(rect, data.pos);
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
@@ -200,7 +200,7 @@ fn on_leave_anim(common: &mut event::CallbackDataCommon, handle_id: WidgetID) {
|
|||||||
10,
|
10,
|
||||||
AnimationEasing::OutQuad,
|
AnimationEasing::OutQuad,
|
||||||
Box::new(move |common, data| {
|
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);
|
data.data.transform = get_anim_transform(1.0 - data.pos, data.widget_size);
|
||||||
anim_rect(rect, 1.0 - data.pos);
|
anim_rect(rect, 1.0 - data.pos);
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
@@ -318,11 +318,11 @@ pub fn construct<U1, U2>(
|
|||||||
style.min_size = style.size;
|
style.min_size = style.size;
|
||||||
style.max_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(
|
let (_background_id, _) = layout.add_child(
|
||||||
body_id,
|
body_id,
|
||||||
Rectangle::create(RectangleParams {
|
WidgetRectangle::create(WidgetRectangleParams {
|
||||||
color: BODY_COLOR,
|
color: BODY_COLOR,
|
||||||
round: WLength::Percent(1.0),
|
round: WLength::Percent(1.0),
|
||||||
border_color: BODY_BORDER_COLOR,
|
border_color: BODY_BORDER_COLOR,
|
||||||
@@ -361,11 +361,11 @@ pub fn construct<U1, U2>(
|
|||||||
|
|
||||||
// invisible outer handle body
|
// invisible outer handle body
|
||||||
let (slider_handle_id, slider_handle_node) =
|
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(
|
let (slider_handle_rect_id, _) = layout.add_child(
|
||||||
slider_handle_id,
|
slider_handle_id,
|
||||||
Rectangle::create(RectangleParams {
|
WidgetRectangle::create(WidgetRectangleParams {
|
||||||
color: HANDLE_COLOR,
|
color: HANDLE_COLOR,
|
||||||
border_color: HANDLE_BORDER_COLOR,
|
border_color: HANDLE_BORDER_COLOR,
|
||||||
border: 2.0,
|
border: 2.0,
|
||||||
@@ -393,9 +393,9 @@ pub fn construct<U1, U2>(
|
|||||||
|
|
||||||
let (slider_text_id, _) = layout.add_child(
|
let (slider_text_id, _) = layout.add_child(
|
||||||
slider_handle_id,
|
slider_handle_id,
|
||||||
TextLabel::create(
|
WidgetLabel::create(
|
||||||
&mut i18n,
|
&mut i18n,
|
||||||
TextParams {
|
WidgetLabelParams {
|
||||||
content: Translation::default(),
|
content: Translation::default(),
|
||||||
style: TextStyle {
|
style: TextStyle {
|
||||||
weight: Some(FontWeight::Bold),
|
weight: Some(FontWeight::Bold),
|
||||||
@@ -432,6 +432,6 @@ pub fn construct<U1, U2>(
|
|||||||
listener_handles: lhandles,
|
listener_handles: lhandles,
|
||||||
});
|
});
|
||||||
|
|
||||||
layout.defer_component_init(slider.clone());
|
layout.defer_component_init(Component(slider.clone()));
|
||||||
Ok(slider)
|
Ok(slider)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use glam::{Mat4, Vec2};
|
|||||||
use taffy::TraversePartialTree;
|
use taffy::TraversePartialTree;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
layout::BoxWidget,
|
layout::Widget,
|
||||||
renderer_vk::text::custom_glyph::CustomGlyph,
|
renderer_vk::text::custom_glyph::CustomGlyph,
|
||||||
transform_stack::{self, TransformStack},
|
transform_stack::{self, TransformStack},
|
||||||
widget::{self},
|
widget::{self},
|
||||||
@@ -38,7 +38,7 @@ impl Boundary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Color {
|
pub struct Color {
|
||||||
pub r: f32,
|
pub r: f32,
|
||||||
pub g: f32,
|
pub g: f32,
|
||||||
@@ -69,7 +69,7 @@ impl Default for Color {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
pub enum GradientMode {
|
pub enum GradientMode {
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
@@ -108,7 +108,7 @@ fn draw_widget(
|
|||||||
state: &mut DrawState,
|
state: &mut DrawState,
|
||||||
node_id: taffy::NodeId,
|
node_id: taffy::NodeId,
|
||||||
style: &taffy::Style,
|
style: &taffy::Style,
|
||||||
widget: &BoxWidget,
|
widget: &Widget,
|
||||||
parent_transform: &glam::Mat4,
|
parent_transform: &glam::Mat4,
|
||||||
) {
|
) {
|
||||||
let Ok(l) = layout.state.tree.layout(node_id) else {
|
let Ok(l) = layout.state.tree.layout(node_id) else {
|
||||||
@@ -116,7 +116,7 @@ fn draw_widget(
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut widget_state = widget.lock();
|
let mut widget_state = widget.state();
|
||||||
|
|
||||||
let transform = widget_state.data.transform * *parent_transform;
|
let transform = widget_state.data.transform * *parent_transform;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::assets::AssetProvider;
|
|||||||
// a string which optionally has translation key in it
|
// a string which optionally has translation key in it
|
||||||
// it will hopefully support dynamic language changing soon
|
// it will hopefully support dynamic language changing soon
|
||||||
// for now it's just a simple string container
|
// for now it's just a simple string container
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Translation {
|
pub struct Translation {
|
||||||
text: Rc<str>,
|
text: Rc<str>,
|
||||||
translated: bool, // if true, `text` is a translation key
|
translated: bool, // if true, `text` is a translation key
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
use std::{collections::VecDeque, rc::Rc, sync::Arc};
|
use std::{
|
||||||
|
cell::{RefCell, RefMut},
|
||||||
|
collections::VecDeque,
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
animation::Animations,
|
animation::Animations,
|
||||||
@@ -6,11 +10,10 @@ use crate::{
|
|||||||
event::{self, EventAlterables, EventListenerCollection},
|
event::{self, EventAlterables, EventListenerCollection},
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
transform_stack::Transform,
|
transform_stack::Transform,
|
||||||
widget::{self, EventParams, WidgetObj, WidgetState, div::Div},
|
widget::{self, EventParams, WidgetObj, WidgetState, div::WidgetDiv},
|
||||||
};
|
};
|
||||||
|
|
||||||
use glam::{Vec2, vec2};
|
use glam::{Vec2, vec2};
|
||||||
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
|
|
||||||
use slotmap::{HopSlotMap, SecondaryMap, new_key_type};
|
use slotmap::{HopSlotMap, SecondaryMap, new_key_type};
|
||||||
use taffy::{TaffyTree, TraversePartialTree};
|
use taffy::{TaffyTree, TraversePartialTree};
|
||||||
|
|
||||||
@@ -18,9 +21,26 @@ new_key_type! {
|
|||||||
pub struct WidgetID;
|
pub struct WidgetID;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type BoxWidget = Arc<Mutex<WidgetState>>;
|
#[derive(Clone)]
|
||||||
|
pub struct Widget(Rc<RefCell<WidgetState>>);
|
||||||
|
|
||||||
pub struct WidgetMap(HopSlotMap<WidgetID, BoxWidget>);
|
impl Widget {
|
||||||
|
pub fn new(widget_state: WidgetState) -> Self {
|
||||||
|
Self(Rc::new(RefCell::new(widget_state)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// panics on failure
|
||||||
|
// TODO: panic-less alternative
|
||||||
|
pub fn get_as_mut<T: 'static>(&self) -> RefMut<T> {
|
||||||
|
RefMut::map(self.0.borrow_mut(), |w| w.obj.get_as_mut::<T>())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn state(&self) -> RefMut<WidgetState> {
|
||||||
|
self.0.borrow_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WidgetMap(HopSlotMap<WidgetID, Widget>);
|
||||||
pub type WidgetNodeMap = SecondaryMap<WidgetID, taffy::NodeId>;
|
pub type WidgetNodeMap = SecondaryMap<WidgetID, taffy::NodeId>;
|
||||||
|
|
||||||
impl WidgetMap {
|
impl WidgetMap {
|
||||||
@@ -28,21 +48,21 @@ impl WidgetMap {
|
|||||||
Self(HopSlotMap::with_key())
|
Self(HopSlotMap::with_key())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_as<T: 'static>(&self, handle: WidgetID) -> Option<MappedMutexGuard<T>> {
|
pub fn get_as<T: 'static>(&self, handle: WidgetID) -> Option<RefMut<T>> {
|
||||||
let widget = self.0.get(handle)?;
|
Some(self.0.get(handle)?.get_as_mut::<T>())
|
||||||
Some(MutexGuard::map(widget.lock(), |w| w.obj.get_as_mut::<T>()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, handle: WidgetID) -> Option<&BoxWidget> {
|
pub fn get(&self, handle: WidgetID) -> Option<&Widget> {
|
||||||
self.0.get(handle)
|
self.0.get(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, obj: BoxWidget) -> WidgetID {
|
pub fn insert(&mut self, obj: Widget) -> WidgetID {
|
||||||
self.0.insert(obj)
|
self.0.insert(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cast to specific widget type, does nothing if widget ID is expired
|
// cast to specific widget type, does nothing if widget ID is expired
|
||||||
// panics in case if the widget type is wrong
|
// panics in case if the widget type is wrong
|
||||||
|
// TODO: panic-less alternative
|
||||||
pub fn call<WIDGET, FUNC>(&self, widget_id: WidgetID, func: FUNC)
|
pub fn call<WIDGET, FUNC>(&self, widget_id: WidgetID, func: FUNC)
|
||||||
where
|
where
|
||||||
WIDGET: WidgetObj,
|
WIDGET: WidgetObj,
|
||||||
@@ -53,10 +73,7 @@ impl WidgetMap {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut lock = widget.lock();
|
func(&mut widget.get_as_mut::<WIDGET>());
|
||||||
let m = lock.obj.get_as_mut::<WIDGET>();
|
|
||||||
|
|
||||||
func(m);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,13 +82,12 @@ pub struct LayoutState {
|
|||||||
pub widgets: WidgetMap,
|
pub widgets: WidgetMap,
|
||||||
pub nodes: WidgetNodeMap,
|
pub nodes: WidgetNodeMap,
|
||||||
pub tree: taffy::tree::TaffyTree<WidgetID>,
|
pub tree: taffy::tree::TaffyTree<WidgetID>,
|
||||||
pub alterables: EventAlterables,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Layout {
|
pub struct Layout {
|
||||||
pub state: LayoutState,
|
pub state: LayoutState,
|
||||||
|
|
||||||
pub components_to_init: VecDeque<Rc<dyn Component>>,
|
pub components_to_init: VecDeque<Component>,
|
||||||
|
|
||||||
pub root_widget: WidgetID,
|
pub root_widget: WidgetID,
|
||||||
pub root_node: taffy::NodeId,
|
pub root_node: taffy::NodeId,
|
||||||
@@ -90,11 +106,11 @@ fn add_child_internal(
|
|||||||
widgets: &mut WidgetMap,
|
widgets: &mut WidgetMap,
|
||||||
nodes: &mut WidgetNodeMap,
|
nodes: &mut WidgetNodeMap,
|
||||||
parent_node: Option<taffy::NodeId>,
|
parent_node: Option<taffy::NodeId>,
|
||||||
widget: WidgetState,
|
widget_state: WidgetState,
|
||||||
style: taffy::Style,
|
style: taffy::Style,
|
||||||
) -> anyhow::Result<(WidgetID, taffy::NodeId)> {
|
) -> anyhow::Result<(WidgetID, taffy::NodeId)> {
|
||||||
#[allow(clippy::arc_with_non_send_sync)]
|
#[allow(clippy::arc_with_non_send_sync)]
|
||||||
let child_id = widgets.insert(Arc::new(Mutex::new(widget)));
|
let child_id = widgets.insert(Widget::new(widget_state));
|
||||||
let child_node = tree.new_leaf_with_context(style, child_id)?;
|
let child_node = tree.new_leaf_with_context(style, child_id)?;
|
||||||
|
|
||||||
if let Some(parent_node) = parent_node {
|
if let Some(parent_node) = parent_node {
|
||||||
@@ -131,7 +147,7 @@ impl Layout {
|
|||||||
let mut alterables = EventAlterables::default();
|
let mut alterables = EventAlterables::default();
|
||||||
|
|
||||||
while let Some(c) = self.components_to_init.pop_front() {
|
while let Some(c) = self.components_to_init.pop_front() {
|
||||||
c.init(&mut InitData {
|
c.0.init(&mut InitData {
|
||||||
state: &self.state,
|
state: &self.state,
|
||||||
alterables: &mut alterables,
|
alterables: &mut alterables,
|
||||||
});
|
});
|
||||||
@@ -142,7 +158,7 @@ impl Layout {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn defer_component_init(&mut self, component: Rc<dyn Component>) {
|
pub fn defer_component_init(&mut self, component: Component) {
|
||||||
self.components_to_init.push_back(component);
|
self.components_to_init.push_back(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,8 +197,6 @@ impl Layout {
|
|||||||
anyhow::bail!("invalid widget");
|
anyhow::bail!("invalid widget");
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut widget = widget.lock();
|
|
||||||
|
|
||||||
let transform = Transform {
|
let transform = Transform {
|
||||||
pos: Vec2::new(l.location.x, l.location.y),
|
pos: Vec2::new(l.location.x, l.location.y),
|
||||||
dim: Vec2::new(l.size.width, l.size.height),
|
dim: Vec2::new(l.size.width, l.size.height),
|
||||||
@@ -203,6 +217,8 @@ impl Layout {
|
|||||||
|
|
||||||
let listeners_vec = listeners.get(widget_id);
|
let listeners_vec = listeners.get(widget_id);
|
||||||
|
|
||||||
|
let mut widget = widget.0.borrow_mut();
|
||||||
|
|
||||||
match widget.process_event(
|
match widget.process_event(
|
||||||
widget_id,
|
widget_id,
|
||||||
listeners_vec,
|
listeners_vec,
|
||||||
@@ -283,7 +299,6 @@ impl Layout {
|
|||||||
widgets: WidgetMap::new(),
|
widgets: WidgetMap::new(),
|
||||||
nodes: WidgetNodeMap::default(),
|
nodes: WidgetNodeMap::default(),
|
||||||
globals,
|
globals,
|
||||||
alterables: EventAlterables::default(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let (root_widget, root_node) = add_child_internal(
|
let (root_widget, root_node) = add_child_internal(
|
||||||
@@ -291,7 +306,7 @@ impl Layout {
|
|||||||
&mut state.widgets,
|
&mut state.widgets,
|
||||||
&mut state.nodes,
|
&mut state.nodes,
|
||||||
None, // no parent
|
None, // no parent
|
||||||
Div::create()?,
|
WidgetDiv::create()?,
|
||||||
taffy::Style {
|
taffy::Style {
|
||||||
size: taffy::Size::auto(),
|
size: taffy::Size::auto(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -343,7 +358,10 @@ impl Layout {
|
|||||||
None => taffy::Size::ZERO,
|
None => taffy::Size::ZERO,
|
||||||
Some(h) => {
|
Some(h) => {
|
||||||
if let Some(w) = self.state.widgets.get(*h) {
|
if let Some(w) = self.state.widgets.get(*h) {
|
||||||
w.lock().obj.measure(known_dimensions, available_space)
|
w.0
|
||||||
|
.borrow_mut()
|
||||||
|
.obj
|
||||||
|
.measure(known_dimensions, available_space)
|
||||||
} else {
|
} else {
|
||||||
taffy::Size::ZERO
|
taffy::Size::ZERO
|
||||||
}
|
}
|
||||||
@@ -352,13 +370,15 @@ impl Layout {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
let root_size = self.state.tree.layout(self.root_node).unwrap().size;
|
let root_size = self.state.tree.layout(self.root_node).unwrap().size;
|
||||||
|
if self.content_size.x != root_size.width || self.content_size.y != root_size.height {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"content size {:.0}x{:.0} → {:.0}x{:.0}",
|
"content size changed: {:.0}x{:.0} → {:.0}x{:.0}",
|
||||||
self.content_size.x,
|
self.content_size.x,
|
||||||
self.content_size.y,
|
self.content_size.y,
|
||||||
root_size.width,
|
root_size.width,
|
||||||
root_size.height
|
root_size.height
|
||||||
);
|
);
|
||||||
|
}
|
||||||
self.content_size = vec2(root_size.width, root_size.height);
|
self.content_size = vec2(root_size.width, root_size.height);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -369,8 +389,6 @@ impl Layout {
|
|||||||
self.animations.tick(&self.state, &mut alterables);
|
self.animations.tick(&self.state, &mut alterables);
|
||||||
self.process_pending_components()?;
|
self.process_pending_components()?;
|
||||||
self.process_alterables(alterables)?;
|
self.process_alterables(alterables)?;
|
||||||
let state_alterables = std::mem::take(&mut self.state.alterables);
|
|
||||||
self.process_alterables(state_alterables)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
components::button,
|
components::{Component, button},
|
||||||
drawing::Color,
|
drawing::Color,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::WidgetID,
|
layout::WidgetID,
|
||||||
@@ -69,7 +69,7 @@ pub fn parse_component_button<'a, U1, U2>(
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
process_component(file, ctx, node, component)?;
|
process_component(file, ctx, node, Component(component))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
components::slider,
|
components::{Component, slider},
|
||||||
layout::WidgetID,
|
layout::WidgetID,
|
||||||
parser::{
|
parser::{
|
||||||
ParserContext, ParserFile, iter_attribs, parse_check_f32, process_component, style::parse_style,
|
ParserContext, ParserFile, iter_attribs, parse_check_f32, process_component, style::parse_style,
|
||||||
@@ -48,7 +48,7 @@ pub fn parse_component_slider<'a, U1, U2>(
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
process_component(file, ctx, node, component)?;
|
process_component(file, ctx, node, Component(component))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,12 @@ mod widget_rectangle;
|
|||||||
mod widget_sprite;
|
mod widget_sprite;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
any::AnyTrait,
|
|
||||||
assets::AssetProvider,
|
assets::AssetProvider,
|
||||||
components::Component,
|
components::{Component, ComponentTrait, ComponentWeak},
|
||||||
drawing::{self},
|
drawing::{self},
|
||||||
event::EventListenerCollection,
|
event::EventListenerCollection,
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
layout::{Layout, WidgetID},
|
layout::{Layout, LayoutState, Widget, WidgetID},
|
||||||
parser::{
|
parser::{
|
||||||
component_button::parse_component_button, component_slider::parse_component_slider,
|
component_button::parse_component_button, component_slider::parse_component_slider,
|
||||||
widget_div::parse_widget_div, widget_label::parse_widget_label,
|
widget_div::parse_widget_div, widget_label::parse_widget_label,
|
||||||
@@ -56,14 +55,14 @@ pub struct ParserState {
|
|||||||
pub ids: HashMap<Rc<str>, WidgetID>,
|
pub ids: HashMap<Rc<str>, WidgetID>,
|
||||||
macro_attribs: HashMap<Rc<str>, MacroAttribs>,
|
macro_attribs: HashMap<Rc<str>, MacroAttribs>,
|
||||||
pub var_map: HashMap<Rc<str>, Rc<str>>,
|
pub var_map: HashMap<Rc<str>, Rc<str>>,
|
||||||
pub components: Vec<Rc<dyn Component>>,
|
pub components: Vec<Component>,
|
||||||
pub components_id_map: HashMap<Rc<str>, std::rc::Weak<dyn Component>>,
|
pub components_id_map: HashMap<Rc<str>, std::rc::Weak<dyn ComponentTrait>>,
|
||||||
pub templates: HashMap<Rc<str>, Rc<Template>>,
|
pub templates: HashMap<Rc<str>, Rc<Template>>,
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParserState {
|
impl ParserState {
|
||||||
pub fn fetch_component(&self, id: &str) -> anyhow::Result<Rc<dyn Component>> {
|
pub fn fetch_component(&self, id: &str) -> anyhow::Result<Component> {
|
||||||
let Some(weak) = self.components_id_map.get(id) else {
|
let Some(weak) = self.components_id_map.get(id) else {
|
||||||
anyhow::bail!("Component by ID \"{}\" doesn't exist", id);
|
anyhow::bail!("Component by ID \"{}\" doesn't exist", id);
|
||||||
};
|
};
|
||||||
@@ -72,27 +71,36 @@ impl ParserState {
|
|||||||
anyhow::bail!("Component by ID \"{}\" doesn't exist", id);
|
anyhow::bail!("Component by ID \"{}\" doesn't exist", id);
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(component)
|
Ok(Component(component))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch_component_as<T: 'static>(&self, id: &str) -> anyhow::Result<Rc<T>> {
|
pub fn fetch_component_as<T: 'static>(&self, id: &str) -> anyhow::Result<Rc<T>> {
|
||||||
let component = self.fetch_component(id)?;
|
let component = self.fetch_component(id)?;
|
||||||
|
|
||||||
// FIXME: check T type id
|
if !(*component.0).as_any().is::<T>() {
|
||||||
log::warn!("fetch_component_as WIP");
|
anyhow::bail!("fetch_component_as({}): type not matching", id);
|
||||||
unsafe {
|
|
||||||
let raw = Rc::into_raw(component);
|
|
||||||
Ok(Rc::from_raw(raw as _))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch_widget(&self, id: &str) -> anyhow::Result<WidgetID> {
|
// safety: we already checked it above, should be safe to directly cast it
|
||||||
|
unsafe { Ok(Rc::from_raw(Rc::into_raw(component.0) as _)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_widget_id(&self, id: &str) -> anyhow::Result<WidgetID> {
|
||||||
match self.ids.get(id) {
|
match self.ids.get(id) {
|
||||||
Some(id) => Ok(*id),
|
Some(id) => Ok(*id),
|
||||||
None => anyhow::bail!("Widget by ID \"{}\" doesn't exist", id),
|
None => anyhow::bail!("Widget by ID \"{}\" doesn't exist", id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fetch_widget<T: 'static>(&self, state: &LayoutState, id: &str) -> anyhow::Result<Widget> {
|
||||||
|
let widget_id = self.get_widget_id(id)?;
|
||||||
|
let widget = state
|
||||||
|
.widgets
|
||||||
|
.get(widget_id)
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("fetch_widget_as({}): widget not found", id))?;
|
||||||
|
Ok(widget.clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process_template<U1, U2>(
|
pub fn process_template<U1, U2>(
|
||||||
&mut self,
|
&mut self,
|
||||||
template_name: &str,
|
template_name: &str,
|
||||||
@@ -153,8 +161,8 @@ struct ParserContext<'a, U1, U2> {
|
|||||||
macro_attribs: HashMap<Rc<str>, MacroAttribs>,
|
macro_attribs: HashMap<Rc<str>, MacroAttribs>,
|
||||||
ids: HashMap<Rc<str>, WidgetID>,
|
ids: HashMap<Rc<str>, WidgetID>,
|
||||||
templates: HashMap<Rc<str>, Rc<Template>>,
|
templates: HashMap<Rc<str>, Rc<Template>>,
|
||||||
components: Vec<Rc<dyn Component>>,
|
components: Vec<Component>,
|
||||||
components_id_map: HashMap<Rc<str>, std::rc::Weak<dyn Component>>,
|
components_id_map: HashMap<Rc<str>, ComponentWeak>,
|
||||||
dev_mode: bool,
|
dev_mode: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,7 +569,7 @@ fn process_component<'a, U1, U2>(
|
|||||||
file: &'a ParserFile,
|
file: &'a ParserFile,
|
||||||
ctx: &mut ParserContext<U1, U2>,
|
ctx: &mut ParserContext<U1, U2>,
|
||||||
node: roxmltree::Node<'a, 'a>,
|
node: roxmltree::Node<'a, 'a>,
|
||||||
component: Rc<dyn Component>,
|
component: Component,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let attribs: Vec<_> = iter_attribs(file, ctx, &node, false).collect();
|
let attribs: Vec<_> = iter_attribs(file, ctx, &node, false).collect();
|
||||||
|
|
||||||
@@ -571,7 +579,7 @@ fn process_component<'a, U1, U2>(
|
|||||||
"id" => {
|
"id" => {
|
||||||
if ctx
|
if ctx
|
||||||
.components_id_map
|
.components_id_map
|
||||||
.insert(value.clone(), Rc::downgrade(&component))
|
.insert(value.clone(), component.weak())
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
log::warn!("duplicate component ID \"{value}\" in the same layout file!");
|
log::warn!("duplicate component ID \"{value}\" in the same layout file!");
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
layout::WidgetID,
|
layout::WidgetID,
|
||||||
parser::{
|
parser::{
|
||||||
ParserContext, ParserFile, iter_attribs, parse_children, parse_widget_universal, style::parse_style,
|
ParserContext, ParserFile, iter_attribs, parse_children, parse_widget_universal,
|
||||||
|
style::parse_style,
|
||||||
},
|
},
|
||||||
widget,
|
widget,
|
||||||
};
|
};
|
||||||
@@ -17,7 +18,7 @@ pub fn parse_widget_div<'a, U1, U2>(
|
|||||||
|
|
||||||
let (new_id, _) = ctx
|
let (new_id, _) = ctx
|
||||||
.layout
|
.layout
|
||||||
.add_child(parent_id, widget::div::Div::create()?, style)?;
|
.add_child(parent_id, widget::div::WidgetDiv::create()?, style)?;
|
||||||
|
|
||||||
parse_widget_universal(file, ctx, node, new_id)?;
|
parse_widget_universal(file, ctx, node, new_id)?;
|
||||||
parse_children(file, ctx, node, new_id)?;
|
parse_children(file, ctx, node, new_id)?;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::{
|
|||||||
ParserContext, ParserFile, iter_attribs, parse_children, parse_widget_universal,
|
ParserContext, ParserFile, iter_attribs, parse_children, parse_widget_universal,
|
||||||
style::{parse_style, parse_text_style},
|
style::{parse_style, parse_text_style},
|
||||||
},
|
},
|
||||||
widget::text::{TextLabel, TextParams},
|
widget::label::{WidgetLabelParams, WidgetLabel},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse_widget_label<'a, U1, U2>(
|
pub fn parse_widget_label<'a, U1, U2>(
|
||||||
@@ -14,7 +14,7 @@ pub fn parse_widget_label<'a, U1, U2>(
|
|||||||
node: roxmltree::Node<'a, 'a>,
|
node: roxmltree::Node<'a, 'a>,
|
||||||
parent_id: WidgetID,
|
parent_id: WidgetID,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let mut params = TextParams::default();
|
let mut params = WidgetLabelParams::default();
|
||||||
let attribs: Vec<_> = iter_attribs(file, ctx, &node, false).collect();
|
let attribs: Vec<_> = iter_attribs(file, ctx, &node, false).collect();
|
||||||
|
|
||||||
let style = parse_style(&attribs);
|
let style = parse_style(&attribs);
|
||||||
@@ -36,7 +36,7 @@ pub fn parse_widget_label<'a, U1, U2>(
|
|||||||
let (new_id, _) =
|
let (new_id, _) =
|
||||||
ctx
|
ctx
|
||||||
.layout
|
.layout
|
||||||
.add_child(parent_id, TextLabel::create(&mut i18n, params)?, style)?;
|
.add_child(parent_id, WidgetLabel::create(&mut i18n, params)?, style)?;
|
||||||
|
|
||||||
parse_widget_universal(file, ctx, node, new_id)?;
|
parse_widget_universal(file, ctx, node, new_id)?;
|
||||||
parse_children(file, ctx, node, new_id)?;
|
parse_children(file, ctx, node, new_id)?;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::{
|
|||||||
print_invalid_attrib,
|
print_invalid_attrib,
|
||||||
style::{parse_color, parse_round, parse_style},
|
style::{parse_color, parse_round, parse_style},
|
||||||
},
|
},
|
||||||
widget::{self, rectangle::RectangleParams},
|
widget::{self, rectangle::WidgetRectangleParams},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse_widget_rectangle<'a, U1, U2>(
|
pub fn parse_widget_rectangle<'a, U1, U2>(
|
||||||
@@ -15,7 +15,7 @@ pub fn parse_widget_rectangle<'a, U1, U2>(
|
|||||||
node: roxmltree::Node<'a, 'a>,
|
node: roxmltree::Node<'a, 'a>,
|
||||||
parent_id: WidgetID,
|
parent_id: WidgetID,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let mut params = RectangleParams::default();
|
let mut params = WidgetRectangleParams::default();
|
||||||
let attribs: Vec<_> = iter_attribs(file, ctx, &node, false).collect();
|
let attribs: Vec<_> = iter_attribs(file, ctx, &node, false).collect();
|
||||||
let style = parse_style(&attribs);
|
let style = parse_style(&attribs);
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ pub fn parse_widget_rectangle<'a, U1, U2>(
|
|||||||
|
|
||||||
let (new_id, _) = ctx.layout.add_child(
|
let (new_id, _) = ctx.layout.add_child(
|
||||||
parent_id,
|
parent_id,
|
||||||
widget::rectangle::Rectangle::create(params)?,
|
widget::rectangle::WidgetRectangle::create(params)?,
|
||||||
style,
|
style,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::{
|
|||||||
style::parse_style,
|
style::parse_style,
|
||||||
},
|
},
|
||||||
renderer_vk::text::custom_glyph::{CustomGlyphContent, CustomGlyphData},
|
renderer_vk::text::custom_glyph::{CustomGlyphContent, CustomGlyphData},
|
||||||
widget::sprite::{SpriteBox, SpriteBoxParams},
|
widget::sprite::{WidgetSprite, WidgetSpriteParams},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{parse_color_hex, print_invalid_attrib};
|
use super::{parse_color_hex, print_invalid_attrib};
|
||||||
@@ -16,7 +16,7 @@ pub fn parse_widget_sprite<'a, U1, U2>(
|
|||||||
node: roxmltree::Node<'a, 'a>,
|
node: roxmltree::Node<'a, 'a>,
|
||||||
parent_id: WidgetID,
|
parent_id: WidgetID,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let mut params = SpriteBoxParams::default();
|
let mut params = WidgetSpriteParams::default();
|
||||||
let attribs: Vec<_> = iter_attribs(file, ctx, &node, false).collect();
|
let attribs: Vec<_> = iter_attribs(file, ctx, &node, false).collect();
|
||||||
let style = parse_style(&attribs);
|
let style = parse_style(&attribs);
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ pub fn parse_widget_sprite<'a, U1, U2>(
|
|||||||
|
|
||||||
let (new_id, _) = ctx
|
let (new_id, _) = ctx
|
||||||
.layout
|
.layout
|
||||||
.add_child(parent_id, SpriteBox::create(params)?, style)?;
|
.add_child(parent_id, WidgetSprite::create(params)?, style)?;
|
||||||
|
|
||||||
parse_widget_universal(file, ctx, node, new_id)?;
|
parse_widget_universal(file, ctx, node, new_id)?;
|
||||||
parse_children(file, ctx, node, new_id)?;
|
parse_children(file, ctx, node, new_id)?;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use super::{WidgetObj, WidgetState};
|
use super::{WidgetObj, WidgetState};
|
||||||
|
|
||||||
pub struct Div {}
|
pub struct WidgetDiv {}
|
||||||
|
|
||||||
impl Div {
|
impl WidgetDiv {
|
||||||
pub fn create() -> anyhow::Result<WidgetState> {
|
pub fn create() -> anyhow::Result<WidgetState> {
|
||||||
WidgetState::new(Box::new(Self {}))
|
WidgetState::new(Box::new(Self {}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetObj for Div {
|
impl WidgetObj for WidgetDiv {
|
||||||
fn draw(&mut self, _state: &mut super::DrawState, _params: &super::DrawParams) {
|
fn draw(&mut self, _state: &mut super::DrawState, _params: &super::DrawParams) {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,19 +12,19 @@ use crate::{
|
|||||||
use super::{WidgetObj, WidgetState};
|
use super::{WidgetObj, WidgetState};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TextParams {
|
pub struct WidgetLabelParams {
|
||||||
pub content: Translation,
|
pub content: Translation,
|
||||||
pub style: TextStyle,
|
pub style: TextStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TextLabel {
|
pub struct WidgetLabel {
|
||||||
params: TextParams,
|
params: WidgetLabelParams,
|
||||||
buffer: Rc<RefCell<Buffer>>,
|
buffer: Rc<RefCell<Buffer>>,
|
||||||
last_boundary: Boundary,
|
last_boundary: Boundary,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextLabel {
|
impl WidgetLabel {
|
||||||
pub fn create(i18n: &mut I18n, params: TextParams) -> anyhow::Result<WidgetState> {
|
pub fn create(i18n: &mut I18n, params: WidgetLabelParams) -> anyhow::Result<WidgetState> {
|
||||||
let metrics = Metrics::from(¶ms.style);
|
let metrics = Metrics::from(¶ms.style);
|
||||||
let attrs = Attrs::from(¶ms.style);
|
let attrs = Attrs::from(¶ms.style);
|
||||||
let wrap = Wrap::from(¶ms.style);
|
let wrap = Wrap::from(¶ms.style);
|
||||||
@@ -70,7 +70,7 @@ impl TextLabel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetObj for TextLabel {
|
impl WidgetObj for WidgetLabel {
|
||||||
fn draw(&mut self, state: &mut super::DrawState, _params: &super::DrawParams) {
|
fn draw(&mut self, state: &mut super::DrawState, _params: &super::DrawParams) {
|
||||||
let boundary = drawing::Boundary::construct(state.transform_stack);
|
let boundary = drawing::Boundary::construct(state.transform_stack);
|
||||||
|
|
||||||
@@ -14,9 +14,9 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub mod div;
|
pub mod div;
|
||||||
|
pub mod label;
|
||||||
pub mod rectangle;
|
pub mod rectangle;
|
||||||
pub mod sprite;
|
pub mod sprite;
|
||||||
pub mod text;
|
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
pub struct WidgetData {
|
pub struct WidgetData {
|
||||||
@@ -173,11 +173,15 @@ pub fn get_scrollbar_info(l: &taffy::Layout) -> Option<ScrollbarInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl dyn WidgetObj {
|
impl dyn WidgetObj {
|
||||||
|
// panics on failure
|
||||||
|
// TODO: panic-less alternative
|
||||||
pub fn get_as<T: 'static>(&self) -> &T {
|
pub fn get_as<T: 'static>(&self) -> &T {
|
||||||
let any = self.as_any();
|
let any = self.as_any();
|
||||||
any.downcast_ref::<T>().unwrap()
|
any.downcast_ref::<T>().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// panics on failure
|
||||||
|
// TODO: panic-less alternative
|
||||||
pub fn get_as_mut<T: 'static>(&mut self) -> &mut T {
|
pub fn get_as_mut<T: 'static>(&mut self) -> &mut T {
|
||||||
let any = self.as_any_mut();
|
let any = self.as_any_mut();
|
||||||
any.downcast_mut::<T>().unwrap()
|
any.downcast_mut::<T>().unwrap()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::{
|
|||||||
use super::{WidgetObj, WidgetState};
|
use super::{WidgetObj, WidgetState};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct RectangleParams {
|
pub struct WidgetRectangleParams {
|
||||||
pub color: drawing::Color,
|
pub color: drawing::Color,
|
||||||
pub color2: drawing::Color,
|
pub color2: drawing::Color,
|
||||||
pub gradient: GradientMode,
|
pub gradient: GradientMode,
|
||||||
@@ -17,17 +17,17 @@ pub struct RectangleParams {
|
|||||||
pub round: WLength,
|
pub round: WLength,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Rectangle {
|
pub struct WidgetRectangle {
|
||||||
pub params: RectangleParams,
|
pub params: WidgetRectangleParams,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rectangle {
|
impl WidgetRectangle {
|
||||||
pub fn create(params: RectangleParams) -> anyhow::Result<WidgetState> {
|
pub fn create(params: WidgetRectangleParams) -> anyhow::Result<WidgetState> {
|
||||||
WidgetState::new(Box::new(Rectangle { params }))
|
WidgetState::new(Box::new(WidgetRectangle { params }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetObj for Rectangle {
|
impl WidgetObj for WidgetRectangle {
|
||||||
fn draw(&mut self, state: &mut super::DrawState, _params: &super::DrawParams) {
|
fn draw(&mut self, state: &mut super::DrawState, _params: &super::DrawParams) {
|
||||||
let boundary = drawing::Boundary::construct(state.transform_stack);
|
let boundary = drawing::Boundary::construct(state.transform_stack);
|
||||||
|
|
||||||
|
|||||||
@@ -12,24 +12,24 @@ use crate::{
|
|||||||
|
|
||||||
use super::{WidgetObj, WidgetState};
|
use super::{WidgetObj, WidgetState};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct SpriteBoxParams {
|
pub struct WidgetSpriteParams {
|
||||||
pub glyph_data: Option<CustomGlyphData>,
|
pub glyph_data: Option<CustomGlyphData>,
|
||||||
pub color: Option<drawing::Color>,
|
pub color: Option<drawing::Color>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct SpriteBox {
|
pub struct WidgetSprite {
|
||||||
params: SpriteBoxParams,
|
params: WidgetSpriteParams,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpriteBox {
|
impl WidgetSprite {
|
||||||
pub fn create(params: SpriteBoxParams) -> anyhow::Result<WidgetState> {
|
pub fn create(params: WidgetSpriteParams) -> anyhow::Result<WidgetState> {
|
||||||
WidgetState::new(Box::new(Self { params }))
|
WidgetState::new(Box::new(Self { params }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetObj for SpriteBox {
|
impl WidgetObj for WidgetSprite {
|
||||||
fn draw(&mut self, state: &mut super::DrawState, _params: &super::DrawParams) {
|
fn draw(&mut self, state: &mut super::DrawState, _params: &super::DrawParams) {
|
||||||
let boundary = drawing::Boundary::construct(state.transform_stack);
|
let boundary = drawing::Boundary::construct(state.transform_stack);
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,10 @@ use crate::{
|
|||||||
overlay::{FrameMeta, OverlayBackend, ShouldRender, ui_transform},
|
overlay::{FrameMeta, OverlayBackend, ShouldRender, ui_transform},
|
||||||
},
|
},
|
||||||
graphics::{CommandBuffers, ExtentExt},
|
graphics::{CommandBuffers, ExtentExt},
|
||||||
gui,
|
|
||||||
state::AppState,
|
state::AppState,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{asset::GuiAsset, timer::GuiTimer, timestep::Timestep};
|
use super::{timer::GuiTimer, timestep::Timestep};
|
||||||
|
|
||||||
const MAX_SIZE: u32 = 2048;
|
const MAX_SIZE: u32 = 2048;
|
||||||
const MAX_SIZE_VEC2: Vec2 = vec2(MAX_SIZE as _, MAX_SIZE as _);
|
const MAX_SIZE_VEC2: Vec2 = vec2(MAX_SIZE as _, MAX_SIZE as _);
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ use wgui::{
|
|||||||
renderer_vk::util,
|
renderer_vk::util,
|
||||||
taffy::{self, prelude::length},
|
taffy::{self, prelude::length},
|
||||||
widget::{
|
widget::{
|
||||||
div::Div,
|
div::WidgetDiv,
|
||||||
rectangle::{Rectangle, RectangleParams},
|
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||||
util::WLength,
|
util::WLength,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -56,7 +56,7 @@ where
|
|||||||
|
|
||||||
let (background, _) = panel.layout.add_child(
|
let (background, _) = panel.layout.add_child(
|
||||||
panel.layout.root_widget,
|
panel.layout.root_widget,
|
||||||
Rectangle::create(RectangleParams {
|
WidgetRectangle::create(WidgetRectangleParams {
|
||||||
color: wgui::drawing::Color::new(0., 0., 0., 0.6),
|
color: wgui::drawing::Color::new(0., 0., 0., 0.6),
|
||||||
round: WLength::Units(4.0),
|
round: WLength::Units(4.0),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -85,7 +85,7 @@ where
|
|||||||
for row in 0..layout.key_sizes.len() {
|
for row in 0..layout.key_sizes.len() {
|
||||||
let (div, _) = panel.layout.add_child(
|
let (div, _) = panel.layout.add_child(
|
||||||
background,
|
background,
|
||||||
Div::create().unwrap(),
|
WidgetDiv::create().unwrap(),
|
||||||
taffy::Style {
|
taffy::Style {
|
||||||
flex_direction: taffy::FlexDirection::Row,
|
flex_direction: taffy::FlexDirection::Row,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -106,7 +106,7 @@ where
|
|||||||
let Some(key) = layout.get_key_data(keymap.as_ref(), has_altgr, col, row) else {
|
let Some(key) = layout.get_key_data(keymap.as_ref(), has_altgr, col, row) else {
|
||||||
let _ = panel.layout.add_child(
|
let _ = panel.layout.add_child(
|
||||||
div,
|
div,
|
||||||
Div::create()?,
|
WidgetDiv::create()?,
|
||||||
taffy::Style {
|
taffy::Style {
|
||||||
size: taffy_size,
|
size: taffy_size,
|
||||||
min_size: taffy_size,
|
min_size: taffy_size,
|
||||||
@@ -173,7 +173,7 @@ where
|
|||||||
.layout
|
.layout
|
||||||
.state
|
.state
|
||||||
.widgets
|
.widgets
|
||||||
.get_as::<Rectangle>(*widget_id)
|
.get_as::<WidgetRectangle>(*widget_id)
|
||||||
.unwrap(); // want panic
|
.unwrap(); // want panic
|
||||||
|
|
||||||
Rc::new(KeyState {
|
Rc::new(KeyState {
|
||||||
@@ -291,7 +291,7 @@ fn get_anim_transform(pos: f32, widget_size: Vec2) -> Mat4 {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_anim_color(key_state: &KeyState, rect: &mut Rectangle, pos: f32) {
|
fn set_anim_color(key_state: &KeyState, rect: &mut WidgetRectangle, pos: f32) {
|
||||||
let br1 = pos * 0.25;
|
let br1 = pos * 0.25;
|
||||||
let br2 = pos * 0.15;
|
let br2 = pos * 0.15;
|
||||||
|
|
||||||
@@ -314,7 +314,7 @@ fn on_enter_anim(
|
|||||||
10,
|
10,
|
||||||
AnimationEasing::OutBack,
|
AnimationEasing::OutBack,
|
||||||
Box::new(move |common, data| {
|
Box::new(move |common, data| {
|
||||||
let rect = data.obj.get_as_mut::<Rectangle>();
|
let rect = data.obj.get_as_mut::<WidgetRectangle>();
|
||||||
set_anim_color(&key_state, rect, data.pos);
|
set_anim_color(&key_state, rect, data.pos);
|
||||||
data.data.transform = get_anim_transform(data.pos, data.widget_size);
|
data.data.transform = get_anim_transform(data.pos, data.widget_size);
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
@@ -332,7 +332,7 @@ fn on_leave_anim(
|
|||||||
15,
|
15,
|
||||||
AnimationEasing::OutQuad,
|
AnimationEasing::OutQuad,
|
||||||
Box::new(move |common, data| {
|
Box::new(move |common, data| {
|
||||||
let rect = data.obj.get_as_mut::<Rectangle>();
|
let rect = data.obj.get_as_mut::<WidgetRectangle>();
|
||||||
set_anim_color(&key_state, rect, 1.0 - data.pos);
|
set_anim_color(&key_state, rect, 1.0 - data.pos);
|
||||||
data.data.transform = get_anim_transform(1.0 - data.pos, data.widget_size);
|
data.data.transform = get_anim_transform(1.0 - data.pos, data.widget_size);
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
@@ -348,7 +348,7 @@ fn on_press_anim(
|
|||||||
if key_state.drawn_state.get() {
|
if key_state.drawn_state.get() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let rect = data.obj.get_as_mut::<Rectangle>();
|
let rect = data.obj.get_as_mut::<WidgetRectangle>();
|
||||||
rect.params.border_color = Color::new(1.0, 1.0, 1.0, 1.0);
|
rect.params.border_color = Color::new(1.0, 1.0, 1.0, 1.0);
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
key_state.drawn_state.set(true);
|
key_state.drawn_state.set(true);
|
||||||
@@ -362,7 +362,7 @@ fn on_release_anim(
|
|||||||
if !key_state.drawn_state.get() {
|
if !key_state.drawn_state.get() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let rect = data.obj.get_as_mut::<Rectangle>();
|
let rect = data.obj.get_as_mut::<WidgetRectangle>();
|
||||||
rect.params.border_color = key_state.border_color;
|
rect.params.border_color = key_state.border_color;
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
key_state.drawn_state.set(false);
|
key_state.drawn_state.set(false);
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ use wgui::{
|
|||||||
prelude::{auto, length, percent},
|
prelude::{auto, length, percent},
|
||||||
},
|
},
|
||||||
widget::{
|
widget::{
|
||||||
rectangle::{Rectangle, RectangleParams},
|
label::{WidgetLabelParams, WidgetLabel},
|
||||||
text::{TextLabel, TextParams},
|
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||||
util::WLength,
|
util::WLength,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -176,7 +176,7 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<(OverlayState, Box<dyn
|
|||||||
.layout
|
.layout
|
||||||
.add_child(
|
.add_child(
|
||||||
panel.layout.root_widget,
|
panel.layout.root_widget,
|
||||||
Rectangle::create(RectangleParams {
|
WidgetRectangle::create(WidgetRectangleParams {
|
||||||
color: parse_color_hex("#1e2030").unwrap(),
|
color: parse_color_hex("#1e2030").unwrap(),
|
||||||
border_color: parse_color_hex("#5e7090").unwrap(),
|
border_color: parse_color_hex("#5e7090").unwrap(),
|
||||||
border: 1.0,
|
border: 1.0,
|
||||||
@@ -196,9 +196,9 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<(OverlayState, Box<dyn
|
|||||||
|
|
||||||
let _ = panel.layout.add_child(
|
let _ = panel.layout.add_child(
|
||||||
rect,
|
rect,
|
||||||
TextLabel::create(
|
WidgetLabel::create(
|
||||||
&mut i18n,
|
&mut i18n,
|
||||||
TextParams {
|
WidgetLabelParams {
|
||||||
content: Translation::from_raw_text(&title),
|
content: Translation::from_raw_text(&title),
|
||||||
style: TextStyle {
|
style: TextStyle {
|
||||||
color: parse_color_hex("#ffffff"),
|
color: parse_color_hex("#ffffff"),
|
||||||
@@ -219,9 +219,9 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<(OverlayState, Box<dyn
|
|||||||
|
|
||||||
let _ = panel.layout.add_child(
|
let _ = panel.layout.add_child(
|
||||||
rect,
|
rect,
|
||||||
TextLabel::create(
|
WidgetLabel::create(
|
||||||
&mut i18n,
|
&mut i18n,
|
||||||
TextParams {
|
WidgetLabelParams {
|
||||||
content: Translation::from_raw_text(&toast.body),
|
content: Translation::from_raw_text(&toast.body),
|
||||||
style: TextStyle {
|
style: TextStyle {
|
||||||
weight: Some(FontWeight::Bold),
|
weight: Some(FontWeight::Bold),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use regex::Regex;
|
|||||||
use wgui::{
|
use wgui::{
|
||||||
event::{self, EventListenerKind},
|
event::{self, EventListenerKind},
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
widget::text::TextLabel,
|
widget::label::WidgetLabel,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -46,7 +46,7 @@ where
|
|||||||
.layout
|
.layout
|
||||||
.state
|
.state
|
||||||
.widgets
|
.widgets
|
||||||
.get_as::<TextLabel>(*widget_id)
|
.get_as::<WidgetLabel>(*widget_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let format = match role {
|
let format = match role {
|
||||||
@@ -165,6 +165,6 @@ fn clock_on_tick(
|
|||||||
|tz| format!("{}", Local::now().with_timezone(tz).format(&clock.format)),
|
|tz| format!("{}", Local::now().with_timezone(tz).format(&clock.format)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let label = data.obj.get_as_mut::<TextLabel>();
|
let label = data.obj.get_as_mut::<WidgetLabel>();
|
||||||
label.set_text(&mut common.i18n(), Translation::from_raw_text(&date_time));
|
label.set_text(&mut common.i18n(), Translation::from_raw_text(&date_time));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user