Skip to main content

jellyflow_layout/
preset.rs

1use jellyflow_core::{CanvasSize, NodeId};
2use serde::{Deserialize, Serialize};
3
4use crate::builtin::{BuiltinLayoutPreset, builtin_request};
5use crate::engine::{
6    LayoutDirection, LayoutEngineId, LayoutEngineRequest, LayoutOptions, LayoutRequest,
7    LayoutScope, LayoutSpacing,
8};
9
10/// Builder for common layout presets.
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12pub struct LayoutPresetBuilder {
13    request: LayoutEngineRequest,
14}
15
16impl Default for LayoutPresetBuilder {
17    fn default() -> Self {
18        Self::workflow()
19    }
20}
21
22impl LayoutPresetBuilder {
23    /// Returns a layered workflow preset.
24    pub fn workflow() -> Self {
25        Self {
26            request: builtin_request(BuiltinLayoutPreset::Workflow),
27        }
28    }
29
30    /// Returns a tree-shaped layered preset.
31    pub fn tree() -> Self {
32        Self {
33            request: builtin_request(BuiltinLayoutPreset::Tree),
34        }
35    }
36
37    /// Returns a radial mind-map preset.
38    pub fn mind_map() -> Self {
39        Self {
40            request: builtin_request(BuiltinLayoutPreset::MindMap),
41        }
42    }
43
44    /// Returns a freeform mind-map preset.
45    pub fn freeform() -> Self {
46        Self {
47            request: builtin_request(BuiltinLayoutPreset::Freeform),
48        }
49    }
50
51    /// Creates a preset builder for a specific engine.
52    pub fn new(engine: impl Into<LayoutEngineId>, layout: LayoutRequest) -> Self {
53        Self {
54            request: LayoutEngineRequest::new(engine, layout),
55        }
56    }
57
58    /// Uses a different engine.
59    pub fn with_engine(mut self, engine: impl Into<LayoutEngineId>) -> Self {
60        self.request.engine = engine.into();
61        self
62    }
63
64    /// Uses a different layout request.
65    pub fn with_layout(mut self, layout: LayoutRequest) -> Self {
66        self.request.layout = layout;
67        self
68    }
69
70    /// Sets layout options.
71    pub fn with_options(mut self, options: LayoutOptions) -> Self {
72        self.request.layout.options = options;
73        self
74    }
75
76    /// Uses a different layered layout direction.
77    pub fn with_direction(mut self, direction: LayoutDirection) -> Self {
78        self.request.layout.options.direction = direction;
79        self
80    }
81
82    /// Uses a different layered spacing profile.
83    pub fn with_spacing(mut self, spacing: LayoutSpacing) -> Self {
84        self.request.layout.options.spacing = spacing;
85        self
86    }
87
88    /// Uses a different margin.
89    pub fn with_margin(mut self, margin: CanvasSize) -> Self {
90        self.request.layout.options.margin = margin;
91        self
92    }
93
94    /// Uses a different fallback node size.
95    pub fn with_default_node_size(mut self, size: CanvasSize) -> Self {
96        self.request.layout.options.default_node_size = size;
97        self
98    }
99
100    /// Uses a different fallback node origin.
101    pub fn with_node_origin(mut self, node_origin: (f32, f32)) -> Self {
102        self.request.layout.options.node_origin = node_origin;
103        self
104    }
105
106    /// Targets all visible nodes.
107    pub fn all(mut self) -> Self {
108        self.request.layout.scope = LayoutScope::All;
109        self
110    }
111
112    /// Targets a selected set of nodes.
113    pub fn nodes(mut self, nodes: impl IntoIterator<Item = NodeId>) -> Self {
114        self.request.layout.scope = LayoutScope::Nodes {
115            nodes: nodes.into_iter().collect(),
116        };
117        self
118    }
119
120    /// Uses a different request scope.
121    pub fn with_scope(mut self, scope: LayoutScope) -> Self {
122        self.request.layout.scope = scope;
123        self
124    }
125
126    /// Adds request-local measured node sizes.
127    pub fn with_measured_node_sizes(
128        mut self,
129        sizes: impl IntoIterator<Item = (NodeId, CanvasSize)>,
130    ) -> Self {
131        self.request.layout.measured_node_sizes.extend(sizes);
132        self
133    }
134
135    /// Builds a layout engine request.
136    pub fn build(self) -> LayoutEngineRequest {
137        self.request
138    }
139}
140
141impl From<LayoutPresetBuilder> for LayoutEngineRequest {
142    fn from(value: LayoutPresetBuilder) -> Self {
143        value.build()
144    }
145}