diff --git a/osu.Android.props b/osu.Android.props index afc5d4ec52..78ceaa8616 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game.Tournament/Components/DateTextBox.cs b/osu.Game.Tournament/Components/DateTextBox.cs index aee5241e35..a1b5ac38ea 100644 --- a/osu.Game.Tournament/Components/DateTextBox.cs +++ b/osu.Game.Tournament/Components/DateTextBox.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tournament.Components { base.Bindable = new Bindable(); - ((OsuTextBox)Control).OnCommit = (sender, newText) => + ((OsuTextBox)Control).OnCommit += (sender, newText) => { try { diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index f8810c778f..8b0caddbc6 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -59,12 +59,13 @@ namespace osu.Game.Online.Chat RelativeSizeAxes = Axes.X, Height = textbox_height, PlaceholderText = "type your message", - OnCommit = postMessage, ReleaseFocusOnCommit = false, HoldFocus = true, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, }); + + textbox.OnCommit += postMessage; } Channel.BindValueChanged(channelChanged); diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index c53eccf78b..8bc7e21047 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -146,7 +146,6 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Height = 1, PlaceholderText = "type your message", - OnCommit = postMessage, ReleaseFocusOnCommit = false, HoldFocus = true, } @@ -186,6 +185,8 @@ namespace osu.Game.Overlays }, }; + textbox.OnCommit += postMessage; + ChannelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue; ChannelTabControl.ChannelSelectorActive.ValueChanged += active => ChannelSelectionOverlay.State.Value = active.NewValue ? Visibility.Visible : Visibility.Hidden; ChannelSelectionOverlay.State.ValueChanged += state => diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 050e687dfb..b8d04eab4e 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Music }, }; - filter.Search.OnCommit = (sender, newText) => + filter.Search.OnCommit += (sender, newText) => { BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 34e5da4ef4..f96e204f62 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -236,7 +236,6 @@ namespace osu.Game.Overlays.Settings.Sections.General PlaceholderText = "password", RelativeSizeAxes = Axes.X, TabbableContentContainer = this, - OnCommit = (sender, newText) => performLogin() }, new SettingsCheckbox { @@ -276,6 +275,8 @@ namespace osu.Game.Overlays.Settings.Sections.General } } }; + + password.OnCommit += (sender, newText) => performLogin(); } public override bool AcceptsFocus => true; diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index 58a7f97e5f..78766d9777 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -2,27 +2,23 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Edit.Timing { internal class DifficultySection : Section { - private SettingsSlider multiplier; + private SliderWithTextBoxInput multiplierSlider; [BackgroundDependencyLoader] private void load() { Flow.AddRange(new[] { - multiplier = new SettingsSlider + multiplierSlider = new SliderWithTextBoxInput("Speed Multiplier") { - LabelText = "Speed Multiplier", - Bindable = new DifficultyControlPoint().SpeedMultiplierBindable, - RelativeSizeAxes = Axes.X, + Current = new DifficultyControlPoint().SpeedMultiplierBindable } }); } @@ -31,7 +27,7 @@ namespace osu.Game.Screens.Edit.Timing { if (point.NewValue != null) { - multiplier.Bindable = point.NewValue.SpeedMultiplierBindable; + multiplierSlider.Current = point.NewValue.SpeedMultiplierBindable; } } diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index 4665c77991..de986e28ca 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -2,18 +2,17 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.UserInterfaceV2; -using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Edit.Timing { internal class SampleSection : Section { private LabelledTextBox bank; - private SettingsSlider volume; + private SliderWithTextBoxInput volume; [BackgroundDependencyLoader] private void load() @@ -24,10 +23,9 @@ namespace osu.Game.Screens.Edit.Timing { Label = "Bank Name", }, - volume = new SettingsSlider + volume = new SliderWithTextBoxInput("Volume") { - Bindable = new SampleControlPoint().SampleVolumeBindable, - LabelText = "Volume", + Current = new SampleControlPoint().SampleVolumeBindable, } }); } @@ -37,7 +35,7 @@ namespace osu.Game.Screens.Edit.Timing if (point.NewValue != null) { bank.Current = point.NewValue.SampleBankBindable; - volume.Bindable = point.NewValue.SampleVolumeBindable; + volume.Current = point.NewValue.SampleVolumeBindable; } } diff --git a/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs b/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs new file mode 100644 index 0000000000..14023b0c35 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs @@ -0,0 +1,77 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays.Settings; + +namespace osu.Game.Screens.Edit.Timing +{ + internal class SliderWithTextBoxInput : CompositeDrawable, IHasCurrentValue + where T : struct, IEquatable, IComparable, IConvertible + { + private readonly SettingsSlider slider; + + public SliderWithTextBoxInput(string labelText) + { + LabelledTextBox textbox; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChildren = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + textbox = new LabelledTextBox + { + Label = labelText, + }, + slider = new SettingsSlider + { + RelativeSizeAxes = Axes.X, + } + } + }, + }; + + textbox.OnCommit += (t, isNew) => + { + if (!isNew) return; + + try + { + slider.Bindable.Parse(t.Text); + } + catch + { + // TriggerChange below will restore the previous text value on failure. + } + + // This is run regardless of parsing success as the parsed number may not actually trigger a change + // due to bindable clamping. Even in such a case we want to update the textbox to a sane visual state. + Current.TriggerChange(); + }; + + Current.BindValueChanged(val => + { + textbox.Text = val.NewValue.ToString(); + }, true); + } + + public Bindable Current + { + get => slider.Bindable; + set => slider.Bindable = value; + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index cc79dd2acc..0202441537 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -65,18 +65,19 @@ namespace osu.Game.Screens.Edit.Timing { if (!isNew) return; - if (double.TryParse(Current.Value, out double doubleVal)) + try { - try - { + if (double.TryParse(Current.Value, out double doubleVal) && doubleVal > 0) beatLengthBindable.Value = beatLengthToBpm(doubleVal); - } - catch - { - // will restore the previous text value on failure. - beatLengthBindable.TriggerChange(); - } } + catch + { + // TriggerChange below will restore the previous text value on failure. + } + + // This is run regardless of parsing success as the parsed number may not actually trigger a change + // due to bindable clamping. Even in such a case we want to update the textbox to a sane visual state. + beatLengthBindable.TriggerChange(); }; beatLengthBindable.BindValueChanged(val => diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5fa1685d9b..3a839ac1a4 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,7 +24,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 60708a39e2..48c91f0d53 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -80,7 +80,7 @@ - +