ringkernel_procint/gui/panels/
patterns_panel.rs1use 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
9pub struct PatternsPanel;
11
12impl Default for PatternsPanel {
13 fn default() -> Self {
14 Self
15 }
16}
17
18impl PatternsPanel {
19 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 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 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 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}