From b60eb87e347fe6c5ad5d9a376e12accc4e472438 Mon Sep 17 00:00:00 2001 From: Arthur Roberts Date: Fri, 16 Jun 2023 18:40:01 +0100 Subject: [PATCH] Attempt at moving away some of the launcher logic from the GUI --- src/infos.rs | 56 +++++++++++++++++++++++++++++++++++- src/main.rs | 81 +++++++++++++++++++++++----------------------------- 2 files changed, 90 insertions(+), 47 deletions(-) diff --git a/src/infos.rs b/src/infos.rs index 42d6a84..5adb4fa 100644 --- a/src/infos.rs +++ b/src/infos.rs @@ -20,6 +20,60 @@ pub struct LauncherInfo { pub name: String, } +pub struct LauncherManager { + pub launchers: Vec, + pub current_selected: Option, +} + +impl LauncherManager { + pub fn new() -> LauncherManager { + LauncherManager { + launchers: Vec::new(), + current_selected: None, + } + } + pub fn add(&mut self, launcher: LauncherInfo) { + self.launchers.push(launcher); + } + pub fn get(&self, index: usize) -> Option<(&LauncherInfo, bool)> { + if index > self.launchers.len() { + None + } else { + Some((self.launchers.get(index).unwrap(), index == self.current_selected.unwrap_or(std::usize::MAX))) + } + } + pub fn get_current(&self) -> Option<&LauncherInfo> { + match self.current_selected { + None => None, + Some(pos) => Some(self.launchers.get(pos).unwrap()), + } + } + pub fn set_current(&mut self, index: usize) { + assert!(index <= self.launchers.len()); + self.current_selected = Some(index); + } + pub fn clear_current(&mut self) { + self.current_selected = None; + } + pub fn remove_launcher(&mut self, index: usize) { + assert!(index <= self.launchers.len()); + self.launchers.remove(index); + } + pub fn iter_with_pos_and_selected( + &mut self, + ) -> impl Iterator + '_ { + self.launchers + .iter_mut() + .enumerate() + .map(|(i, l)| (l, i, i == self.current_selected.unwrap_or(std::usize::MAX))) + } +} + +pub struct IwadManager { + pub wads: Vec, + pub current_selected: Option, +} + #[derive(PartialEq, Clone, Copy)] pub enum Difficulty { None, @@ -64,5 +118,5 @@ impl Difficulty { Difficulty::Hard => "4", Difficulty::Nightmare => "5", } - } + } } diff --git a/src/main.rs b/src/main.rs index ae3ce78..6408288 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use config::{default_save_filename, load_config, save_config, Config}; use eframe::egui; use eframe::egui::Color32; -use infos::{Difficulty, LauncherInfo, WadInfo}; +use infos::{Difficulty, LauncherInfo, LauncherManager, WadInfo}; use native_dialog::{MessageDialog, MessageType}; use std::path::PathBuf; use std::process::Command; @@ -21,10 +21,9 @@ fn main() -> Result<(), eframe::Error> { } struct RustDoomLauncher { - all_launchers: Vec, + launcher_manager: LauncherManager, all_iwads: Vec, all_pwads: Vec, - selected_launcher: Option, selected_iwad: Option, selected_pwads: Vec, name: String, @@ -55,10 +54,9 @@ enum MyErrors { impl Default for RustDoomLauncher { fn default() -> Self { Self { - all_launchers: Vec::new(), + launcher_manager: LauncherManager::new(), all_iwads: Vec::new(), all_pwads: Vec::new(), - selected_launcher: None, selected_iwad: None, selected_pwads: Vec::new(), name: "".to_string(), @@ -93,7 +91,7 @@ impl RustDoomLauncher { } if let Some(launchers) = config.launchers { for launcher in launchers { - self.all_launchers.push(launcher.clone()); + self.launcher_manager.add(launcher); } } } @@ -164,8 +162,8 @@ impl RustDoomLauncher { } fn launcher_and_iwad(&self) -> Result<(&LauncherInfo, &WadInfo), MyErrors> { - let launcher = match self.selected_launcher { - Some(l) => self.all_launchers.get(l).unwrap(), + let launcher = match self.launcher_manager.get_current() { + Some(l) => l, None => { return Err(MyErrors::NoLauncher); } @@ -185,7 +183,7 @@ impl eframe::App for RustDoomLauncher { let config = Config { iwads: Some(self.all_iwads.clone()), pwads: Some(self.all_pwads.clone()), - launchers: Some(self.all_launchers.clone()), + launchers: Some(self.launcher_manager.launchers.clone()), }; save_config(&self.config_filename, &config).unwrap(); true @@ -214,25 +212,32 @@ impl eframe::App for RustDoomLauncher { ui.vertical(|ui| { ui.label("Launchers"); let mut remove_pos: Option = None; - for (pos, launcher) in self.all_launchers.iter().enumerate() { + let mut add_pos: Option = None; + for (launcher, pos, selected) in + self.launcher_manager.iter_with_pos_and_selected() + { ui.horizontal(|ui| { if ui - .add(egui::SelectableLabel::new( - self.selected_launcher.is_some() - && *self.selected_launcher.as_ref().unwrap() == pos, - &launcher.name, - )) + .add(egui::SelectableLabel::new(selected, &launcher.name)) .clicked() { - self.selected_launcher = Some(pos); + add_pos = Some(pos); } if ui.button("❌").clicked() { remove_pos = Some(pos); } }); } + // I'm unsure whether there's a better way to do this. + // The iterator borrow is a mutable borrow - thus compiler doesn't let me + // do a mutable thing in the middle of that, which I guess is fair enough, + // but I would like to break out of the loop as soon as that occurs... + // Completely unsure if let Some(rp) = remove_pos { - self.all_launchers.remove(rp); + self.launcher_manager.remove_launcher(rp); + } + if let Some(ap) = add_pos { + self.launcher_manager.set_current(ap); } }); ui.separator(); @@ -261,21 +266,10 @@ impl eframe::App for RustDoomLauncher { self.selected_pwads.contains(&pos), &pwad.name, ); - /* - let tmp = ui.add(pwad_label); - let click_response = tmp.interact(egui::Sense::click()); - let right_click_response = tmp.interact(egui::Sense::secondary_click()); - */ + if ui.add(pwad_label).clicked() { self.selected_pwads.push(pos); } - /* - TODO - no idea how this works - if ui.add(pwad_label).secondary_clicked() { - self.all_pwads.remove(pos); - continue; - } - */ } }); }); @@ -317,20 +311,15 @@ impl eframe::App for RustDoomLauncher { ui.horizontal_wrapped(|ui| { // I don't actually think using SelectableLabel is correct here - // but it'll at least do the highlighting when hovered nicely - if let Some(l) = self.selected_launcher { - if let Some(iwad) = self.all_launchers.get(l) { - if ui - .add(egui::SelectableLabel::new(false, &iwad.name)) - .clicked() - { - self.selected_launcher = None; - } - } else { - self.selected_launcher = None; + + if let Some(l) = self.launcher_manager.get_current() { + if ui.add(egui::SelectableLabel::new(false, &l.name)).clicked() { + self.launcher_manager.clear_current(); } } else { ui.label("Select a launcher plz"); } + if let Some(i) = self.selected_iwad { if let Some(iwad) = self.all_iwads.get(i) { if ui @@ -403,12 +392,12 @@ impl eframe::App for RustDoomLauncher { ui.label("What sort of file is it?"); if ui .add(egui::SelectableLabel::new( - self.selected_file_type == FileType::Pwad, - "PWAD", + self.selected_file_type == FileType::Launcher, + "Launcher", )) .clicked() { - self.selected_file_type = FileType::Pwad + self.selected_file_type = FileType::Launcher } if ui .add(egui::SelectableLabel::new( @@ -421,12 +410,12 @@ impl eframe::App for RustDoomLauncher { } if ui .add(egui::SelectableLabel::new( - self.selected_file_type == FileType::Launcher, - "Launcher", + self.selected_file_type == FileType::Pwad, + "PWAD", )) .clicked() { - self.selected_file_type = FileType::Launcher + self.selected_file_type = FileType::Pwad } }); if ui.button("Add!").clicked() { @@ -447,7 +436,7 @@ impl eframe::App for RustDoomLauncher { }); } FileType::Launcher => { - self.all_launchers.push(LauncherInfo { + self.launcher_manager.add(LauncherInfo { name: self.name.clone(), path: self.selected_file_path.clone(), });