Added a command manager

This commit is contained in:
2023-06-18 20:42:37 +01:00
parent bf41c9d70a
commit 849902ce84
2 changed files with 192 additions and 104 deletions

View File

@@ -3,10 +3,112 @@ use std::fmt;
use std::path::PathBuf;
use std::slice::Iter;
// TODO - write some impl stuff in here so the main GUI stuff
// is a little bit more decoupled from this. I think a Display
// and perhaps the path to string conversion too could be
// removed from the GUI part
pub struct CommandManager {
pub launcher: Option<PathBuf>,
pub iwad: Option<PathBuf>,
pub pwads: Vec<PathBuf>,
pub warp: String,
pub difficulty: Option<Difficulty>,
pub fast_monsters: bool,
pub respawning_monsters: bool,
pub command_string: String,
}
pub enum CommandErrors {
NoLauncher,
NoIwad,
}
impl CommandManager {
pub fn new() -> Self {
Self {
launcher: None,
iwad: None,
pwads: Vec::new(),
warp: "".to_string(),
difficulty: None,
fast_monsters: false,
respawning_monsters: false,
command_string: "".to_string(),
}
}
pub fn remove_iwad(&mut self) {
self.iwad = None;
self.generate_command_str();
}
pub fn add_iwad(&mut self, iwad: &WadInfo) {
self.iwad = Some(iwad.path.clone());
self.generate_command_str();
}
pub fn add_pwads(&mut self, pwads: &Vec<&WadInfo>) {
self.pwads = Vec::new();
for pwad in pwads {
self.pwads.push(pwad.path.clone());
self.generate_command_str();
}
}
pub fn add_launcher(&mut self, launcher: &LauncherInfo) {
self.launcher = Some(launcher.path.clone());
self.generate_command_str();
}
pub fn remove_launcher(&mut self) {
self.launcher = None;
self.generate_command_str();
}
pub fn generate_command(&self) -> Result<(String, Vec<String>), CommandErrors> {
let launcher = if let Some(launcher) = &self.launcher {
launcher
} else {
return Err(CommandErrors::NoLauncher);
};
let iwad = if let Some(iwad) = &self.iwad {
iwad
} else {
return Err(CommandErrors::NoIwad);
};
let mut command = vec!["-iwad".to_string(), iwad.clone().into_os_string().into_string().unwrap()];
for pwad in &self.pwads {
command.push("-file".to_string());
command.push(pwad.clone().into_os_string().into_string().unwrap());
}
if let Some(d) = self.difficulty {
command.push("-skill".to_string());
command.push(d.flag_number().to_string());
}
if !self.warp.is_empty() {
command.push("-warp".to_string());
command.push(self.warp.to_string());
}
if self.respawning_monsters {
command.push("-respawn".to_string());
}
if self.fast_monsters {
command.push("-fast".to_string());
}
Ok((launcher.to_str().unwrap().to_string(), command))
}
pub fn generate_command_str(&mut self) -> Result<(), CommandErrors> {
match self.generate_command() {
Err(e) => {
self.command_string = "plz add ".to_string();
match e {
CommandErrors::NoIwad => self.command_string.push_str("an iwad"),
CommandErrors::NoLauncher => self.command_string.push_str("a launcher"),
}
},
Ok((launcher, rest)) => {
let mut command = "".to_string();
// Feels like a bit of a hack, but it works I think
command.push_str(&format!(" '{}'", launcher));
for c in rest {
command.push_str(&format!(" '{}'", c));
}
self.command_string = command;
}
}
Ok(())
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct WadInfo {
@@ -20,28 +122,29 @@ pub struct LauncherInfo {
pub name: String,
}
//trait Manager {}
pub struct MultiManager<T> {
pub selectable: Vec<T>,
pub current_selected: Vec<usize>,
}
impl <T> MultiManager<T> {
impl<T: Clone> MultiManager<T> {
pub fn new() -> Self {
Self {
selectable: Vec::new(),
current_selected: Vec::new(),
}
}
pub fn add(&mut self, item: T) {
self.selectable.push(item);
pub fn add(&mut self, item: &T) {
self.selectable.push(item.clone());
}
pub fn get(&self, index: usize) -> Option<(&T, bool)> {
if index > self.selectable.len() {
None
} else {
Some((self.selectable.get(index).unwrap(), self.current_selected.contains(&index)))
Some((
self.selectable.get(index).unwrap(),
self.current_selected.contains(&index),
))
}
}
pub fn get_current(&self) -> Vec<&T> {
@@ -52,7 +155,7 @@ impl <T> MultiManager<T> {
}
current_selected_items
}
pub fn add_current(&mut self, index: usize) {
pub fn set_current(&mut self, index: usize) {
assert!(index < self.selectable.len());
self.current_selected.push(index);
}
@@ -63,6 +166,21 @@ impl <T> MultiManager<T> {
pub fn remove_selectable(&mut self, index: usize) {
assert!(index < self.selectable.len());
self.selectable.remove(index);
let mut new_selected: Vec<usize> = Vec::new();
for s in &self.current_selected {
println!("{}", s);
if *s == index {
continue
} else if *s > index {
new_selected.push(s - 1);
} else {
new_selected.push(*s);
}
}
self.current_selected = new_selected;
}
pub fn is_currently_selected(self, index: usize) -> bool {
self.current_selected.contains(&index)
}
pub fn iter_selectable_with_pos_and_selected(
&mut self,
@@ -79,21 +197,24 @@ pub struct SingleManager<T> {
pub current_selected: Option<usize>,
}
impl <T> SingleManager<T> {
impl<T: Clone> SingleManager<T> {
pub fn new() -> Self {
Self {
selectable: Vec::new(),
current_selected: None,
}
}
pub fn add(&mut self, item: T) {
self.selectable.push(item);
pub fn add(&mut self, item: &T) {
self.selectable.push(item.clone());
}
pub fn get(&self, index: usize) -> Option<(&T, bool)> {
if index > self.selectable.len() {
None
} else {
Some((self.selectable.get(index).unwrap(), index == self.current_selected.unwrap_or(std::usize::MAX)))
Some((
self.selectable.get(index).unwrap(),
index == self.current_selected.unwrap_or(std::usize::MAX),
))
}
}
pub fn get_current(&self) -> Option<&T> {
@@ -112,6 +233,9 @@ impl <T> SingleManager<T> {
pub fn remove_selectable(&mut self, index: usize) {
assert!(index < self.selectable.len());
self.selectable.remove(index);
if self.current_selected.is_some() && index == self.current_selected.unwrap() {
self.current_selected = None;
}
}
pub fn iter_selectable_with_pos_and_selected(
&mut self,