wgui: StyleSetRequest
This commit is contained in:
@@ -13,6 +13,7 @@ use wgui::{
|
||||
checkbox::ComponentCheckbox,
|
||||
},
|
||||
drawing::Color,
|
||||
event::StyleSetRequest,
|
||||
font_config::WguiFontConfig,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
@@ -123,17 +124,14 @@ impl TestbedGeneric {
|
||||
let div_visibility = state.fetch_widget(&layout.state, "div_visibility")?;
|
||||
|
||||
cb_visible.on_toggle(Box::new(move |common, evt| {
|
||||
let mut style = common
|
||||
.state
|
||||
.get_widget_style(div_visibility.id)
|
||||
.unwrap()
|
||||
.clone();
|
||||
style.display = if evt.checked {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
};
|
||||
common.alterables.set_style(div_visibility.id, style);
|
||||
common.alterables.set_style(
|
||||
div_visibility.id,
|
||||
StyleSetRequest::Display(if evt.checked {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
}),
|
||||
);
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
animation::{Animation, AnimationEasing},
|
||||
components::{Component, ComponentBase, ComponentTrait, RefreshData},
|
||||
drawing::{self},
|
||||
event::{self, CallbackDataCommon, EventListenerCollection, EventListenerKind},
|
||||
event::{self, CallbackDataCommon, EventAlterables, EventListenerCollection, EventListenerKind, StyleSetRequest},
|
||||
i18n::Translation,
|
||||
layout::{WidgetID, WidgetPair},
|
||||
renderer_vk::{
|
||||
@@ -76,13 +76,11 @@ struct State {
|
||||
}
|
||||
|
||||
struct Data {
|
||||
#[allow(dead_code)]
|
||||
body: WidgetID, // Div
|
||||
body_node: taffy::NodeId,
|
||||
slider_handle_rect_id: WidgetID, // Rectangle
|
||||
slider_text_id: WidgetID, // Text
|
||||
slider_handle: WidgetPair,
|
||||
slider_handle_id: WidgetID,
|
||||
slider_handle_node_id: taffy::NodeId,
|
||||
slider_body_node: taffy::NodeId,
|
||||
}
|
||||
|
||||
pub struct SliderValueChangedEvent {
|
||||
@@ -140,26 +138,31 @@ fn get_width(slider_body_node: taffy::NodeId, tree: &taffy::tree::TaffyTree<Widg
|
||||
}
|
||||
|
||||
fn conf_handle_style(
|
||||
alterables: &mut EventAlterables,
|
||||
values: &ValuesMinMax,
|
||||
slider_body_node: taffy::NodeId,
|
||||
slider_handle_id: WidgetID,
|
||||
body_node: taffy::NodeId,
|
||||
slider_handle_style: &taffy::Style,
|
||||
tree: &taffy::tree::TaffyTree<WidgetID>,
|
||||
) -> Option<taffy::Style> {
|
||||
) -> bool {
|
||||
/* returns false if nothing changed */
|
||||
let norm = values.to_normalized();
|
||||
|
||||
// convert normalized value to taffy percentage margin in percent
|
||||
let width = get_width(slider_body_node, tree);
|
||||
let width = get_width(body_node, tree);
|
||||
let percent_margin = (HANDLE_WIDTH / width) / 2.0;
|
||||
|
||||
let new_percent = percent(percent_margin + norm * (1.0 - percent_margin * 2.0));
|
||||
|
||||
if slider_handle_style.margin.left == new_percent {
|
||||
None // nothing changed
|
||||
} else {
|
||||
let mut new_style = slider_handle_style.clone();
|
||||
new_style.margin.left = new_percent;
|
||||
Some(new_style)
|
||||
return false; // nothing changed
|
||||
}
|
||||
|
||||
let mut margin = slider_handle_style.margin;
|
||||
margin.left = new_percent;
|
||||
alterables.set_style(slider_handle_id, StyleSetRequest::Margin(margin));
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
const PAD_PERCENT: f32 = 0.75;
|
||||
@@ -180,7 +183,7 @@ impl State {
|
||||
|
||||
let norm = map_mouse_x_to_normalized(
|
||||
mouse_pos.x - HANDLE_WIDTH / 2.0,
|
||||
get_width(data.slider_body_node, &common.state.tree) - HANDLE_WIDTH,
|
||||
get_width(data.body_node, &common.state.tree) - HANDLE_WIDTH,
|
||||
);
|
||||
|
||||
let target_value = self.values.get_from_normalized(norm);
|
||||
@@ -206,13 +209,19 @@ impl State {
|
||||
|
||||
let changed = self.values.value != before;
|
||||
let style = common.state.tree.style(data.slider_handle_node_id).unwrap();
|
||||
let Some(new_style) = conf_handle_style(&self.values, data.slider_body_node, style, &common.state.tree) else {
|
||||
return; //nothing changed visually
|
||||
};
|
||||
if !conf_handle_style(
|
||||
common.alterables,
|
||||
&self.values,
|
||||
data.slider_handle_id,
|
||||
data.body_node,
|
||||
style,
|
||||
&common.state.tree,
|
||||
) {
|
||||
return; // nothing changed visually
|
||||
}
|
||||
|
||||
common.alterables.mark_dirty(data.slider_handle_node_id);
|
||||
common.alterables.mark_redraw();
|
||||
common.alterables.set_style(data.slider_handle.id, new_style);
|
||||
|
||||
if let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(data.slider_text_id) {
|
||||
Self::update_text(common, &mut label, self.values.value);
|
||||
@@ -467,10 +476,9 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
||||
)?;
|
||||
|
||||
let data = Rc::new(Data {
|
||||
body: body_id,
|
||||
slider_handle,
|
||||
slider_handle_rect_id: slider_handle_rect.id,
|
||||
slider_body_node,
|
||||
body_node: slider_body_node,
|
||||
slider_handle_id: slider_handle.id,
|
||||
slider_handle_node_id,
|
||||
slider_text_id: slider_text.id,
|
||||
});
|
||||
|
||||
@@ -92,11 +92,16 @@ impl Event {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum StyleSetRequest {
|
||||
Display(taffy::Display),
|
||||
Margin(taffy::Rect<taffy::LengthPercentageAuto>),
|
||||
}
|
||||
|
||||
// alterables which will be dispatched in the next loop iteration phase
|
||||
#[derive(Default)]
|
||||
pub struct EventAlterables {
|
||||
pub dirty_nodes: Vec<taffy::NodeId>,
|
||||
pub style_set_requests: Vec<(WidgetID, taffy::Style)>,
|
||||
pub style_set_requests: Vec<(WidgetID, StyleSetRequest)>,
|
||||
pub animations: Vec<animation::Animation>,
|
||||
pub widgets_to_tick: HashSet<WidgetID>, // widgets which needs to be ticked in the next `Layout::update()` fn
|
||||
pub transform_stack: TransformStack,
|
||||
@@ -112,8 +117,8 @@ impl EventAlterables {
|
||||
self.needs_redraw = true;
|
||||
}
|
||||
|
||||
pub fn set_style(&mut self, widget_id: WidgetID, style: taffy::Style) {
|
||||
self.style_set_requests.push((widget_id, style));
|
||||
pub fn set_style(&mut self, widget_id: WidgetID, request: StyleSetRequest) {
|
||||
self.style_set_requests.push((widget_id, request));
|
||||
}
|
||||
|
||||
pub fn mark_dirty(&mut self, node_id: taffy::NodeId) {
|
||||
|
||||
@@ -721,20 +721,33 @@ impl Layout {
|
||||
}
|
||||
}
|
||||
|
||||
for (widget_id, new_style) in alterables.style_set_requests {
|
||||
if let Some(node_id) = self.state.nodes.get(widget_id) {
|
||||
let old_style = self.state.tree.style(*node_id).unwrap() /* always safe */;
|
||||
for (widget_id, style_request) in alterables.style_set_requests {
|
||||
let Some(node_id) = self.state.nodes.get(widget_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// refresh the component in case if visibility/display mode has changed
|
||||
if old_style.display != new_style.display
|
||||
&& let Some(component) = self.registered_components_to_refresh.get(node_id)
|
||||
{
|
||||
self.components_to_refresh_once.insert(component.clone());
|
||||
}
|
||||
// taffy requires us to copy this whole 536-byte style struct.
|
||||
// we can't get `&mut Style` directly from taffy unfortunately
|
||||
let mut cur_style = self.state.tree.style(*node_id).unwrap().clone() /* always safe */;
|
||||
|
||||
if let Err(e) = self.state.tree.set_style(*node_id, new_style) {
|
||||
log::error!("failed to set style for taffy widget ID {node_id:?}: {e:?}");
|
||||
match style_request {
|
||||
event::StyleSetRequest::Display(display) => {
|
||||
// refresh the component in case if visibility/display mode has changed
|
||||
if cur_style.display != display
|
||||
&& let Some(component) = self.registered_components_to_refresh.get(node_id)
|
||||
{
|
||||
self.components_to_refresh_once.insert(component.clone());
|
||||
}
|
||||
|
||||
cur_style.display = display;
|
||||
}
|
||||
event::StyleSetRequest::Margin(margin) => {
|
||||
cur_style.margin = margin;
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = self.state.tree.set_style(*node_id, cur_style) {
|
||||
log::error!("failed to set style for taffy widget ID {node_id:?}: {e:?}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use button::setup_custom_button;
|
||||
use glam::{vec2, Affine2, Vec2};
|
||||
use glam::{Affine2, Vec2, vec2};
|
||||
use label::setup_custom_label;
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
@@ -9,14 +9,14 @@ use wgui::{
|
||||
event::{
|
||||
Event as WguiEvent, EventAlterables, EventCallback, EventListenerID, EventListenerKind,
|
||||
InternalStateChangeEvent, MouseButtonIndex, MouseDownEvent, MouseLeaveEvent,
|
||||
MouseMotionEvent, MouseUpEvent, MouseWheelEvent,
|
||||
MouseMotionEvent, MouseUpEvent, MouseWheelEvent, StyleSetRequest,
|
||||
},
|
||||
gfx::cmd::WGfxClearMode,
|
||||
layout::{Layout, LayoutParams, WidgetID},
|
||||
parser::{CustomAttribsInfoOwned, ParserState},
|
||||
renderer_vk::context::Context as WguiContext,
|
||||
taffy,
|
||||
widget::{label::WidgetLabel, rectangle::WidgetRectangle, EventResult},
|
||||
widget::{EventResult, label::WidgetLabel, rectangle::WidgetRectangle},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -24,7 +24,7 @@ use crate::{
|
||||
state::AppState,
|
||||
subsystem::hid::WheelDelta,
|
||||
windowing::backend::{
|
||||
ui_transform, FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender,
|
||||
FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender, ui_transform,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -228,14 +228,7 @@ impl<S: 'static> GuiPanel<S> {
|
||||
display: taffy::Display,
|
||||
alterables: &mut EventAlterables,
|
||||
) {
|
||||
let mut style = self
|
||||
.layout
|
||||
.state
|
||||
.get_widget_style(widget_id)
|
||||
.unwrap_or(&taffy::Style::DEFAULT)
|
||||
.clone();
|
||||
style.display = display;
|
||||
alterables.set_style(widget_id, style);
|
||||
alterables.set_style(widget_id, StyleSetRequest::Display(display));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
use std::{collections::HashMap, rc::Rc};
|
||||
|
||||
use wgui::{
|
||||
components::button::ComponentButton, event::CallbackDataCommon, layout::WidgetID,
|
||||
parser::Fetchable, taffy,
|
||||
components::button::ComponentButton,
|
||||
event::{CallbackDataCommon, StyleSetRequest},
|
||||
layout::WidgetID,
|
||||
parser::Fetchable,
|
||||
taffy,
|
||||
};
|
||||
|
||||
use crate::gui::panel::GuiPanel;
|
||||
@@ -76,19 +79,15 @@ impl ButtonPaneTabSwitcher {
|
||||
}
|
||||
|
||||
fn set_tab_active(common: &mut CallbackDataCommon, data: &TabData, active: bool) {
|
||||
let mut style = common
|
||||
.state
|
||||
.get_widget_style(data.pane)
|
||||
.unwrap_or(&taffy::Style::DEFAULT)
|
||||
.clone();
|
||||
common.alterables.set_style(
|
||||
data.pane,
|
||||
StyleSetRequest::Display(if active {
|
||||
taffy::Display::Block
|
||||
} else {
|
||||
taffy::Display::None
|
||||
}),
|
||||
);
|
||||
|
||||
style.display = if active {
|
||||
taffy::Display::Block
|
||||
} else {
|
||||
taffy::Display::None
|
||||
};
|
||||
|
||||
common.alterables.set_style(data.pane, style);
|
||||
if let Some(button) = data.button.as_ref() {
|
||||
button.set_sticky_state(common, active);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user