wgui: attrib pairs
This commit is contained in:
@@ -24,11 +24,19 @@
|
||||
<CheckBox text="i'm checked by default" checked="1" />
|
||||
</div>
|
||||
|
||||
<label text="custom attrib test, you should see three rectangles below, each of them in R, G and B" />
|
||||
<label text="custom attrib test, you should see size rectangles below, each of them in R, G and B (if TESTBED is generic)" />
|
||||
<div flex_direction="row" gap="8">
|
||||
<rectangle _my_custom="red" width="16" height="16" />
|
||||
<rectangle _my_custom="green" width="16" height="16" />
|
||||
<rectangle _my_custom="blue" width="16" height="16" />
|
||||
<label text="lighter:" />
|
||||
|
||||
<rectangle _my_custom="red" _mult="1.0" width="16" height="16" />
|
||||
<rectangle _my_custom="green" _mult="1.0" width="16" height="16" />
|
||||
<rectangle _my_custom="blue" _mult="1.0" width="16" height="16" />
|
||||
|
||||
<label text="darker:" />
|
||||
|
||||
<rectangle _my_custom="red" _mult="0.5" width="16" height="16" />
|
||||
<rectangle _my_custom="green" _mult="0.5" width="16" height="16" />
|
||||
<rectangle _my_custom="blue" _mult="0.5" width="16" height="16" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -62,16 +62,28 @@ impl TestbedGeneric {
|
||||
let globals = WguiGlobals::new(Box::new(assets::Asset {}), Default::default())?;
|
||||
|
||||
let extra = ParseDocumentExtra {
|
||||
on_custom_attrib: Some(Box::new(move |par| {
|
||||
if par.attrib == "my_custom" {
|
||||
let mut rect = par.get_widget_as::<WidgetRectangle>().unwrap();
|
||||
rect.params.color = match par.value {
|
||||
"red" => Color::new(1.0, 0.0, 0.0, 1.0),
|
||||
"green" => Color::new(0.0, 1.0, 0.0, 1.0),
|
||||
"blue" => Color::new(0.0, 0.0, 1.0, 1.0),
|
||||
_ => Color::new(1.0, 1.0, 1.0, 1.0),
|
||||
}
|
||||
}
|
||||
on_custom_attribs: Some(Box::new(move |par| {
|
||||
let Some(my_custom_value) = par.get_value("my_custom") else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(mult_value) = par.get_value("mult") else {
|
||||
return;
|
||||
};
|
||||
|
||||
let mult_f32 = mult_value.parse::<f32>().unwrap();
|
||||
|
||||
let mut color = match my_custom_value {
|
||||
"red" => Color::new(1.0, 0.0, 0.0, 1.0),
|
||||
"green" => Color::new(0.0, 1.0, 0.0, 1.0),
|
||||
"blue" => Color::new(0.0, 0.0, 1.0, 1.0),
|
||||
_ => Color::new(1.0, 1.0, 1.0, 1.0),
|
||||
};
|
||||
|
||||
color = color.mult_rgb(mult_f32);
|
||||
|
||||
let mut rect = par.get_widget_as::<WidgetRectangle>().unwrap();
|
||||
rect.params.color = color;
|
||||
})),
|
||||
dev_mode: false,
|
||||
};
|
||||
|
||||
@@ -61,6 +61,16 @@ impl Color {
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn mult_rgb(&self, n: f32) -> Self {
|
||||
Self {
|
||||
r: self.r * n,
|
||||
g: self.g * n,
|
||||
b: self.b * n,
|
||||
a: self.a,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn lerp(&self, other: &Self, n: f32) -> Self {
|
||||
Self {
|
||||
@@ -159,12 +169,7 @@ fn draw_widget(
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_children(
|
||||
layout: &Layout,
|
||||
state: &mut DrawState,
|
||||
parent_node_id: taffy::NodeId,
|
||||
model: &glam::Mat4,
|
||||
) {
|
||||
fn draw_children(layout: &Layout, state: &mut DrawState, parent_node_id: taffy::NodeId, model: &glam::Mat4) {
|
||||
for node_id in layout.state.tree.child_ids(parent_node_id) {
|
||||
let Some(widget_id) = layout.state.tree.get_node_context(node_id).copied() else {
|
||||
debug_assert!(false);
|
||||
@@ -207,14 +212,7 @@ pub fn draw(layout: &Layout) -> anyhow::Result<Vec<RenderPrimitive>> {
|
||||
depth: 0.0,
|
||||
};
|
||||
|
||||
draw_widget(
|
||||
layout,
|
||||
&mut params,
|
||||
layout.root_node,
|
||||
style,
|
||||
root_widget,
|
||||
&model,
|
||||
);
|
||||
draw_widget(layout, &mut params, layout.root_node, style, root_widget, &model);
|
||||
|
||||
Ok(primitives)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use ouroboros::self_referencing;
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
cell::RefMut,
|
||||
collections::HashMap,
|
||||
@@ -640,7 +641,9 @@ fn parse_child<'a, U1, U2>(
|
||||
|
||||
// check for custom attributes (if the callback is set)
|
||||
if let Some(widget_id) = new_widget_id {
|
||||
if let Some(on_custom_attrib) = &ctx.doc_params.extra.on_custom_attrib {
|
||||
if let Some(on_custom_attribs) = &ctx.doc_params.extra.on_custom_attribs {
|
||||
let mut pairs = SmallVec::<[CustomAttribPair; 4]>::new();
|
||||
|
||||
for attrib in child_node.attributes() {
|
||||
let attr_name = attrib.name();
|
||||
if !attr_name.starts_with('_') || attr_name.is_empty() {
|
||||
@@ -649,12 +652,18 @@ fn parse_child<'a, U1, U2>(
|
||||
|
||||
let attr_without_prefix = &attr_name[1..]; // safe
|
||||
|
||||
on_custom_attrib(CustomAttribInfo {
|
||||
pairs.push(CustomAttribPair {
|
||||
attrib: attr_without_prefix,
|
||||
value: attrib.value(),
|
||||
});
|
||||
}
|
||||
|
||||
if !pairs.is_empty() {
|
||||
on_custom_attribs(CustomAttribsInfo {
|
||||
widgets: &ctx.layout.state.widgets,
|
||||
parent_id,
|
||||
widget_id,
|
||||
attrib: attr_without_prefix,
|
||||
value: attrib.value(),
|
||||
pairs: &pairs,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -694,16 +703,20 @@ fn create_default_context<'a, U1, U2>(
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CustomAttribInfo<'a> {
|
||||
pub parent_id: WidgetID,
|
||||
pub widget_id: WidgetID,
|
||||
pub widgets: &'a WidgetMap,
|
||||
pub struct CustomAttribPair<'a> {
|
||||
pub attrib: &'a str, // without _ at the beginning
|
||||
pub value: &'a str,
|
||||
}
|
||||
|
||||
pub struct CustomAttribsInfo<'a> {
|
||||
pub parent_id: WidgetID,
|
||||
pub widget_id: WidgetID,
|
||||
pub widgets: &'a WidgetMap,
|
||||
pub pairs: &'a [CustomAttribPair<'a>],
|
||||
}
|
||||
|
||||
// helper functions
|
||||
impl CustomAttribInfo<'_> {
|
||||
impl CustomAttribsInfo<'_> {
|
||||
pub fn get_widget(&self) -> Option<&Widget> {
|
||||
self.widgets.get(self.widget_id)
|
||||
}
|
||||
@@ -711,13 +724,24 @@ impl CustomAttribInfo<'_> {
|
||||
pub fn get_widget_as<T: 'static>(&self) -> Option<RefMut<T>> {
|
||||
self.widgets.get(self.widget_id)?.get_as_mut::<T>()
|
||||
}
|
||||
|
||||
pub fn get_value(&self, attrib_name: &str) -> Option<&str> {
|
||||
// O(n) search, these pairs won't be problematically big anyways
|
||||
for pair in self.pairs {
|
||||
if pair.attrib == attrib_name {
|
||||
return Some(pair.value);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub type OnCustomAttribFunc = Box<dyn Fn(CustomAttribInfo)>;
|
||||
pub type OnCustomAttribsFunc = Box<dyn Fn(CustomAttribsInfo)>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ParseDocumentExtra {
|
||||
pub on_custom_attrib: Option<OnCustomAttribFunc>, // all attributes with '_' character prepended
|
||||
pub on_custom_attribs: Option<OnCustomAttribsFunc>, // all attributes with '_' character prepended
|
||||
pub dev_mode: bool,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user