A game framework written with osu! in mind.

Merge branch 'hide-popover-on-target-disposal' into popover-handle-hover

+38 -16
+32
osu.Framework.Tests/Visual/UserInterface/TestScenePopoverContainer.cs
··· 413 413 } 414 414 415 415 [Test] 416 + public void TestPopoverCleanupOnTargetHide() 417 + { 418 + DrawableWithPopover target = null; 419 + 420 + AddStep("add button", () => popoverContainer.Child = target = new DrawableWithPopover 421 + { 422 + Width = 200, 423 + Height = 30, 424 + Anchor = Anchor.Centre, 425 + Origin = Anchor.Centre, 426 + Text = "open", 427 + CreateContent = _ => new BasicPopover 428 + { 429 + Child = new SpriteText 430 + { 431 + Text = "This popover should be cleaned up when its button is hidden", 432 + } 433 + } 434 + }); 435 + 436 + AddStep("click button", () => 437 + { 438 + InputManager.MoveMouseTo(target); 439 + InputManager.Click(MouseButton.Left); 440 + }); 441 + AddAssert("popover created", () => this.ChildrenOfType<Popover>().Any()); 442 + 443 + AddStep("hide button", () => target.Hide()); 444 + AddUntilStep("no popover present", () => !this.ChildrenOfType<Popover>().Any()); 445 + } 446 + 447 + [Test] 416 448 public void TestPopoverEventHandling() 417 449 { 418 450 EventHandlingContainer eventHandlingContainer = null;
+6 -16
osu.Framework/Graphics/Cursor/PopoverContainer.cs
··· 53 53 currentPopover?.Hide(); 54 54 currentPopover?.Expire(); 55 55 56 - if (target is Drawable oldDrawableTarget) 57 - oldDrawableTarget.OnDispose -= onTargetDisposed; 58 - 59 56 target = newTarget; 60 57 61 58 var newPopover = target?.GetPopover(); 62 59 if (newPopover == null) 63 60 return false; 64 61 65 - if (target is Drawable newDrawableTarget) 66 - newDrawableTarget.OnDispose += onTargetDisposed; 67 - 68 62 dismissOnMouseDownContainer.Add(currentPopover = newPopover); 69 63 currentPopover.Show(); 70 64 return true; 71 65 } 72 66 73 - private void onTargetDisposed() => Schedule(() => SetTarget(null)); 74 - 75 67 protected override void UpdateAfterChildren() 76 68 { 77 69 base.UpdateAfterChildren(); 70 + 71 + if ((target as Drawable)?.FindClosestParent<PopoverContainer>() != this || target?.IsPresent != true) 72 + { 73 + SetTarget(null); 74 + return; 75 + } 78 76 79 77 updatePopoverPositioning(); 80 78 } ··· 195 193 196 194 // the final size is the intersection of the X/Y areas. 197 195 return availableSize; 198 - } 199 - 200 - protected override void Dispose(bool isDisposing) 201 - { 202 - base.Dispose(isDisposing); 203 - 204 - if (target is Drawable drawableTarget) 205 - drawableTarget.OnDispose -= onTargetDisposed; 206 196 } 207 197 208 198 private class DismissOnMouseDownContainer : Container