From 5870316724dc319c5c99e13556f981af4c03fc1d Mon Sep 17 00:00:00 2001 From: Observer KRypt0n_ Date: Tue, 21 Feb 2023 17:32:57 +0200 Subject: [PATCH] general settings: added test launcher style switcher - classic style loads its background from "config's_tmp_path/background" so from "launcher folder/background" by default - icons will be changed in some future --- anime-launcher-sdk | 2 +- assets/images/classic.svg | 12 ++++ assets/images/modern.svg | 12 ++++ assets/resources.xml | 6 ++ src/main.rs | 20 +++++-- src/ui/main.rs | 102 ++++++++++++++++++++++++++++++---- src/ui/preferences/general.rs | 55 ++++++++++++++++++ src/ui/preferences/main.rs | 37 +++++++++++- 8 files changed, 228 insertions(+), 18 deletions(-) create mode 100644 assets/images/classic.svg create mode 100644 assets/images/modern.svg diff --git a/anime-launcher-sdk b/anime-launcher-sdk index 8a32066..a62aeef 160000 --- a/anime-launcher-sdk +++ b/anime-launcher-sdk @@ -1 +1 @@ -Subproject commit 8a32066c07cd471fe2a33ecfa778edffb8796f19 +Subproject commit a62aeef9cd9caa0e147fddcf05f4c412c942b736 diff --git a/assets/images/classic.svg b/assets/images/classic.svg new file mode 100644 index 0000000..114a96d --- /dev/null +++ b/assets/images/classic.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/images/modern.svg b/assets/images/modern.svg new file mode 100644 index 0000000..69a431f --- /dev/null +++ b/assets/images/modern.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/resources.xml b/assets/resources.xml index 4be0b90..1ac85ed 100644 --- a/assets/resources.xml +++ b/assets/resources.xml @@ -3,4 +3,10 @@ images/icon.png + + images/modern.svg + + + images/classic.svg + \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 795a7bb..84a13cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,8 @@ use anime_launcher_sdk::anime_game_core::genshin::prelude::*; use tracing_subscriber::prelude::*; +use std::path::PathBuf; + pub mod i18n; pub mod ui; @@ -110,14 +112,22 @@ fn main() { } // Create the app - let app = RelmApp::new("moe.launcher.an-anime-game-launcher"); + let app = RelmApp::new(APP_ID); // Set global css - relm4::set_global_css(" - progressbar > text { + relm4::set_global_css(&format!(" + progressbar > text {{ margin-bottom: 4px; - } - "); + }} + + window.classic-style {{ + background: url(\"file://{}/background\"); + background-repeat: no-repeat; + background-size: cover; + }} + ", + CONFIG.launcher.temp.as_ref().unwrap_or(&PathBuf::from("/tmp")).to_string_lossy() + )); // Run the app app.run::(()); diff --git a/src/ui/main.rs b/src/ui/main.rs index 6bdbb84..e7a2b12 100644 --- a/src/ui/main.rs +++ b/src/ui/main.rs @@ -8,6 +8,9 @@ use relm4::{ use gtk::prelude::*; use adw::prelude::*; +use anime_launcher_sdk::config::launcher::LauncherStyle; + +use crate::*; use crate::i18n::tr; use super::preferences::main::App as PreferencesApp; @@ -25,13 +28,16 @@ static mut PREFERENCES_WINDOW: Option> = None; static mut ABOUT_DIALOG: Option> = None; pub struct App { - loading: Option> + loading: Option>, + style: LauncherStyle } #[derive(Debug)] pub enum AppMsg { + PerformAction, OpenPreferences, - ClosePreferences + ClosePreferences, + UpdateLauncherStyle(LauncherStyle) } #[relm4::component(pub)] @@ -57,12 +63,47 @@ impl SimpleComponent for App { view! { main_window = adw::Window { set_title: Some("An Anime Game Launcher"), - set_default_size: (900, 600), + + #[watch] + set_default_size: ( + match model.style { + LauncherStyle::Modern => 900, + LauncherStyle::Classic => 1094 // (w = 1280 / 730 * h, where 1280x730 is default background picture resolution) + }, + match model.style { + LauncherStyle::Modern => 600, + LauncherStyle::Classic => 624 + } + ), + + #[watch] + add_css_class: match model.style { + LauncherStyle::Modern => "", + LauncherStyle::Classic => "classic-style" + }, + + #[watch] + remove_css_class: match model.style { + LauncherStyle::Modern => "classic-style", + LauncherStyle::Classic => "" + }, gtk::Box { set_orientation: gtk::Orientation::Vertical, adw::HeaderBar { + #[watch] + add_css_class: match model.style { + LauncherStyle::Modern => "", + LauncherStyle::Classic => "flat" + }, + + #[watch] + remove_css_class: match model.style { + LauncherStyle::Modern => "flat", + LauncherStyle::Classic => "" + }, + pack_end = >k::MenuButton { set_icon_name: "open-menu-symbolic", set_menu_model: Some(&main_menu) @@ -89,6 +130,9 @@ impl SimpleComponent for App { set_visible: model.loading.is_none(), add = &adw::PreferencesGroup { + #[watch] + set_visible: model.style == LauncherStyle::Modern, + gtk::Image { set_resource: Some("/org/app/images/icon.png"), set_vexpand: true, @@ -103,11 +147,33 @@ impl SimpleComponent for App { }, add = &adw::PreferencesGroup { - set_valign: gtk::Align::Center, + #[watch] + set_valign: match model.style { + LauncherStyle::Modern => gtk::Align::Center, + LauncherStyle::Classic => gtk::Align::End + }, + + #[watch] + set_width_request: match model.style { + LauncherStyle::Modern => -1, + LauncherStyle::Classic => 800 + }, + set_vexpand: true, gtk::Box { - set_halign: gtk::Align::Center, + #[watch] + set_halign: match model.style { + LauncherStyle::Modern => gtk::Align::Center, + LauncherStyle::Classic => gtk::Align::End + }, + + #[watch] + set_height_request: match model.style { + LauncherStyle::Modern => -1, + LauncherStyle::Classic => 40 + }, + set_margin_top: 64, set_spacing: 8, @@ -117,12 +183,16 @@ impl SimpleComponent for App { set_width_request: 200, add_css_class: "suggested-action", - connect_clicked => |_| { - anime_launcher_sdk::game::run().expect("Failed to run the game"); - } + connect_clicked => AppMsg::PerformAction }, gtk::Button { + #[watch] + set_width_request: match model.style { + LauncherStyle::Modern => -1, + LauncherStyle::Classic => 40 + }, + set_icon_name: "emblem-system-symbolic", connect_clicked => AppMsg::OpenPreferences @@ -137,12 +207,13 @@ impl SimpleComponent for App { fn init( _counter: Self::Init, root: &Self::Root, - _sender: ComponentSender, + sender: ComponentSender, ) -> ComponentParts { tracing::info!("Initializing main window"); let model = App { - loading: None + loading: None, + style: CONFIG.launcher.style }; let widgets = view_output!(); @@ -156,7 +227,7 @@ impl SimpleComponent for App { unsafe { PREFERENCES_WINDOW = Some(PreferencesApp::builder() .launch(widgets.main_window.clone().into()) - .detach()); + .forward(sender.input_sender(), std::convert::identity)); ABOUT_DIALOG = Some(AboutDialog::builder() .transient_for(widgets.main_window.clone()) @@ -166,6 +237,7 @@ impl SimpleComponent for App { let group = RelmActionGroup::::new(); + // TODO group.add_action::(&RelmAction::new_stateless(move |_| { println!("Open launcher folder!"); })); @@ -197,6 +269,10 @@ impl SimpleComponent for App { tracing::debug!("Called main window event: {:?}", msg); match msg { + AppMsg::PerformAction => { + anime_launcher_sdk::game::run().expect("Failed to run the game"); + } + AppMsg::OpenPreferences => unsafe { PREFERENCES_WINDOW.as_ref().unwrap_unchecked().widget().show(); } @@ -204,6 +280,10 @@ impl SimpleComponent for App { AppMsg::ClosePreferences => unsafe { PREFERENCES_WINDOW.as_ref().unwrap_unchecked().widget().hide(); } + + AppMsg::UpdateLauncherStyle(style) => { + self.style = style; + } } } } diff --git a/src/ui/preferences/general.rs b/src/ui/preferences/general.rs index ca55707..aa1ff5e 100644 --- a/src/ui/preferences/general.rs +++ b/src/ui/preferences/general.rs @@ -16,6 +16,61 @@ impl WidgetTemplate for General { set_title: &tr("general"), set_icon_name: Some("applications-system-symbolic"), + add = &adw::PreferencesGroup { + set_title: "Appearance", + + gtk::Box { + set_orientation: gtk::Orientation::Horizontal, + set_halign: gtk::Align::Center, + + set_spacing: 32, + + gtk::Box { + set_orientation: gtk::Orientation::Vertical, + + #[name(modern_style_button)] + gtk::ToggleButton { + add_css_class: "card", + + set_width_request: 180, + set_height_request: 120, + + gtk::Image { + set_from_resource: Some("/org/app/images/modern.svg") + } + }, + + gtk::Label { + set_text: "Modern", + + set_margin_top: 16 + } + }, + + gtk::Box { + set_orientation: gtk::Orientation::Vertical, + + #[name(classic_style_button)] + gtk::ToggleButton { + add_css_class: "card", + + set_width_request: 180, + set_height_request: 120, + + gtk::Image { + set_from_resource: Some("/org/app/images/classic.svg") + } + }, + + gtk::Label { + set_text: "Classic", + + set_margin_top: 16 + } + } + } + }, + add = &adw::PreferencesGroup { set_title: &tr("general"), diff --git a/src/ui/preferences/main.rs b/src/ui/preferences/main.rs index 0ed5fe0..bd4ca01 100644 --- a/src/ui/preferences/main.rs +++ b/src/ui/preferences/main.rs @@ -5,6 +5,7 @@ use gtk::prelude::*; use adw::prelude::*; use anime_launcher_sdk::config; +use anime_launcher_sdk::config::launcher::LauncherStyle; use anime_launcher_sdk::components::*; use anime_launcher_sdk::wincompatlib::prelude::*; @@ -20,6 +21,8 @@ pub struct App { wine_components: AsyncController, dxvk_components: AsyncController, + style: LauncherStyle, + downloaded_wine_versions: Vec, downloaded_dxvk_versions: Vec, @@ -36,6 +39,7 @@ pub enum AppMsg { title: String, description: Option }, + UpdateLauncherStyle(LauncherStyle), WineRecommendedOnly(bool), DxvkRecommendedOnly(bool), UpdateDownloadedWine, @@ -50,7 +54,7 @@ pub enum AppMsg { impl SimpleAsyncComponent for App { type Init = gtk::Window; type Input = AppMsg; - type Output = (); + type Output = crate::ui::main::AppMsg; view! { preferences_window = adw::PreferencesWindow { @@ -65,6 +69,22 @@ impl SimpleAsyncComponent for App { // but I have no idea how to do it other way // There're no graphical glitches so don't care + #[template_child] + modern_style_button { + #[watch] + set_active: model.style == LauncherStyle::Modern, + + connect_clicked => AppMsg::UpdateLauncherStyle(LauncherStyle::Modern) + }, + + #[template_child] + classic_style_button { + #[watch] + set_active: model.style == LauncherStyle::Classic, + + connect_clicked => AppMsg::UpdateLauncherStyle(LauncherStyle::Classic) + }, + #[template_child] wine_versions { add = model.wine_components.widget(), @@ -191,6 +211,8 @@ impl SimpleAsyncComponent for App { }) .forward(sender.input_sender(), std::convert::identity), + style: CONFIG.launcher.style, + downloaded_wine_versions: vec![], downloaded_dxvk_versions: vec![], @@ -253,6 +275,19 @@ impl SimpleAsyncComponent for App { PREFERENCES_WINDOW.as_ref().unwrap_unchecked().add_toast(&toast); } + #[allow(unused_must_use)] + AppMsg::UpdateLauncherStyle(style) => { + if let Ok(mut config) = config::get() { + config.launcher.style = style; + + config::update(config); + } + + self.style = style; + + sender.output(Self::Output::UpdateLauncherStyle(style)); + } + AppMsg::WineRecommendedOnly(state) => { // todo self.wine_components.sender().send(components::list::AppMsg::ShowRecommendedOnly(state)).unwrap();