Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
161 commits
Select commit Hold shift + click to select a range
933e2ae
Add rank polymorphism node audit classifying all 271 nodes
Keavon Jul 3, 2026
a6c202e
Implement StaticType for Item<T>
Keavon Jul 3, 2026
0f7a40c
Generate Item and mapped List wire variants for nodes declaring an It…
Keavon Jul 3, 2026
4943f98
Migrate nine nodes to Item element-wise kernels, dissolving the blend…
Keavon Jul 3, 2026
b23817c
Document the Item kernel implementation and staging plan
Keavon Jul 3, 2026
8b77ed6
Route Item<Vector> through TaggedValue::TypeDefault
Keavon Jul 3, 2026
7658c14
Add executor integration tests covering the Item and List wire variants
Keavon Jul 3, 2026
76b0664
Collapse element-wise Item/List wire pairs to the List form for conve…
Keavon Jul 3, 2026
8575ef9
Migrate sixteen vector modifier nodes to Item element-wise kernels
Keavon Jul 3, 2026
0d781fe
Migrate Sample Image, Extend Image to Bounds, and Dehaze to Item elem…
Keavon Jul 3, 2026
62c2160
Fix bevel_with_transform test to actually exercise the transform attr…
Keavon Jul 3, 2026
2c35ac2
Implement From<T> for Item<T>
Keavon Jul 3, 2026
4a92466
Register PromoteNode rank adapters wrapping bare values into Item wires
Keavon Jul 3, 2026
833f0a1
Insert PromoteNode adapters for Item/List wire pair fields in the pre…
Keavon Jul 3, 2026
6e1fb6b
Define a real promote node backing the PromoteNode registry identifiers
Keavon Jul 3, 2026
cb17c05
Zip ranked Item connectors by frame slot in the mapped element-wise v…
Keavon Jul 3, 2026
445b836
Register ItemToListNode singleton raise adapters
Keavon Jul 3, 2026
0a68bb4
Resolve Item wires against List connectors by inserting promotion ada…
Keavon Jul 3, 2026
759d00f
Rank the Offset Points distance connector and prove mixed-rank resolu…
Keavon Jul 3, 2026
fe5407e
Implement Clampable for Item and List wires with per-variant clamp bo…
Keavon Jul 4, 2026
5d54e82
Rank the Round Corners radius connector, exercising hard bounds on a …
Keavon Jul 4, 2026
d42e2db
Implement ApplyTransform for Item
Keavon Jul 4, 2026
69306ca
Add Item wire implementations to the Transform node, keeping rank-0 c…
Keavon Jul 4, 2026
dba71c2
Detect element-wise nodes by lazy primary connectors declaring Output…
Keavon Jul 4, 2026
2d2b81b
Convert Transform to an Item kernel with ranked parameters, deliverin…
Keavon Jul 4, 2026
00e7b75
Rename Apply Transform to Bake Transform, baking item transforms on V…
Keavon Jul 4, 2026
5cad9de
Promote bare wires onto Item connectors at resolution via WrapItemNod…
Keavon Jul 4, 2026
76d97c4
Rank the numeric, vector, and boolean parameters across the migrated …
Keavon Jul 4, 2026
2e7fe14
Rank the enum, integer, and seed parameters, registering their rank a…
Keavon Jul 4, 2026
048d483
Amend the audit with the DashPattern value type resolution
Keavon Jul 4, 2026
ebbefc9
Migrate the string family to Item element-wise kernels
Keavon Jul 5, 2026
951eac1
Unwrap Item wires into bare legacy connectors at resolution via Unwra…
Keavon Jul 5, 2026
1d6ebdb
Shadow owned node parameters in bodies instead of mut in signatures
Keavon Jul 5, 2026
5da54d2
Migrate the math family and string measure nodes to Item element-wise…
Keavon Jul 5, 2026
6829dd2
Convert the comparison and clamp nodes to Item kernels, dropping unre…
Keavon Jul 5, 2026
dd35b16
Flat-map expander kernels returning List under the mapped variant's f…
Keavon Jul 5, 2026
ecf07f3
Migrate the expander nodes to Item kernels flat-mapping under the frame
Keavon Jul 5, 2026
c222273
Remove the unused peel_list helper
Keavon Jul 5, 2026
8738f48
Rank the raster adjustment and blending kernels, recontextualizing sh…
Keavon Jul 5, 2026
bac8df1
Update the rank polymorphism roadmap for the landed shader-node and a…
Keavon Jul 5, 2026
4a7264d
Rename the GPU Item stand-in to ShaderItem, aliased as Item at its sh…
Keavon Jul 5, 2026
fc3a0e0
Flip the vector shape generators to emit rank-0 Item<Vector>
Keavon Jul 5, 2026
0d55d3d
Parse ranked Item<T> parameter defaults against the bare element type
Keavon Jul 5, 2026
9fdae0f
Parse an element-wise primary's scalar default against the bare eleme…
Keavon Jul 5, 2026
c2f3443
Add the DashPattern value type for stroke dash sequences
Keavon Jul 6, 2026
b80aeb5
Rank the Fill and Stroke nodes element-wise and give Stroke a DashPat…
Keavon Jul 6, 2026
b1b07e7
Register rank adapters for the ranked Stroke enum parameters
Keavon Jul 6, 2026
96ae3e8
Display Item wires in the Data panel without a List's ID column
Keavon Jul 6, 2026
e55bd28
Register MonitorNode for Item wire types so the Data panel introspect…
Keavon Jul 6, 2026
b7e240a
Color and double Item/List wires and cleave layer-stack connectors in…
Keavon Jul 6, 2026
46d123c
Route wire color and rank through hidden nodes and refresh them on ty…
Keavon Jul 6, 2026
c7ad32e
Rework the DashPattern connector conversions with element-wise promot…
Keavon Jul 6, 2026
34417b1
Rank the remaining value, context, aggregation, and transform nodes o…
Keavon Jul 6, 2026
1122587
Back DashPattern with a List<f64> so the Data panel can introspect it…
Keavon Jul 7, 2026
38d6291
Carry a single Item<T> through varargs so the Read context nodes emit…
Keavon Jul 7, 2026
51319b8
Relax rank validation for aggregation shapes, add element adapters, a…
Keavon Jul 7, 2026
a3627d9
Rank the remaining bare and unnecessarily-List connectors across the …
Keavon Jul 7, 2026
a8b5b61
Add Graphic::None and the FillChoice paint value, making colors and g…
Keavon Jul 7, 2026
12b048d
Rename GradientStops to Gradient and the legacy Gradient/Fill structs…
Keavon Jul 7, 2026
0d85f0c
Restore generator frame-from-params ranking to the roadmap as a plann…
Keavon Jul 7, 2026
02b7495
Rename the ranked-field adapter identifier from PromoteNode to FieldA…
Keavon Jul 7, 2026
9774258
Unload only the wires whose displayed style changed when types update
Keavon Jul 7, 2026
f111b85
Peel wire rank in the editor's semantic type checks so rank-0 layers …
Keavon Jul 7, 2026
1a00031
Restore the whole-List Transform variant so rank-1 content wires reso…
Keavon Jul 7, 2026
c20b39d
Register the Item wire forms for the Memoize and Context Modification…
Keavon Jul 7, 2026
bcd4d91
Give every ranked connector a field adapter and add numeric cast vari…
Keavon Jul 7, 2026
c830979
Key a ranked param's type default off its Item wire form when no lite…
Keavon Jul 7, 2026
5f9633a
Inherit the layer's content value when splicing a node into an empty …
Keavon Jul 7, 2026
81784e0
Migrate stale List-form TypeDefault inputs to the definition's curren…
Keavon Jul 7, 2026
8edef36
Generate the mapped wire variant only when the element-wise node has …
Keavon Jul 7, 2026
26c9d21
Let a bare wire feed a List connector via a wrap-raise adapter, coste…
Keavon Jul 7, 2026
5598e39
Add a zip companion to the whole-List Transform so ranked List parame…
Keavon Jul 7, 2026
dac0b2c
Add the Sum, Average, Minimum, Maximum, Any, and All list reducers
Keavon Jul 7, 2026
9f0554d
Convert the measure family to element-wise Item kernels per the audit…
Keavon Jul 7, 2026
0b5864e
Prefer the bare element value over the Item type default so ranked pa…
Keavon Jul 7, 2026
b883310
Rename GradientStopsUI to GradientUI
Keavon Jul 7, 2026
a025b80
Split Fill's optional transform into a _has_transform bool and a rank…
Keavon Jul 7, 2026
a758f50
Rename the migration-only OptionalDAffine2 TaggedValue to LegacyOptio…
Keavon Jul 7, 2026
b042188
Flow byte buffers as Item<Resource> instead of List<u8> across the by…
Keavon Jul 8, 2026
75d4b69
Macro-generate the list-content wire variant, retiring the hand-writt…
Keavon Jul 8, 2026
e028c0f
Let ()-primary generators take ranked params and frame over them via …
Keavon Jul 8, 2026
90ceaaa
Rank the vector shape generators' params to Item, adding a rank-aware…
Keavon Jul 8, 2026
39edbc3
Rank the value, color, and text generator params to Item
Keavon Jul 8, 2026
1e532ec
Rank the raster, web-request, and context-reader generator params to …
Keavon Jul 8, 2026
d6dd4dd
Fix the repeat and brush test wirings left behind by the param-rankin…
Keavon Jul 8, 2026
7f34fe7
Delete the vestigial Some, Unwrap Option, and Size Of debug nodes
Keavon Jul 8, 2026
d1b8c74
Delete the Attach Attribute node, folding its role into Write Attribute
Keavon Jul 8, 2026
d17775d
Add the Filter and Sort list companion nodes
Keavon Jul 8, 2026
68762f4
Guard the removed-definition migration swap target with a test
Keavon Jul 8, 2026
ed42506
Add the Box Corners value type in place of the rectangle corner radiu…
Keavon Jul 8, 2026
3c450e6
Split Text to Vector's per-glyph mode into a Text to Vector Glyphs node
Keavon Jul 8, 2026
69b764c
Rank the Combine Channels node's channel connectors to Item
Keavon Jul 8, 2026
2f71f8c
Make Map Points an element-wise node
Keavon Jul 8, 2026
739bf46
Delete the deprecated Upload Texture node
Keavon Jul 8, 2026
9938116
Update the implementation roadmap to reflect the landed stages
Keavon Jul 8, 2026
4d0da35
Let monitor introspection read rank-0 wires, locking in the layer coe…
Keavon Jul 8, 2026
8ee49bd
Prefer the rank-0 default when disconnecting a rank-capable input
Keavon Jul 8, 2026
fd46bff
Make Path Modify an element-wise node
Keavon Jul 8, 2026
b78836b
Wrap node paths in a NodeIdPath newtype so they flow as a single Item
Keavon Jul 8, 2026
0ea14e3
Give Item<Raster<CPU>> a default so an unconnected Brush background r…
Keavon Jul 9, 2026
0c6a963
Stop the Brush node from setting layer attributes its paint operation…
Keavon Jul 9, 2026
847b33b
Present-gate Flatten Path's adopted layer path like its fill and stroke
Keavon Jul 9, 2026
216a957
Gate carried layer attributes on static column presence, not runtime …
Keavon Jul 9, 2026
d4975bf
Give the remaining graphic Item<T> types a default so unconnected pri…
Keavon Jul 9, 2026
49f8124
Dispatch a ranked param's Properties widget from its rank-0 element type
Keavon Jul 9, 2026
f721a79
Make Extract Transform an element-wise node, restoring the Origins to…
Keavon Jul 9, 2026
314c783
Rename Flatten Path to Combine Paths
Keavon Jul 9, 2026
1cb7ab0
Stamp Legacy Layer Extend's adopted layer path as a readable NodeIdPath
Keavon Jul 9, 2026
a7438f0
Drop the dead List<u8> and List<NodeId> wire rows
Keavon Jul 9, 2026
4d7bb80
Rank Flatten Graphic's Fully Flatten toggle to Item
Keavon Jul 9, 2026
fd848a8
Update the implementation roadmap with the endgame scope
Keavon Jul 9, 2026
bbbee3d
Make Combine Paths a reducer that collapses the whole frame into one …
Keavon Jul 9, 2026
7a1291d
Stop type-converter nodes from carrying the source's unrelated attrib…
Keavon Jul 9, 2026
e10fd8e
Format the Origins to Polyline regression test
Keavon Jul 9, 2026
d06fa6e
Wrap the Brush node's trace in a BrushTrace newtype so it flows as on…
Keavon Jul 9, 2026
dcd4d92
Make Switch a framed element-wise select, bundling whole collections
Keavon Jul 9, 2026
914003d
Widen and align element-type coverage across the list and graphic nodes
Keavon Jul 9, 2026
1c794ae
Register the compiler's cache chain pair for every ranked enum and ne…
Keavon Jul 9, 2026
155cb1c
Fix wire colors for Passthrough outputs, bundled lists, and bools, an…
Keavon Jul 9, 2026
0805d89
Represent List wire types structurally with Type::List, replacing nam…
Keavon Jul 9, 2026
5583b90
Treat scope and data fields as environment, rank scope wires as Item,…
Keavon Jul 11, 2026
95aeea1
Delete the vestigial Clone debug node
Keavon Jul 11, 2026
0f3d417
Reinstate Upload Texture as an element-wise node and fix the GPU vari…
Keavon Jul 11, 2026
500c5ba
Rename Combine Paths back to Flatten Path, deferring that rename to i…
Keavon Jul 11, 2026
f5253a6
Deduplicate the promotion adapter registrations into the field adapte…
Keavon Jul 11, 2026
abbdb04
Rank Write Attribute's value connector to Item<AttributeValueDyn>, re…
Keavon Jul 11, 2026
18d773c
Vertical wire styling
Keavon Jul 11, 2026
f83c767
Store the editor layer path attribute as a bare NodeIdPath, not an It…
Keavon Jul 11, 2026
50dc761
Rank Context Modification's features connector to Item<ContextFeature…
Keavon Jul 12, 2026
a6289dc
Rank Path Modify's modification parameter to Item<Box<VectorModificat…
Keavon Jul 12, 2026
2c2e82c
Rename the field adapter node family to input adapter
Keavon Jul 12, 2026
e6524bd
Drop the dead bare scalar rows from Context Modification's implementa…
Keavon Jul 12, 2026
abecff0
Move the dynamic executor's test module into its own file
Keavon Jul 12, 2026
5921360
Drop the registry's unreachable bare rows for Memoize, the cache chai…
Keavon Jul 12, 2026
60b4f82
Materialize stored TaggedValues as ranked Item wires at the source
Keavon Jul 12, 2026
82d2361
Remove the bare-wire promotion and adapter machinery made dead by ran…
Keavon Jul 12, 2026
0e3bb2f
Plant the input adapter for List-only inputs, composing position conv…
Keavon Jul 12, 2026
74c63f2
Consolidate Into/Convert conversions into the input adapter umbrella …
Keavon Jul 12, 2026
e11e699
Fix grouped layers gaining a phantom None stack element from the Fill…
Keavon Jul 13, 2026
a372c06
Enforce ranked node inputs in the macro, rejecting bare wire declarat…
Keavon Jul 13, 2026
ab89f6e
Remove the unit Context => () machinery rows, leaving () purely as th…
Keavon Jul 13, 2026
1608cbd
Add a --signatures rank-audit mode to node-docs for the ranked-wire m…
Keavon Jul 13, 2026
72284fe
Remove the node-docs --signatures rank-audit mode now that ranked wir…
Keavon Jul 13, 2026
d2c7484
Migrate legacy no-color values on the Black & White, Color Overlay, a…
Keavon Jul 13, 2026
dcfb61b
Rewrite the element-wise accessor wire type at the primary input, not…
Keavon Jul 13, 2026
60911ed
Register the cache chain for Resource wires, replacing the lone hand-…
Keavon Jul 13, 2026
468fda2
Gate the remaining Raster<GPU> registry rows behind the gpu feature
Keavon Jul 13, 2026
97dc120
Let List<DVec2> wires erase to ListDyn for the attribute reader and e…
Keavon Jul 13, 2026
ef8066b
Rename Extract Element to Item at Index, Count Elements to List Lengt…
Keavon Jul 13, 2026
5e5bf6b
Store paint picks as plain color/gradient values, removing the FillCh…
Keavon Jul 13, 2026
c4ed905
Code review restructuring
Keavon Jul 13, 2026
336b917
Sort by the consumed sort_key attribute or natural element order, add…
Keavon Jul 14, 2026
ac00a6c
Remove the new list-combinator and reducer nodes to defer them to a f…
Keavon Jul 15, 2026
6ab1d0b
Parse Fill and Stroke color defaults through the paint wire's Graphic…
Keavon Jul 15, 2026
21f8ea4
Emit ranked implementation-row default types structurally so their el…
Keavon Jul 15, 2026
bfdb4db
Exempt the deliberate no-paint choice from the stale List-form TypeDe…
Keavon Jul 15, 2026
3d8ee2d
Migrate the legacy 4-input Fill directly to the split has-transform s…
Keavon Jul 15, 2026
44fb93f
Upgrade the demo artwork
Keavon Jul 15, 2026
dd9d66b
Fix the valid AI review findings: Item eq/hash contract, table-era no…
Keavon Jul 15, 2026
0668705
Remove the rank polymorphism working documents
Keavon Jul 15, 2026
ff7714d
Hash Item attribute values directly instead of debug-formatting them,…
Keavon Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion demo-artwork/changing-seasons.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/isometric-fountain.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/marbled-mandelbrot.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/painted-dreams.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/parametric-dunescape.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/procedural-string-lights.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/red-dress.graphite

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo-artwork/valley-of-spires.graphite

Large diffs are not rendered by default.

15 changes: 13 additions & 2 deletions editor/src/messages/clipboard/clipboard_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,20 @@ impl MessageHandler<ClipboardMessage, ClipboardMessageContext<'_>> for Clipboard
let mut vectors = Vec::new();
let mut resources = Vec::new();
for item in items {
// Pasted templates skip document migration, so stored types normalize here
match item {
ClipboardItem::Layer(entry) => layers.push(entry),
ClipboardItem::Nodes(nodes) => node_groups.push(nodes),
ClipboardItem::Layer(mut entry) => {
for (_, template) in &mut entry.nodes {
template.document_node.normalize_stored_types();
}
layers.push(entry);
}
ClipboardItem::Nodes(mut nodes) => {
for (_, template) in &mut nodes {
template.document_node.normalize_stored_types();
}
node_groups.push(nodes);
}
ClipboardItem::Vector(vector) => vectors.push(vector),
ClipboardItem::Resource(resource) => resources.push(resource),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::messages::prelude::*;
use graphene_std::Color;
use graphene_std::color::SRGBA8;
use graphene_std::core_types::misc::parse_css_color;
use graphene_std::vector::style::{FillChoice, FillChoiceUI, GradientStops, GradientStopsUI};
use graphene_std::vector::style::{FillChoice, FillChoiceUI, Gradient, GradientUI};

/// Bounds for a midpoint position (relative to the interval between two adjacent gradient stops).
const MIN_MIDPOINT: f64 = 0.01;
Expand All @@ -28,7 +28,7 @@ pub struct ColorPickerMessageHandler {
old_is_none: bool,

// When set, the picker is editing a gradient: the visual pickers and inputs target the active stop's color.
gradient: Option<GradientStops>,
gradient: Option<Gradient>,
active_marker_index: Option<u32>,
active_marker_is_midpoint: bool,

Expand Down Expand Up @@ -430,7 +430,7 @@ impl ColorPickerMessageHandler {
// For gradient editing, the markers' handle colors mirror their gradient stop colors
let markers = gradient.iter().map(|stop| SpectrumMarker::new(stop.position, stop.midpoint, stop.color)).collect();
let mut row_widgets = vec![
SpectrumInput::new(GradientStopsUI::from(gradient))
SpectrumInput::new(GradientUI::from(gradient))
.markers(markers)
.active_marker_index(self.active_marker_index)
.active_marker_is_midpoint(self.active_marker_is_midpoint)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use derivative::*;
use graphene_std::Color;
use graphene_std::color::SRGBA8;
use graphene_std::transform::ReferencePoint;
use graphene_std::vector::style::{FillChoiceUI, GradientStopsUI};
use graphene_std::vector::style::{FillChoiceUI, GradientUI};
use graphite_proc_macros::WidgetBuilder;

#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
Expand Down Expand Up @@ -531,7 +531,7 @@ pub struct SpectrumInput {
// Content
/// The colored gradient drawn behind the markers (display-only, caller-owned).
#[widget_builder(constructor)]
pub track: GradientStopsUI,
pub track: GradientUI,
/// CSS `linear-gradient(...)` string for the track strip's `background-image`. Auto-populated from `track` at layout-send time.
#[serde(rename = "trackCSS")]
#[widget_builder(skip)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ use glam::{Affine2, DAffine2, Vec2};
use graph_craft::document::NodeId;
use graphene_std::blending::BlendMode;
use graphene_std::color::SRGBA8;
use graphene_std::gradient::GradientStops;
use graphene_std::list::List;
use graphene_std::gradient::Gradient;
use graphene_std::list::{Item, List, NodeIdPath};
use graphene_std::memo::IORecord;
use graphene_std::raster_types::{CPU, GPU, Raster};
use graphene_std::vector::Vector;
use graphene_std::vector::style::{FillChoice, FillChoiceUI, GradientSpreadMethod, GradientType};
use graphene_std::vector::misc::BoxCorners;
use graphene_std::vector::style::{DashPattern, FillChoice, FillChoiceUI, GradientSpreadMethod, GradientType};
use graphene_std::{Artboard, Color, Context, Graphic};
use std::any::Any;
use std::sync::Arc;
Expand Down Expand Up @@ -176,10 +177,10 @@ macro_rules! generate_layout_downcast {
}
// TODO: We simply try all these types sequentially. Find a better strategy.
fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'static>, data: &mut LayoutData) -> Option<Vec<LayoutGroup>> {
// `List<NodeId>` is interpreted as a path (e.g. the value produced by `path_of_subgraph`), shown as a
// `Item<NodeIdPath>` is interpreted as a path (e.g. the value produced by `path_of_subgraph`), shown as a
// `List` where each item's NodeId resolves against the prefix made up of the items above it.
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, List<NodeId>>>() {
return Some(table_node_id_path_layout_with_breadcrumb(&io.output, data));
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Item<NodeIdPath>>>() {
return Some(table_node_id_path_layout_with_breadcrumb(&io.output.element().0, data));
}
generate_layout_downcast!(introspected_data, data, [
List<Artboard>,
Expand All @@ -188,16 +189,34 @@ fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'st
List<Raster<CPU>>,
List<Raster<GPU>>,
List<Color>,
List<GradientStops>,
List<Gradient>,
List<String>,
List<f64>,
List<u8>,
List<bool>,
List<DAffine2>,
List<BlendMode>,
List<GradientType>,
List<GradientSpreadMethod>,
GradientStops,
Item<Artboard>,
Item<Graphic>,
Item<Vector>,
Item<Raster<CPU>>,
Item<Raster<GPU>>,
Item<Color>,
Item<Gradient>,
Item<String>,
Item<f64>,
Item<u8>,
Item<u32>,
Item<bool>,
Item<DVec2>,
Item<DAffine2>,
Item<BlendMode>,
Item<GradientType>,
Item<GradientSpreadMethod>,
Item<DashPattern>,
Item<BoxCorners>,
Gradient,
f64,
u32,
u64,
Expand Down Expand Up @@ -246,6 +265,57 @@ trait TableItemLayout {
}
}

impl<T: TableItemLayout> TableItemLayout for Item<T> {
fn type_name() -> &'static str {
T::type_name()
}
fn identifier(&self) -> String {
self.element().identifier()
}
fn value_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
if let Some(step) = data.desired_path.get(data.current_depth).cloned() {
match step {
PathStep::Element(_) => {
data.current_depth += 1;
let result = self.element().layout_with_breadcrumb(data);
data.current_depth -= 1;
return result;
}
PathStep::Attribute { key, .. } => {
if let Some(any) = self.attributes().get_any(&key) {
data.current_depth += 1;
if let Some(result) = drilldown_attribute_layout(any, data) {
data.current_depth -= 1;
return result;
}
data.current_depth -= 1;
warn!("Drilldown unsupported for attribute {key:?}");
}
data.desired_path.truncate(data.current_depth);
}
}
}

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)];
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 text = self.attributes().display_value(key, display_value_override).unwrap_or_else(|| "-".to_string());
TextLabel::new(text).narrow(true).widget_instance()
});
values.push(widget);
}

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)]
}
}

impl<T: TableItemLayout> TableItemLayout for List<T> {
fn type_name() -> &'static str {
"List"
Expand Down Expand Up @@ -324,12 +394,53 @@ impl TableItemLayout for Artboard {
}
}

impl TableItemLayout for DashPattern {
fn type_name() -> &'static str {
"DashPattern"
}
fn identifier(&self) -> String {
"DashPattern".to_string()
}
// 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)
}
// 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_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
self.0.layout_with_breadcrumb(data)
}
}

impl TableItemLayout for BoxCorners {
fn type_name() -> &'static str {
"BoxCorners"
}
fn identifier(&self) -> String {
"BoxCorners".to_string()
}
// 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)
}
// 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_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
self.0.layout_with_breadcrumb(data)
}
}

impl TableItemLayout for Graphic {
fn type_name() -> &'static str {
"Graphic"
}
fn identifier(&self) -> String {
match self {
Self::None => "None".to_string(),
Self::Graphic(list) => list.identifier(),
Self::Vector(list) => list.identifier(),
Self::RasterCPU(list) => list.identifier(),
Expand All @@ -345,6 +456,7 @@ impl TableItemLayout for Graphic {
}
fn value_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
match self {
Self::None => label("None"),
Self::Graphic(list) => list.layout_with_breadcrumb(data),
Self::Vector(list) => list.layout_with_breadcrumb(data),
Self::RasterCPU(list) => list.layout_with_breadcrumb(data),
Expand Down Expand Up @@ -512,7 +624,7 @@ impl TableItemLayout for Raster<GPU> {
format!("Raster ({} x {})", self.data().width(), self.data().height())
}
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
let widgets = vec![TextLabel::new("Raster is a texture on the GPU and cannot currently be displayed here").widget_instance()];
let widgets = vec![TextLabel::new("This raster data is a texture on the GPU. It currently cannot be displayed here.").widget_instance()];
vec![LayoutGroup::row(widgets)]
}
}
Expand All @@ -537,7 +649,7 @@ impl TableItemLayout for Color {
}
}

impl TableItemLayout for GradientStops {
impl TableItemLayout for Gradient {
fn type_name() -> &'static str {
"Gradient"
}
Expand Down Expand Up @@ -905,12 +1017,10 @@ macro_rules! known_item_types {
List<Raster<CPU>>,
List<Raster<GPU>>,
List<Color>,
List<GradientStops>,
List<Gradient>,
List<String>,
List<NodeId>,
List<f64>,
List<u8>,
GradientStops,
Gradient,
Color,
NodeId,
DAffine2,
Expand Down Expand Up @@ -949,6 +1059,10 @@ fn display_value_override(any: &dyn Any) -> Option<String> {
/// 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> {
// `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));
}
macro_rules! check {
( $($ty:ty),* $(,)? ) => {
$(
Expand Down Expand Up @@ -1005,10 +1119,10 @@ fn table_node_id_path_layout_with_breadcrumb(path: &List<NodeId>, data: &mut Lay
/// Mirrors [`dispatch_value_widget`] but routes to [`TableItemLayout::layout_with_breadcrumb`].
/// Returns `None` for unrecognized types.
fn drilldown_attribute_layout(any: &dyn Any, data: &mut LayoutData) -> Option<Vec<LayoutGroup>> {
// `List<NodeId>` is interpreted as a path (e.g. the `editor:layer_path` attribute), so each item's NodeId value
// resolves against the prefix made up of preceding items. Handled before the generic `List<T>` blanket impl.
if let Some(path) = any.downcast_ref::<List<NodeId>>() {
return Some(table_node_id_path_layout_with_breadcrumb(path, data));
// `NodeIdPath` is interpreted as a path (e.g. the `editor:layer_path` attribute), so each item's NodeId value
// resolves against the prefix made up of preceding items. Handled before the generic blanket impl.
if let Some(path) = any.downcast_ref::<NodeIdPath>() {
return Some(table_node_id_path_layout_with_breadcrumb(&path.0, data));
}
macro_rules! check {
( $($ty:ty),* $(,)? ) => {
Expand Down
Loading
Loading