Skip to main content

framework_tool_tui/tui/component/
pd_ports_panel.rs

1use crate::{
2    framework::info::{FrameworkInfo, PdPortInfo},
3    tui::{component::Component, theme::Theme},
4};
5use ratatui::{
6    layout::{Constraint, Flex, Layout, Rect},
7    style::Style,
8    widgets::{Block, BorderType, Borders, Paragraph},
9    Frame,
10};
11
12pub struct PdPortsPanelComponent;
13
14impl Default for PdPortsPanelComponent {
15    fn default() -> Self {
16        Self::new()
17    }
18}
19
20impl PdPortsPanelComponent {
21    pub fn new() -> Self {
22        PdPortsPanelComponent
23    }
24
25    fn render_port_block(
26        &self,
27        frame: &mut Frame,
28        area: Rect,
29        name: &str,
30        theme: &Theme,
31        info: &Option<PdPortInfo>,
32    ) {
33        let block = Block::default()
34            .title(format!(" {} ", name))
35            .borders(Borders::ALL)
36            .border_type(BorderType::Plain);
37
38        if let Some(info) = info {
39            let [key_area, value_area] =
40                Layout::horizontal([Constraint::Fill(1), Constraint::Fill(1)])
41                    .margin(1)
42                    .spacing(1)
43                    .areas(block.inner(area));
44
45            let keys_block = Block::default().borders(Borders::NONE);
46            let values_block = Block::default().borders(Borders::NONE);
47
48            let [role_key_area, dualrole_key_area, charging_type_key_area, voltage_now_key_area, voltage_max_key_area, current_limit_key_area, current_max_key_area, max_power_key_area] =
49                Layout::vertical([
50                    Constraint::Length(1),
51                    Constraint::Length(1),
52                    Constraint::Length(1),
53                    Constraint::Length(1),
54                    Constraint::Length(1),
55                    Constraint::Length(1),
56                    Constraint::Length(1),
57                    Constraint::Length(1),
58                ])
59                .flex(Flex::Legacy)
60                .areas(keys_block.inner(key_area));
61            let [role_value_area, dualrole_value_area, charging_type_value_area, voltage_now_value_area, voltage_max_value_area, current_limit_value_area, current_max_value_area, max_power_value_area] =
62                Layout::vertical([
63                    Constraint::Length(1),
64                    Constraint::Length(1),
65                    Constraint::Length(1),
66                    Constraint::Length(1),
67                    Constraint::Length(1),
68                    Constraint::Length(1),
69                    Constraint::Length(1),
70                    Constraint::Length(1),
71                ])
72                .flex(Flex::Legacy)
73                .areas(values_block.inner(value_area));
74
75            self.render_role(frame, role_key_area, role_value_area, theme, info);
76            self.render_dualrole(frame, dualrole_key_area, dualrole_value_area, theme, info);
77            self.render_charging_type(
78                frame,
79                charging_type_key_area,
80                charging_type_value_area,
81                theme,
82                info,
83            );
84            self.render_voltage_now(
85                frame,
86                voltage_now_key_area,
87                voltage_now_value_area,
88                theme,
89                info,
90            );
91            self.render_voltage_max(
92                frame,
93                voltage_max_key_area,
94                voltage_max_value_area,
95                theme,
96                info,
97            );
98            self.render_current_limit(
99                frame,
100                current_limit_key_area,
101                current_limit_value_area,
102                theme,
103                info,
104            );
105            self.render_current_max(
106                frame,
107                current_max_key_area,
108                current_max_value_area,
109                theme,
110                info,
111            );
112            self.render_max_power(frame, max_power_key_area, max_power_value_area, theme, info);
113        }
114
115        frame.render_widget(block, area);
116    }
117
118    fn render_role(
119        &self,
120        frame: &mut Frame,
121        key_area: Rect,
122        value_area: Rect,
123        theme: &Theme,
124        info: &PdPortInfo,
125    ) {
126        frame.render_widget(Paragraph::new("Role"), key_area);
127        frame.render_widget(
128            Paragraph::new(info.role.as_str()).style(Style::default().fg(theme.informative_text)),
129            value_area,
130        );
131    }
132
133    fn render_dualrole(
134        &self,
135        frame: &mut Frame,
136        key_area: Rect,
137        value_area: Rect,
138        theme: &Theme,
139        info: &PdPortInfo,
140    ) {
141        frame.render_widget(Paragraph::new("Dual role"), key_area);
142        frame.render_widget(
143            Paragraph::new(info.dualrole.as_str())
144                .style(Style::default().fg(theme.informative_text)),
145            value_area,
146        );
147    }
148
149    fn render_charging_type(
150        &self,
151        frame: &mut Frame,
152        key_area: Rect,
153        value_area: Rect,
154        theme: &Theme,
155        info: &PdPortInfo,
156    ) {
157        frame.render_widget(Paragraph::new("Charging type"), key_area);
158        frame.render_widget(
159            Paragraph::new(info.charging_type.as_str())
160                .style(Style::default().fg(theme.informative_text)),
161            value_area,
162        );
163    }
164
165    fn render_voltage_now(
166        &self,
167        frame: &mut Frame,
168        key_area: Rect,
169        value_area: Rect,
170        theme: &Theme,
171        info: &PdPortInfo,
172    ) {
173        frame.render_widget(Paragraph::new("Voltage now"), key_area);
174        frame.render_widget(
175            Paragraph::new(format!("{:.1} V", info.voltage_now))
176                .style(Style::default().fg(theme.informative_text)),
177            value_area,
178        );
179    }
180
181    fn render_voltage_max(
182        &self,
183        frame: &mut Frame,
184        key_area: Rect,
185        value_area: Rect,
186        theme: &Theme,
187        info: &PdPortInfo,
188    ) {
189        frame.render_widget(Paragraph::new("Voltage max"), key_area);
190        frame.render_widget(
191            Paragraph::new(format!("{:.1} V", info.voltage_max))
192                .style(Style::default().fg(theme.informative_text)),
193            value_area,
194        );
195    }
196
197    fn render_current_limit(
198        &self,
199        frame: &mut Frame,
200        key_area: Rect,
201        value_area: Rect,
202        theme: &Theme,
203        info: &PdPortInfo,
204    ) {
205        frame.render_widget(Paragraph::new("Current limit"), key_area);
206        frame.render_widget(
207            Paragraph::new(format!("{} mA", info.current_limit))
208                .style(Style::default().fg(theme.informative_text)),
209            value_area,
210        );
211    }
212
213    fn render_current_max(
214        &self,
215        frame: &mut Frame,
216        key_area: Rect,
217        value_area: Rect,
218        theme: &Theme,
219        info: &PdPortInfo,
220    ) {
221        frame.render_widget(Paragraph::new("Current max"), key_area);
222        frame.render_widget(
223            Paragraph::new(format!("{} mA", info.current_max))
224                .style(Style::default().fg(theme.informative_text)),
225            value_area,
226        );
227    }
228
229    fn render_max_power(
230        &self,
231        frame: &mut Frame,
232        key_area: Rect,
233        value_area: Rect,
234        theme: &Theme,
235        info: &PdPortInfo,
236    ) {
237        frame.render_widget(Paragraph::new("Max power"), key_area);
238        frame.render_widget(
239            Paragraph::new(format!(
240                "{}.{} W",
241                info.max_power / 1000,
242                info.max_power % 1000
243            ))
244            .style(Style::default().fg(theme.informative_text)),
245            value_area,
246        );
247    }
248}
249
250impl Component for PdPortsPanelComponent {
251    fn render(&mut self, frame: &mut Frame, area: Rect, theme: &Theme, info: &FrameworkInfo) {
252        let block = Block::default()
253            .title(" PD ports ")
254            .borders(Borders::ALL)
255            .border_style(Style::default().fg(theme.border))
256            .border_type(BorderType::Rounded);
257
258        let [left_area, right_area] =
259            Layout::horizontal([Constraint::Fill(1), Constraint::Fill(1)]).areas(block.inner(area));
260
261        let [left_back_area, left_front_area] =
262            Layout::vertical([Constraint::Min(5), Constraint::Min(0)])
263                .margin(1)
264                .areas(left_area);
265        let [right_back_area, right_front_area] =
266            Layout::vertical([Constraint::Min(5), Constraint::Min(0)])
267                .margin(1)
268                .areas(right_area);
269
270        self.render_port_block(
271            frame,
272            left_back_area,
273            "Left back",
274            theme,
275            &info.pd_ports.left_back,
276        );
277        self.render_port_block(
278            frame,
279            left_front_area,
280            "Left front",
281            theme,
282            &info.pd_ports.left_front,
283        );
284        self.render_port_block(
285            frame,
286            right_back_area,
287            "Right back",
288            theme,
289            &info.pd_ports.right_back,
290        );
291        self.render_port_block(
292            frame,
293            right_front_area,
294            "Right front",
295            theme,
296            &info.pd_ports.right_front,
297        );
298
299        frame.render_widget(block, area);
300    }
301}