1#[derive(Debug, Clone)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub struct VisualizationTheme {
5 pub name: String,
7 pub background_color: String,
9 pub node: NodeTheme,
11 pub edge: EdgeTheme,
13 pub text: TextTheme,
15 pub highlight: HighlightTheme,
17}
18
19#[derive(Debug, Clone)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22pub struct NodeTheme {
23 pub fill_color: String,
25 pub stroke_color: String,
27 pub stroke_width: f32,
29 pub border_radius: f32,
31 pub shadow: ShadowConfig,
33}
34
35#[derive(Debug, Clone)]
37#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
38pub struct EdgeTheme {
39 pub color: String,
41 pub width: f32,
43 pub style: String,
45 pub arrow: ArrowConfig,
47}
48
49#[derive(Debug, Clone)]
51#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
52pub struct TextTheme {
53 pub font_family: String,
55 pub font_size: f32,
57 pub color: String,
59 pub font_weight: String,
61}
62
63#[derive(Debug, Clone)]
65#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
66pub struct HighlightTheme {
67 pub selected_color: String,
69 pub hover_color: String,
71 pub error_color: String,
73 pub warning_color: String,
75}
76
77#[derive(Debug, Clone)]
79#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
80pub struct ShadowConfig {
81 pub enabled: bool,
83 pub color: String,
85 pub offset_x: f32,
87 pub offset_y: f32,
89 pub blur_radius: f32,
91}
92
93#[derive(Debug, Clone)]
95#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
96pub struct ArrowConfig {
97 pub enabled: bool,
99 pub size: f32,
101 pub arrow_type: String,
103}
104
105impl VisualizationTheme {
106 pub fn to_render_config(&self) -> crate::render::RenderConfig {
108 crate::render::RenderConfig {
109 background_color: self.background_color.clone(),
110 node_fill_color: self.node.fill_color.clone(),
111 node_stroke_color: self.node.stroke_color.clone(),
112 node_stroke_width: self.node.stroke_width as f64,
113 edge_color: self.edge.color.clone(),
114 edge_width: self.edge.width as f64,
115 text_color: self.text.color.clone(),
116 text_size: self.text.font_size as f64,
117 font_family: self.text.font_family.clone(),
118 show_arrows: self.edge.arrow.enabled,
119 arrow_size: self.edge.arrow.size as f64,
120 ..Default::default()
121 }
122 }
123}
124
125impl Default for VisualizationTheme {
126 fn default() -> Self {
127 Self::light()
128 }
129}
130
131impl VisualizationTheme {
132 pub fn light() -> Self {
134 Self {
135 name: "Light".to_string(),
136 background_color: "#FFFFFF".to_string(),
137 node: NodeTheme {
138 fill_color: "#F8F9FA".to_string(),
139 stroke_color: "#DEE2E6".to_string(),
140 stroke_width: 1.0,
141 border_radius: 4.0,
142 shadow: ShadowConfig { enabled: true, color: "rgba(0, 0, 0, 0.1)".to_string(), offset_x: 0.0, offset_y: 2.0, blur_radius: 4.0 },
143 },
144 edge: EdgeTheme { color: "#6C757D".to_string(), width: 1.5, style: "solid".to_string(), arrow: ArrowConfig { enabled: true, size: 8.0, arrow_type: "triangle".to_string() } },
145 text: TextTheme { font_family: "Arial, sans-serif".to_string(), font_size: 12.0, color: "#212529".to_string(), font_weight: "normal".to_string() },
146 highlight: HighlightTheme { selected_color: "#007BFF".to_string(), hover_color: "#0056B3".to_string(), error_color: "#DC3545".to_string(), warning_color: "#FFC107".to_string() },
147 }
148 }
149
150 pub fn dark() -> Self {
152 Self {
153 name: "Dark".to_string(),
154 background_color: "#1E1E1E".to_string(),
155 node: NodeTheme {
156 fill_color: "#2D2D30".to_string(),
157 stroke_color: "#3E3E42".to_string(),
158 stroke_width: 1.0,
159 border_radius: 4.0,
160 shadow: ShadowConfig { enabled: true, color: "rgba(0, 0, 0, 0.3)".to_string(), offset_x: 0.0, offset_y: 2.0, blur_radius: 4.0 },
161 },
162 edge: EdgeTheme { color: "#CCCCCC".to_string(), width: 1.5, style: "solid".to_string(), arrow: ArrowConfig { enabled: true, size: 8.0, arrow_type: "triangle".to_string() } },
163 text: TextTheme { font_family: "Arial, sans-serif".to_string(), font_size: 12.0, color: "#CCCCCC".to_string(), font_weight: "normal".to_string() },
164 highlight: HighlightTheme { selected_color: "#0E639C".to_string(), hover_color: "#1177BB".to_string(), error_color: "#F14C4C".to_string(), warning_color: "#FFCC02".to_string() },
165 }
166 }
167
168 pub fn one_light() -> Self {
170 Self {
171 name: "One Light".to_string(),
172 background_color: "#FAFAFA".to_string(),
173 node: NodeTheme {
174 fill_color: "#FFFFFF".to_string(),
175 stroke_color: "#E1E4E8".to_string(),
176 stroke_width: 1.0,
177 border_radius: 6.0,
178 shadow: ShadowConfig { enabled: true, color: "rgba(149, 157, 165, 0.2)".to_string(), offset_x: 0.0, offset_y: 8.0, blur_radius: 24.0 },
179 },
180 edge: EdgeTheme { color: "#586069".to_string(), width: 1.5, style: "solid".to_string(), arrow: ArrowConfig { enabled: true, size: 8.0, arrow_type: "triangle".to_string() } },
181 text: TextTheme { font_family: "SF Pro Display, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif".to_string(), font_size: 12.0, color: "#24292E".to_string(), font_weight: "400".to_string() },
182 highlight: HighlightTheme { selected_color: "#0366D6".to_string(), hover_color: "#0256CC".to_string(), error_color: "#D73A49".to_string(), warning_color: "#F66A0A".to_string() },
183 }
184 }
185
186 pub fn one_dark_pro() -> Self {
188 Self {
189 name: "One Dark Pro".to_string(),
190 background_color: "#282C34".to_string(),
191 node: NodeTheme {
192 fill_color: "#21252B".to_string(),
193 stroke_color: "#3E4451".to_string(),
194 stroke_width: 1.0,
195 border_radius: 6.0,
196 shadow: ShadowConfig { enabled: true, color: "rgba(0, 0, 0, 0.4)".to_string(), offset_x: 0.0, offset_y: 8.0, blur_radius: 24.0 },
197 },
198 edge: EdgeTheme { color: "#ABB2BF".to_string(), width: 1.5, style: "solid".to_string(), arrow: ArrowConfig { enabled: true, size: 8.0, arrow_type: "triangle".to_string() } },
199 text: TextTheme { font_family: "SF Mono, Monaco, Inconsolata, Roboto Mono, monospace".to_string(), font_size: 12.0, color: "#ABB2BF".to_string(), font_weight: "400".to_string() },
200 highlight: HighlightTheme { selected_color: "#61AFEF".to_string(), hover_color: "#528BFF".to_string(), error_color: "#E06C75".to_string(), warning_color: "#E5C07B".to_string() },
201 }
202 }
203
204 pub fn github() -> Self {
206 Self {
207 name: "GitHub".to_string(),
208 background_color: "#FFFFFF".to_string(),
209 node: NodeTheme {
210 fill_color: "#F6F8FA".to_string(),
211 stroke_color: "#D0D7DE".to_string(),
212 stroke_width: 1.0,
213 border_radius: 6.0,
214 shadow: ShadowConfig { enabled: true, color: "rgba(31, 35, 40, 0.04)".to_string(), offset_x: 0.0, offset_y: 1.0, blur_radius: 0.0 },
215 },
216 edge: EdgeTheme { color: "#656D76".to_string(), width: 1.0, style: "solid".to_string(), arrow: ArrowConfig { enabled: true, size: 6.0, arrow_type: "triangle".to_string() } },
217 text: TextTheme { font_family: "-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif".to_string(), font_size: 12.0, color: "#24292F".to_string(), font_weight: "400".to_string() },
218 highlight: HighlightTheme { selected_color: "#0969DA".to_string(), hover_color: "#0860CA".to_string(), error_color: "#CF222E".to_string(), warning_color: "#9A6700".to_string() },
219 }
220 }
221}