a lot of the widgets work!
This commit is contained in:
parent
9cfa17ee0e
commit
41ab8c5289
5 changed files with 374 additions and 70 deletions
87
Cargo.lock
generated
87
Cargo.lock
generated
|
@ -290,7 +290,7 @@ version = "0.1.0"
|
||||||
source = "git+https://github.com/italicsjenga/baseview#1949bda39b673ce8d7c9d6104046388e5af1a944"
|
source = "git+https://github.com/italicsjenga/baseview#1949bda39b673ce8d7c9d6104046388e5af1a944"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa 0.24.1",
|
"cocoa 0.24.1",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keyboard-types",
|
"keyboard-types",
|
||||||
"nix 0.22.3",
|
"nix 0.22.3",
|
||||||
"objc",
|
"objc",
|
||||||
|
@ -452,18 +452,16 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cacao"
|
name = "cacao"
|
||||||
version = "0.4.0-beta2"
|
version = "0.4.0-beta2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/italicsjenga/cacao#6a3ed259b28f9bfd093293f61cd659247aa7375f"
|
||||||
checksum = "6de2bcb2324367ffb6ea53f977fab8234fa59e9a57e88f0f7be1ad7cb425c7b9"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitmask-enum",
|
"bitmask-enum",
|
||||||
"block",
|
"block2",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (git+https://github.com/madsmtm/core-foundation-rs.git?rev=7d593d016175755e492a92ef89edca68ac3bd5cd)",
|
||||||
"core-graphics 0.23.1",
|
"core-graphics 0.23.1",
|
||||||
"dispatch",
|
"dispatch",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"objc",
|
"objc2",
|
||||||
"objc_id",
|
|
||||||
"os_info",
|
"os_info",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
@ -636,7 +634,7 @@ dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"block",
|
"block",
|
||||||
"cocoa-foundation",
|
"cocoa-foundation",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"core-graphics 0.22.3",
|
"core-graphics 0.22.3",
|
||||||
"foreign-types 0.3.2",
|
"foreign-types 0.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -651,8 +649,8 @@ checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"block",
|
"block",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"core-graphics-types",
|
"core-graphics-types 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc",
|
||||||
"objc",
|
"objc",
|
||||||
]
|
]
|
||||||
|
@ -721,6 +719,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "git+https://github.com/madsmtm/core-foundation-rs.git?rev=7d593d016175755e492a92ef89edca68ac3bd5cd#7d593d016175755e492a92ef89edca68ac3bd5cd"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys 0.8.6",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -733,6 +740,14 @@ version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "git+https://github.com/madsmtm/core-foundation-rs.git?rev=7d593d016175755e492a92ef89edca68ac3bd5cd#7d593d016175755e492a92ef89edca68ac3bd5cd"
|
||||||
|
dependencies = [
|
||||||
|
"objc2-encode",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-graphics"
|
name = "core-graphics"
|
||||||
version = "0.19.2"
|
version = "0.19.2"
|
||||||
|
@ -752,8 +767,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"
|
checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"core-graphics-types",
|
"core-graphics-types 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"foreign-types 0.3.2",
|
"foreign-types 0.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
@ -761,14 +776,14 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-graphics"
|
name = "core-graphics"
|
||||||
version = "0.23.1"
|
version = "0.23.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/madsmtm/core-foundation-rs.git?rev=7d593d016175755e492a92ef89edca68ac3bd5cd#7d593d016175755e492a92ef89edca68ac3bd5cd"
|
||||||
checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (git+https://github.com/madsmtm/core-foundation-rs.git?rev=7d593d016175755e492a92ef89edca68ac3bd5cd)",
|
||||||
"core-graphics-types",
|
"core-graphics-types 0.1.2 (git+https://github.com/madsmtm/core-foundation-rs.git?rev=7d593d016175755e492a92ef89edca68ac3bd5cd)",
|
||||||
"foreign-types 0.5.0",
|
"foreign-types 0.5.0",
|
||||||
"libc",
|
"libc",
|
||||||
|
"objc2-encode",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -778,10 +793,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33"
|
checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-graphics-types"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "git+https://github.com/madsmtm/core-foundation-rs.git?rev=7d593d016175755e492a92ef89edca68ac3bd5cd#7d593d016175755e492a92ef89edca68ac3bd5cd"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"core-foundation 0.9.3 (git+https://github.com/madsmtm/core-foundation-rs.git?rev=7d593d016175755e492a92ef89edca68ac3bd5cd)",
|
||||||
|
"libc",
|
||||||
|
"objc2-encode",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-media-sys"
|
name = "core-media-sys"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -833,7 +859,7 @@ version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a7847ca018a67204508b77cb9e6de670125075f7464fff5f673023378fa34f5"
|
checksum = "1a7847ca018a67204508b77cb9e6de670125075f7464fff5f673023378fa34f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"core-foundation-sys 0.8.4",
|
"core-foundation-sys 0.8.4",
|
||||||
"coremidi-sys",
|
"coremidi-sys",
|
||||||
]
|
]
|
||||||
|
@ -1334,7 +1360,7 @@ dependencies = [
|
||||||
"gilrs",
|
"gilrs",
|
||||||
"image",
|
"image",
|
||||||
"nokhwa",
|
"nokhwa",
|
||||||
"objc",
|
"objc2",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"send_wrapper",
|
"send_wrapper",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -1410,7 +1436,7 @@ version = "0.5.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ccc99e9b8d63ffcaa334c4babfa31f46e156618a11f63efb6e8e6bcb37b830d"
|
checksum = "5ccc99e9b8d63ffcaa334c4babfa31f46e156618a11f63efb6e8e6bcb37b830d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"io-kit-sys",
|
"io-kit-sys",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -2093,7 +2119,7 @@ checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"block",
|
"block",
|
||||||
"core-graphics-types",
|
"core-graphics-types 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"foreign-types 0.3.2",
|
"foreign-types 0.3.2",
|
||||||
"log",
|
"log",
|
||||||
"objc",
|
"objc",
|
||||||
|
@ -2286,7 +2312,7 @@ dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"clap",
|
"clap",
|
||||||
"clap-sys",
|
"clap-sys",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cpal",
|
"cpal",
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
"jack",
|
"jack",
|
||||||
|
@ -2563,9 +2589,9 @@ checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2"
|
name = "objc2"
|
||||||
version = "0.3.0-beta.3.patch-leaks.3"
|
version = "0.3.0-beta.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468"
|
checksum = "fe31e5425d3d0b89a15982c024392815da40689aceb34bad364d58732bcfd649"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block2",
|
"block2",
|
||||||
"objc-sys",
|
"objc-sys",
|
||||||
|
@ -2590,15 +2616,6 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "objc_id"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
|
||||||
dependencies = [
|
|
||||||
"objc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.32.1"
|
version = "0.32.1"
|
||||||
|
@ -3942,7 +3959,7 @@ dependencies = [
|
||||||
"bit-set",
|
"bit-set",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"block",
|
"block",
|
||||||
"core-graphics-types",
|
"core-graphics-types 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"d3d12",
|
"d3d12",
|
||||||
"foreign-types 0.3.2",
|
"foreign-types 0.3.2",
|
||||||
"fxhash",
|
"fxhash",
|
||||||
|
@ -4229,7 +4246,7 @@ dependencies = [
|
||||||
"android-activity",
|
"android-activity",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"core-foundation 0.9.3",
|
"core-foundation 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"core-graphics 0.22.3",
|
"core-graphics 0.22.3",
|
||||||
"dispatch",
|
"dispatch",
|
||||||
"instant",
|
"instant",
|
||||||
|
|
|
@ -43,5 +43,5 @@ chrono = "0.4"
|
||||||
twinc_emu_vst = { path = "../gb-vst", default-features = false }
|
twinc_emu_vst = { path = "../gb-vst", default-features = false }
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "macos"))'.dependencies]
|
[target.'cfg(any(target_os = "macos"))'.dependencies]
|
||||||
cacao = "0.4.0-beta2"
|
cacao = { git = "https://github.com/italicsjenga/cacao" }
|
||||||
objc = "0.2"
|
objc = { version = "=0.3.0-beta.3", package = "objc2" }
|
||||||
|
|
|
@ -51,6 +51,7 @@ impl AppDelegate for TwincUiApp {
|
||||||
fn did_finish_launching(&self) {
|
fn did_finish_launching(&self) {
|
||||||
App::set_menu(menu());
|
App::set_menu(menu());
|
||||||
App::activate();
|
App::activate();
|
||||||
|
self.preferences.read().unwrap().show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,20 +3,27 @@ use cacao::{
|
||||||
view::{View, ViewDelegate},
|
view::{View, ViewDelegate},
|
||||||
};
|
};
|
||||||
use gb_emu::StandaloneConfig;
|
use gb_emu::StandaloneConfig;
|
||||||
use gb_emu_lib::config::{Config, ConfigManager};
|
use gb_emu_lib::config::{Config, ConfigManager, ResolutionOverride};
|
||||||
|
|
||||||
use crate::macos::dispatch;
|
use crate::macos::dispatch;
|
||||||
|
|
||||||
use self::widgets::{PathView, ToggleView};
|
use self::widgets::{PathView, StepperView, ToggleView};
|
||||||
|
|
||||||
mod widgets;
|
mod widgets;
|
||||||
|
|
||||||
pub(crate) struct CorePreferencesContentView {
|
pub(crate) struct CorePreferencesContentView {
|
||||||
config: Config,
|
config: Config,
|
||||||
config_manager: ConfigManager,
|
config_manager: ConfigManager,
|
||||||
|
dmg_bootrom: PathView,
|
||||||
|
cgb_bootrom: PathView,
|
||||||
show_bootrom: ToggleView,
|
show_bootrom: ToggleView,
|
||||||
prefer_cgb: ToggleView,
|
prefer_cgb: ToggleView,
|
||||||
dmg_bootrom: PathView,
|
dmg_shader: PathView,
|
||||||
|
dmg_resizable: ToggleView,
|
||||||
|
dmg_resolution: StepperView,
|
||||||
|
cgb_shader: PathView,
|
||||||
|
cgb_resizable: ToggleView,
|
||||||
|
cgb_resolution: StepperView,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CorePreferencesContentView {
|
impl CorePreferencesContentView {
|
||||||
|
@ -24,9 +31,16 @@ impl CorePreferencesContentView {
|
||||||
Self {
|
Self {
|
||||||
config: config_manager.load_or_create_base_config(),
|
config: config_manager.load_or_create_base_config(),
|
||||||
config_manager,
|
config_manager,
|
||||||
|
dmg_bootrom: Default::default(),
|
||||||
|
cgb_bootrom: Default::default(),
|
||||||
show_bootrom: Default::default(),
|
show_bootrom: Default::default(),
|
||||||
prefer_cgb: Default::default(),
|
prefer_cgb: Default::default(),
|
||||||
dmg_bootrom: Default::default(),
|
dmg_shader: Default::default(),
|
||||||
|
dmg_resizable: Default::default(),
|
||||||
|
dmg_resolution: Default::default(),
|
||||||
|
cgb_shader: Default::default(),
|
||||||
|
cgb_resizable: Default::default(),
|
||||||
|
cgb_resolution: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +50,24 @@ impl CorePreferencesContentView {
|
||||||
self.config.show_bootrom = !self.config.show_bootrom
|
self.config.show_bootrom = !self.config.show_bootrom
|
||||||
}
|
}
|
||||||
CorePreferencesUpdates::PreferCGB => self.config.prefer_cgb = !self.config.prefer_cgb,
|
CorePreferencesUpdates::PreferCGB => self.config.prefer_cgb = !self.config.prefer_cgb,
|
||||||
|
CorePreferencesUpdates::DmgResolution => {
|
||||||
|
let val = self.dmg_resolution.update();
|
||||||
|
self.config.vulkan_config.dmg_resolution_override =
|
||||||
|
ResolutionOverride::Scale(val.round() as usize)
|
||||||
|
}
|
||||||
|
CorePreferencesUpdates::CgbResolution => {
|
||||||
|
let val = self.cgb_resolution.update();
|
||||||
|
self.config.vulkan_config.cgb_resolution_override =
|
||||||
|
ResolutionOverride::Scale(val.round() as usize)
|
||||||
|
}
|
||||||
|
CorePreferencesUpdates::DmgResizable => {
|
||||||
|
self.config.vulkan_config.dmg_shader_resizable =
|
||||||
|
!self.config.vulkan_config.dmg_shader_resizable
|
||||||
|
}
|
||||||
|
CorePreferencesUpdates::CgbResizable => {
|
||||||
|
self.config.vulkan_config.cgb_shader_resizable =
|
||||||
|
!self.config.vulkan_config.cgb_shader_resizable
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.config_manager
|
self.config_manager
|
||||||
|
@ -47,14 +79,26 @@ impl CorePreferencesContentView {
|
||||||
pub(crate) enum CorePreferencesUpdates {
|
pub(crate) enum CorePreferencesUpdates {
|
||||||
ShowBootrom,
|
ShowBootrom,
|
||||||
PreferCGB,
|
PreferCGB,
|
||||||
|
DmgResolution,
|
||||||
|
CgbResolution,
|
||||||
|
DmgResizable,
|
||||||
|
CgbResizable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ViewDelegate for CorePreferencesContentView {
|
impl ViewDelegate for CorePreferencesContentView {
|
||||||
const NAME: &'static str = "CorePreferencesContentView";
|
const NAME: &'static str = "CorePreferencesContentView";
|
||||||
|
|
||||||
fn did_load(&mut self, view: View) {
|
fn did_load(&mut self, view: View) {
|
||||||
|
self.dmg_bootrom
|
||||||
|
.configure("DMG bootrom:", "", self.config.dmg_bootrom.clone());
|
||||||
|
view.add_subview(&self.dmg_bootrom.view);
|
||||||
|
|
||||||
|
self.cgb_bootrom
|
||||||
|
.configure("CGB bootrom:", "", self.config.cgb_bootrom.clone());
|
||||||
|
view.add_subview(&self.cgb_bootrom.view);
|
||||||
|
|
||||||
self.show_bootrom
|
self.show_bootrom
|
||||||
.configure("Show BootROM", "", self.config.show_bootrom, |_v| {
|
.configure("Show BootROM", self.config.show_bootrom, |_v| {
|
||||||
dispatch(crate::macos::AppMessage::Preferences(
|
dispatch(crate::macos::AppMessage::Preferences(
|
||||||
super::PreferencesMessage::UpdateCore(CorePreferencesUpdates::ShowBootrom),
|
super::PreferencesMessage::UpdateCore(CorePreferencesUpdates::ShowBootrom),
|
||||||
))
|
))
|
||||||
|
@ -63,7 +107,6 @@ impl ViewDelegate for CorePreferencesContentView {
|
||||||
|
|
||||||
self.prefer_cgb.configure(
|
self.prefer_cgb.configure(
|
||||||
"Prefer Game Boy Colour mode",
|
"Prefer Game Boy Colour mode",
|
||||||
"",
|
|
||||||
self.config.prefer_cgb,
|
self.config.prefer_cgb,
|
||||||
|_v| {
|
|_v| {
|
||||||
dispatch(crate::macos::AppMessage::Preferences(
|
dispatch(crate::macos::AppMessage::Preferences(
|
||||||
|
@ -73,16 +116,95 @@ impl ViewDelegate for CorePreferencesContentView {
|
||||||
);
|
);
|
||||||
view.add_subview(&self.prefer_cgb.view);
|
view.add_subview(&self.prefer_cgb.view);
|
||||||
|
|
||||||
self.dmg_bootrom
|
let dmg_resolution_override = match self.config.vulkan_config.dmg_resolution_override {
|
||||||
.configure("DMG bootrom", self.config.dmg_bootrom.clone());
|
ResolutionOverride::Scale(v) => v,
|
||||||
view.add_subview(&self.dmg_bootrom.view);
|
ResolutionOverride::Default => 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.dmg_resolution.configure(
|
||||||
|
"DMG resolution scale",
|
||||||
|
1.,
|
||||||
|
10.,
|
||||||
|
1.0,
|
||||||
|
0,
|
||||||
|
Some(dmg_resolution_override as f64),
|
||||||
|
|_v| {
|
||||||
|
dispatch(crate::macos::AppMessage::Preferences(
|
||||||
|
super::PreferencesMessage::UpdateCore(CorePreferencesUpdates::DmgResolution),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
view.add_subview(&self.dmg_resolution.view);
|
||||||
|
|
||||||
|
self.dmg_shader.configure(
|
||||||
|
"DMG shader",
|
||||||
|
"",
|
||||||
|
self.config.vulkan_config.dmg_shader_path.clone(),
|
||||||
|
);
|
||||||
|
view.add_subview(&self.dmg_shader.view);
|
||||||
|
|
||||||
|
self.dmg_resizable.configure(
|
||||||
|
"Resizable",
|
||||||
|
self.config.vulkan_config.dmg_shader_resizable,
|
||||||
|
|_v| {
|
||||||
|
dispatch(crate::macos::AppMessage::Preferences(
|
||||||
|
super::PreferencesMessage::UpdateCore(CorePreferencesUpdates::DmgResizable),
|
||||||
|
))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
view.add_subview(&self.dmg_resizable.view);
|
||||||
|
|
||||||
|
let cgb_resolution_override = match self.config.vulkan_config.cgb_resolution_override {
|
||||||
|
ResolutionOverride::Scale(v) => v,
|
||||||
|
ResolutionOverride::Default => 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.cgb_resolution.configure(
|
||||||
|
"CGB resolution scale",
|
||||||
|
1.,
|
||||||
|
10.,
|
||||||
|
1.0,
|
||||||
|
0,
|
||||||
|
Some(cgb_resolution_override as f64),
|
||||||
|
|_v| {
|
||||||
|
dispatch(crate::macos::AppMessage::Preferences(
|
||||||
|
super::PreferencesMessage::UpdateCore(CorePreferencesUpdates::CgbResolution),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
view.add_subview(&self.cgb_resolution.view);
|
||||||
|
|
||||||
|
self.cgb_shader.configure(
|
||||||
|
"CGB shader",
|
||||||
|
"",
|
||||||
|
self.config.vulkan_config.cgb_shader_path.clone(),
|
||||||
|
);
|
||||||
|
view.add_subview(&self.cgb_shader.view);
|
||||||
|
|
||||||
|
self.cgb_resizable.configure(
|
||||||
|
"Resizable",
|
||||||
|
self.config.vulkan_config.cgb_shader_resizable,
|
||||||
|
|_v| {
|
||||||
|
dispatch(crate::macos::AppMessage::Preferences(
|
||||||
|
super::PreferencesMessage::UpdateCore(CorePreferencesUpdates::CgbResizable),
|
||||||
|
))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
view.add_subview(&self.cgb_resizable.view);
|
||||||
|
|
||||||
widgets::auto_layout(
|
widgets::auto_layout(
|
||||||
&view,
|
&view,
|
||||||
vec![
|
vec![
|
||||||
|
&self.dmg_bootrom.view,
|
||||||
|
&self.cgb_bootrom.view,
|
||||||
&self.show_bootrom.view,
|
&self.show_bootrom.view,
|
||||||
&self.prefer_cgb.view,
|
&self.prefer_cgb.view,
|
||||||
&self.dmg_bootrom.view,
|
&self.dmg_resolution.view,
|
||||||
|
&self.dmg_shader.view,
|
||||||
|
&self.dmg_resizable.view,
|
||||||
|
&self.cgb_resolution.view,
|
||||||
|
&self.cgb_shader.view,
|
||||||
|
&self.cgb_resizable.view,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -125,7 +247,6 @@ impl ViewDelegate for StandalonePreferencesContentView {
|
||||||
fn did_load(&mut self, view: View) {
|
fn did_load(&mut self, view: View) {
|
||||||
self.group_screenshots_by_rom.configure(
|
self.group_screenshots_by_rom.configure(
|
||||||
"Group screenshots by ROM",
|
"Group screenshots by ROM",
|
||||||
"",
|
|
||||||
self.config.group_screenshots_by_rom,
|
self.config.group_screenshots_by_rom,
|
||||||
|_v| {
|
|_v| {
|
||||||
dispatch(crate::macos::AppMessage::Preferences(
|
dispatch(crate::macos::AppMessage::Preferences(
|
||||||
|
@ -179,7 +300,6 @@ impl ViewDelegate for VstPreferencesContentView {
|
||||||
fn did_load(&mut self, view: View) {
|
fn did_load(&mut self, view: View) {
|
||||||
self.force_skip_bootrom.configure(
|
self.force_skip_bootrom.configure(
|
||||||
"Force skip bootrom",
|
"Force skip bootrom",
|
||||||
"",
|
|
||||||
self.config.force_skip_bootrom,
|
self.config.force_skip_bootrom,
|
||||||
|_v| {
|
|_v| {
|
||||||
dispatch(crate::macos::AppMessage::Preferences(
|
dispatch(crate::macos::AppMessage::Preferences(
|
||||||
|
|
|
@ -1,16 +1,24 @@
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use cacao::button::Button;
|
use cacao::button::Button;
|
||||||
use cacao::input::TextField;
|
use cacao::input::TextField;
|
||||||
use cacao::layout::{Layout, LayoutConstraint};
|
use cacao::layout::{Layout, LayoutConstraint};
|
||||||
|
use cacao::select::Select;
|
||||||
|
use cacao::stepper::Stepper;
|
||||||
use cacao::switch::Switch;
|
use cacao::switch::Switch;
|
||||||
use cacao::text::Label;
|
use cacao::text::Label;
|
||||||
use cacao::view::View;
|
use cacao::view::View;
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
|
|
||||||
|
const LEFT_MARGIN: f64 = 150.;
|
||||||
|
|
||||||
pub(crate) fn auto_layout(container: &View, items: Vec<&View>) {
|
pub(crate) fn auto_layout(container: &View, items: Vec<&View>) {
|
||||||
for (i, item) in items.iter().enumerate() {
|
for (i, item) in items.iter().enumerate() {
|
||||||
LayoutConstraint::activate(&[
|
LayoutConstraint::activate(&[
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
item.top.constraint_equal_to(&items[i - 1].bottom)
|
item.top
|
||||||
|
.constraint_equal_to(&items[i - 1].bottom)
|
||||||
|
.offset(11.)
|
||||||
} else {
|
} else {
|
||||||
item.top.constraint_equal_to(&container.top).offset(22.)
|
item.top.constraint_equal_to(&container.top).offset(22.)
|
||||||
},
|
},
|
||||||
|
@ -35,7 +43,6 @@ pub struct ToggleView {
|
||||||
pub view: View,
|
pub view: View,
|
||||||
pub switch: Switch,
|
pub switch: Switch,
|
||||||
pub title: Label,
|
pub title: Label,
|
||||||
pub subtitle: Label,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ToggleView {
|
impl Default for ToggleView {
|
||||||
|
@ -48,41 +55,33 @@ impl Default for ToggleView {
|
||||||
let title = Label::new();
|
let title = Label::new();
|
||||||
view.add_subview(&title);
|
view.add_subview(&title);
|
||||||
|
|
||||||
let subtitle = Label::new();
|
|
||||||
view.add_subview(&subtitle);
|
|
||||||
|
|
||||||
LayoutConstraint::activate(&[
|
LayoutConstraint::activate(&[
|
||||||
switch.top.constraint_equal_to(&view.top),
|
switch.top.constraint_equal_to(&view.top),
|
||||||
switch.leading.constraint_equal_to(&view.leading),
|
switch
|
||||||
|
.leading
|
||||||
|
.constraint_equal_to(&view.leading)
|
||||||
|
.offset(LEFT_MARGIN),
|
||||||
switch.width.constraint_equal_to_constant(24.),
|
switch.width.constraint_equal_to_constant(24.),
|
||||||
title.top.constraint_equal_to(&view.top),
|
title.top.constraint_equal_to(&view.top),
|
||||||
title.leading.constraint_equal_to(&switch.trailing),
|
title.leading.constraint_equal_to(&switch.trailing),
|
||||||
title.trailing.constraint_equal_to(&view.trailing),
|
title.trailing.constraint_equal_to(&view.trailing),
|
||||||
subtitle.top.constraint_equal_to(&title.bottom),
|
title.bottom.constraint_equal_to(&view.bottom),
|
||||||
subtitle.leading.constraint_equal_to(&switch.trailing),
|
|
||||||
subtitle.trailing.constraint_equal_to(&view.trailing),
|
|
||||||
subtitle.bottom.constraint_equal_to(&view.bottom),
|
|
||||||
subtitle
|
|
||||||
.width
|
|
||||||
.constraint_greater_than_or_equal_to_constant(200.),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
ToggleView {
|
ToggleView {
|
||||||
view,
|
view,
|
||||||
switch,
|
switch,
|
||||||
title,
|
title,
|
||||||
subtitle,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToggleView {
|
impl ToggleView {
|
||||||
pub fn configure<F>(&mut self, text: &str, subtitle: &str, state: bool, handler: F)
|
pub fn configure<F>(&mut self, text: &str, state: bool, handler: F)
|
||||||
where
|
where
|
||||||
F: Fn(*const Object) + Send + Sync + 'static,
|
F: Fn(*const Object) + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.title.set_text(text);
|
self.title.set_text(text);
|
||||||
self.subtitle.set_text(subtitle);
|
|
||||||
self.switch.set_action(handler);
|
self.switch.set_action(handler);
|
||||||
self.switch.set_checked(state);
|
self.switch.set_checked(state);
|
||||||
}
|
}
|
||||||
|
@ -92,20 +91,34 @@ pub struct PathView {
|
||||||
pub view: View,
|
pub view: View,
|
||||||
pub field: TextField,
|
pub field: TextField,
|
||||||
pub button: Button,
|
pub button: Button,
|
||||||
|
pub title: Label,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PathView {
|
impl Default for PathView {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let view = View::new();
|
let view = View::new();
|
||||||
|
|
||||||
let field = TextField::new();
|
let field = TextField::new();
|
||||||
field.set_uses_single_line(true);
|
field.set_uses_single_line(true);
|
||||||
|
field.set_truncates_last_visible_line(false);
|
||||||
|
field.set_line_break_mode(cacao::text::LineBreakMode::TruncateMiddle);
|
||||||
view.add_subview(&field);
|
view.add_subview(&field);
|
||||||
|
|
||||||
let button = Button::new("Browse");
|
let button = Button::new("Browse");
|
||||||
view.add_subview(&button);
|
view.add_subview(&button);
|
||||||
|
let title = Label::new();
|
||||||
|
view.add_subview(&title);
|
||||||
|
title.set_text_alignment(cacao::text::TextAlign::Right);
|
||||||
|
|
||||||
LayoutConstraint::activate(&[
|
LayoutConstraint::activate(&[
|
||||||
|
title.center_y.constraint_equal_to(&view.center_y),
|
||||||
|
title.leading.constraint_equal_to(&view.leading),
|
||||||
|
title.width.constraint_equal_to_constant(LEFT_MARGIN - 10.),
|
||||||
field.top.constraint_equal_to(&view.top),
|
field.top.constraint_equal_to(&view.top),
|
||||||
field.leading.constraint_equal_to(&view.leading),
|
field
|
||||||
|
.leading
|
||||||
|
.constraint_equal_to(&title.trailing)
|
||||||
|
.offset(10.),
|
||||||
field.bottom.constraint_equal_to(&view.bottom),
|
field.bottom.constraint_equal_to(&view.bottom),
|
||||||
field
|
field
|
||||||
.trailing
|
.trailing
|
||||||
|
@ -113,26 +126,179 @@ impl Default for PathView {
|
||||||
.offset(-10.),
|
.offset(-10.),
|
||||||
field
|
field
|
||||||
.width
|
.width
|
||||||
.constraint_greater_than_or_equal_to_constant(400.),
|
.constraint_greater_than_or_equal_to_constant(200.),
|
||||||
|
button.center_y.constraint_equal_to(&view.center_y),
|
||||||
button.trailing.constraint_equal_to(&view.trailing),
|
button.trailing.constraint_equal_to(&view.trailing),
|
||||||
button.width.constraint_equal_to_constant(100.),
|
button.width.constraint_equal_to_constant(100.),
|
||||||
button.top.constraint_equal_to(&view.top),
|
|
||||||
button.bottom.constraint_equal_to(&view.bottom),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
view,
|
view,
|
||||||
field,
|
field,
|
||||||
button,
|
button,
|
||||||
|
title,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PathView {
|
impl PathView {
|
||||||
pub fn configure(&mut self, placeholder: &str, state: Option<String>) {
|
pub fn configure(&mut self, title: &str, placeholder: &str, state: Option<String>) {
|
||||||
|
self.title.set_text(title);
|
||||||
self.field.set_placeholder_text(placeholder);
|
self.field.set_placeholder_text(placeholder);
|
||||||
if let Some(state) = state {
|
if let Some(state) = state {
|
||||||
self.field.set_text(&state);
|
self.field.set_text(&state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PickerView<T>
|
||||||
|
where
|
||||||
|
T: ToString,
|
||||||
|
{
|
||||||
|
pub view: View,
|
||||||
|
pub select: Select,
|
||||||
|
pub title: Label,
|
||||||
|
_p: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for PickerView<T>
|
||||||
|
where
|
||||||
|
T: ToString,
|
||||||
|
{
|
||||||
|
fn default() -> Self {
|
||||||
|
let view = View::new();
|
||||||
|
|
||||||
|
let select = Select::new();
|
||||||
|
|
||||||
|
view.add_subview(&select);
|
||||||
|
|
||||||
|
let title = Label::new();
|
||||||
|
view.add_subview(&title);
|
||||||
|
title.set_text_alignment(cacao::text::TextAlign::Right);
|
||||||
|
|
||||||
|
LayoutConstraint::activate(&[
|
||||||
|
title.center_y.constraint_equal_to(&view.center_y),
|
||||||
|
title.leading.constraint_equal_to(&view.leading),
|
||||||
|
title.width.constraint_equal_to_constant(LEFT_MARGIN - 10.),
|
||||||
|
select.top.constraint_equal_to(&view.top),
|
||||||
|
select
|
||||||
|
.leading
|
||||||
|
.constraint_equal_to(&title.trailing)
|
||||||
|
.offset(10.),
|
||||||
|
select.bottom.constraint_equal_to(&view.bottom),
|
||||||
|
select.trailing.constraint_equal_to(&view.trailing),
|
||||||
|
select
|
||||||
|
.width
|
||||||
|
.constraint_greater_than_or_equal_to_constant(200.),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
view,
|
||||||
|
select,
|
||||||
|
title,
|
||||||
|
_p: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> PickerView<T>
|
||||||
|
where
|
||||||
|
T: ToString,
|
||||||
|
{
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn configure(&mut self, title: &str, values: Vec<T>) {
|
||||||
|
self.title.set_text(title);
|
||||||
|
for val in &values {
|
||||||
|
self.select.add_item(val.to_string().as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StepperView {
|
||||||
|
pub view: View,
|
||||||
|
pub field: TextField,
|
||||||
|
pub stepper: Stepper,
|
||||||
|
pub title: Label,
|
||||||
|
pub decimal_places: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StepperView {
|
||||||
|
fn default() -> Self {
|
||||||
|
let view = View::new();
|
||||||
|
|
||||||
|
let stepper = Stepper::new();
|
||||||
|
stepper.set_wraps(false);
|
||||||
|
view.add_subview(&stepper);
|
||||||
|
|
||||||
|
let field = TextField::new();
|
||||||
|
field.set_uses_single_line(true);
|
||||||
|
field.set_editable(false);
|
||||||
|
view.add_subview(&field);
|
||||||
|
|
||||||
|
let title = Label::new();
|
||||||
|
view.add_subview(&title);
|
||||||
|
title.set_text_alignment(cacao::text::TextAlign::Right);
|
||||||
|
|
||||||
|
LayoutConstraint::activate(&[
|
||||||
|
title.center_y.constraint_equal_to(&view.center_y),
|
||||||
|
title.leading.constraint_equal_to(&view.leading),
|
||||||
|
title.width.constraint_equal_to_constant(LEFT_MARGIN - 10.),
|
||||||
|
field.top.constraint_equal_to(&view.top),
|
||||||
|
field
|
||||||
|
.leading
|
||||||
|
.constraint_equal_to(&title.trailing)
|
||||||
|
.offset(10.),
|
||||||
|
stepper.center_y.constraint_equal_to(&view.center_y),
|
||||||
|
stepper
|
||||||
|
.leading
|
||||||
|
.constraint_equal_to(&field.trailing)
|
||||||
|
.offset(5.),
|
||||||
|
field.bottom.constraint_equal_to(&view.bottom),
|
||||||
|
field
|
||||||
|
.width
|
||||||
|
.constraint_greater_than_or_equal_to_constant(80.),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
view,
|
||||||
|
field,
|
||||||
|
stepper,
|
||||||
|
title,
|
||||||
|
decimal_places: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StepperView {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn configure<F>(
|
||||||
|
&mut self,
|
||||||
|
title: &str,
|
||||||
|
min: f64,
|
||||||
|
max: f64,
|
||||||
|
increment: f64,
|
||||||
|
decimal_places: usize,
|
||||||
|
initial_value: Option<f64>,
|
||||||
|
handler: F,
|
||||||
|
) where
|
||||||
|
F: Fn(*const Object) + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
self.title.set_text(title);
|
||||||
|
self.decimal_places = decimal_places;
|
||||||
|
if let Some(val) = initial_value {
|
||||||
|
self.stepper.set_value(val);
|
||||||
|
}
|
||||||
|
self.stepper.set_min_value(min);
|
||||||
|
self.stepper.set_max_value(max);
|
||||||
|
self.stepper.set_increment(increment);
|
||||||
|
self.stepper.set_action(handler);
|
||||||
|
self.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self) -> f64 {
|
||||||
|
let val = self.stepper.get_value();
|
||||||
|
self.field
|
||||||
|
.set_text(format!("{:.1$}", val, self.decimal_places).as_str());
|
||||||
|
val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue