Wire live serial data into matrix renderer

This commit is contained in:
lennlouisgeek
2026-05-20 01:23:02 +08:00
parent a7b617419d
commit d2c9fad556
18 changed files with 874 additions and 63 deletions

115
src/ui.rs
View File

@@ -1,6 +1,7 @@
use eframe::egui;
use crate::{
connection::{ConnectionManager, ConnectionState},
theme::{ENGINEERING_DARK, accent_text, dim_text, group_frame, panel_frame, tag_button},
utils::serial_enum,
};
@@ -29,6 +30,7 @@ pub struct ConfigPanelState {
pub struct ConnectPanelState {
pub mode: SerialMode,
pub port: Vec<String>,
pub selected_port: String,
pub duration: u8,
pub manual: bool,
pub rows: u8,
@@ -87,9 +89,11 @@ impl Default for ConfigPanelState {
impl Default for ConnectPanelState {
fn default() -> Self {
let port = serial_enum().unwrap();
let selected_port = port.first().cloned().unwrap_or_default();
Self {
mode: SerialMode::SingleModule,
port,
selected_port,
duration: 10,
manual: false,
rows: 12,
@@ -119,19 +123,18 @@ pub fn draw_connect_panel(
ctx: &egui::Context,
panel: &mut FloatingPanelState,
config: &mut ConnectPanelState,
connection: &ConnectionManager,
) {
let conn_state = connection.state();
let is_connected = matches!(
conn_state,
ConnectionState::Connected | ConnectionState::Streaming
);
draw_center_floating_panel(ctx, panel, "connect_center_panel", 64.0, |ui| {
ui.set_min_width(320.0);
ui.vertical(|ui| {
// ui.horizontal_centered(|ui| {
// mode_button(ui, &mut config.mode, SerialMode::SingleModule, "单模块");
// ui.add_space(8.0);
// mode_button(ui, &mut config.mode, SerialMode::Manual, "全手");
// ui.add_space(8.0);
// mode_button(ui, &mut config.mode, SerialMode::Model, "模型");
// });
let button_width = 96.0;
let gap = 8.0;
let total_width = button_width * 3.0 + gap * 2.0;
@@ -161,18 +164,39 @@ pub fn draw_connect_panel(
ui.colored_label(ENGINEERING_DARK.text, "串口");
egui::ComboBox::from_id_salt("connect_ports")
.width(130.0)
.selected_text(
config
.port
.first()
.map(String::as_str)
.unwrap_or("无可用串口"),
)
.selected_text(if config.selected_port.is_empty() {
"无可用串口".to_owned()
} else {
config.selected_port.clone()
})
.show_ui(ui, |ui| {
for port in &config.port {
let _ = ui.selectable_label(false, port);
let label = port.clone();
ui.selectable_value(
&mut config.selected_port,
port.clone(),
label,
);
}
});
if ui
.add(
egui::Button::new("")
.fill(ENGINEERING_DARK.panel_strong)
.stroke(egui::Stroke::new(1.0, ENGINEERING_DARK.border_soft))
.min_size(egui::vec2(24.0, 20.0)),
)
.on_hover_text("刷新串口")
.clicked()
{
if let Ok(ports) = serial_enum() {
if !ports.contains(&config.selected_port) {
config.selected_port =
ports.first().cloned().unwrap_or_default();
}
config.port = ports;
}
}
ui.add_space(10.0);
ui.label("频率");
@@ -203,6 +227,65 @@ pub fn draw_connect_panel(
});
})
});
ui.add_space(8.0);
// Connection status and button row
ui.horizontal(|ui| {
let status_text = match conn_state {
ConnectionState::Disconnected => "未连接",
ConnectionState::Connecting => "连接中...",
ConnectionState::Connected => "已连接",
ConnectionState::Streaming => "采集中",
ConnectionState::Error => "连接错误",
};
let status_color = match conn_state {
ConnectionState::Disconnected => ENGINEERING_DARK.text_dim,
ConnectionState::Connecting => egui::Color32::from_rgb(200, 180, 60),
ConnectionState::Connected => egui::Color32::from_rgb(158, 184, 101),
ConnectionState::Streaming => egui::Color32::from_rgb(100, 200, 255),
ConnectionState::Error => egui::Color32::from_rgb(255, 98, 82),
};
ui.colored_label(status_color, status_text);
let used = 100.0;
let remaining = (ui.available_width() - used).max(0.0);
ui.add_space(remaining);
let btn_label = if is_connected { "断开" } else { "连接" };
let btn_fill = if is_connected {
egui::Color32::from_rgb(180, 60, 60)
} else {
ENGINEERING_DARK.accent
};
let btn_stroke = if is_connected {
egui::Stroke::new(1.0, egui::Color32::from_rgb(220, 80, 80))
} else {
egui::Stroke::new(1.0, ENGINEERING_DARK.accent_hot)
};
if ui
.add(
egui::Button::new(
egui::RichText::new(btn_label).color(egui::Color32::WHITE),
)
.fill(btn_fill)
.stroke(btn_stroke)
.min_size(egui::vec2(96.0, 28.0)),
)
.clicked()
{
if is_connected {
connection.disconnect();
} else if !config.selected_port.is_empty() {
connection.connect(
&config.selected_port,
config.rows as u32,
config.cols as u32,
);
}
}
});
});
});
}