framework_tool_tui/tui/component/
main.rs1use std::sync::Arc;
2
3use ratatui::{
4 crossterm::event::{Event, KeyCode, KeyEventKind},
5 layout::{Constraint, Layout, Rect},
6 Frame,
7};
8
9use crate::{
10 framework::{fingerprint::Fingerprint, info::FrameworkInfo},
11 tui::{
12 component::{
13 brightness_panel::BrightnessPanelComponent, charge_panel::ChargePanelComponent,
14 pd_ports_panel::PdPortsPanelComponent, privacy_panel::PrivacyPanelComponent,
15 smbios_panel::SmbiosPanelComponent, AdjustableComponent, Component,
16 },
17 theme::Theme,
18 },
19};
20
21pub struct MainComponent {
22 privacy_panel: PrivacyPanelComponent,
23 smbios_panel: SmbiosPanelComponent,
24 pd_ports_panel: PdPortsPanelComponent,
25 adjustable_panels: Vec<Box<dyn AdjustableComponent>>,
26 selected_panel: Option<usize>,
27}
28
29impl MainComponent {
30 pub fn new(finterprint: Arc<Fingerprint>, info: &FrameworkInfo) -> Self {
31 let mut adjustable_panels: Vec<Box<dyn AdjustableComponent>> = Vec::new();
32 let charge_panel = Box::new(ChargePanelComponent::new());
33
34 adjustable_panels.push(charge_panel);
35
36 if Self::is_brightness_supported(info) {
37 let brightness_panel = Box::new(BrightnessPanelComponent::new(finterprint));
38
39 adjustable_panels.push(brightness_panel);
40 }
41
42 Self {
43 privacy_panel: PrivacyPanelComponent,
44 smbios_panel: SmbiosPanelComponent,
45 pd_ports_panel: PdPortsPanelComponent::new(),
46 adjustable_panels,
47 selected_panel: None,
48 }
49 }
50
51 fn switch_panels(&mut self) {
52 let len = self.adjustable_panels.len();
53
54 if let Some(selected_panel) = self.selected_panel {
55 if selected_panel < len - 1 {
56 let next = selected_panel + 1;
57
58 self.adjustable_panels[selected_panel].panel().toggle();
59 self.adjustable_panels[next].panel().toggle();
60
61 self.selected_panel = Some(next);
62 } else {
63 self.adjustable_panels[selected_panel].panel().toggle();
64 self.selected_panel = None;
65 }
66 } else {
67 self.adjustable_panels[0].panel().toggle();
68 self.selected_panel = Some(0);
69 }
70 }
71
72 fn render_privacy_and_smbios_panels(
73 &mut self,
74 frame: &mut Frame,
75 area: Rect,
76 theme: &Theme,
77 info: &FrameworkInfo,
78 ) {
79 let [privacy_panel_area, smbios_panel_area] =
80 Layout::horizontal([Constraint::Min(0), Constraint::Min(0)]).areas(area);
81
82 self.privacy_panel
84 .render(frame, privacy_panel_area, theme, info);
85
86 self.smbios_panel
88 .render(frame, smbios_panel_area, theme, info);
89 }
90
91 fn is_brightness_supported(info: &FrameworkInfo) -> bool {
92 info.platform != Some(framework_lib::smbios::Platform::Framework12IntelGen13)
94 }
95}
96
97impl Component for MainComponent {
98 fn handle_input(&mut self, event: Event) -> Option<crate::app::AppEvent> {
99 if let Event::Key(key) = &event {
100 if key.kind == KeyEventKind::Press && key.code == KeyCode::Tab {
101 self.switch_panels();
102 }
103 }
104
105 self.adjustable_panels
106 .iter_mut()
107 .find_map(|panel| panel.handle_input(event.clone()))
108 }
109
110 fn render(&mut self, frame: &mut Frame, area: Rect, theme: &Theme, info: &FrameworkInfo) {
111 let [top_area, pd_ports_panel_area] =
112 Layout::vertical([Constraint::Max(15), Constraint::Min(0)]).areas(area);
113 let [charge_panel_area, top_right_area] =
114 Layout::horizontal([Constraint::Min(0), Constraint::Min(0)]).areas(top_area);
115
116 self.adjustable_panels[0].render(frame, charge_panel_area, theme, info);
118
119 if Self::is_brightness_supported(info) {
121 let [brightness_panel_area, privacy_and_smbios_panels_area] =
122 Layout::vertical([Constraint::Min(7), Constraint::Min(7)]).areas(top_right_area);
123
124 self.adjustable_panels[1].render(frame, brightness_panel_area, theme, info);
126
127 self.render_privacy_and_smbios_panels(
129 frame,
130 privacy_and_smbios_panels_area,
131 theme,
132 info,
133 );
134 } else {
135 self.render_privacy_and_smbios_panels(frame, top_right_area, theme, info);
137 }
138
139 self.pd_ports_panel
141 .render(frame, pd_ports_panel_area, theme, info);
142 }
143}