cbtop/bricks/panels/
help.rs1use crate::brick::{Brick, BrickAssertion, BrickBudget, BrickVerification};
4use presentar_core::{Canvas, Point, TextStyle};
5use presentar_terminal::Theme;
6use std::any::Any;
7
8pub struct HelpPanelBrick {
9 pub theme: Theme,
10}
11
12impl HelpPanelBrick {
13 pub fn new() -> Self {
14 Self {
15 theme: Theme::tokyo_night(),
16 }
17 }
18
19 pub fn paint(&self, canvas: &mut dyn Canvas, _width: f32, _height: f32) {
20 let title_style = TextStyle {
21 color: self.theme.foreground,
22 ..Default::default()
23 };
24 let key_style = TextStyle {
25 color: self.theme.cpu.sample(0.3), ..Default::default()
27 };
28 let desc_style = TextStyle {
29 color: self.theme.dim,
30 ..Default::default()
31 };
32
33 canvas.draw_text(
34 "Help - Keyboard Controls",
35 Point::new(2.0, 2.0),
36 &title_style,
37 );
38
39 let controls = [
40 ("1-9", "Switch panels"),
41 ("Space", "Start/Stop load generation"),
42 ("+/-", "Increase/Decrease intensity"),
43 ("b", "Cycle backend (SIMD/wgpu/CUDA/All)"),
44 ("w", "Cycle workload type"),
45 ("[/]", "Decrease/Increase problem size"),
46 ("r", "Reset statistics"),
47 ("q/Esc", "Quit"),
48 ];
49
50 for (i, (key, desc)) in controls.iter().enumerate() {
51 let y = 4.0 + i as f32;
52 canvas.draw_text(&format!("{:>8}", key), Point::new(4.0, y), &key_style);
53 canvas.draw_text(&format!(" {}", desc), Point::new(12.0, y), &desc_style);
54 }
55 }
56}
57
58impl Brick for HelpPanelBrick {
59 fn brick_name(&self) -> &'static str {
60 "help_panel"
61 }
62
63 fn assertions(&self) -> Vec<BrickAssertion> {
64 vec![BrickAssertion::MinWidth(30), BrickAssertion::MinHeight(10)]
65 }
66
67 fn budget(&self) -> BrickBudget {
68 BrickBudget::FRAME_60FPS
69 }
70
71 fn verify(&self) -> BrickVerification {
72 let mut v = BrickVerification::new();
73 for assertion in self.assertions() {
74 v.check(&assertion);
75 }
76 v
77 }
78
79 fn as_any(&self) -> &dyn Any {
80 self
81 }
82}
83
84impl Default for HelpPanelBrick {
85 fn default() -> Self {
86 Self::new()
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use presentar_core::RecordingCanvas;
94
95 #[test]
96 fn test_help_panel_brick_name() {
97 let panel = HelpPanelBrick::new();
98 assert_eq!(panel.brick_name(), "help_panel");
99 }
100
101 #[test]
102 fn test_help_panel_has_assertions() {
103 let panel = HelpPanelBrick::new();
104 assert!(!panel.assertions().is_empty());
105 }
106
107 #[test]
108 fn test_help_panel_paint() {
109 let panel = HelpPanelBrick::new();
110 let mut canvas = RecordingCanvas::new();
111
112 panel.paint(&mut canvas, 80.0, 24.0);
113
114 assert!(!canvas.is_empty());
117 assert!(canvas.command_count() >= 10);
118 }
119
120 #[test]
121 fn test_help_panel_default() {
122 let panel = HelpPanelBrick::default();
123 assert_eq!(panel.brick_name(), "help_panel");
124 }
125
126 #[test]
127 fn test_help_panel_verify() {
128 let panel = HelpPanelBrick::new();
129 let verification = panel.verify();
130 assert!(verification.is_valid());
131 }
132
133 #[test]
134 fn test_help_panel_budget() {
135 let panel = HelpPanelBrick::new();
136 let budget = panel.budget();
137 assert_eq!(budget.total_ms(), 16); }
139}