diff --git a/src/advanced_frame.rs b/src/advanced_frame.rs new file mode 100644 index 0000000..4a44edf --- /dev/null +++ b/src/advanced_frame.rs @@ -0,0 +1,137 @@ +use iced::{Text, Element, Column, Button, button, Length, Alignment, alignment, Row, text_input, Padding}; + +use crate::{Message, instance::Instance, style}; + +#[derive(Debug, Clone)] +pub enum AdvancedMessage { + NameTextInputChanged(String), + ArgsTextInputChanged(String), +} + +#[derive(Debug)] +pub struct AdvancedFrame { + old_name: String, + instance: Option, + + close_button: button::State, + name_input: text_input::State, + args_input: text_input::State +} + +impl Default for AdvancedFrame { + fn default() -> Self { + Self { + old_name: String::default(), + instance: None, + close_button: button::State::default(), + name_input: text_input::State::default(), + args_input: text_input::State::default() + } + } +} + +impl AdvancedFrame { + pub fn new(new_instance: Instance) -> Self { + Self { + old_name: String::from(&new_instance.name), + instance: Some(new_instance), + ..Default::default() + } + } + + pub fn update(&mut self, message: AdvancedMessage) { + match message { + AdvancedMessage::NameTextInputChanged(string) => { + self.instance.as_mut().unwrap().name = string; + } + + AdvancedMessage::ArgsTextInputChanged(string) => { + self.instance.as_mut().unwrap().args = string; + } + } + } + + pub fn view(&mut self) -> Element { + + let close_button = Button::new(&mut self.close_button, style::close_icon()) + .style(style::Button::Icon) + .on_press(match &self.instance { + Some(inst) => Message::CloseAdvanced(self.old_name.clone(), inst.clone()), + None => Message::Dummy(()), + }); + + let mut p = Padding::new(0); + p.bottom = 60; + + let out = Column::new() + .push( + Row::new() + .width(Length::Fill) + .align_items(Alignment::End) + .push( + Text::new("Advanced Settings") + .size(26) + .horizontal_alignment(alignment::Horizontal::Center) + .width(Length::Fill), + ) + .push(close_button) + .padding(p) + ) + .padding(40) + .width(iced::Length::FillPortion(3)) + .spacing(6); + + if let Some(instance) = &self.instance { + + let name_input = text_input::TextInput::new( + &mut self.name_input, + "Instance name", + &instance.name, + name_text_input_changed + ).padding(4); + + let out = out + .push( + Row::new() + .push( + { + let text = format!("Instance name:"); + Text::new(text) + .size(18) + } + ) + .push( + name_input + ) + .spacing(14) + .align_items(Alignment::Center) + ) + .push( + text_input::TextInput::new( + &mut self.args_input, + "Executable arguments", + &instance.args, + args_text_input_changed + ).padding(4) + ); + + out + .push( + Text::new("-h or --help to log help") + ) + .into() + } else { + out + .push(Text::new("How in the...")) + .into() + } + } +} + +fn name_text_input_changed(string: String) -> Message { + Message::AdvancedMessage(AdvancedMessage::NameTextInputChanged(string)) +} + +fn args_text_input_changed(string: String) -> Message { + Message::AdvancedMessage(AdvancedMessage::ArgsTextInputChanged(string)) +} diff --git a/src/install.rs b/src/install.rs index 6c1430b..fd92e87 100644 --- a/src/install.rs +++ b/src/install.rs @@ -93,6 +93,7 @@ pub fn install( Ok(Instance::new( destination, executable_path, + String::new(), name, version, instance_type, diff --git a/src/instance.rs b/src/instance.rs index 7fc4109..51dfc57 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -57,6 +57,8 @@ pub struct Instance { #[serde(skip)] folder_button: button::State, #[serde(skip)] + advanced_button: button::State, + #[serde(skip)] delete_button: button::State, #[serde(skip)] @@ -64,6 +66,7 @@ pub struct Instance { pub path: PathBuf, pub executable: PathBuf, + pub args: String, pub name: String, pub version: String, pub instance_type: InstanceType, @@ -149,6 +152,7 @@ pub enum InstanceMessage { Play(bool), Update, Folder, + Advanced, Delete, StateChanged(InstanceState), } @@ -157,6 +161,7 @@ impl Instance { pub fn new( path: PathBuf, executable: PathBuf, + args: String, name: String, version: String, instance_type: InstanceType, @@ -166,6 +171,7 @@ impl Instance { Self { path, executable, + args, name, version, instance_type, @@ -175,6 +181,7 @@ impl Instance { play_button: button::State::default(), update_button: button::State::default(), folder_button: button::State::default(), + advanced_button: button::State::default(), delete_button: button::State::default(), } } @@ -198,6 +205,7 @@ impl Instance { self.executable.clone(), self.name.clone(), do_debug, + self.args.clone() ), move |()| { Message::InstanceMessage( @@ -225,6 +233,12 @@ impl Instance { InstanceMessage::Folder => { iced::Command::perform(open_folder(self.path.clone()), Message::Dummy) } + InstanceMessage::Advanced => { + let name = self.name.clone(); + iced::Command::perform(dummy(), move |_| { + Message::OpenAdvanced(name.clone()) + }) + } InstanceMessage::Delete => { let name = self.name.clone(); iced::Command::perform(delete(self.path.clone()), move |_| { @@ -249,6 +263,9 @@ impl Instance { let folder_button = Button::new(&mut self.folder_button, style::folder_icon()) .style(style::Button::Icon) .on_press(InstanceMessage::Folder); + let advanced_button = Button::new(&mut self.advanced_button, style::advanced_icon()) + .style(style::Button::Icon) + .on_press(InstanceMessage::Advanced); let mut delete_button = Button::new(&mut self.delete_button, style::delete_icon()) .style(style::Button::Destructive); @@ -317,6 +334,7 @@ impl Instance { .push(play_button) .push(update_button) .push(folder_button) + .push(advanced_button) .push(delete_button) } }) @@ -335,6 +353,7 @@ pub async fn perform_install( send_message(Message::AddInstance(Instance::new( path.clone(), "provisional".into(), + String::new(), name.clone(), instance_source.identifier.clone(), instance_type, @@ -383,15 +402,15 @@ pub async fn perform_update(instance: Instance) { } } -pub async fn perform_play(path: PathBuf, executable: PathBuf, name: String, do_debug: bool) { +pub async fn perform_play(path: PathBuf, executable: PathBuf, name: String, do_debug: bool, args: String) { send_message(Message::MusicMessage(MusicCommand::Pause)); - if let Err(e) = play(path, executable, name, do_debug).await { + if let Err(e) = play(path, executable, name, do_debug, args).await { error!("Failed to run game: {:#}", e); } send_message(Message::MusicMessage(MusicCommand::Play)); } -pub async fn play(path: PathBuf, executable: PathBuf, name: String, do_debug: bool) -> Result<()> { +pub async fn play(path: PathBuf, executable: PathBuf, name: String, do_debug: bool, args: String) -> Result<()> { let mut log_path = path; log_path.push("logs"); fs::create_dir_all(&log_path)?; @@ -415,9 +434,9 @@ pub async fn play(path: PathBuf, executable: PathBuf, name: String, do_debug: bo let mut cmd = Command::new(&executable); let output = if do_debug { - cmd.arg("-d").output() + cmd.args(["-d", &args]).output() } else { - cmd.output() + cmd.arg(args).output() }; match output { Ok(output) => { diff --git a/src/instances_frame_holder.rs b/src/instances_frame_holder.rs new file mode 100644 index 0000000..a58423c --- /dev/null +++ b/src/instances_frame_holder.rs @@ -0,0 +1,39 @@ +use iced::Element; + +use crate::advanced_frame; +use crate::instances_frame; +use crate::Message; + +#[derive(Debug)] +pub enum AdvancedFrameOpen { + Open(advanced_frame::AdvancedFrame), + Closed +} + +#[derive(Debug)] +pub struct InstanceFrameHolder { + pub instances_frame: instances_frame::InstancesFrame, + pub advanced_frame_open: AdvancedFrameOpen, +} + +impl Default for InstanceFrameHolder { + fn default() -> Self { + InstanceFrameHolder { + instances_frame: instances_frame::InstancesFrame::default(), + advanced_frame_open: AdvancedFrameOpen::Closed + } + } +} + +impl InstanceFrameHolder { + pub fn view(&mut self) -> Element { + match &mut self.advanced_frame_open { + AdvancedFrameOpen::Open(advanced_frame) => { + advanced_frame.view() + }, + AdvancedFrameOpen::Closed => { + self.instances_frame.view() + } + } + } +} diff --git a/src/main.rs b/src/main.rs index ecb6aa0..bd84119 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,10 +14,12 @@ use std::sync::mpsc::Sender; use std::thread; use std::time::Duration; +use advanced_frame::AdvancedFrame; use iced::{ alignment, button, scrollable, Alignment, Application, Button, Column, Command, Container, Element, Length, Row, Scrollable, Settings, Space, Subscription, Text, }; +use instances_frame_holder::AdvancedFrameOpen; use std::collections::VecDeque; use std::sync::Mutex; @@ -27,12 +29,14 @@ use crate::music::{MusicCommand, MusicState}; use crate::plugins_frame::PluginMessage; use lazy_static::lazy_static; +mod advanced_frame; mod archive; mod github; mod install; mod install_frame; mod instance; mod instances_frame; +mod instances_frame_holder; mod jenkins; mod logger; mod music; @@ -72,7 +76,7 @@ struct ESLauncher { music_button: button::State, music_state: MusicState, install_frame: install_frame::InstallFrame, - instances_frame: instances_frame::InstancesFrame, + instances_frame_holder: instances_frame_holder::InstanceFrameHolder, plugins_frame: plugins_frame::PluginsFrameState, log_scrollable: scrollable::State, message_receiver: MessageReceiver, @@ -95,6 +99,9 @@ pub enum Message { PluginMessage(String, PluginMessage), AddInstance(Instance), RemoveInstance(Option), + OpenAdvanced(String), + CloseAdvanced(String, Instance), + AdvancedMessage(advanced_frame::AdvancedMessage), Dummy(()), MusicMessage(MusicCommand), ViewChanged(MainView), @@ -131,7 +138,7 @@ impl Application for ESLauncher { music_button: button::State::default(), music_state: MusicState::Playing, install_frame: install_frame::InstallFrame::default(), - instances_frame: instances_frame::InstancesFrame::default(), + instances_frame_holder: instances_frame_holder::InstanceFrameHolder::default(), plugins_frame: plugins_frame_state, log_scrollable: scrollable::State::default(), message_receiver: MessageReceiver {}, @@ -152,7 +159,7 @@ impl Application for ESLauncher { match message { Message::InstallFrameMessage(msg) => return self.install_frame.update(msg), Message::InstanceMessage(name, msg) => { - match self.instances_frame.instances.get_mut(&name) { + match self.instances_frame_holder.instances_frame.instances.get_mut(&name) { None => error!("Failed to find internal Instance with name {}", &name), Some(instance) => return instance.update(msg), } @@ -169,17 +176,37 @@ impl Application for ESLauncher { } Message::AddInstance(instance) => { let is_ready = instance.state.is_ready(); - self.instances_frame + self.instances_frame_holder + .instances_frame .instances .insert(instance.name.clone(), instance); if is_ready { - instance::perform_save_instances(self.instances_frame.instances.clone()) + instance::perform_save_instances(self.instances_frame_holder.instances_frame.instances.clone()) }; } Message::RemoveInstance(option) => { if let Some(name) = option { - self.instances_frame.instances.remove(&name); - instance::perform_save_instances(self.instances_frame.instances.clone()); + self.instances_frame_holder.instances_frame.instances.remove(&name); + instance::perform_save_instances(self.instances_frame_holder.instances_frame.instances.clone()); + } + } + Message::OpenAdvanced(instance_name) => { + if let Some(instance) = self.instances_frame_holder.instances_frame.instances.get(&instance_name) { + self.instances_frame_holder.advanced_frame_open = AdvancedFrameOpen::Open(AdvancedFrame::new(instance.clone())) + } + } + Message::CloseAdvanced(old_instance_name, new_instance) => { + self.instances_frame_holder.instances_frame.instances.remove(&old_instance_name); + self.instances_frame_holder.instances_frame.instances.insert(new_instance.name.clone(), new_instance); + instance::perform_save_instances(self.instances_frame_holder.instances_frame.instances.clone()); + self.instances_frame_holder.advanced_frame_open = AdvancedFrameOpen::Closed; + } + Message::AdvancedMessage(msg) => { + match &mut self.instances_frame_holder.advanced_frame_open { + AdvancedFrameOpen::Open(frame) => { + frame.update(msg); + } + AdvancedFrameOpen::Closed => {} } } Message::MusicMessage(cmd) => { @@ -239,7 +266,7 @@ impl Application for ESLauncher { let main_view = match self.view { MainView::Instances => Container::new( Row::new() - .push(self.instances_frame.view()) + .push(self.instances_frame_holder.view()) .push(self.install_frame.view().map(Message::InstallFrameMessage)) .spacing(50), ), diff --git a/src/style.rs b/src/style.rs index b7b9b7f..9d341a6 100644 --- a/src/style.rs +++ b/src/style.rs @@ -43,6 +43,14 @@ pub fn folder_icon() -> Text { icon('\u{E930}') } +pub fn advanced_icon() -> Text { + icon('\u{E994}') +} + +pub fn close_icon() -> Text { + icon('\u{EA0F}') +} + pub enum Button { Icon, Destructive,