1use crate::ui::icons::Icons;
22use ratatui::style::{Color, Style};
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum ConnectionStatus {
27 Connected,
29 Connecting,
31 Disconnected,
33 Error,
35}
36
37impl ConnectionStatus {
38 pub fn icon(&self) -> &'static str {
40 match self {
41 Self::Connected => "π’",
42 Self::Connecting => "π‘",
43 Self::Disconnected => "π΄",
44 Self::Error => "β",
45 }
46 }
47
48 pub fn color(&self) -> Color {
50 match self {
51 Self::Connected => Color::Green,
52 Self::Connecting => Color::Yellow,
53 Self::Disconnected => Color::Red,
54 Self::Error => Color::Red,
55 }
56 }
57
58 pub fn text(&self) -> &'static str {
60 match self {
61 Self::Connected => "Connected",
62 Self::Connecting => "Connecting",
63 Self::Disconnected => "Disconnected",
64 Self::Error => "Connection Error",
65 }
66 }
67
68 pub fn display(&self) -> String {
70 format!("{} {}", self.icon(), self.text())
71 }
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76pub enum RpcStatus {
77 Success,
79 Error,
81 Loading,
83 Timeout,
85 Idle,
87}
88
89impl RpcStatus {
90 pub fn icon(&self) -> &'static str {
92 match self {
93 Self::Success => Icons::SUCCESS,
94 Self::Error => Icons::ERROR,
95 Self::Loading => Icons::PROCESSING,
96 Self::Timeout => Icons::WARNING,
97 Self::Idle => "βΈοΈ",
98 }
99 }
100
101 pub fn color(&self) -> Color {
103 match self {
104 Self::Success => Color::Green,
105 Self::Error => Color::Red,
106 Self::Loading => Color::Blue,
107 Self::Timeout => Color::Yellow,
108 Self::Idle => Color::Gray,
109 }
110 }
111
112 pub fn display(&self, operation: &str) -> String {
114 match self {
115 Self::Success => format!("{} {}", self.icon(), operation),
116 Self::Error => format!("{} {} Failed", self.icon(), operation),
117 Self::Loading => format!("{} {}...", self.icon(), operation),
118 Self::Timeout => format!("{} {} Timeout", self.icon(), operation),
119 Self::Idle => "Ready".to_string(),
120 }
121 }
122}
123
124#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub enum ExecutionStatus {
127 Running,
129 Paused,
131 Finished,
133 Failed,
135 Start,
137 End,
139}
140
141impl ExecutionStatus {
142 pub fn icon(&self) -> &'static str {
144 match self {
145 Self::Running => "βΆοΈ",
146 Self::Paused => "βΈοΈ",
147 Self::Finished => Icons::SUCCESS,
148 Self::Failed => Icons::ERROR,
149 Self::Start => "π",
150 Self::End => "π",
151 }
152 }
153
154 pub fn color(&self) -> Color {
156 match self {
157 Self::Running => Color::Green,
158 Self::Paused => Color::Yellow,
159 Self::Finished => Color::Green,
160 Self::Failed => Color::Red,
161 Self::Start => Color::Blue,
162 Self::End => Color::Blue,
163 }
164 }
165
166 pub fn display(&self) -> String {
168 match self {
169 Self::Running => format!("{} Running", self.icon()),
170 Self::Paused => format!("{} Paused", self.icon()),
171 Self::Finished => format!("{} Finished", self.icon()),
172 Self::Failed => format!("{} Failed", self.icon()),
173 Self::Start => format!("{} At Start", self.icon()),
174 Self::End => format!("{} At End", self.icon()),
175 }
176 }
177}
178
179#[derive(Debug, Clone, Copy, PartialEq, Eq)]
181pub enum PanelStatus {
182 Focused,
184 Unfocused,
186 HasUpdates,
188 Error,
190}
191
192impl PanelStatus {
193 pub fn indicator(&self) -> &'static str {
195 match self {
196 Self::Focused => "β",
197 Self::Unfocused => "β",
198 Self::HasUpdates => "β",
199 Self::Error => "β ",
200 }
201 }
202
203 pub fn color(&self) -> Color {
205 match self {
206 Self::Focused => Color::Cyan,
207 Self::Unfocused => Color::Gray,
208 Self::HasUpdates => Color::Yellow,
209 Self::Error => Color::Red,
210 }
211 }
212}
213
214#[derive(Debug, Clone, Copy, PartialEq, Eq)]
216pub enum FileStatus {
217 SourceAvailable,
219 OpcodesOnly,
221 HasExecution,
223 Modified,
225 ReadOnly,
227 NotFound,
229}
230
231impl FileStatus {
232 pub fn icon(&self) -> &'static str {
234 match self {
235 Self::SourceAvailable => Icons::FILE,
236 Self::OpcodesOnly => "π§",
237 Self::HasExecution => "βΊ",
238 Self::Modified => "π",
239 Self::ReadOnly => "π",
240 Self::NotFound => "β",
241 }
242 }
243
244 pub fn color(&self) -> Color {
246 match self {
247 Self::SourceAvailable => Color::Green,
248 Self::OpcodesOnly => Color::Yellow,
249 Self::HasExecution => Color::Cyan,
250 Self::Modified => Color::Blue,
251 Self::ReadOnly => Color::Gray,
252 Self::NotFound => Color::Red,
253 }
254 }
255
256 pub fn display(&self, filename: &str) -> String {
258 format!("{} {}", self.icon(), filename)
259 }
260}
261
262#[derive(Debug, Clone, Copy, PartialEq, Eq)]
264pub enum BreakpointStatus {
265 Active,
267 Disabled,
269 Hit,
271 Invalid,
273}
274
275impl BreakpointStatus {
276 pub fn icon(&self) -> &'static str {
278 match self {
279 Self::Active => "β",
280 Self::Disabled => "β",
281 Self::Hit => "β",
282 Self::Invalid => "β ",
283 }
284 }
285
286 pub fn color(&self) -> Color {
288 match self {
289 Self::Active => Color::Red,
290 Self::Disabled => Color::Gray,
291 Self::Hit => Color::Yellow,
292 Self::Invalid => Color::Red,
293 }
294 }
295
296 pub fn styled_span(&self) -> ratatui::text::Span<'static> {
298 ratatui::text::Span::styled(self.icon(), Style::default().fg(self.color()))
299 }
300}
301
302pub struct StatusBar {
304 connection: Option<ConnectionStatus>,
306 rpc: Option<(RpcStatus, String)>,
308 execution: Option<ExecutionStatus>,
310 current_panel: Option<String>,
312 messages: Vec<String>,
314}
315
316impl StatusBar {
317 pub fn new() -> Self {
319 Self {
320 connection: None,
321 rpc: None,
322 execution: None,
323 current_panel: None,
324 messages: Vec::new(),
325 }
326 }
327
328 pub fn connection(mut self, status: ConnectionStatus) -> Self {
330 self.connection = Some(status);
331 self
332 }
333
334 pub fn rpc(mut self, status: RpcStatus, operation: String) -> Self {
336 self.rpc = Some((status, operation));
337 self
338 }
339
340 pub fn execution(mut self, status: ExecutionStatus) -> Self {
342 self.execution = Some(status);
343 self
344 }
345
346 pub fn current_panel(mut self, panel: String) -> Self {
348 self.current_panel = Some(panel);
349 self
350 }
351
352 pub fn message<S: Into<String>>(mut self, msg: S) -> Self {
354 self.messages.push(msg.into());
355 self
356 }
357
358 pub fn build(&self) -> String {
360 let mut parts = Vec::new();
361
362 if let Some(conn) = self.connection {
364 parts.push(conn.display());
365 }
366
367 if let Some((status, op)) = &self.rpc {
369 parts.push(status.display(op));
370 }
371
372 if let Some(exec) = self.execution {
374 parts.push(exec.display());
375 }
376
377 if let Some(panel) = &self.current_panel {
379 parts.push(format!("Panel: {panel}"));
380 }
381
382 parts.extend(self.messages.clone());
384
385 parts.join(" | ")
386 }
387}
388
389impl Default for StatusBar {
390 fn default() -> Self {
391 Self::new()
392 }
393}