Made Single and Multi Managers
Feels like something kind of cool to do...
This commit is contained in:
101
src/infos.rs
101
src/infos.rs
@@ -20,60 +20,109 @@ pub struct LauncherInfo {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
pub struct LauncherManager {
|
||||
pub launchers: Vec<LauncherInfo>,
|
||||
//trait Manager {}
|
||||
|
||||
pub struct MultiManager<T> {
|
||||
pub selectable: Vec<T>,
|
||||
pub current_selected: Vec<usize>,
|
||||
}
|
||||
|
||||
impl <T> 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 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)))
|
||||
}
|
||||
}
|
||||
pub fn get_current(&self) -> Vec<&T> {
|
||||
let mut current_selected_items = Vec::new();
|
||||
for item in &self.current_selected {
|
||||
assert!(item < &self.selectable.len());
|
||||
current_selected_items.push(self.selectable.get(*item).unwrap());
|
||||
}
|
||||
current_selected_items
|
||||
}
|
||||
pub fn add_current(&mut self, index: usize) {
|
||||
assert!(index < self.selectable.len());
|
||||
self.current_selected.push(index);
|
||||
}
|
||||
pub fn remove_current(&mut self, index: usize) {
|
||||
assert!(index < self.current_selected.len());
|
||||
self.current_selected.remove(index);
|
||||
}
|
||||
pub fn remove_selectable(&mut self, index: usize) {
|
||||
assert!(index < self.selectable.len());
|
||||
self.selectable.remove(index);
|
||||
}
|
||||
pub fn iter_selectable_with_pos_and_selected(
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = (&mut T, usize, bool)> + '_ {
|
||||
self.selectable
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.map(|(i, l)| (l, i, self.current_selected.contains(&i)))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SingleManager<T> {
|
||||
pub selectable: Vec<T>,
|
||||
pub current_selected: Option<usize>,
|
||||
}
|
||||
|
||||
impl LauncherManager {
|
||||
pub fn new() -> LauncherManager {
|
||||
LauncherManager {
|
||||
launchers: Vec::new(),
|
||||
impl <T> SingleManager<T> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
selectable: Vec::new(),
|
||||
current_selected: None,
|
||||
}
|
||||
}
|
||||
pub fn add(&mut self, launcher: LauncherInfo) {
|
||||
self.launchers.push(launcher);
|
||||
pub fn add(&mut self, item: T) {
|
||||
self.selectable.push(item);
|
||||
}
|
||||
pub fn get(&self, index: usize) -> Option<(&LauncherInfo, bool)> {
|
||||
if index > self.launchers.len() {
|
||||
pub fn get(&self, index: usize) -> Option<(&T, bool)> {
|
||||
if index > self.selectable.len() {
|
||||
None
|
||||
} else {
|
||||
Some((self.launchers.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<&LauncherInfo> {
|
||||
pub fn get_current(&self) -> Option<&T> {
|
||||
match self.current_selected {
|
||||
None => None,
|
||||
Some(pos) => Some(self.launchers.get(pos).unwrap()),
|
||||
Some(pos) => Some(self.selectable.get(pos).unwrap()),
|
||||
}
|
||||
}
|
||||
pub fn set_current(&mut self, index: usize) {
|
||||
assert!(index <= self.launchers.len());
|
||||
assert!(index < self.selectable.len());
|
||||
self.current_selected = Some(index);
|
||||
}
|
||||
pub fn clear_current(&mut self) {
|
||||
pub fn remove_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 remove_selectable(&mut self, index: usize) {
|
||||
assert!(index < self.selectable.len());
|
||||
self.selectable.remove(index);
|
||||
}
|
||||
pub fn iter_with_pos_and_selected(
|
||||
pub fn iter_selectable_with_pos_and_selected(
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = (&mut LauncherInfo, usize, bool)> + '_ {
|
||||
self.launchers
|
||||
) -> impl Iterator<Item = (&mut T, usize, bool)> + '_ {
|
||||
self.selectable
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.map(|(i, l)| (l, i, i == self.current_selected.unwrap_or(std::usize::MAX)))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IwadManager {
|
||||
pub wads: Vec<WadInfo>,
|
||||
pub current_selected: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
pub enum Difficulty {
|
||||
None,
|
||||
|
||||
170
src/main.rs
170
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, LauncherManager, WadInfo};
|
||||
use infos::{Difficulty, LauncherInfo, MultiManager, SingleManager, WadInfo};
|
||||
use native_dialog::{MessageDialog, MessageType};
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
@@ -20,12 +20,22 @@ fn main() -> Result<(), eframe::Error> {
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum FileType {
|
||||
Iwad,
|
||||
Pwad,
|
||||
Launcher,
|
||||
}
|
||||
// Great name, I know
|
||||
enum MyErrors {
|
||||
NoLauncher,
|
||||
NoIwad,
|
||||
}
|
||||
|
||||
struct RustDoomLauncher {
|
||||
launcher_manager: LauncherManager,
|
||||
all_iwads: Vec<WadInfo>,
|
||||
all_pwads: Vec<WadInfo>,
|
||||
selected_iwad: Option<usize>,
|
||||
selected_pwads: Vec<usize>,
|
||||
launcher_manager: SingleManager<LauncherInfo>,
|
||||
iwad_manager: SingleManager<WadInfo>,
|
||||
pwad_manager: MultiManager<WadInfo>,
|
||||
name: String,
|
||||
config_filename: PathBuf,
|
||||
config_file_loaded: bool,
|
||||
@@ -39,26 +49,12 @@ struct RustDoomLauncher {
|
||||
selected_file_path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum FileType {
|
||||
Iwad,
|
||||
Pwad,
|
||||
Launcher,
|
||||
}
|
||||
// Great name, I know
|
||||
enum MyErrors {
|
||||
NoLauncher,
|
||||
NoIwad,
|
||||
}
|
||||
|
||||
impl Default for RustDoomLauncher {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
launcher_manager: LauncherManager::new(),
|
||||
all_iwads: Vec::new(),
|
||||
all_pwads: Vec::new(),
|
||||
selected_iwad: None,
|
||||
selected_pwads: Vec::new(),
|
||||
launcher_manager: SingleManager::new(),
|
||||
iwad_manager: SingleManager::new(),
|
||||
pwad_manager: MultiManager::new(),
|
||||
name: "".to_string(),
|
||||
config_filename: default_save_filename(),
|
||||
config_file_loaded: false,
|
||||
@@ -81,12 +77,12 @@ impl RustDoomLauncher {
|
||||
let config = load_config(&self.config_filename).unwrap();
|
||||
if let Some(iwads) = config.iwads {
|
||||
for iwad in iwads {
|
||||
self.all_iwads.push(iwad.clone());
|
||||
self.iwad_manager.add(iwad);
|
||||
}
|
||||
}
|
||||
if let Some(pwads) = config.pwads {
|
||||
for pwad in pwads {
|
||||
self.all_pwads.push(pwad.clone());
|
||||
self.pwad_manager.add(pwad.clone());
|
||||
}
|
||||
}
|
||||
if let Some(launchers) = config.launchers {
|
||||
@@ -116,9 +112,8 @@ impl RustDoomLauncher {
|
||||
Ok((l, i)) => (l, i),
|
||||
};
|
||||
let mut command = vec!["-iwad", iwad.path.to_str().unwrap()];
|
||||
for pwad_index in &self.selected_pwads {
|
||||
for pwad in &self.pwad_manager.get_current() {
|
||||
command.push("-file");
|
||||
let pwad = self.all_pwads.get(*pwad_index).unwrap();
|
||||
command.push(pwad.path.to_str().unwrap());
|
||||
}
|
||||
if self.difficulty != Difficulty::None {
|
||||
@@ -168,8 +163,8 @@ impl RustDoomLauncher {
|
||||
return Err(MyErrors::NoLauncher);
|
||||
}
|
||||
};
|
||||
let iwad = match self.selected_iwad {
|
||||
Some(i) => self.all_iwads.get(i).unwrap(),
|
||||
let iwad = match self.iwad_manager.get_current() {
|
||||
Some(iwad) => iwad,
|
||||
None => {
|
||||
return Err(MyErrors::NoIwad);
|
||||
}
|
||||
@@ -181,9 +176,9 @@ impl RustDoomLauncher {
|
||||
impl eframe::App for RustDoomLauncher {
|
||||
fn on_close_event(&mut self) -> bool {
|
||||
let config = Config {
|
||||
iwads: Some(self.all_iwads.clone()),
|
||||
pwads: Some(self.all_pwads.clone()),
|
||||
launchers: Some(self.launcher_manager.launchers.clone()),
|
||||
iwads: Some(self.iwad_manager.selectable.clone()),
|
||||
pwads: Some(self.iwad_manager.selectable.clone()),
|
||||
launchers: Some(self.launcher_manager.selectable.clone()),
|
||||
};
|
||||
save_config(&self.config_filename, &config).unwrap();
|
||||
true
|
||||
@@ -214,7 +209,7 @@ impl eframe::App for RustDoomLauncher {
|
||||
let mut remove_pos: Option<usize> = None;
|
||||
let mut add_pos: Option<usize> = None;
|
||||
for (launcher, pos, selected) in
|
||||
self.launcher_manager.iter_with_pos_and_selected()
|
||||
self.launcher_manager.iter_selectable_with_pos_and_selected()
|
||||
{
|
||||
ui.horizontal(|ui| {
|
||||
if ui
|
||||
@@ -229,12 +224,12 @@ impl eframe::App for RustDoomLauncher {
|
||||
});
|
||||
}
|
||||
// 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
|
||||
// The iterator call 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.launcher_manager.remove_launcher(rp);
|
||||
self.launcher_manager.remove_selectable(rp);
|
||||
}
|
||||
if let Some(ap) = add_pos {
|
||||
self.launcher_manager.set_current(ap);
|
||||
@@ -244,32 +239,53 @@ impl eframe::App for RustDoomLauncher {
|
||||
ui.vertical(|ui| {
|
||||
ui.set_min_width(100.0);
|
||||
ui.label("IWADs");
|
||||
for (pos, iwad) in self.all_iwads.iter().enumerate() {
|
||||
if ui
|
||||
.add(egui::SelectableLabel::new(
|
||||
self.selected_iwad.is_some()
|
||||
&& *self.selected_iwad.as_ref().unwrap() == pos,
|
||||
&iwad.name,
|
||||
))
|
||||
.clicked()
|
||||
{
|
||||
self.selected_iwad = Some(pos);
|
||||
}
|
||||
let mut remove_pos: Option<usize> = None;
|
||||
let mut add_pos: Option<usize> = None;
|
||||
for (launcher, pos, selected) in self.iwad_manager.iter_selectable_with_pos_and_selected()
|
||||
{
|
||||
ui.horizontal(|ui| {
|
||||
if ui
|
||||
.add(egui::SelectableLabel::new(selected, &launcher.name))
|
||||
.clicked()
|
||||
{
|
||||
add_pos = Some(pos);
|
||||
}
|
||||
if ui.button("❌").clicked() {
|
||||
remove_pos = Some(pos);
|
||||
}
|
||||
});
|
||||
}
|
||||
if let Some(rp) = remove_pos {
|
||||
self.iwad_manager.remove_selectable(rp);
|
||||
}
|
||||
if let Some(ap) = add_pos {
|
||||
self.iwad_manager.set_current(ap);
|
||||
}
|
||||
});
|
||||
ui.separator();
|
||||
ui.vertical(|ui| {
|
||||
ui.set_min_width(100.0);
|
||||
ui.label("PWADs");
|
||||
for (pos, pwad) in self.all_pwads.iter().enumerate() {
|
||||
let pwad_label = egui::SelectableLabel::new(
|
||||
self.selected_pwads.contains(&pos),
|
||||
&pwad.name,
|
||||
);
|
||||
|
||||
if ui.add(pwad_label).clicked() {
|
||||
self.selected_pwads.push(pos);
|
||||
}
|
||||
let mut remove_pos: Option<usize> = None;
|
||||
let mut add_pos: Option<usize> = None;
|
||||
for (pwad, pos, selected) in self.pwad_manager.iter_selectable_with_pos_and_selected() {
|
||||
ui.horizontal(|ui| {
|
||||
if ui
|
||||
.add(egui::SelectableLabel::new(selected, &pwad.name))
|
||||
.clicked()
|
||||
{
|
||||
add_pos = Some(pos);
|
||||
}
|
||||
if ui.button("❌").clicked() {
|
||||
remove_pos = Some(pos);
|
||||
}
|
||||
});
|
||||
}
|
||||
if let Some(rp) = remove_pos {
|
||||
self.pwad_manager.remove_selectable(rp);
|
||||
}
|
||||
if let Some(ap) = add_pos {
|
||||
self.pwad_manager.add_current(ap);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -314,45 +330,36 @@ impl eframe::App for RustDoomLauncher {
|
||||
|
||||
if let Some(l) = self.launcher_manager.get_current() {
|
||||
if ui.add(egui::SelectableLabel::new(false, &l.name)).clicked() {
|
||||
self.launcher_manager.clear_current();
|
||||
self.launcher_manager.remove_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
|
||||
.add(egui::SelectableLabel::new(false, &iwad.name))
|
||||
.clicked()
|
||||
{
|
||||
self.selected_iwad = None;
|
||||
}
|
||||
} else {
|
||||
self.selected_iwad = None;
|
||||
if let Some(iwad) = self.iwad_manager.get_current() {
|
||||
if ui
|
||||
.add(egui::SelectableLabel::new(false, &iwad.name))
|
||||
.clicked()
|
||||
{
|
||||
self.launcher_manager.remove_current();
|
||||
}
|
||||
} else {
|
||||
ui.label("Select an iwad plz");
|
||||
}
|
||||
// This feels ver much more C-like, but I think it works?
|
||||
// Probably should have a little bit more checking around the unwrap calls
|
||||
let mut pos = 0_usize;
|
||||
while pos < self.selected_pwads.len() {
|
||||
let mut remove: Option<usize> = None;
|
||||
for (pos, pwad) in self.pwad_manager.get_current().iter().enumerate() {
|
||||
if ui
|
||||
.add(egui::SelectableLabel::new(
|
||||
false,
|
||||
&self
|
||||
.all_pwads
|
||||
.get(*self.selected_pwads.get(pos).unwrap())
|
||||
.unwrap()
|
||||
.name,
|
||||
))
|
||||
.add(egui::SelectableLabel::new(false, &pwad.name))
|
||||
.clicked()
|
||||
{
|
||||
self.selected_pwads.remove(pos);
|
||||
continue;
|
||||
remove = Some(pos);
|
||||
break;
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
if let Some(r) = remove {
|
||||
self.pwad_manager.remove_current(r);
|
||||
}
|
||||
});
|
||||
if self.display_command {
|
||||
@@ -365,6 +372,7 @@ impl eframe::App for RustDoomLauncher {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
egui::Window::new("Add WAD or Launcher")
|
||||
.open(&mut self.add_stuff_window_displayed)
|
||||
.show(ctx, |ui| {
|
||||
@@ -424,13 +432,13 @@ impl eframe::App for RustDoomLauncher {
|
||||
}
|
||||
match self.selected_file_type {
|
||||
FileType::Iwad => {
|
||||
self.all_iwads.push(WadInfo {
|
||||
self.iwad_manager.add(WadInfo {
|
||||
name: self.name.clone(),
|
||||
path: self.selected_file_path.clone(),
|
||||
});
|
||||
}
|
||||
FileType::Pwad => {
|
||||
self.all_pwads.push(WadInfo {
|
||||
self.pwad_manager.add(WadInfo {
|
||||
name: self.name.clone(),
|
||||
path: self.selected_file_path.clone(),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user