Switcher unmounts in all windows

Fixes #139
This commit is contained in:
Jonathan Johnson 2024-08-28 08:49:26 -07:00
parent 53d3c58cbb
commit 0dd18826c9
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
6 changed files with 197 additions and 103 deletions

View file

@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
animating the transition. The previous behavior caused nested collapsed animating the transition. The previous behavior caused nested collapsed
widgets to grow and shrink in an accordian-like fashion rather than animating widgets to grow and shrink in an accordian-like fashion rather than animating
together. together.
- `Switcher` now unmounts child widgets in all windows it is mounted in. Fixes
[#139][139].
### Added ### Added
@ -35,6 +37,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `MakeWidget::to_checkbox()` - `MakeWidget::to_checkbox()`
- `WidgetInstance::to_window()` - `WidgetInstance::to_window()`
[139]: https://github.com/khonsulabs/cushy/issues/139
## v0.4.0 (2024-08-20) ## v0.4.0 (2024-08-20)
### Breaking Changes ### Breaking Changes

166
Cargo.lock generated
View file

@ -123,9 +123,9 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]] [[package]]
name = "appit" name = "appit"
version = "0.3.1" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6869c02a8fdc42d78e60388824dbd5e331f763a7e1b8530eff4ea5c56df3438" checksum = "7a158c9d2660ce603c741d513b44cdd97a4553e0749d4e49e45b9480fc72c162"
dependencies = [ dependencies = [
"winit", "winit",
] ]
@ -171,7 +171,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -209,32 +209,32 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]] [[package]]
name = "attribute-derive" name = "attribute-derive"
version = "0.10.0" version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f6763469f78790650fe2b25ea8c2947b1bf5889b7be7833e23f383437fa8fc5" checksum = "36f18fc482cf559bca9efe778ba2fd0d1c16a31d5d24a2c886ed16b2d217e454"
dependencies = [ dependencies = [
"attribute-derive-macro", "attribute-derive-macro",
"derive-where", "derive-where",
"manyhow", "manyhow",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
name = "attribute-derive-macro" name = "attribute-derive-macro"
version = "0.10.0" version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1318b422e4ad618775982a521842870d74ab4e07cf7588a968bc6d68c62a4ff" checksum = "a85958950e587256a16c72325ff3c4f3e4db25999173e9ca2864665be84ff63b"
dependencies = [ dependencies = [
"collection_literals", "collection_literals",
"interpolator", "interpolator",
"manyhow", "manyhow",
"proc-macro-utils 0.10.0", "proc-macro-utils",
"proc-macro2", "proc-macro2",
"quote", "quote",
"quote-use", "quote-use",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -316,9 +316,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]] [[package]]
name = "bitstream-io" name = "bitstream-io"
version = "2.5.1" version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "586ebf43072a4f103bc979b12dc36bc82bed5c2a340e16344e1253d53263c3fa" checksum = "b81e1519b0d82120d2fd469d5bfb2919a9361c48b02d82d04befc1cdd2002452"
[[package]] [[package]]
name = "block" name = "block"
@ -355,9 +355,9 @@ checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.17.0" version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fd4c6dcc3b0aea2f5c0b4b82c2b15fe39ddbc76041a310848f4706edf76bb31" checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2"
dependencies = [ dependencies = [
"bytemuck_derive", "bytemuck_derive",
] ]
@ -370,7 +370,7 @@ checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -419,9 +419,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.1.13" version = "1.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6"
dependencies = [ dependencies = [
"jobserver", "jobserver",
"libc", "libc",
@ -704,7 +704,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"quote-use", "quote-use",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -726,7 +726,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -817,9 +817,9 @@ dependencies = [
[[package]] [[package]]
name = "euclid" name = "euclid"
version = "0.22.10" version = "0.22.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f0eb73b934648cd7a4a61f1b15391cd95dab0b4da6e2e66c2a072c144b4a20" checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48"
dependencies = [ dependencies = [
"num-traits", "num-traits",
] ]
@ -870,9 +870,9 @@ dependencies = [
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.32" version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666" checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"miniz_oxide 0.8.0", "miniz_oxide 0.8.0",
@ -943,7 +943,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -1214,7 +1214,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -1476,23 +1476,23 @@ dependencies = [
[[package]] [[package]]
name = "manyhow" name = "manyhow"
version = "0.11.3" version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5b8ea82a2287fe7b26aea89c0c02957886d7e97eabffc1f9d2031feaa6f82e6" checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587"
dependencies = [ dependencies = [
"manyhow-macros", "manyhow-macros",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
name = "manyhow-macros" name = "manyhow-macros"
version = "0.11.3" version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae36e8d9b4095531e43de72ed424f0f4a98cba40f7e5a99366f9818769489272" checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495"
dependencies = [ dependencies = [
"proc-macro-utils 0.8.0", "proc-macro-utils",
"proc-macro2", "proc-macro2",
"quote", "quote",
] ]
@ -1686,7 +1686,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -1737,7 +1737,7 @@ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -2012,7 +2012,7 @@ dependencies = [
"by_address", "by_address",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -2080,7 +2080,7 @@ dependencies = [
"phf_shared", "phf_shared",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -2109,7 +2109,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -2193,32 +2193,21 @@ checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
[[package]] [[package]]
name = "prettyplease" name = "prettyplease"
version = "0.2.20" version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "3.1.0" version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
dependencies = [ dependencies = [
"toml_edit 0.21.1", "toml_edit",
]
[[package]]
name = "proc-macro-utils"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f59e109e2f795a5070e69578c4dc101068139f74616778025ae1011d4cd41a8"
dependencies = [
"proc-macro2",
"quote",
"smallvec",
] ]
[[package]] [[package]]
@ -2257,7 +2246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -2286,18 +2275,18 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.36" version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]] [[package]]
name = "quote-use" name = "quote-use"
version = "0.8.3" 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 = "48e96ac59974192a2fa6ee55a41211cf1385c5b2a8636a4c3068b3b3dd599ece" checksum = "9619db1197b497a36178cfc736dc96b271fe918875fbf1344c436a7e93d0321e"
dependencies = [ dependencies = [
"quote", "quote",
"quote-use-macros", "quote-use-macros",
@ -2305,15 +2294,14 @@ dependencies = [
[[package]] [[package]]
name = "quote-use-macros" name = "quote-use-macros"
version = "0.8.3" 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 = "b4c57308e9dde4d7be9af804f6deeaa9951e1de1d5ffce6142eb964750109f7e" checksum = "82ebfb7faafadc06a7ab141a6f67bcfb24cb8beb158c6fe933f2f035afa99f35"
dependencies = [ dependencies = [
"derive-where", "proc-macro-utils",
"proc-macro-utils 0.8.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -2540,9 +2528,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.34" version = "0.38.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.6.0",
"errno", "errno",
@ -2610,22 +2598,22 @@ checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.208" version = "1.0.209"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.208" version = "1.0.209"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -2807,9 +2795,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.75" version = "2.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2870,7 +2858,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -2953,7 +2941,7 @@ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"toml_edit 0.22.20", "toml_edit",
] ]
[[package]] [[package]]
@ -2965,17 +2953,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "toml_edit"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
dependencies = [
"indexmap",
"toml_datetime",
"winnow 0.5.40",
]
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.22.20" version = "0.22.20"
@ -2986,7 +2963,7 @@ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"winnow 0.6.18", "winnow",
] ]
[[package]] [[package]]
@ -3008,7 +2985,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]
@ -3195,7 +3172,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3229,7 +3206,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3803,15 +3780,6 @@ dependencies = [
"xkbcommon-dl", "xkbcommon-dl",
] ]
[[package]]
name = "winnow"
version = "0.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.18" version = "0.6.18"
@ -3914,7 +3882,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.75", "syn 2.0.76",
] ]
[[package]] [[package]]

View file

@ -0,0 +1,53 @@
//! Shows the ability to share widgets between multiple windows.
//!
//! This example was created to test a fix for
//! <https://github.com/khonsulabs/cushy/issues/139>. The issue was that if the
//! same Switcher widget was shown on two separate windows, only one window
//! would unmount the existing widget.
//!
//! When running this example after the bug has been fixed, unmounted messages
//! should be printed twice: once per each window.
use cushy::value::{Dynamic, Switchable};
use cushy::widget::MakeWidget;
use cushy::widgets::Custom;
use cushy::{Open, PendingApp, Run};
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
enum Contents {
A,
B,
}
fn main() -> cushy::Result {
let mut app = PendingApp::default();
let selected = Dynamic::new(Contents::A);
// Open up another window containing our controls
selected
.new_radio(Contents::A, "A")
.and(selected.new_radio(Contents::B, "B"))
.into_rows()
.open(&mut app)?;
let display = selected
.switcher(|contents, _| match contents {
Contents::A => Custom::new("A")
.on_unmounted(|_| {
println!("A unmounted");
})
.make_widget(),
Contents::B => Custom::new("B")
.on_unmounted(|_| {
println!("B unmounted");
})
.make_widget(),
})
.make_widget();
// Open two windows with the same switcher instance
display.to_window().open(&mut app)?;
display.to_window().open(&mut app)?;
app.run()
}

View file

@ -2499,6 +2499,12 @@ impl WidgetRef {
} }
} }
impl From<WidgetRef> for WindowLocal<MountedWidget> {
fn from(value: WidgetRef) -> Self {
value.mounted
}
}
impl AsRef<WidgetId> for WidgetRef { impl AsRef<WidgetId> for WidgetRef {
fn as_ref(&self) -> &WidgetId { fn as_ref(&self) -> &WidgetId {
self.instance.as_ref() self.instance.as_ref()

View file

@ -1,10 +1,14 @@
use std::fmt::Debug; use std::fmt::Debug;
use std::mem;
use ahash::HashMap;
use figures::Size; use figures::Size;
use kludgine::KludgineId;
use crate::context::LayoutContext; use crate::context::{AsEventContext, LayoutContext};
use crate::value::{Dynamic, DynamicReader, IntoDynamic, IntoReader, Source}; use crate::value::{Dynamic, DynamicReader, IntoDynamic, IntoReader, Source};
use crate::widget::{WidgetInstance, WidgetRef, WrapperWidget}; use crate::widget::{MountedWidget, WidgetInstance, WidgetRef, WrapperWidget};
use crate::window::WindowLocal;
use crate::ConstraintLimit; use crate::ConstraintLimit;
/// A widget that switches its contents based on a value of `T`. /// A widget that switches its contents based on a value of `T`.
@ -12,6 +16,7 @@ use crate::ConstraintLimit;
pub struct Switcher { pub struct Switcher {
source: DynamicReader<WidgetInstance>, source: DynamicReader<WidgetInstance>,
child: WidgetRef, child: WidgetRef,
pending_unmount: HashMap<KludgineId, MountedWidget>,
} }
impl Switcher { impl Switcher {
@ -39,7 +44,11 @@ impl Switcher {
pub fn new(source: impl IntoReader<WidgetInstance>) -> Self { pub fn new(source: impl IntoReader<WidgetInstance>) -> Self {
let source = source.into_reader(); let source = source.into_reader();
let child = WidgetRef::new(source.get()); let child = WidgetRef::new(source.get());
Self { source, child } Self {
source,
child,
pending_unmount: HashMap::default(),
}
} }
} }
@ -54,12 +63,32 @@ impl WrapperWidget for Switcher {
available_space: Size<ConstraintLimit>, available_space: Size<ConstraintLimit>,
context: &mut LayoutContext<'_, '_, '_, '_>, context: &mut LayoutContext<'_, '_, '_, '_>,
) -> Size<ConstraintLimit> { ) -> Size<ConstraintLimit> {
if let Some(pending_unmount) = self.pending_unmount.remove(&context.kludgine_id()) {
context.remove_child(&pending_unmount);
}
let current_source = self.source.get_tracking_invalidate(context); let current_source = self.source.get_tracking_invalidate(context);
if &current_source != self.child.widget() { if &current_source != self.child.widget() {
// immediately unmount in the current context.
self.child.unmount_in(context); self.child.unmount_in(context);
self.child = WidgetRef::new(current_source); let old_mounts = <WindowLocal<MountedWidget>>::from(mem::replace(
&mut self.child,
WidgetRef::new(current_source),
));
// For all other contexts, we have to wait until this callback to
// try unmounting.
for (id, mounted) in old_mounts {
let existing = self.pending_unmount.insert(id, mounted);
debug_assert!(
existing.is_none(),
"Existing unmount found, but should have already been unmounted"
);
}
} }
context.invalidate_when_changed(&self.source); context.invalidate_when_changed(&self.source);
available_space available_space
} }
} }

View file

@ -2439,10 +2439,26 @@ impl<T> WindowLocal<T> {
self.by_window.get(&context.kludgine_id()) self.by_window.get(&context.kludgine_id())
} }
/// Looks up an exclusive reference to the value for this window, returning
/// None if not found.
///
/// Internally this API uses [`HashMap::get`](hash_map::HashMap::get).
#[must_use]
pub fn get_mut(&mut self, context: &WidgetContext<'_>) -> Option<&mut T> {
self.by_window.get_mut(&context.kludgine_id())
}
/// Removes any stored value for this window. /// Removes any stored value for this window.
pub fn clear_for(&mut self, context: &WidgetContext<'_>) -> Option<T> { pub fn clear_for(&mut self, context: &WidgetContext<'_>) -> Option<T> {
self.by_window.remove(&context.kludgine_id()) self.by_window.remove(&context.kludgine_id())
} }
/// Returns an iterator over the per-window values stored in this
/// collection.
#[must_use]
pub fn iter(&self) -> hash_map::Iter<'_, KludgineId, T> {
self.into_iter()
}
} }
impl<T> Default for WindowLocal<T> { impl<T> Default for WindowLocal<T> {
@ -2453,6 +2469,24 @@ impl<T> Default for WindowLocal<T> {
} }
} }
impl<T> IntoIterator for WindowLocal<T> {
type IntoIter = hash_map::IntoIter<KludgineId, T>;
type Item = (KludgineId, T);
fn into_iter(self) -> Self::IntoIter {
self.by_window.into_iter()
}
}
impl<'a, T> IntoIterator for &'a WindowLocal<T> {
type IntoIter = hash_map::Iter<'a, KludgineId, T>;
type Item = (&'a KludgineId, &'a T);
fn into_iter(self) -> Self::IntoIter {
self.by_window.iter()
}
}
/// The state of a [`VirtualWindow`]. /// The state of a [`VirtualWindow`].
pub struct VirtualState { pub struct VirtualState {
/// State that may be updated outside of the window's event callbacks. /// State that may be updated outside of the window's event callbacks.