From 9bc1f3f014178f19c5c174ba60bcff8d617762d7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 6 Mar 2022 23:34:12 +0300 Subject: [PATCH] Further refactor and simplify `ChannelScrollContainer` --- .../Online/TestSceneStandAloneChatDisplay.cs | 3 +- .../Overlays/Chat/ChannelScrollContainer.cs | 78 +++++++++++++++++++ osu.Game/Overlays/Chat/DrawableChannel.cs | 50 ------------ 3 files changed, 79 insertions(+), 52 deletions(-) create mode 100644 osu.Game/Overlays/Chat/ChannelScrollContainer.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index 9b9ee0e084..a21647712d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -9,7 +9,6 @@ using System; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Chat; using osuTK.Input; @@ -337,7 +336,7 @@ namespace osu.Game.Tests.Visual.Online public DrawableChannel DrawableChannel => InternalChildren.OfType().First(); - public UserTrackingScrollContainer ScrollContainer => (UserTrackingScrollContainer)((Container)DrawableChannel.Child).Child; + public ChannelScrollContainer ScrollContainer => (ChannelScrollContainer)((Container)DrawableChannel.Child).Child; public FillFlowContainer FillFlow => (FillFlowContainer)ScrollContainer.Child; diff --git a/osu.Game/Overlays/Chat/ChannelScrollContainer.cs b/osu.Game/Overlays/Chat/ChannelScrollContainer.cs new file mode 100644 index 0000000000..23bc683661 --- /dev/null +++ b/osu.Game/Overlays/Chat/ChannelScrollContainer.cs @@ -0,0 +1,78 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Utils; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Overlays.Chat +{ + /// + /// An with functionality to automatically scroll whenever the maximum scrollable distance increases. + /// + public class ChannelScrollContainer : OsuScrollContainer + { + /// + /// The chat will be automatically scrolled to end if and only if + /// the distance between the current scroll position and the end of the scroll + /// is less than this value. + /// + private const float auto_scroll_leniency = 10f; + + private bool trackNewContent = true; + + protected override void Update() + { + base.Update(); + + // If our behaviour hasn't been overriden and there has been new content added to the container, we should update our scroll position to track it. + bool requiresScrollUpdate = trackNewContent && !IsScrolledToEnd(); + + if (requiresScrollUpdate) + { + // Schedule required to allow FillFlow to be the correct size. + Schedule(() => + { + if (trackNewContent) + { + if (Current < ScrollableExtent) + ScrollToEnd(); + } + }); + } + } + + private void updateTrackState() => trackNewContent = IsScrolledToEnd(auto_scroll_leniency); + + // todo: we may eventually want this encapsulated in a "OnScrollChange" event handler method provided by ScrollContainer. + // important to note that this intentionally doesn't consider OffsetScrollPosition, but could make it do so with side changes. + + #region Scroll handling + + protected override void OnUserScroll(float value, bool animated = true, double? distanceDecay = null) + { + base.OnUserScroll(value, animated, distanceDecay); + updateTrackState(); + } + + public new void ScrollIntoView(Drawable d, bool animated = true) + { + base.ScrollIntoView(d, animated); + updateTrackState(); + } + + public new void ScrollToStart(bool animated = true, bool allowDuringDrag = false) + { + base.ScrollToStart(animated, allowDuringDrag); + updateTrackState(); + } + + public new void ScrollToEnd(bool animated = true, bool allowDuringDrag = false) + { + base.ScrollToEnd(animated, allowDuringDrag); + updateTrackState(); + } + + #endregion + } +} diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index ccad55b809..6220beeb82 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -11,9 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Utils; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; @@ -236,53 +234,5 @@ namespace osu.Game.Overlays.Chat }; } } - - /// - /// An with functionality to automatically scroll whenever the maximum scrollable distance increases. - /// - private class ChannelScrollContainer : UserTrackingScrollContainer - { - /// - /// The chat will be automatically scrolled to end if and only if - /// the distance between the current scroll position and the end of the scroll - /// is less than this value. - /// - private const float auto_scroll_leniency = 10f; - - private bool trackNewContent = true; - private float? lastExtent; - - protected override void OnScrollChange(bool byUser) - { - base.OnScrollChange(byUser); - - if (byUser) - lastExtent = null; - - trackNewContent = IsScrolledToEnd(auto_scroll_leniency); - } - - protected override void Update() - { - base.Update(); - - // If the user hasn't overridden our behaviour and there has been new content added to the container, we should update our scroll position to track it. - bool requiresScrollUpdate = trackNewContent && (lastExtent == null || Precision.AlmostBigger(ScrollableExtent, lastExtent.Value)); - - if (requiresScrollUpdate) - { - // Schedule required to allow FillFlow to be the correct size. - Schedule(() => - { - if (trackNewContent) - { - if (Current < ScrollableExtent) - ScrollToEnd(); - lastExtent = ScrollableExtent; - } - }); - } - } - } } }