use std::sync::Arc;
use ratatui::{
crossterm::event::{Event, KeyCode, KeyEventKind},
layout::{Constraint, Layout, Rect},
Frame,
};
use crate::{
framework::{fingerprint::Fingerprint, info::FrameworkInfo},
tui::{
component::{
brightness_panel::BrightnessPanelComponent, charge_panel::ChargePanelComponent,
pd_ports_panel::PdPortsPanelComponent, privacy_panel::PrivacyPanelComponent,
smbios_panel::SmbiosPanelComponent, AdjustableComponent, Component,
},
theme::Theme,
},
};
pub struct MainComponent {
privacy_panel: PrivacyPanelComponent,
smbios_panel: SmbiosPanelComponent,
pd_ports_panel: PdPortsPanelComponent,
adjustable_panels: Vec<Box<dyn AdjustableComponent>>,
selected_panel: Option<usize>,
}
impl MainComponent {
pub fn new(finterprint: Arc<Fingerprint>, info: &FrameworkInfo) -> Self {
let mut adjustable_panels: Vec<Box<dyn AdjustableComponent>> = Vec::new();
let charge_panel = Box::new(ChargePanelComponent::new());
adjustable_panels.push(charge_panel);
if Self::is_brightness_supported(info) {
let brightness_panel = Box::new(BrightnessPanelComponent::new(finterprint));
adjustable_panels.push(brightness_panel);
}
Self {
privacy_panel: PrivacyPanelComponent,
smbios_panel: SmbiosPanelComponent,
pd_ports_panel: PdPortsPanelComponent::new(),
adjustable_panels,
selected_panel: None,
}
}
fn switch_panels(&mut self) {
let len = self.adjustable_panels.len();
if let Some(selected_panel) = self.selected_panel {
if selected_panel < len - 1 {
let next = selected_panel + 1;
self.adjustable_panels[selected_panel].panel().toggle();
self.adjustable_panels[next].panel().toggle();
self.selected_panel = Some(next);
} else {
self.adjustable_panels[selected_panel].panel().toggle();
self.selected_panel = None;
}
} else {
self.adjustable_panels[0].panel().toggle();
self.selected_panel = Some(0);
}
}
fn render_privacy_and_smbios_panels(
&mut self,
frame: &mut Frame,
area: Rect,
theme: &Theme,
info: &FrameworkInfo,
) {
let [privacy_panel_area, smbios_panel_area] =
Layout::horizontal([Constraint::Min(0), Constraint::Min(0)]).areas(area);
self.privacy_panel
.render(frame, privacy_panel_area, theme, info);
self.smbios_panel
.render(frame, smbios_panel_area, theme, info);
}
fn is_brightness_supported(info: &FrameworkInfo) -> bool {
info.platform != Some(framework_lib::smbios::Platform::Framework12IntelGen13)
}
}
impl Component for MainComponent {
fn handle_input(&mut self, event: Event) -> Option<crate::app::AppEvent> {
if let Event::Key(key) = &event {
if key.kind == KeyEventKind::Press && key.code == KeyCode::Tab {
self.switch_panels();
}
}
self.adjustable_panels
.iter_mut()
.find_map(|panel| panel.handle_input(event.clone()))
}
fn render(&mut self, frame: &mut Frame, area: Rect, theme: &Theme, info: &FrameworkInfo) {
let [top_area, pd_ports_panel_area] =
Layout::vertical([Constraint::Max(15), Constraint::Min(0)]).areas(area);
let [charge_panel_area, top_right_area] =
Layout::horizontal([Constraint::Min(0), Constraint::Min(0)]).areas(top_area);
self.adjustable_panels[0].render(frame, charge_panel_area, theme, info);
if Self::is_brightness_supported(info) {
let [brightness_panel_area, privacy_and_smbios_panels_area] =
Layout::vertical([Constraint::Min(7), Constraint::Min(7)]).areas(top_right_area);
self.adjustable_panels[1].render(frame, brightness_panel_area, theme, info);
self.render_privacy_and_smbios_panels(
frame,
privacy_and_smbios_panels_area,
theme,
info,
);
} else {
self.render_privacy_and_smbios_panels(frame, top_right_area, theme, info);
}
self.pd_ports_panel
.render(frame, pd_ports_panel_area, theme, info);
}
}