From 0b428d94e751dc4a5fbe19418bfb5994cebfa54c Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Sun, 24 May 2026 13:04:10 -0400 Subject: major ui rework --- src/ui.rs | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 186 insertions(+), 39 deletions(-) (limited to 'src/ui.rs') diff --git a/src/ui.rs b/src/ui.rs index e1972d9..fd40ac9 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,24 +1,81 @@ -pub mod topbar; -pub mod bodies_window; -pub mod fleet_window; -pub mod fleet_schedule; +pub mod contact; +mod current_system_widget; +mod contacts_widget; +mod fleets_widget; +mod schedule_widget; +mod time_control_widget; use std::{borrow::Borrow, cell::RefCell}; use crate::GameState; -use crate::solar_system::body::BodyId; -use crate::ui::bodies_window::BodiesWindowState; -use crate::ui::fleet_window::FleetWindowState; -use crate::ui::topbar::TopBarState; +use crate::fleet::FleetsManager; +use crate::solar_system::{Kilometers, SolarSystem, SystemId}; +use crate::timeman::Second; +use crate::ui::contact::MapContact; +use crate::ui::contacts_widget::{ContactsListWidget, FocusedContactWidget}; +use crate::ui::current_system_widget::CurrentSystemWidget; +use crate::ui::fleets_widget::{FleetsControlPanel, FleetsListWidget}; +use crate::ui::time_control_widget::TimeControlWidget; -#[derive(Default, Clone)] +#[derive(Default, Eq, PartialEq)] +pub enum LeftPanelMenuMode +{ + #[default] + Contacts, + Fleets +} + +#[derive(Default)] pub struct State { - pub camera_target: Option, + pub current_system: Option, + pub camera_target: Option, + pub selected_contact: Option, + + pub manual_tick: Second, + pub auto_tick: (bool, Second), + + pub left_panel_menu: LeftPanelMenuMode, + pub fleets_control_panel: FleetsControlPanel +} + +pub fn set_theme(ctx: &egui::Context) +{ + ctx.set_theme(egui::Theme::Dark); + ctx.style_mut_of(egui::Theme::Dark, |style| { + let bg_color = egui::Color32::from_gray(64); + style.visuals.panel_fill = bg_color; + style.visuals.window_fill =bg_color; + + style.visuals.window_stroke = egui::Stroke::NONE; + + style.visuals.menu_corner_radius = egui::CornerRadius::ZERO; + style.visuals.widgets.noninteractive.corner_radius = egui::CornerRadius::ZERO; + style.visuals.widgets.inactive.corner_radius = egui::CornerRadius::ZERO; + style.visuals.widgets.hovered.corner_radius = egui::CornerRadius::ZERO; + style.visuals.widgets.active.corner_radius = egui::CornerRadius::ZERO; + style.visuals.widgets.open.corner_radius = egui::CornerRadius::ZERO; - pub topbar_sate: TopBarState, - pub bodies_window: BodiesWindowState, - pub fleet_window: FleetWindowState + style.visuals.widgets.hovered.bg_fill = egui::Color32::from_gray(128); + + style.visuals.widgets.inactive.bg_fill = egui::Color32::from_gray(96); + style.visuals.widgets.inactive.weak_bg_fill = egui::Color32::from_gray(96); + style.visuals.widgets.inactive.fg_stroke = egui::Stroke::new(2.0, egui::Color32::from_gray(196)); + + style.visuals.widgets.active.bg_fill = egui::Color32::from_gray(128); + style.visuals.widgets.active.fg_stroke = egui::Stroke::new(2.0, egui::Color32::from_gray(255)); + + style.visuals.selection.bg_fill = egui::Color32::from_gray(96); + style.visuals.selection.stroke.color = egui::Color32::WHITE; + style.visuals.override_text_color = Some(egui::Color32::WHITE); + style.override_text_style = Some(egui::TextStyle::Monospace); + + style.spacing.window_margin = egui::Margin::same(12); + + style.visuals.widgets.noninteractive.bg_stroke = egui::Stroke::NONE; + + style.interaction.selectable_labels = false; + }); } impl State @@ -28,38 +85,128 @@ impl State game_state: &RefCell, ui: &mut egui::Ui) { - let mut game_state = game_state.borrow_mut(); - let topbar_action = self.topbar_sate.paint( - ui, - &game_state, - &self.bodies_window, - &self.fleet_window); + egui::Panel::top("Top panel") + .resizable(false) + .show_inside(ui, + |panel_ui| { + self.show_topbar(&mut game_state.borrow_mut(), panel_ui); + }); - if let Some(by) = topbar_action.advance_tick { - game_state.timeman_mut().advance(by) - } - if topbar_action.toggle_bodies_window { self.bodies_window.open = !self.bodies_window.open; } - if topbar_action.toggle_fleets_window { self.fleet_window.open = !self.fleet_window.open; } - - if let Some(current_system_id) = self.topbar_sate.current_system { - let current_system = &game_state.solar_systems()[current_system_id]; - let bodies_window_action = - self.bodies_window.paint(ui, current_system); - if bodies_window_action.focus_body.is_some() { - self.camera_target = bodies_window_action.focus_body; + let remaining_rect = ui.max_rect(); + let square_size = remaining_rect.height(); + let panel_width = ((remaining_rect.width() - square_size) / 2.0).floor().max(200.0); + + egui::Panel::left("Left panel") + .resizable(false) + .exact_size(panel_width) + .show_inside(ui, + |panel_ui| { + self.show_left_panel(&mut game_state.borrow_mut(), panel_ui); + }); + + egui::Panel::right("Right panel") + .resizable(false) + .exact_size(panel_width) + .show_inside(ui, + |panel_ui| { + + }); +} + + pub fn show_topbar( + &mut self, + game_state: &mut GameState, + ui: &mut egui::Ui) + { + ui.horizontal(|horizontal| { + let star_systems = game_state.solar_systems(); + let fleets_man = game_state.fleets(); + + horizontal.add(CurrentSystemWidget::new(star_systems, &mut self.current_system)); + + if let Some(system_id) = self.current_system { + let current_system = &star_systems[system_id]; + + horizontal.add(egui::Separator::default().spacing(12.0)); + horizontal.add(FocusedContactWidget::new( + self.camera_target.clone(), + current_system, fleets_man)); } - let fleet_window_action = - self.fleet_window.paint( - ui, - game_state.borrow(), - &self.topbar_sate.current_system, - &self.camera_target); + //Horrible hack to allow for right-alignment. + //I chose to use EGUI so i'll stick with EGUI! + horizontal.add_space(horizontal.available_width()-224.0); + let tcw = TimeControlWidget::new(&mut self.manual_tick, &mut self.auto_tick) + .show_ui(horizontal); - if let Some(new_fleet) = fleet_window_action.new_fleet { - game_state.new_fleet_from_ui(new_fleet); + if let Some(tick) = tcw.inner { + game_state.timeman_mut().advance(tick); } + }); + } + + pub fn show_left_panel( + &mut self, + game_state: &mut GameState, + ui: &mut egui::Ui) + { + if self.current_system.is_none() { + return; } + + ui.vertical(|vertical| { + let star_systems = game_state.solar_systems(); + let fleets = game_state.fleets(); + let current_system = &star_systems[self.current_system.unwrap()]; + + vertical.horizontal(|horizontal| { + if horizontal.selectable_label( + self.left_panel_menu == LeftPanelMenuMode::Contacts, + "Contacts") + .clicked() { + self.left_panel_menu = LeftPanelMenuMode::Contacts; + } + if horizontal.selectable_label( + self.left_panel_menu == LeftPanelMenuMode::Fleets, + "Fleets") + .clicked() { + self.left_panel_menu = LeftPanelMenuMode::Fleets; + } + }); + + match self.left_panel_menu { + LeftPanelMenuMode::Contacts => { + let camera_refocus = ContactsListWidget::new( + &mut self.selected_contact, + current_system, + fleets) + .show_ui(vertical); + if camera_refocus.inner.is_some() { + self.camera_target = camera_refocus.inner; + } + }, + LeftPanelMenuMode::Fleets => { + let flw_resp = + FleetsListWidget::new(fleets, &mut self.selected_contact) + .show_ui(vertical); + + + let fcp_resp = self.fleets_control_panel.show( + &self.selected_contact, + fleets, current_system, + vertical); + + if let Some(refocus) = flw_resp.refocus { + self.current_system = Some(refocus.0); + self.camera_target = Some(refocus.1); + } + + if let Some(new_fleet) = fcp_resp.new_fleet { + game_state.new_fleet_from_modal(new_fleet, current_system.id(), self.selected_contact); + } + } + }; + }); } } -- cgit v1.2.3