|
|
|
|
@@ -307,6 +307,10 @@ fn column_headings(value: &[&str]) -> Vec<WidgetInstance> {
|
|
|
|
|
value.iter().map(|text| TextLabel::new(*text).widget_instance()).collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn single_widget_cells(widgets: Vec<WidgetInstance>) -> Vec<Vec<WidgetInstance>> {
|
|
|
|
|
widgets.into_iter().map(|widget| vec![widget]).collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn label(x: impl Into<String>) -> Vec<LayoutGroup> {
|
|
|
|
|
let error = vec![TextLabel::new(x).widget_instance()];
|
|
|
|
|
vec![LayoutGroup::row(error)]
|
|
|
|
|
@@ -319,18 +323,20 @@ trait TableItemLayout {
|
|
|
|
|
data.breadcrumbs.push(self.identifier());
|
|
|
|
|
self.value_page(data)
|
|
|
|
|
}
|
|
|
|
|
/// Renders this value as a single inline widget inside an item of a `List`.
|
|
|
|
|
/// `target` is the [`PathStep`] to push when the widget is clicked to drill into the value.
|
|
|
|
|
/// Renders this value as the inline widgets filling one table cell inside an item of a `List`.
|
|
|
|
|
/// `target` is the [`PathStep`] to push when a widget is clicked to drill into the value.
|
|
|
|
|
/// `data` provides shared context (notably `network_interface`) for types whose label or content
|
|
|
|
|
/// depends on lookup beyond their own value (e.g. `NodeId` resolving a node's display name).
|
|
|
|
|
/// The default is a button labeled with `identifier()`. Types whose values are best shown
|
|
|
|
|
/// inline (colors, transforms, primitives, etc.) override this to ignore `target` and
|
|
|
|
|
/// return a richer non-navigating widget.
|
|
|
|
|
fn value_widget(&self, target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
TextButton::new(self.identifier())
|
|
|
|
|
.on_update(move |_| DataPanelMessage::PushToElementPath { step: target.clone() }.into())
|
|
|
|
|
.narrow(true)
|
|
|
|
|
.widget_instance()
|
|
|
|
|
/// The default is a single button labeled with `identifier()`. Types whose values are best shown
|
|
|
|
|
/// inline (colors, transforms, primitives, etc.) override this to ignore `target` and return a
|
|
|
|
|
/// richer non-navigating widget, optionally joined by companions like a drill-in button.
|
|
|
|
|
fn value_widgets(&self, target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
vec![
|
|
|
|
|
TextButton::new(self.identifier())
|
|
|
|
|
.on_update(move |_| DataPanelMessage::PushToElementPath { step: target.clone() }.into())
|
|
|
|
|
.narrow(true)
|
|
|
|
|
.widget_instance(),
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![]
|
|
|
|
|
@@ -371,20 +377,20 @@ impl<T: TableItemLayout> TableItemLayout for Item<T> {
|
|
|
|
|
let attribute_keys: Vec<String> = self.attributes().keys().map(str::to_string).collect();
|
|
|
|
|
|
|
|
|
|
// A single element, so no leading ID column, unlike the `List` table
|
|
|
|
|
let mut values = vec![self.element().value_widget(PathStep::Element(0), data)];
|
|
|
|
|
let mut values = vec![self.element().value_widgets(PathStep::Element(0), data)];
|
|
|
|
|
for key in &attribute_keys {
|
|
|
|
|
let target = PathStep::Attribute { row: 0, key: key.clone() };
|
|
|
|
|
let widget = self.attributes().get_any(key).and_then(|any| dispatch_value_widget(any, target, data)).unwrap_or_else(|| {
|
|
|
|
|
let cell = self.attributes().get_any(key).and_then(|any| dispatch_value_widgets(any, target, data)).unwrap_or_else(|| {
|
|
|
|
|
let text = self.attributes().display_value(key, display_value_override).unwrap_or_else(|| "-".to_string());
|
|
|
|
|
TextLabel::new(text).narrow(true).widget_instance()
|
|
|
|
|
vec![TextLabel::new(text).narrow(true).widget_instance()]
|
|
|
|
|
});
|
|
|
|
|
values.push(widget);
|
|
|
|
|
values.push(cell);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut column_names = vec!["element"];
|
|
|
|
|
column_names.extend(attribute_keys.iter().map(|s| s.as_str()));
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::table(vec![column_headings(&column_names), values], false)]
|
|
|
|
|
vec![LayoutGroup::table_of_cells(vec![single_widget_cells(column_headings(&column_names)), values], false)]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -429,14 +435,17 @@ impl<T: TableItemLayout> TableItemLayout for List<T> {
|
|
|
|
|
let mut rows = (0..self.len())
|
|
|
|
|
.map(|index| {
|
|
|
|
|
let element = self.element(index).unwrap();
|
|
|
|
|
let mut values = vec![TextLabel::new(format!("{index}")).narrow(true).widget_instance(), element.value_widget(PathStep::Element(index), data)];
|
|
|
|
|
let mut values = vec![
|
|
|
|
|
vec![TextLabel::new(format!("{index}")).narrow(true).widget_instance()],
|
|
|
|
|
element.value_widgets(PathStep::Element(index), data),
|
|
|
|
|
];
|
|
|
|
|
for key in &attribute_keys {
|
|
|
|
|
let target = PathStep::Attribute { row: index, key: key.clone() };
|
|
|
|
|
let widget = self.attribute_any(key, index).and_then(|any| dispatch_value_widget(any, target, data)).unwrap_or_else(|| {
|
|
|
|
|
let cell = self.attribute_any(key, index).and_then(|any| dispatch_value_widgets(any, target, data)).unwrap_or_else(|| {
|
|
|
|
|
let text = self.attribute_display_value(key, index, display_value_override).unwrap_or_else(|| "-".to_string());
|
|
|
|
|
TextLabel::new(text).narrow(true).widget_instance()
|
|
|
|
|
vec![TextLabel::new(text).narrow(true).widget_instance()]
|
|
|
|
|
});
|
|
|
|
|
values.push(widget);
|
|
|
|
|
values.push(cell);
|
|
|
|
|
}
|
|
|
|
|
values
|
|
|
|
|
})
|
|
|
|
|
@@ -444,9 +453,9 @@ impl<T: TableItemLayout> TableItemLayout for List<T> {
|
|
|
|
|
|
|
|
|
|
let mut column_names = vec!["", "element"];
|
|
|
|
|
column_names.extend(attribute_keys.iter().map(|s| s.as_str()));
|
|
|
|
|
rows.insert(0, column_headings(&column_names));
|
|
|
|
|
rows.insert(0, single_widget_cells(column_headings(&column_names)));
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::table(rows, false)]
|
|
|
|
|
vec![LayoutGroup::table_of_cells(rows, false)]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -478,8 +487,8 @@ impl TableItemLayout for DashPattern {
|
|
|
|
|
self.value_page(data)
|
|
|
|
|
}
|
|
|
|
|
// Label the spreadsheet's element button with the inner list's identifier, like Artboard
|
|
|
|
|
fn value_widget(&self, target: PathStep, data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
self.0.value_widget(target, data)
|
|
|
|
|
fn value_widgets(&self, target: PathStep, data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
self.0.value_widgets(target, data)
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
self.0.layout_with_breadcrumb(data)
|
|
|
|
|
@@ -498,8 +507,8 @@ impl TableItemLayout for BoxCorners {
|
|
|
|
|
self.value_page(data)
|
|
|
|
|
}
|
|
|
|
|
// Label the spreadsheet's element button with the inner list's identifier, like Artboard
|
|
|
|
|
fn value_widget(&self, target: PathStep, data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
self.0.value_widget(target, data)
|
|
|
|
|
fn value_widgets(&self, target: PathStep, data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
self.0.value_widgets(target, data)
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
self.0.layout_with_breadcrumb(data)
|
|
|
|
|
@@ -709,16 +718,17 @@ impl TableItemLayout for Color {
|
|
|
|
|
fn identifier(&self) -> String {
|
|
|
|
|
format!("Color (#{})", SRGBA8::from(*self).to_rgba_hex())
|
|
|
|
|
}
|
|
|
|
|
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
ColorInput::new(FillChoiceUI::from(&FillChoice::Solid(*self)))
|
|
|
|
|
.disabled(true)
|
|
|
|
|
.menu_direction(Some(MenuDirection::Top))
|
|
|
|
|
.narrow(true)
|
|
|
|
|
.widget_instance()
|
|
|
|
|
fn value_widgets(&self, _target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
vec![
|
|
|
|
|
ColorInput::new(FillChoiceUI::from(&FillChoice::Solid(*self)))
|
|
|
|
|
.disabled(true)
|
|
|
|
|
.menu_direction(Some(MenuDirection::Top))
|
|
|
|
|
.narrow(true)
|
|
|
|
|
.widget_instance(),
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = vec![self.value_widget(PathStep::Element(0), _data)];
|
|
|
|
|
vec![LayoutGroup::row(widgets)]
|
|
|
|
|
vec![LayoutGroup::row(self.value_widgets(PathStep::Element(0), _data))]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -729,16 +739,27 @@ impl TableItemLayout for Gradient {
|
|
|
|
|
fn identifier(&self) -> String {
|
|
|
|
|
format!("Gradient ({} stops)", self.len())
|
|
|
|
|
}
|
|
|
|
|
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
ColorInput::new(FillChoiceUI::from(&FillChoice::Gradient(self.clone())))
|
|
|
|
|
.menu_direction(Some(MenuDirection::Top))
|
|
|
|
|
.disabled(true)
|
|
|
|
|
.narrow(true)
|
|
|
|
|
.widget_instance()
|
|
|
|
|
// The wrapping `Item` already contributes the breadcrumb; the inner list supplies the next level
|
|
|
|
|
fn layout_with_breadcrumb(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
self.value_page(data)
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = vec![self.value_widget(PathStep::Element(0), _data)];
|
|
|
|
|
vec![LayoutGroup::row(widgets)]
|
|
|
|
|
// The preview widget doesn't navigate, so a drill-in button beside it opens the newtype's underlying color list
|
|
|
|
|
fn value_widgets(&self, target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
vec![
|
|
|
|
|
TextButton::new(self.as_color_list().identifier())
|
|
|
|
|
.on_update(move |_| DataPanelMessage::PushToElementPath { step: target.clone() }.into())
|
|
|
|
|
.narrow(true)
|
|
|
|
|
.widget_instance(),
|
|
|
|
|
Separator::new(SeparatorStyle::Related).widget_instance(),
|
|
|
|
|
ColorInput::new(FillChoiceUI::from(&FillChoice::Gradient(self.clone())))
|
|
|
|
|
.menu_direction(Some(MenuDirection::Top))
|
|
|
|
|
.disabled(true)
|
|
|
|
|
.narrow(true)
|
|
|
|
|
.widget_instance(),
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
self.as_color_list().layout_with_breadcrumb(data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -854,11 +875,11 @@ impl TableItemLayout for bool {
|
|
|
|
|
fn identifier(&self) -> String {
|
|
|
|
|
"Bool".to_string()
|
|
|
|
|
}
|
|
|
|
|
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
CheckboxInput::new(*self).disabled(true).widget_instance()
|
|
|
|
|
fn value_widgets(&self, _target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
vec![CheckboxInput::new(*self).disabled(true).widget_instance()]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
|
|
|
|
|
vec![LayoutGroup::row(self.value_widgets(PathStep::Element(0), _data))]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -888,11 +909,11 @@ impl TableItemLayout for Option<f64> {
|
|
|
|
|
fn identifier(&self) -> String {
|
|
|
|
|
"Option<f64>".to_string()
|
|
|
|
|
}
|
|
|
|
|
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
TextLabel::new(format!("{self:?}")).narrow(true).widget_instance()
|
|
|
|
|
fn value_widgets(&self, _target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
vec![TextLabel::new(format!("{self:?}")).narrow(true).widget_instance()]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
|
|
|
|
|
vec![LayoutGroup::row(self.value_widgets(PathStep::Element(0), _data))]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -903,11 +924,11 @@ impl TableItemLayout for DVec2 {
|
|
|
|
|
fn identifier(&self) -> String {
|
|
|
|
|
"Vec2".to_string()
|
|
|
|
|
}
|
|
|
|
|
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
TextLabel::new(format_dvec2(*self)).narrow(true).widget_instance()
|
|
|
|
|
fn value_widgets(&self, _target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
vec![TextLabel::new(format_dvec2(*self)).narrow(true).widget_instance()]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
|
|
|
|
|
vec![LayoutGroup::row(self.value_widgets(PathStep::Element(0), _data))]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -918,11 +939,11 @@ impl TableItemLayout for Vec2 {
|
|
|
|
|
fn identifier(&self) -> String {
|
|
|
|
|
"Vec2".to_string()
|
|
|
|
|
}
|
|
|
|
|
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
TextLabel::new(format_dvec2(DVec2::new(self.x as f64, self.y as f64))).narrow(true).widget_instance()
|
|
|
|
|
fn value_widgets(&self, _target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
vec![TextLabel::new(format_dvec2(DVec2::new(self.x as f64, self.y as f64))).narrow(true).widget_instance()]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
|
|
|
|
|
vec![LayoutGroup::row(self.value_widgets(PathStep::Element(0), _data))]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -933,11 +954,11 @@ impl TableItemLayout for DAffine2 {
|
|
|
|
|
fn identifier(&self) -> String {
|
|
|
|
|
"Transform".to_string()
|
|
|
|
|
}
|
|
|
|
|
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
TextLabel::new(format_transform_matrix(*self)).narrow(true).widget_instance()
|
|
|
|
|
fn value_widgets(&self, _target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
vec![TextLabel::new(format_transform_matrix(*self)).narrow(true).widget_instance()]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
|
|
|
|
|
vec![LayoutGroup::row(self.value_widgets(PathStep::Element(0), _data))]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -948,12 +969,12 @@ impl TableItemLayout for Affine2 {
|
|
|
|
|
fn identifier(&self) -> String {
|
|
|
|
|
"Transform".to_string()
|
|
|
|
|
}
|
|
|
|
|
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
fn value_widgets(&self, _target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
let matrix = DAffine2::from_cols_array(&self.to_cols_array().map(|x| x as f64));
|
|
|
|
|
TextLabel::new(format_transform_matrix(matrix)).narrow(true).widget_instance()
|
|
|
|
|
vec![TextLabel::new(format_transform_matrix(matrix)).narrow(true).widget_instance()]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
|
|
|
|
|
vec![LayoutGroup::row(self.value_widgets(PathStep::Element(0), _data))]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -968,11 +989,11 @@ macro_rules! impl_table_item_layout_for_choice_enum {
|
|
|
|
|
fn identifier(&self) -> String {
|
|
|
|
|
self.to_string()
|
|
|
|
|
}
|
|
|
|
|
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
TextLabel::new(self.to_string()).narrow(true).widget_instance()
|
|
|
|
|
fn value_widgets(&self, _target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
vec![TextLabel::new(self.to_string()).narrow(true).widget_instance()]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
|
|
|
|
|
vec![LayoutGroup::row(self.value_widgets(PathStep::Element(0), _data))]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)*
|
|
|
|
|
@@ -1022,11 +1043,11 @@ impl TableItemLayout for ReferencePoint {
|
|
|
|
|
fn identifier(&self) -> String {
|
|
|
|
|
format!("{self:?}")
|
|
|
|
|
}
|
|
|
|
|
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
TextLabel::new(self.identifier()).narrow(true).widget_instance()
|
|
|
|
|
fn value_widgets(&self, _target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
vec![TextLabel::new(self.identifier()).narrow(true).widget_instance()]
|
|
|
|
|
}
|
|
|
|
|
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
|
|
|
|
|
vec![LayoutGroup::row(self.value_widgets(PathStep::Element(0), _data))]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1056,7 +1077,7 @@ impl TableItemLayout for NodeId {
|
|
|
|
|
// in the Node Graph / Layers panels. The lookup uses `data.node_lookup_network_path` (set by the enclosing
|
|
|
|
|
// `List<NodeId>` if rendering a path) so the resolution succeeds at any nesting depth. The button's icon
|
|
|
|
|
// signals layer-vs-node kind. Falls back to "Node {id}" with no icon if the lookup misses.
|
|
|
|
|
fn value_widget(&self, target: PathStep, data: &LayoutData) -> WidgetInstance {
|
|
|
|
|
fn value_widgets(&self, target: PathStep, data: &LayoutData) -> Vec<WidgetInstance> {
|
|
|
|
|
let label = node_id_display_label(*self, data.network_interface, &data.node_lookup_network_path);
|
|
|
|
|
let mut button = TextButton::new(label)
|
|
|
|
|
.on_update(move |_| DataPanelMessage::PushToElementPath { step: target.clone() }.into())
|
|
|
|
|
@@ -1065,7 +1086,7 @@ impl TableItemLayout for NodeId {
|
|
|
|
|
let icon = if data.network_interface.is_layer(self, &data.node_lookup_network_path) { "Layer" } else { "Node" };
|
|
|
|
|
button = button.icon(icon);
|
|
|
|
|
}
|
|
|
|
|
button.widget_instance()
|
|
|
|
|
vec![button.widget_instance()]
|
|
|
|
|
}
|
|
|
|
|
// The value page shows the node's kind, name (editable), lock/visibility toggles, and a "Select Layer/Node" action button.
|
|
|
|
|
fn value_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
|
|
|
|
@@ -1240,20 +1261,20 @@ fn display_value_override(any: &dyn Any) -> Option<String> {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Type-dispatched widget for displaying an attribute value in a `List<T>` item.
|
|
|
|
|
/// Delegates to [`TableItemLayout::value_widget`] so the same widget code is shared between
|
|
|
|
|
/// Type-dispatched cell widgets for displaying an attribute value in a `List<T>` item.
|
|
|
|
|
/// Delegates to [`TableItemLayout::value_widgets`] so the same widget code is shared between
|
|
|
|
|
/// element-column rendering and attribute-column rendering. Returns `None` for unrecognized
|
|
|
|
|
/// types so the caller can fall back to a debug-formatted [`TextLabel`].
|
|
|
|
|
fn dispatch_value_widget(any: &dyn Any, target: PathStep, data: &LayoutData) -> Option<WidgetInstance> {
|
|
|
|
|
fn dispatch_value_widgets(any: &dyn Any, target: PathStep, data: &LayoutData) -> Option<Vec<WidgetInstance>> {
|
|
|
|
|
// `NodeIdPath` (e.g. the `editor:layer_path` attribute) drills into its inner path list, matching `drilldown_attribute_layout`.
|
|
|
|
|
if let Some(path) = any.downcast_ref::<NodeIdPath>() {
|
|
|
|
|
return Some(path.0.value_widget(target, data));
|
|
|
|
|
return Some(path.0.value_widgets(target, data));
|
|
|
|
|
}
|
|
|
|
|
macro_rules! check {
|
|
|
|
|
( $($ty:ty),* $(,)? ) => {
|
|
|
|
|
$(
|
|
|
|
|
if let Some(value) = any.downcast_ref::<$ty>() {
|
|
|
|
|
return Some(value.value_widget(target, data));
|
|
|
|
|
return Some(value.value_widgets(target, data));
|
|
|
|
|
}
|
|
|
|
|
)*
|
|
|
|
|
};
|
|
|
|
|
@@ -1291,14 +1312,14 @@ fn table_node_id_path_layout_with_breadcrumb(path: &List<NodeId>, data: &mut Lay
|
|
|
|
|
let node_id = path.element(index).unwrap();
|
|
|
|
|
let prefix: Vec<NodeId> = path.iter_element_values().take(index).copied().collect();
|
|
|
|
|
let saved = std::mem::replace(&mut data.node_lookup_network_path, prefix);
|
|
|
|
|
let widget = node_id.value_widget(PathStep::Element(index), data);
|
|
|
|
|
let widgets = node_id.value_widgets(PathStep::Element(index), data);
|
|
|
|
|
data.node_lookup_network_path = saved;
|
|
|
|
|
vec![TextLabel::new(format!("{index}")).narrow(true).widget_instance(), widget]
|
|
|
|
|
vec![vec![TextLabel::new(format!("{index}")).narrow(true).widget_instance()], widgets]
|
|
|
|
|
})
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
rows.insert(0, column_headings(&["", "element"]));
|
|
|
|
|
rows.insert(0, single_widget_cells(column_headings(&["", "element"])));
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::table(rows, false)]
|
|
|
|
|
vec![LayoutGroup::table_of_cells(rows, false)]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Type-dispatched recursion into an attribute value for the Data panel breadcrumb navigation.
|
|
|
|
|
|