diff --git a/Cargo.lock b/Cargo.lock index acbedb7..23846e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,48 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "associative-cache" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46016233fc1bb55c23b856fe556b7db6ccd05119a0a392e04f0b3b7c79058f16" + +[[package]] +name = "atk" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39991bc421ddf72f70159011b323ff49b0f783cc676a7287c59453da2e2531cf" +dependencies = [ + "atk-sys", + "bitflags", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ad703eb64dc058024f0e57ccfa069e15a413b98dbd50a1a950e743b7f11148" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -71,6 +113,21 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-buffer" version = "0.10.3" @@ -92,6 +149,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + [[package]] name = "bytecount" version = "0.6.3" @@ -131,6 +194,31 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "cairo-rs" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3125b15ec28b84c238f6f476c6034016a5f6cc0221cb514ca46c532139fc97d" +dependencies = [ + "bitflags", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c48f4af05fabdcfa9658178e1326efa061853f040ce7d72e33af6885196f421" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + [[package]] name = "cc" version = "1.0.78" @@ -140,6 +228,15 @@ dependencies = [ "jobserver", ] +[[package]] +name = "cfg-expr" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa" +dependencies = [ + "smallvec", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -205,6 +302,37 @@ dependencies = [ "winapi", ] +[[package]] +name = "cocoa" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" +dependencies = [ + "bitflags", + "block", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", + "objc", +] + [[package]] name = "color-eyre" version = "0.6.2" @@ -244,12 +372,75 @@ dependencies = [ "toml", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +dependencies = [ + "bitflags", + "core-foundation", + "foreign-types", + "libc", +] + +[[package]] +name = "core-text" +version = "19.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +dependencies = [ + "core-foundation", + "core-graphics", + "foreign-types", + "libc", +] + [[package]] name = "cpufeatures" version = "0.2.5" @@ -365,6 +556,99 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "druid" +version = "0.7.0" +source = "git+https://github.com/linebender/druid.git#23963d38fdb85761f3a5d1918246958dee3375ad" +dependencies = [ + "console_error_panic_hook", + "druid-derive", + "druid-shell", + "fluent-bundle", + "fluent-langneg", + "fluent-syntax", + "fnv", + "im", + "instant", + "tracing", + "tracing-subscriber", + "tracing-wasm", + "unic-langid", + "unicode-segmentation", + "xi-unicode", +] + +[[package]] +name = "druid-derive" +version = "0.4.0" +source = "git+https://github.com/linebender/druid.git#23963d38fdb85761f3a5d1918246958dee3375ad" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "druid-shell" +version = "0.7.0" +source = "git+https://github.com/linebender/druid.git#23963d38fdb85761f3a5d1918246958dee3375ad" +dependencies = [ + "anyhow", + "bitflags", + "block", + "cairo-rs", + "cfg-if", + "cocoa", + "core-graphics", + "foreign-types", + "gdk-sys", + "glib-sys", + "gtk", + "gtk-sys", + "instant", + "js-sys", + "keyboard-types", + "kurbo", + "objc", + "once_cell", + "piet-common", + "scopeguard", + "time", + "tracing", + "wasm-bindgen", + "web-sys", + "winapi", + "wio", +] + +[[package]] +name = "dtmm" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "confy", + "druid", + "sdk", + "serde", + "tokio", + "toml", + "tracing", + "tracing-error", + "tracing-subscriber", +] + [[package]] name = "dtmt" version = "0.2.0" @@ -394,6 +678,18 @@ dependencies = [ "zip", ] +[[package]] +name = "dwrote" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +dependencies = [ + "lazy_static", + "libc", + "winapi", + "wio", +] + [[package]] name = "endian-type" version = "0.1.2" @@ -461,6 +757,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "field-offset" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92" +dependencies = [ + "memoffset", + "rustc_version", +] + [[package]] name = "flate2" version = "1.0.25" @@ -471,6 +777,61 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fluent-bundle" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e242c601dec9711505f6d5bbff5bedd4b61b2469f2e8bb8e57ee7c9747a87ffd" +dependencies = [ + "fluent-langneg", + "fluent-syntax", + "intl-memoizer", + "intl_pluralrules", + "rustc-hash", + "self_cell", + "smallvec", + "unic-langid", +] + +[[package]] +name = "fluent-langneg" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94" +dependencies = [ + "unic-langid", +] + +[[package]] +name = "fluent-syntax" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0abed97648395c902868fee9026de96483933faa54ea3b40d652f7dfe61ca78" +dependencies = [ + "thiserror", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "futures" version = "0.3.25" @@ -560,6 +921,65 @@ dependencies = [ "slab", ] +[[package]] +name = "gdk" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9cb33da481c6c040404a11f8212d193889e9b435db2c14fd86987f630d3ce1" +dependencies = [ + "bitflags", + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3578c60dee9d029ad86593ed88cb40f35c1b83360e12498d055022385dd9a05" +dependencies = [ + "bitflags", + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3092cf797a5f1210479ea38070d9ae8a5b8e9f8f1be9f32f4643c529c7d70016" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76354f97a913e55b984759a997b693aa7dc71068c9e98bcce51aa167a0a5c5a" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + [[package]] name = "generic-array" version = "0.14.6" @@ -587,12 +1007,158 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" +[[package]] +name = "gio" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a1c84b4534a290a29160ef5c6eff2a9c95833111472e824fc5cb78b513dd092" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9b693b8e39d042a95547fc258a7b07349b1f0b48f4b2fa3108ba3c51c0b5229" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd4df61a866ed7259d6189b8bcb1464989a77f1d85d25d002279bbe9dd38b2f" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "once_cell", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e084807350b01348b6d9dbabb724d1a0bb987f47a2c85de200e98e12e30733bf" +dependencies = [ + "anyhow", + "heck", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61a4f46316d06bfa33a7ac22df6f0524c8be58e3db2d9ca99ccb1f357b62a65" +dependencies = [ + "libc", + "system-deps", +] + [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gobject-sys" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3520bb9c07ae2a12c7f2fbb24d4efc11231c8146a86956413fb1a79bb760a0f1" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4d3507d43908c866c805f74c9dd593c0ce7ba5c38e576e41846639cdcd4bee6" +dependencies = [ + "atk", + "bitflags", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "once_cell", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b5f8946685d5fe44497007786600c2f368ff6b1e61a16251c89f72a97520a3" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfd6557b1018b773e43c8de9d0d13581d6b36190d0501916cbec4731db5ccff" +dependencies = [ + "anyhow", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "heck" version = "0.4.0" @@ -617,6 +1183,20 @@ dependencies = [ "digest", ] +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + [[package]] name = "indenter" version = "0.3.3" @@ -630,6 +1210,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "intl-memoizer" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f" +dependencies = [ + "type-map", + "unic-langid", +] + +[[package]] +name = "intl_pluralrules" +version = "7.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972" +dependencies = [ + "unic-langid", ] [[package]] @@ -669,6 +1271,33 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keyboard-types" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7668b7cff6a51fe61cdde64cd27c8a220786f399501b57ebe36f7d8112fd68" +dependencies = [ + "bitflags", +] + +[[package]] +name = "kurbo" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e119590a03caff1f7a582e8ee8c2164ddcc975791701188132fd1d1b518d3871" +dependencies = [ + "arrayvec", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -706,6 +1335,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "matchers" version = "0.1.0" @@ -715,6 +1353,12 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + [[package]] name = "memchr" version = "2.5.0" @@ -826,6 +1470,15 @@ dependencies = [ "libc", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + [[package]] name = "object" version = "0.30.1" @@ -874,6 +1527,59 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "pango" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdff66b271861037b89d028656184059e03b0b6ccb36003820be19f7200b1e94" +dependencies = [ + "bitflags", + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e134909a9a293e04d2cc31928aa95679c5e4df954d0b85483159bd20d8f047f" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "pangocairo" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ad2ec87789371b551fd2367c10aa37060412ffd3e60abd99491b21b93a3f9b" +dependencies = [ + "bitflags", + "cairo-rs", + "glib", + "libc", + "pango", + "pangocairo-sys", +] + +[[package]] +name = "pangocairo-sys" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "848d2df9b7f1a8c7a19d994de443bcbe5d4382610ccb8e64247f932be74fcf76" +dependencies = [ + "cairo-sys-rs", + "glib-sys", + "libc", + "pango-sys", + "system-deps", +] + [[package]] name = "password-hash" version = "0.4.2" @@ -897,6 +1603,102 @@ dependencies = [ "sha2", ] +[[package]] +name = "pest" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4257b4a04d91f7e9e6290be5d3da4804dd5784fafde3a497d73eb2b4a158c30a" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "piet" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd2a0027c9ea84b51f42ea3148864e6fc58970ad927e78390d5f9cf7cfa2c78" +dependencies = [ + "kurbo", + "unic-bidi", +] + +[[package]] +name = "piet-cairo" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b98e21ec69eefb09d34e34050beb700749547dfc5da7a6cff27089dd59af1b3" +dependencies = [ + "cairo-rs", + "pango", + "pangocairo", + "piet", + "unicode-segmentation", + "xi-unicode", +] + +[[package]] +name = "piet-common" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b7285cc595907be29db4d7f3fb331ae273250365cebf536a4a7b1dafc62978e" +dependencies = [ + "cairo-rs", + "cairo-sys-rs", + "cfg-if", + "core-graphics", + "piet", + "piet-cairo", + "piet-coregraphics", + "piet-direct2d", + "piet-web", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "piet-coregraphics" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32553fa0566ed2f23dadec1078a1e6a5930672f350db54d4267e9358f578ab4f" +dependencies = [ + "associative-cache", + "core-foundation", + "core-foundation-sys", + "core-graphics", + "core-text", + "foreign-types", + "piet", +] + +[[package]] +name = "piet-direct2d" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d65edc9fa5d1710daa2e55e9cc7b65e65794304ffa870a565fb7128f3110ac5" +dependencies = [ + "associative-cache", + "dwrote", + "piet", + "utf16_lit", + "winapi", + "wio", +] + +[[package]] +name = "piet-web" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "303452b9813560d4e4ea37b5792b18578b12f1e47111f1aea1a4cb9392f6fa95" +dependencies = [ + "js-sys", + "piet", + "unicode-segmentation", + "wasm-bindgen", + "web-sys", + "xi-unicode", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -915,6 +1717,17 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +[[package]] +name = "proc-macro-crate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +dependencies = [ + "once_cell", + "thiserror", + "toml", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -982,6 +1795,15 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -1043,6 +1865,21 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.36.6" @@ -1116,6 +1953,30 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "self_cell" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.152" @@ -1185,6 +2046,16 @@ dependencies = [ "libc", ] +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + [[package]] name = "slab" version = "0.4.7" @@ -1238,6 +2109,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "system-deps" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -1317,6 +2201,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aeafdfd935e4a7fe16a91ab711fa52d54df84f9c8f7ca5837a9d1d902ef4c2" +dependencies = [ + "displaydoc", +] + [[package]] name = "tokio" version = "1.24.1" @@ -1439,12 +2332,107 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "tracing-wasm" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" +dependencies = [ + "tracing", + "tracing-subscriber", + "wasm-bindgen", +] + +[[package]] +name = "type-map" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46" +dependencies = [ + "rustc-hash", +] + [[package]] name = "typenum" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "ucd-trie" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" + +[[package]] +name = "unic-bidi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1356b759fb6a82050666f11dce4b6fe3571781f1449f3ef78074e408d468ec09" +dependencies = [ + "matches", + "unic-ucd-bidi", +] + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-langid" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "398f9ad7239db44fd0f80fe068d12ff22d78354080332a5077dc6f52f14dcf2f" +dependencies = [ + "unic-langid-impl", +] + +[[package]] +name = "unic-langid-impl" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff" +dependencies = [ + "tinystr", +] + +[[package]] +name = "unic-ucd-bidi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1d568b51222484e1f8209ce48caa6b430bf352962b877d592c29ab31fb53d8c" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + [[package]] name = "unicase" version = "2.6.0" @@ -1472,6 +2460,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "utf16_lit" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14706d2a800ee8ff38c1d3edb873cd616971ea59eb7c0d046bb44ef59b06a1ae" + [[package]] name = "utf8parse" version = "0.2.0" @@ -1484,6 +2478,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + [[package]] name = "version_check" version = "0.9.4" @@ -1496,6 +2496,70 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "web-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1584,6 +2648,21 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] + +[[package]] +name = "xi-unicode" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" + [[package]] name = "zip" version = "0.6.3" diff --git a/crates/dtmm/Cargo.toml b/crates/dtmm/Cargo.toml new file mode 100644 index 0000000..64361c4 --- /dev/null +++ b/crates/dtmm/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "dtmm" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.0.15", features = ["color", "derive", "std", "cargo", "unicode"] } +color-eyre = "0.6.2" +confy = "0.5.1" +druid = { git = "https://github.com/linebender/druid.git", features = ["im"] } +sdk = { path = "../../lib/sdk", version = "0.2.0" } +serde = "1.0.152" +tokio = "1.23.0" +toml = "0.5.10" +tracing = "0.1.37" +tracing-error = "0.2.0" +tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } diff --git a/crates/dtmm/notes.adoc b/crates/dtmm/notes.adoc new file mode 100644 index 0000000..bbf29e7 --- /dev/null +++ b/crates/dtmm/notes.adoc @@ -0,0 +1,49 @@ += Notes + +== Layout + +- top bar: + - left aligned: a tab bar with "mods", "settings", "about" + - right aligned: a button to start the game + - in the future: center aligned a dropdown to select profiles, and button to edit them +- main view: + - left side: list view of mods + - right side: details pane and buttons + - always visible, first mod in list is selected by default + - buttons: + - add mod + - deploy mods + - remove selected mod + - enable/disable (text changes based on state) + +== Mod list + +- name +- description? +- image? +- click to get details pane? + +== Managing mods + +- for each mod in the list, have a checkbox +- need a button to remove mods +- need a button to add mods from downloaded files +- search + +== Misc + +- settings +- open mod storage + +== Managing the game + +- deploy mods +- + +== Preparing the game + +- click "Install mods" to prepare the game files with the enabled mods + +== Playing the game + +- if overlay file systems are used, the game has to be started through the mod manager diff --git a/crates/dtmm/src/main.rs b/crates/dtmm/src/main.rs new file mode 100644 index 0000000..d73b440 --- /dev/null +++ b/crates/dtmm/src/main.rs @@ -0,0 +1,42 @@ +use clap::command; +use color_eyre::Report; +use color_eyre::Result; +use druid::AppLauncher; +use tracing_error::ErrorLayer; +use tracing_subscriber::prelude::*; +use tracing_subscriber::EnvFilter; + +use crate::state::State; + +mod main_window; +mod state; +mod theme; +mod widget; + +#[tracing::instrument] +#[tokio::main] +async fn main() -> Result<()> { + color_eyre::install()?; + + let _matches = command!().get_matches(); + + { + let fmt_layer = tracing_subscriber::fmt::layer().pretty(); + let filter_layer = + EnvFilter::try_from_default_env().or_else(|_| EnvFilter::try_new("info"))?; + + tracing_subscriber::registry() + .with(filter_layer) + .with(fmt_layer) + .with(ErrorLayer::new( + tracing_subscriber::fmt::format::Pretty::default(), + )) + .init(); + } + + let initial_state = State::new(); + + AppLauncher::with_window(main_window::new()) + .launch(initial_state) + .map_err(Report::new) +} diff --git a/crates/dtmm/src/main_window.rs b/crates/dtmm/src/main_window.rs new file mode 100644 index 0000000..a8b1e71 --- /dev/null +++ b/crates/dtmm/src/main_window.rs @@ -0,0 +1,237 @@ +use druid::im::Vector; +use druid::widget::{ + Align, Button, CrossAxisAlignment, Flex, Label, List, MainAxisAlignment, Maybe, Scroll, Split, + ViewSwitcher, +}; +use druid::{lens, Insets, LensExt, Widget, WidgetExt, WindowDesc}; + +use crate::state::{ModInfo, State, View}; +use crate::theme; +use crate::widget::ExtraWidgetExt; + +const TITLE: &str = "Darktide Mod Manager"; +const WINDOW_WIDTH: f64 = 800.0; +const WINDOW_HEIGHT: f64 = 600.0; +const MOD_DETAILS_MIN_WIDTH: f64 = 325.0; + +pub(crate) fn new() -> WindowDesc { + WindowDesc::new(build_window()) + .title(TITLE) + .window_size((WINDOW_WIDTH, WINDOW_HEIGHT)) +} + +fn build_top_bar() -> impl Widget { + Flex::row() + .must_fill_main_axis(true) + .main_axis_alignment(MainAxisAlignment::SpaceBetween) + .with_child( + Flex::row() + .with_child( + Button::new("Mods").on_click(|_ctx, state: &mut State, _env| { + state.set_current_view(View::Mods) + }), + ) + .with_default_spacer() + .with_child( + Button::new("Settings").on_click(|_ctx, state: &mut State, _env| { + state.set_current_view(View::Settings) + }), + ) + .with_default_spacer() + .with_child( + Button::new("About").on_click(|_ctx, state: &mut State, _env| { + state.set_current_view(View::About) + }), + ), + ) + .with_child( + Flex::row() + .with_child(Button::new("Deploy Mods").on_click( + |_ctx, _state: &mut State, _env| { + todo!(); + }, + )) + .with_default_spacer() + .with_child( + Button::new("Run Game").on_click(|_ctx, _state: &mut State, _env| { + todo!(); + }), + ), + ) + .padding(theme::TOP_BAR_INSETS) + .background(theme::TOP_BAR_BACKGROUND_COLOR) + // TODO: Add bottom border. Need a custom widget for that, as the built-in only provides + // uniform borders on all sides +} + +fn build_mod_list() -> impl Widget { + let list = List::new(|| { + Flex::row() + .must_fill_main_axis(true) + // .with_child( + // Label::dynamic(|enabled, _env| { + // if *enabled { + // "Enabled".into() + // } else { + // "Disabled".into() + // } + // }) + // .lens( + // lens::Identity + // .map( + // |(i, info)| info, + // |(i, info), new_info| { + // todo!(); + // }, + // ) + // .then(ModInfo::enabled), + // ), + // ) + // .with_child(Label::raw().lens(ModInfo::name)) + .on_click(|_ctx, state, _env| { + todo!(); + }) + }); + + Scroll::new(list) + .vertical() + .lens(State::mods.map( + |mods| { + mods.iter() + .enumerate() + .map(|(i, val)| (i, val.clone())) + .collect::>() + }, + |mods, infos| { + infos.into_iter().for_each(|(i, info)| { + mods.set(i, info); + }); + }, + )) + .content_must_fill() +} + +fn build_mod_details() -> impl Widget { + let details_container = Maybe::new( + || { + Flex::column() + .cross_axis_alignment(CrossAxisAlignment::Start) + .with_child(Label::raw().lens(ModInfo::name)) + .with_flex_child(Label::raw().lens(ModInfo::description), 1.0) + }, + Flex::column, + ) + .lens(State::selected_mod); + + let button_move_up = Button::new("Move Up") + .on_click(|_ctx, index: &mut Option, _env| { + if let Some(i) = index.as_mut() { + *i = i.saturating_sub(1) + } + }) + .lens(State::selected_mod_index); + + let button_move_down = Button::new("Move Down") + .on_click(|_ctx, index: &mut Option, _env| { + if let Some(i) = index.as_mut() { + *i = i.saturating_add(1) + } + }) + .lens(State::selected_mod_index); + + let button_toggle_mod = Maybe::new( + || { + Button::dynamic(|enabled, _env| { + if *enabled { + "Disable Mod".into() + } else { + "Enabled Mod".into() + } + }) + .on_click(|_ctx, info: &mut bool, _env| { + *info = !*info; + }) + .lens(ModInfo::enabled) + }, + // TODO: Gray out + || Button::new("Enable Mod"), + ) + .lens(State::selected_mod); + + let button_add_mod = Button::new("Add Mod").on_click(|_ctx, state: &mut State, _env| { + // TODO: Implement properly + let info = ModInfo::new(); + state.add_mod(info); + }); + + let button_delete_mod = Button::new("Delete Mod") + .on_click(|_ctx, data: &mut State, _env| data.delete_selected_mod()); + + let buttons = Flex::column() + .with_child( + Flex::row() + .main_axis_alignment(MainAxisAlignment::End) + .with_child(button_move_up) + .with_default_spacer() + .with_child(button_move_down) + .padding(Insets::uniform_xy(5.0, 2.0)), + ) + .with_child( + Flex::row() + .main_axis_alignment(MainAxisAlignment::End) + .with_child(button_toggle_mod) + .with_default_spacer() + .with_child(button_add_mod) + .with_default_spacer() + .with_child(button_delete_mod) + .padding(Insets::uniform_xy(5.0, 2.0)), + ) + .with_default_spacer(); + + Flex::column() + .must_fill_main_axis(true) + .main_axis_alignment(MainAxisAlignment::SpaceBetween) + .with_flex_child(details_container, 1.0) + .with_child(buttons) +} + +fn build_view_mods() -> impl Widget { + Split::columns(build_mod_list(), build_mod_details()) + .split_point(0.75) + .min_size(0.0, MOD_DETAILS_MIN_WIDTH) + .solid_bar(true) + .bar_size(2.0) + .draggable(true) +} + +fn build_view_settings() -> impl Widget { + Label::new("Settings") +} + +fn build_view_about() -> impl Widget { + Align::centered( + Flex::column() + .with_child(Label::new("Darktide Mod Manager")) + .with_child(Label::new( + "Website: https://git.sclu1034.dev/bitsquid_dt/dtmt", + )), + ) +} + +fn build_main() -> impl Widget { + ViewSwitcher::new( + |state: &State, _env| state.get_current_view(), + |selector, _state, _env| match selector { + View::Mods => Box::new(build_view_mods()), + View::Settings => Box::new(build_view_settings()), + View::About => Box::new(build_view_about()), + }, + ) +} + +fn build_window() -> impl Widget { + Flex::column() + .must_fill_main_axis(true) + .with_child(build_top_bar()) + .with_flex_child(build_main(), 1.0) +} diff --git a/crates/dtmm/src/state.rs b/crates/dtmm/src/state.rs new file mode 100644 index 0000000..0639818 --- /dev/null +++ b/crates/dtmm/src/state.rs @@ -0,0 +1,119 @@ +use std::sync::Arc; + +use druid::im::Vector; +use druid::{Data, Lens}; + +#[derive(Copy, Clone, Data, PartialEq)] +pub(crate) enum View { + Mods, + Settings, + About, +} + +impl Default for View { + fn default() -> Self { + Self::Mods + } +} + +#[derive(Clone, Data, Lens)] +pub(crate) struct ModInfo { + name: String, + description: Arc, + enabled: bool, +} +impl ModInfo { + pub fn new() -> Self { + Self { + name: format!("Test Mod: {:?}", std::time::SystemTime::now()), + description: Arc::new(String::from("A test dummy")), + enabled: false, + } + } +} + +impl PartialEq for ModInfo { + fn eq(&self, other: &Self) -> bool { + self.name.eq(&other.name) + } +} + +#[derive(Clone, Data, Default, Lens)] +pub(crate) struct State { + current_view: View, + mods: Vector, + selected_mod_index: Option, +} + +pub(crate) struct SelectedModLens; + +impl Lens> for SelectedModLens { + fn with) -> V>(&self, data: &State, f: F) -> V { + let info = data + .selected_mod_index + .and_then(|i| data.mods.get(i).cloned()); + + f(&info) + } + + fn with_mut) -> V>(&self, data: &mut State, f: F) -> V { + let mut info = data + .selected_mod_index + .and_then(|i| data.mods.get_mut(i).cloned()); + f(&mut info) + } +} + +/// A Lens that maps an `im::Vector` to `im::Vector<(usize, T)>`, +/// where each element in the destination vector includes its index in the +/// source vector. +pub(crate) struct IndexedVectorLens; + +impl Lens, Vector<(usize, T)>> for IndexedVectorLens { + fn with) -> V>(&self, data: &Vector, f: F) -> V { + let data = data + .iter() + .enumerate() + .map(|(i, val)| (i, val.clone())) + .collect(); + f(&data) + } + + fn with_mut) -> V>( + &self, + data: &mut Vector, + f: F, + ) -> V { + todo!() + } +} + +impl State { + #[allow(non_upper_case_globals)] + pub const selected_mod: SelectedModLens = SelectedModLens; + + pub fn new() -> Self { + Default::default() + } + + pub fn get_current_view(&self) -> View { + self.current_view + } + + pub fn set_current_view(&mut self, view: View) { + self.current_view = view; + } + + pub fn delete_selected_mod(&mut self) { + let Some(index) = self.selected_mod_index else { + return; + }; + + self.mods.remove(index); + } + + pub fn add_mod(&mut self, info: ModInfo) { + self.mods.push_back(info); + self.selected_mod_index = Some(self.mods.len() - 1); + } +} diff --git a/crates/dtmm/src/theme.rs b/crates/dtmm/src/theme.rs new file mode 100644 index 0000000..7658f3f --- /dev/null +++ b/crates/dtmm/src/theme.rs @@ -0,0 +1,4 @@ +use druid::{Color, Insets}; + +pub const TOP_BAR_BACKGROUND_COLOR: Color = Color::rgba8(255, 255, 255, 50); +pub const TOP_BAR_INSETS: Insets = Insets::uniform(5.0); diff --git a/crates/dtmm/src/widget/container.rs b/crates/dtmm/src/widget/container.rs new file mode 100644 index 0000000..e58e64c --- /dev/null +++ b/crates/dtmm/src/widget/container.rs @@ -0,0 +1,7 @@ +use druid::{Data, Widget, WidgetPod}; + +pub struct Container { + child: WidgetPod>>, +} + +impl Container {} diff --git a/crates/dtmm/src/widget/fill_container.rs b/crates/dtmm/src/widget/fill_container.rs new file mode 100644 index 0000000..540715e --- /dev/null +++ b/crates/dtmm/src/widget/fill_container.rs @@ -0,0 +1,63 @@ +use std::f64::INFINITY; + +use druid::widget::prelude::*; +use druid::{Point, WidgetPod}; + +pub struct FillContainer { + child: WidgetPod>>, +} + +impl FillContainer { + pub fn new(child: impl Widget + 'static) -> Self { + Self { + child: WidgetPod::new(child).boxed(), + } + } +} + +impl Widget for FillContainer { + #[tracing::instrument(name = "FillContainer", level = "trace", skip_all)] + fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) { + self.child.event(ctx, event, data, env); + } + + #[tracing::instrument(name = "FillContainer", level = "trace", skip_all)] + fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) { + self.child.lifecycle(ctx, event, data, env) + } + + #[tracing::instrument(name = "FillContainer", level = "trace", skip_all)] + fn update(&mut self, ctx: &mut UpdateCtx, _: &T, data: &T, env: &Env) { + self.child.update(ctx, data, env); + } + + #[tracing::instrument(name = "FillContainer", level = "trace", skip_all)] + fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, data: &T, env: &Env) -> Size { + bc.debug_check("FillContainer"); + + let child_size = self.child.layout(ctx, bc, data, env); + + let w = if bc.is_width_bounded() { + INFINITY + } else { + child_size.width + }; + + let h = if bc.is_height_bounded() { + INFINITY + } else { + child_size.height + }; + + let my_size = bc.constrain(Size::new(w, h)); + + self.child.set_origin(ctx, Point::new(0.0, 0.0)); + tracing::trace!("Computed layout: size={}", my_size); + my_size + } + + #[tracing::instrument(name = "FillContainer", level = "trace", skip_all)] + fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) { + self.child.paint(ctx, data, env); + } +} diff --git a/crates/dtmm/src/widget/mod.rs b/crates/dtmm/src/widget/mod.rs new file mode 100644 index 0000000..9262d0a --- /dev/null +++ b/crates/dtmm/src/widget/mod.rs @@ -0,0 +1,14 @@ +use druid::{Data, Widget}; + +use self::fill_container::FillContainer; + +pub mod container; +pub mod fill_container; + +pub trait ExtraWidgetExt: Widget + Sized + 'static { + fn content_must_fill(self) -> FillContainer { + FillContainer::new(self) + } +} + +impl + 'static> ExtraWidgetExt for W {}