mod: adjustments
This commit is contained in:
@@ -2,6 +2,23 @@
|
|||||||
<interface>
|
<interface>
|
||||||
<requires lib="gtk" version="4.0"/>
|
<requires lib="gtk" version="4.0"/>
|
||||||
<menu id="app-menu">
|
<menu id="app-menu">
|
||||||
|
<section>
|
||||||
|
<submenu>
|
||||||
|
<attribute name="label" translatable="yes">_Appearance</attribute>
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Follow _System</attribute>
|
||||||
|
<attribute name="action">app.theme</attribute>
|
||||||
|
<attribute name="target">system</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">_Dark</attribute>
|
||||||
|
<attribute name="action">app.theme</attribute>
|
||||||
|
<attribute name="target">dark</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</submenu>
|
||||||
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<item>
|
<item>
|
||||||
<attribute name="label" translatable="yes">_About SNES Patcher</attribute>
|
<attribute name="label" translatable="yes">_About SNES Patcher</attribute>
|
||||||
|
|||||||
+12
-5
@@ -2,11 +2,6 @@
|
|||||||
min-width: 356px;
|
min-width: 356px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.heading {
|
.heading {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
@@ -21,3 +16,15 @@
|
|||||||
min-height: 48px;
|
min-height: 48px;
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.intro-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
headerbar.titlebar {
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: none;
|
||||||
|
border-bottom: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|||||||
+61
-1
@@ -7,6 +7,7 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use gtk4::gio;
|
use gtk4::gio;
|
||||||
use gtk4::glib;
|
use gtk4::glib;
|
||||||
|
use gtk4::glib::ToVariant;
|
||||||
use gtk4::pango::EllipsizeMode;
|
use gtk4::pango::EllipsizeMode;
|
||||||
use gtk4::prelude::*;
|
use gtk4::prelude::*;
|
||||||
use gtk4::{
|
use gtk4::{
|
||||||
@@ -17,6 +18,8 @@ use gtk4::{
|
|||||||
|
|
||||||
const APP_ID: &str = "com.wyattjmiller.snespatcher";
|
const APP_ID: &str = "com.wyattjmiller.snespatcher";
|
||||||
const APP_NAME: &str = "SNES Patcher";
|
const APP_NAME: &str = "SNES Patcher";
|
||||||
|
const THEME_SYSTEM: &str = "system";
|
||||||
|
const THEME_DARK: &str = "dark";
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct SelectionState {
|
struct SelectionState {
|
||||||
@@ -71,7 +74,7 @@ fn build_ui(app: &Application) {
|
|||||||
|
|
||||||
let introduction = GtkBox::new(Orientation::Vertical, 8);
|
let introduction = GtkBox::new(Orientation::Vertical, 8);
|
||||||
let heading = Label::new(Some("Patch a Super Nintendo ROM"));
|
let heading = Label::new(Some("Patch a Super Nintendo ROM"));
|
||||||
heading.add_css_class("title");
|
heading.add_css_class("intro-title");
|
||||||
heading.set_justify(Justification::Center);
|
heading.set_justify(Justification::Center);
|
||||||
heading.set_wrap(true);
|
heading.set_wrap(true);
|
||||||
|
|
||||||
@@ -192,6 +195,8 @@ fn build_header_bar(
|
|||||||
header_bar.pack_start(rom_info_button);
|
header_bar.pack_start(rom_info_button);
|
||||||
header_bar.pack_end(&menu_button);
|
header_bar.pack_end(&menu_button);
|
||||||
|
|
||||||
|
add_theme_action(app);
|
||||||
|
|
||||||
let about = gio::SimpleAction::new("about", None);
|
let about = gio::SimpleAction::new("about", None);
|
||||||
about.connect_activate(glib::clone!(@weak window => move |_, _| {
|
about.connect_activate(glib::clone!(@weak window => move |_, _| {
|
||||||
let dialog = AboutDialog::builder()
|
let dialog = AboutDialog::builder()
|
||||||
@@ -219,6 +224,61 @@ fn build_header_bar(
|
|||||||
header_bar
|
header_bar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_theme_action(app: &Application) {
|
||||||
|
let preference = load_theme_preference();
|
||||||
|
let settings = gtk4::Settings::default().expect("Could not access GTK settings");
|
||||||
|
apply_theme_preference(&settings, &preference);
|
||||||
|
|
||||||
|
let theme = gio::SimpleAction::new_stateful(
|
||||||
|
"theme",
|
||||||
|
Some(glib::VariantTy::STRING),
|
||||||
|
&preference.to_variant(),
|
||||||
|
);
|
||||||
|
theme.connect_activate(move |action, parameter| {
|
||||||
|
let Some(preference) = parameter.and_then(|value| value.get::<String>()) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if preference != THEME_SYSTEM && preference != THEME_DARK {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_theme_preference(&settings, &preference);
|
||||||
|
action.set_state(&preference.to_variant());
|
||||||
|
save_theme_preference(&preference);
|
||||||
|
});
|
||||||
|
app.add_action(&theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_theme_preference(settings: >k4::Settings, preference: &str) {
|
||||||
|
settings.set_gtk_application_prefer_dark_theme(preference == THEME_DARK);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn theme_preference_path() -> PathBuf {
|
||||||
|
glib::user_config_dir().join(APP_ID).join("theme")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_theme_preference() -> String {
|
||||||
|
match std::fs::read_to_string(theme_preference_path()) {
|
||||||
|
Ok(preference) if preference.trim() == THEME_DARK => THEME_DARK.to_string(),
|
||||||
|
_ => THEME_SYSTEM.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_theme_preference(preference: &str) {
|
||||||
|
let path = theme_preference_path();
|
||||||
|
let Some(parent) = path.parent() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(error) = std::fs::create_dir_all(parent) {
|
||||||
|
eprintln!("Could not create the preferences directory: {error}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Err(error) = std::fs::write(path, preference) {
|
||||||
|
eprintln!("Could not save the theme preference: {error}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn selection_row(title: &str, placeholder: &str, icon_name: &str) -> SelectionRow {
|
fn selection_row(title: &str, placeholder: &str, icon_name: &str) -> SelectionRow {
|
||||||
let icon = Image::from_icon_name(icon_name);
|
let icon = Image::from_icon_name(icon_name);
|
||||||
icon.set_pixel_size(24);
|
icon.set_pixel_size(24);
|
||||||
|
|||||||
Reference in New Issue
Block a user