jellyflow_layout/
family.rs1use std::collections::BTreeSet;
2use std::fmt;
3
4use serde::{Deserialize, Serialize};
5
6use crate::builtin::{BuiltinLayoutEngine, engine_metadata, layered_dag_family, mind_map_family};
7use crate::engine::LayoutEngineId;
8
9pub const LAYERED_DAG_LAYOUT_FAMILY_ID: &str = "layered_dag";
11pub const MIND_MAP_LAYOUT_FAMILY_ID: &str = "mind_map";
13
14#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
16#[serde(transparent)]
17pub struct LayoutFamilyId(String);
18
19impl LayoutFamilyId {
20 pub fn new(id: impl Into<String>) -> Self {
22 Self(id.into())
23 }
24
25 pub fn layered_dag() -> Self {
27 Self::new(LAYERED_DAG_LAYOUT_FAMILY_ID)
28 }
29
30 pub fn mind_map() -> Self {
32 Self::new(MIND_MAP_LAYOUT_FAMILY_ID)
33 }
34
35 pub fn as_str(&self) -> &str {
37 &self.0
38 }
39}
40
41impl fmt::Display for LayoutFamilyId {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 f.write_str(&self.0)
44 }
45}
46
47impl From<&str> for LayoutFamilyId {
48 fn from(value: &str) -> Self {
49 Self::new(value)
50 }
51}
52
53impl From<String> for LayoutFamilyId {
54 fn from(value: String) -> Self {
55 Self::new(value)
56 }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
61pub struct LayoutFamilyMetadata {
62 pub id: LayoutFamilyId,
63 pub name: String,
64}
65
66impl LayoutFamilyMetadata {
67 pub fn new(id: impl Into<LayoutFamilyId>, name: impl Into<String>) -> Self {
69 Self {
70 id: id.into(),
71 name: name.into(),
72 }
73 }
74
75 pub fn layered_dag() -> Self {
77 layered_dag_family()
78 }
79
80 pub fn mind_map() -> Self {
82 mind_map_family()
83 }
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
88#[serde(rename_all = "snake_case")]
89pub enum LayoutEngineCapability {
90 DirectionalLayout,
92 EdgeRouting,
94 PinnedNodes,
96 OverlapAvoidance,
98}
99
100#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
102pub struct LayoutEngineMetadata {
103 pub engine: LayoutEngineId,
104 pub family: LayoutFamilyId,
105 pub name: String,
106 #[serde(default, skip_serializing_if = "BTreeSet::is_empty")]
107 pub capabilities: BTreeSet<LayoutEngineCapability>,
108}
109
110impl LayoutEngineMetadata {
111 pub fn new(
113 engine: impl Into<LayoutEngineId>,
114 family: impl Into<LayoutFamilyId>,
115 name: impl Into<String>,
116 ) -> Self {
117 Self {
118 engine: engine.into(),
119 family: family.into(),
120 name: name.into(),
121 capabilities: BTreeSet::new(),
122 }
123 }
124
125 pub fn with_capabilities(
127 mut self,
128 capabilities: impl IntoIterator<Item = LayoutEngineCapability>,
129 ) -> Self {
130 self.capabilities.extend(capabilities);
131 self
132 }
133
134 pub fn dugong() -> Self {
136 engine_metadata(BuiltinLayoutEngine::Dugong)
137 }
138
139 pub fn tidy_tree() -> Self {
141 engine_metadata(BuiltinLayoutEngine::TidyTree)
142 }
143
144 pub fn mind_map_radial() -> Self {
146 engine_metadata(BuiltinLayoutEngine::MindMapRadial)
147 }
148
149 pub fn mind_map_freeform() -> Self {
151 engine_metadata(BuiltinLayoutEngine::MindMapFreeform)
152 }
153}