jellyflow-egui
Immediate-mode egui adapter for Jellyflow node graphs.
This crate owns egui rendering, panels, pointer input, and a runnable eframe::App. Graph
semantics stay in the headless Jellyflow crates: schema-driven node creation, selection, drag,
resize, connect, delete, undo/redo, viewport math, layout, and rendering queries all go through
NodeGraphStore.
The demo ships with a sample gallery for workflow, automation builder, mind map, tree, org chart, knowledge-board, ERD-style, and shader/blueprint-style graphs. It includes selection, marquee selection, node dragging, handle-to-handle connections, selected node resize handles, viewport panning and zooming, keyboard nudging, cursor feedback, layout presets, undo/redo, delete, a schema-driven palette, and a read-only inspector.
The samples are product fixtures, not separate domain frameworks:
- Workflow and automation builder reuse schema descriptors, exec/data ports, edge labels, and profile-ready metadata for Dify-like LLM/tool branches and error paths.
- ERD uses the built-in
table-cardrenderer to expose node-local field regions; table ports withfield.*anchors are placed on those field rows, with edge-owned cardinality labels. - Shader graph reuses the built-in
shader-cardrenderer to expose typed port rails, config groups, preview regions, and shader-style data edges without adding a shader compiler backend. - Mind map and org chart stress hierarchy layout with the same node/edge graph model.
- Knowledge board stresses freeform source, claim, question, action, and output cards.
Use JellyflowEguiBridge when embedding the adapter into your own app. Register node schemas in a
NodeRegistry, map each descriptor renderer_key to your own RendererCatalog style, then let the
egui canvas call Jellyflow runtime APIs instead of mutating graph storage directly.
Rich renderers return NodeRenderLayout plus node-local NodeInteractiveRegion values. The egui
adapter consumes those regions for widget placement and anchor-aware handle placement, so complex
nodes can align ports to internal rows without changing the headless graph model.
Schemas can declare matching renderer-neutral NodeSurfaceSlotDescriptor values so field rows,
badges, actions, previews, and nested regions are described as semantic data rather than egui
widgets.
Use slot for the semantic data path and anchor for adapter-local placement or port binding.
Use NodeWidgetRenderInput::region_screen_rect when placing child widgets so clipping stays
consistent with the canvas viewport.
Custom node widgets
Use two adapter-owned renderer traits for complex nodes:
RichNodeRenderermeasures the node and emits node-local interactive regions.EguiNodeWidgetRendererdraws egui child UI into those regions.
Register both implementations under the descriptor renderer_key:
let mut renderers = default;
renderers
.register
.register_rich
.register_widgets;
Then point a schema at that key and anchor ports to the regions produced by the renderer:
let schema = builder
.renderer_key
.default_size
.port
.port
.surface_slot
.surface_slot
.build;
The complete example lives in examples/custom_widget.rs. It builds a custom review-card node with
embedded egui rows, zoom-aware content levels, and ports anchored to row regions.
Visual review gallery
Run cargo run -p jellyflow-egui --example gallery_snapshot to export PNGs for every product
sample into target/jellyflow-egui-gallery. This is intentionally a local review aid instead of a
CI pixel gate, because GPU snapshot output can vary across platforms.
The hard regression gate lives in code-level geometry tests rather than pixel comparison. The egui
library tests cover Dify-style workflow controls, shader/blueprint typed ports, ERD repeatable
fields, mind-map shell density, resize, invalid hover, dropped-wire menus, and inspector descriptor
availability. See docs/testing/node-ui-authoring-regression.md for the matrix and commands.
The crate intentionally depends on eframe; the core jellyflow, jellyflow-core,
jellyflow-layout, and jellyflow-runtime crates remain renderer-free.