mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Add a drill-in button beside Data panel gradient preview widgets (#4398)
This commit is contained in:
@@ -117,23 +117,26 @@ impl LayoutMessageHandler {
|
||||
}
|
||||
LayoutGroup::Table(WidgetTable { rows, .. }) => {
|
||||
for (row_index, row) in rows.iter().enumerate() {
|
||||
for (value_index, value) in row.iter().enumerate() {
|
||||
// Return if this is the correct ID
|
||||
if value.widget_id == widget_id {
|
||||
widget_path.push(row_index);
|
||||
widget_path.push(value_index);
|
||||
return Some((value, widget_path));
|
||||
}
|
||||
for (cell_index, cell) in row.iter().enumerate() {
|
||||
for (value_index, value) in cell.iter().enumerate() {
|
||||
// Return if this is the correct ID
|
||||
if value.widget_id == widget_id {
|
||||
widget_path.push(row_index);
|
||||
widget_path.push(cell_index);
|
||||
widget_path.push(value_index);
|
||||
return Some((value, widget_path));
|
||||
}
|
||||
|
||||
if let Widget::PopoverButton(popover) = &*value.widget {
|
||||
stack.extend(
|
||||
popover
|
||||
.popover_layout
|
||||
.0
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(child, val)| ([widget_path.as_slice(), &[row_index, value_index, child]].concat(), val)),
|
||||
);
|
||||
if let Widget::PopoverButton(popover) = &*value.widget {
|
||||
stack.extend(
|
||||
popover
|
||||
.popover_layout
|
||||
.0
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(child, val)| ([widget_path.as_slice(), &[row_index, cell_index, value_index, child]].concat(), val)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ impl<'a> Iterator for WidgetIter<'a> {
|
||||
self.next()
|
||||
}
|
||||
Some(LayoutGroup::Table(WidgetTable { rows, .. })) => {
|
||||
self.table.extend(rows.iter().flatten().rev());
|
||||
self.table.extend(rows.iter().flatten().flatten().rev());
|
||||
self.next()
|
||||
}
|
||||
Some(LayoutGroup::Section(WidgetSection { layout, .. })) => {
|
||||
@@ -325,7 +325,7 @@ impl<'a> Iterator for WidgetIterMut<'a> {
|
||||
self.next()
|
||||
}
|
||||
Some(LayoutGroup::Table(WidgetTable { rows, .. })) => {
|
||||
self.table.extend(rows.iter_mut().flatten().rev());
|
||||
self.table.extend(rows.iter_mut().flatten().flatten().rev());
|
||||
self.next()
|
||||
}
|
||||
Some(LayoutGroup::Section(WidgetSection { layout, .. })) => {
|
||||
@@ -365,8 +365,9 @@ pub struct WidgetRow {
|
||||
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
|
||||
#[derive(Default, Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct WidgetTable {
|
||||
/// Rows of cells, each cell holding one or more widgets laid out inline.
|
||||
#[serde(rename = "tableWidgets")]
|
||||
pub rows: Vec<Vec<WidgetInstance>>,
|
||||
pub rows: Vec<Vec<Vec<WidgetInstance>>>,
|
||||
pub unstyled: bool,
|
||||
}
|
||||
|
||||
@@ -412,7 +413,14 @@ impl LayoutGroup {
|
||||
Self::Column(WidgetColumn { widgets })
|
||||
}
|
||||
|
||||
/// A table with one widget per cell.
|
||||
pub fn table(rows: Vec<Vec<WidgetInstance>>, unstyled: bool) -> Self {
|
||||
let rows = rows.into_iter().map(|row| row.into_iter().map(|widget| vec![widget]).collect()).collect();
|
||||
Self::Table(WidgetTable { rows, unstyled })
|
||||
}
|
||||
|
||||
/// A table whose cells may each hold multiple widgets laid out inline.
|
||||
pub fn table_of_cells(rows: Vec<Vec<Vec<WidgetInstance>>>, unstyled: bool) -> Self {
|
||||
Self::Table(WidgetTable { rows, unstyled })
|
||||
}
|
||||
|
||||
@@ -600,13 +608,17 @@ impl Diffable for LayoutGroup {
|
||||
}
|
||||
}
|
||||
Self::Table(WidgetTable { rows, .. }) => {
|
||||
for (row_idx, row) in rows.iter().enumerate() {
|
||||
for (col_idx, widget) in row.iter().enumerate() {
|
||||
widget_path.push(row_idx);
|
||||
widget_path.push(col_idx);
|
||||
widget.collect_checkbox_ids(layout_target, widget_path, checkbox_map);
|
||||
widget_path.pop();
|
||||
widget_path.pop();
|
||||
for (row_index, row) in rows.iter().enumerate() {
|
||||
for (column_index, cell) in row.iter().enumerate() {
|
||||
for (widget_index, widget) in cell.iter().enumerate() {
|
||||
widget_path.push(row_index);
|
||||
widget_path.push(column_index);
|
||||
widget_path.push(widget_index);
|
||||
widget.collect_checkbox_ids(layout_target, widget_path, checkbox_map);
|
||||
widget_path.pop();
|
||||
widget_path.pop();
|
||||
widget_path.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -626,13 +638,17 @@ impl Diffable for LayoutGroup {
|
||||
}
|
||||
}
|
||||
Self::Table(WidgetTable { rows, .. }) => {
|
||||
for (row_idx, row) in rows.iter_mut().enumerate() {
|
||||
for (col_idx, widget) in row.iter_mut().enumerate() {
|
||||
widget_path.push(row_idx);
|
||||
widget_path.push(col_idx);
|
||||
widget.replace_widget_ids(layout_target, widget_path, checkbox_map);
|
||||
widget_path.pop();
|
||||
widget_path.pop();
|
||||
for (row_index, row) in rows.iter_mut().enumerate() {
|
||||
for (column_index, cell) in row.iter_mut().enumerate() {
|
||||
for (widget_index, widget) in cell.iter_mut().enumerate() {
|
||||
widget_path.push(row_index);
|
||||
widget_path.push(column_index);
|
||||
widget_path.push(widget_index);
|
||||
widget.replace_widget_ids(layout_target, widget_path, checkbox_map);
|
||||
widget_path.pop();
|
||||
widget_path.pop();
|
||||
widget_path.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user