ringkernel_procint/gui/panels/
patterns_panel.rs

1//! Patterns display panel.
2
3use crate::analytics::PatternAggregator;
4use crate::gui::widgets::pattern_badge;
5use crate::gui::{section_header, styled_panel, Theme};
6use crate::models::PatternType;
7use eframe::egui::{self, Ui};
8
9/// Patterns display panel.
10pub struct PatternsPanel;
11
12impl Default for PatternsPanel {
13    fn default() -> Self {
14        Self
15    }
16}
17
18impl PatternsPanel {
19    /// Render the panel.
20    pub fn render(&mut self, ui: &mut Ui, theme: &Theme, aggregator: &PatternAggregator) {
21        styled_panel(ui, theme, |ui| {
22            section_header(ui, theme, "DETECTED PATTERNS");
23
24            let dist = aggregator.distribution();
25
26            // Pattern badges
27            ui.horizontal_wrapped(|ui| {
28                if dist.bottleneck > 0 {
29                    pattern_badge(ui, "Bottleneck", theme.error, dist.bottleneck);
30                }
31                if dist.loop_count > 0 {
32                    pattern_badge(ui, "Loop", theme.warning, dist.loop_count);
33                }
34                if dist.rework > 0 {
35                    pattern_badge(ui, "Rework", theme.warning, dist.rework);
36                }
37                if dist.long_running > 0 {
38                    pattern_badge(ui, "Long-Running", theme.accent, dist.long_running);
39                }
40                if dist.circular > 0 {
41                    pattern_badge(ui, "Circular", theme.error, dist.circular);
42                }
43            });
44
45            if dist.total() == 0 {
46                ui.label(
47                    egui::RichText::new("No patterns detected")
48                        .size(11.0)
49                        .color(theme.text_muted),
50                );
51            }
52
53            ui.add_space(12.0);
54
55            // Recent patterns list
56            ui.collapsing("Recent Patterns", |ui| {
57                let recent = aggregator.top_patterns(5);
58
59                if recent.is_empty() {
60                    ui.label(
61                        egui::RichText::new("None yet")
62                            .size(11.0)
63                            .color(theme.text_muted),
64                    );
65                } else {
66                    for pattern in recent {
67                        ui.horizontal(|ui| {
68                            let (icon, color) = match pattern.pattern_type {
69                                PatternType::Bottleneck => ("⚠", theme.error),
70                                PatternType::Loop => ("↺", theme.warning),
71                                PatternType::Rework => ("↩", theme.warning),
72                                PatternType::LongRunning => ("⏱", theme.accent),
73                                PatternType::Circular => ("⟳", theme.error),
74                                _ => ("•", theme.text_muted),
75                            };
76
77                            ui.label(egui::RichText::new(icon).color(color));
78                            ui.label(egui::RichText::new(pattern.pattern_type.name()).size(11.0));
79                            ui.label(
80                                egui::RichText::new(format!(
81                                    "({:.0}%)",
82                                    pattern.confidence * 100.0
83                                ))
84                                .size(10.0)
85                                .color(theme.text_muted),
86                            );
87                        });
88                    }
89                }
90            });
91
92            ui.add_space(8.0);
93
94            // Statistics
95            ui.collapsing("Statistics", |ui| {
96                ui.label(format!("Total detected: {}", aggregator.total_detected));
97                ui.label(format!(
98                    "Critical: {}",
99                    aggregator.count_by_severity(crate::models::PatternSeverity::Critical)
100                ));
101                ui.label(format!(
102                    "Warnings: {}",
103                    aggregator.count_by_severity(crate::models::PatternSeverity::Warning)
104                ));
105            });
106        });
107    }
108}