use egui::{Button, CentralPanel, TextEdit, ViewportBuilder, ViewportId}; use winit::event_loop::EventLoopProxy; use crate::{ app::UserEvent, emulator::{EmulatorClient, SimId, SimState}, gdbserver::{GdbServer, GdbServerStatus}, }; use super::AppWindow; pub struct GdbServerWindow { sim_id: SimId, client: EmulatorClient, port_str: String, connected: bool, quit_on_disconnect: bool, server: GdbServer, proxy: EventLoopProxy, } impl GdbServerWindow { pub fn new(sim_id: SimId, client: EmulatorClient, proxy: EventLoopProxy) -> Self { Self { sim_id, client: client.clone(), port_str: (8080 + sim_id.to_index()).to_string(), connected: false, quit_on_disconnect: false, server: GdbServer::new(sim_id, client), proxy, } } pub fn launch(&mut self, port: u16) { self.server.stop(); self.port_str = port.to_string(); self.quit_on_disconnect = true; self.server.start(port); self.connected = true; } } impl AppWindow for GdbServerWindow { fn viewport_id(&self) -> ViewportId { ViewportId::from_hash_of(format!("Debugger-{}", self.sim_id)) } fn sim_id(&self) -> SimId { self.sim_id } fn initial_viewport(&self) -> ViewportBuilder { ViewportBuilder::default() .with_title(format!("GDB Server ({})", self.sim_id)) .with_inner_size((300.0, 200.0)) } fn show(&mut self, ctx: &egui::Context) { let port_num: Option = self.port_str.parse().ok(); let status = self.server.status(); CentralPanel::default().show(ctx, |ui| { ui.horizontal(|ui| { if port_num.is_none() { let style = ui.style_mut(); let error = style.visuals.error_fg_color; style.visuals.widgets.active.bg_stroke.color = error; style.visuals.widgets.hovered.bg_stroke.color = error; } ui.label("Port"); let port_editor = TextEdit::singleline(&mut self.port_str).desired_width(100.0); ui.add_enabled(!status.running(), port_editor); ui.checkbox(&mut self.quit_on_disconnect, "Quit on disconnect"); }); if !status.running() { if self.connected && self.quit_on_disconnect { self.proxy.send_event(UserEvent::Quit(self.sim_id)).unwrap(); } else { self.connected = false; } let start_button = Button::new("Start"); let can_start = port_num.is_some() && self.client.sim_state(self.sim_id) == SimState::Ready; if ui.add_enabled(can_start, start_button).clicked() { let port = port_num.unwrap(); self.server.start(port); self.connected = true; } } else { let stop_button = Button::new("Stop"); if ui.add(stop_button).clicked() { self.server.stop(); } } match &status { GdbServerStatus::Stopped => {} GdbServerStatus::Connecting => { ui.label("Connecting..."); } GdbServerStatus::Running => { ui.label("Running"); } GdbServerStatus::Error(message) => { ui.label(message); } } }); } }