1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct VisualizationTheme {
6 pub name: String,
8 pub background_color: String,
10 pub node: NodeTheme,
12 pub edge: EdgeTheme,
14 pub text: TextTheme,
16 pub highlight: HighlightTheme,
18}
19
20#[derive(Debug, Clone, Serialize, 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, Serialize, Deserialize)]
37pub struct EdgeTheme {
38 pub color: String,
40 pub width: f32,
42 pub style: String,
44 pub arrow: ArrowConfig,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct TextTheme {
51 pub font_family: String,
53 pub font_size: f32,
55 pub color: String,
57 pub font_weight: String,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct HighlightTheme {
64 pub selected_color: String,
66 pub hover_color: String,
68 pub error_color: String,
70 pub warning_color: String,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct ShadowConfig {
77 pub enabled: bool,
79 pub color: String,
81 pub offset_x: f32,
83 pub offset_y: f32,
85 pub blur_radius: f32,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct ArrowConfig {
92 pub enabled: bool,
94 pub size: f32,
96 pub arrow_type: String,
98}
99
100impl VisualizationTheme {
101 pub fn to_render_config(&self) -> crate::render::RenderConfig {
103 crate::render::RenderConfig {
104 background_color: self.background_color.clone(),
105 node_fill_color: self.node.fill_color.clone(),
106 node_stroke_color: self.node.stroke_color.clone(),
107 node_stroke_width: self.node.stroke_width as f64,
108 edge_color: self.edge.color.clone(),
109 edge_width: self.edge.width as f64,
110 text_color: self.text.color.clone(),
111 text_size: self.text.font_size as f64,
112 font_family: self.text.font_family.clone(),
113 show_arrows: self.edge.arrow.enabled,
114 arrow_size: self.edge.arrow.size as f64,
115 ..Default::default()
116 }
117 }
118}
119
120impl Default for VisualizationTheme {
121 fn default() -> Self {
122 Self::light()
123 }
124}
125
126impl VisualizationTheme {
127 pub fn light() -> Self {
129 Self {
130 name: "Light".to_string(),
131 background_color: "#FFFFFF".to_string(),
132 node: NodeTheme {
133 fill_color: "#F8F9FA".to_string(),
134 stroke_color: "#DEE2E6".to_string(),
135 stroke_width: 1.0,
136 border_radius: 4.0,
137 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 },
138 },
139 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() } },
140 text: TextTheme { font_family: "Arial, sans-serif".to_string(), font_size: 12.0, color: "#212529".to_string(), font_weight: "normal".to_string() },
141 highlight: HighlightTheme { selected_color: "#007BFF".to_string(), hover_color: "#0056B3".to_string(), error_color: "#DC3545".to_string(), warning_color: "#FFC107".to_string() },
142 }
143 }
144
145 pub fn dark() -> Self {
147 Self {
148 name: "Dark".to_string(),
149 background_color: "#1E1E1E".to_string(),
150 node: NodeTheme {
151 fill_color: "#2D2D30".to_string(),
152 stroke_color: "#3E3E42".to_string(),
153 stroke_width: 1.0,
154 border_radius: 4.0,
155 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 },
156 },
157 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() } },
158 text: TextTheme { font_family: "Arial, sans-serif".to_string(), font_size: 12.0, color: "#CCCCCC".to_string(), font_weight: "normal".to_string() },
159 highlight: HighlightTheme { selected_color: "#0E639C".to_string(), hover_color: "#1177BB".to_string(), error_color: "#F14C4C".to_string(), warning_color: "#FFCC02".to_string() },
160 }
161 }
162
163 pub fn one_light() -> Self {
165 Self {
166 name: "One Light".to_string(),
167 background_color: "#FAFAFA".to_string(),
168 node: NodeTheme {
169 fill_color: "#FFFFFF".to_string(),
170 stroke_color: "#E1E4E8".to_string(),
171 stroke_width: 1.0,
172 border_radius: 6.0,
173 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 },
174 },
175 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() } },
176 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() },
177 highlight: HighlightTheme { selected_color: "#0366D6".to_string(), hover_color: "#0256CC".to_string(), error_color: "#D73A49".to_string(), warning_color: "#F66A0A".to_string() },
178 }
179 }
180
181 pub fn one_dark_pro() -> Self {
183 Self {
184 name: "One Dark Pro".to_string(),
185 background_color: "#282C34".to_string(),
186 node: NodeTheme {
187 fill_color: "#21252B".to_string(),
188 stroke_color: "#3E4451".to_string(),
189 stroke_width: 1.0,
190 border_radius: 6.0,
191 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 },
192 },
193 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() } },
194 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() },
195 highlight: HighlightTheme { selected_color: "#61AFEF".to_string(), hover_color: "#528BFF".to_string(), error_color: "#E06C75".to_string(), warning_color: "#E5C07B".to_string() },
196 }
197 }
198
199 pub fn github() -> Self {
201 Self {
202 name: "GitHub".to_string(),
203 background_color: "#FFFFFF".to_string(),
204 node: NodeTheme {
205 fill_color: "#F6F8FA".to_string(),
206 stroke_color: "#D0D7DE".to_string(),
207 stroke_width: 1.0,
208 border_radius: 6.0,
209 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 },
210 },
211 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() } },
212 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() },
213 highlight: HighlightTheme { selected_color: "#0969DA".to_string(), hover_color: "#0860CA".to_string(), error_color: "#CF222E".to_string(), warning_color: "#9A6700".to_string() },
214 }
215 }
216}