A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using osu.Framework.Bindables;
5
6namespace osu.Framework.Graphics.Containers
7{
8 /// <summary>
9 /// A container which adds a basic visibility state.
10 /// </summary>
11 public abstract class VisibilityContainer : Container
12 {
13 /// <summary>
14 /// The current visibility state.
15 /// </summary>
16 public readonly Bindable<Visibility> State = new Bindable<Visibility>();
17
18 private bool didInitialHide;
19
20 /// <summary>
21 /// Whether we should be in a hidden state when first displayed.
22 /// Override this and set to true to *always* perform a <see cref="PopIn"/> animation even when the state is non-hidden at
23 /// first display.
24 /// </summary>
25 protected virtual bool StartHidden => State.Value == Visibility.Hidden;
26
27 protected override void LoadAsyncComplete()
28 {
29 base.LoadAsyncComplete();
30
31 if (StartHidden)
32 {
33 // do this without triggering the StateChanged event, since hidden is a default.
34 PopOut();
35 FinishTransforms(true);
36 didInitialHide = true;
37 }
38 }
39
40 protected override void LoadComplete()
41 {
42 State.BindValueChanged(UpdateState, State.Value == Visibility.Visible || !didInitialHide);
43
44 base.LoadComplete();
45 }
46
47 /// <summary>
48 /// Show this container by setting its visibility to <see cref="Visibility.Visible"/>.
49 /// </summary>
50 public override void Show() => State.Value = Visibility.Visible;
51
52 /// <summary>
53 /// Hide this container by setting its visibility to <see cref="Visibility.Hidden"/>.
54 /// </summary>
55 public override void Hide() => State.Value = Visibility.Hidden;
56
57 /// <summary>
58 /// Toggle this container's visibility.
59 /// </summary>
60 public void ToggleVisibility() => State.Value = State.Value == Visibility.Visible ? Visibility.Hidden : Visibility.Visible;
61
62 public override bool PropagateNonPositionalInputSubTree => base.PropagateNonPositionalInputSubTree && State.Value == Visibility.Visible;
63 public override bool PropagatePositionalInputSubTree => base.PropagatePositionalInputSubTree && State.Value == Visibility.Visible;
64
65 /// <summary>
66 /// Implement any transition to be played when <see cref="State"/> becomes <see cref="Visibility.Visible"/>.
67 /// </summary>
68 protected abstract void PopIn();
69
70 /// <summary>
71 /// Implement any transition to be played when <see cref="State"/> becomes <see cref="Visibility.Hidden"/>.
72 /// Will be invoked once on <see cref="LoadComplete"/> if <see cref="StartHidden"/> is set.
73 /// </summary>
74 protected abstract void PopOut();
75
76 /// <summary>
77 /// Called whenever <see cref="VisibilityContainer.State"/> is changed.
78 /// Used to update this container's elements according to the new visibility state.
79 /// </summary>
80 /// <param name="state">The <see cref="ValueChangedEvent{T}"/> provided by <see cref="VisibilityContainer.State"/></param>
81 protected virtual void UpdateState(ValueChangedEvent<Visibility> state)
82 {
83 switch (state.NewValue)
84 {
85 case Visibility.Hidden:
86 PopOut();
87 break;
88
89 case Visibility.Visible:
90 PopIn();
91 break;
92 }
93 }
94 }
95
96 public enum Visibility
97 {
98 Hidden,
99 Visible
100 }
101}