diff --git a/PerformanceCalculatorGUI/Components/ExtendedProfileScore.cs b/PerformanceCalculatorGUI/Components/ExtendedProfileScore.cs index e8aacd4e2..795015ea6 100644 --- a/PerformanceCalculatorGUI/Components/ExtendedProfileScore.cs +++ b/PerformanceCalculatorGUI/Components/ExtendedProfileScore.cs @@ -80,7 +80,7 @@ public partial class ExtendedProfileScore : CompositeDrawable private const float performance_background_shear = 0.45f; - protected readonly ExtendedScore Score; + public readonly ExtendedScore Score; [Resolved] private OsuColour colours { get; set; } diff --git a/PerformanceCalculatorGUI/Components/ProfileSortCriteria.cs b/PerformanceCalculatorGUI/Components/ProfileSortCriteria.cs new file mode 100644 index 000000000..bd664a8ff --- /dev/null +++ b/PerformanceCalculatorGUI/Components/ProfileSortCriteria.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace PerformanceCalculatorGUI.Components +{ + public enum ProfileSortCriteria + { + Live, + Difference, + Local + } +} diff --git a/PerformanceCalculatorGUI/Screens/ProfileScreen.cs b/PerformanceCalculatorGUI/Screens/ProfileScreen.cs index e46a56381..d2e597936 100644 --- a/PerformanceCalculatorGUI/Screens/ProfileScreen.cs +++ b/PerformanceCalculatorGUI/Screens/ProfileScreen.cs @@ -11,6 +11,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterfaceV2; @@ -19,9 +20,11 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osuTK.Graphics; +using osuTK.Input; using PerformanceCalculatorGUI.Components; using PerformanceCalculatorGUI.Components.TextBoxes; using PerformanceCalculatorGUI.Configuration; +using ButtonState = PerformanceCalculatorGUI.Components.ButtonState; namespace PerformanceCalculatorGUI.Screens { @@ -35,7 +38,7 @@ public partial class ProfileScreen : PerformanceCalculatorScreen private GridContainer layout; - private FillFlowContainer scores; + private FillFlowContainer scores; private LabelledTextBox usernameTextBox; private Container userPanelContainer; @@ -45,6 +48,9 @@ public partial class ProfileScreen : PerformanceCalculatorScreen private CancellationTokenSource calculationCancellatonToken; + private OverlaySortTabControl sortingTabControl; + private readonly Bindable sorting = new Bindable(ProfileSortCriteria.Local); + [Resolved] private NotificationDisplay notificationDisplay { get; set; } @@ -78,7 +84,13 @@ private void load() { RelativeSizeAxes = Axes.Both, ColumnDimensions = new[] { new Dimension() }, - RowDimensions = new[] { new Dimension(GridSizeMode.Absolute, username_container_height), new Dimension(GridSizeMode.Absolute), new Dimension() }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, username_container_height), + new Dimension(GridSizeMode.Absolute), + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, Content = new[] { new Drawable[] @@ -128,11 +140,30 @@ private void load() } }, new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + sortingTabControl = new OverlaySortTabControl + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Margin = new MarginPadding { Right = 22 }, + Current = { BindTarget = sorting }, + Alpha = 0 + } + } + } + }, + new Drawable[] { new OsuScrollContainer(Direction.Vertical) { RelativeSizeAxes = Axes.Both, - Child = scores = new FillFlowContainer + Child = scores = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -149,6 +180,7 @@ private void load() }; usernameTextBox.OnCommit += (_, _) => { calculateProfile(usernameTextBox.Current.Value); }; + sorting.ValueChanged += e => { updateSorting(e.NewValue); }; if (RuntimeInfo.IsDesktop) HotReloadCallbackReceiver.CompilationFinished += _ => Schedule(() => { calculateProfile(currentUser); }); @@ -191,7 +223,16 @@ private void calculateProfile(string username) RelativeSizeAxes = Axes.X }); - layout.RowDimensions = new[] { new Dimension(GridSizeMode.Absolute, username_container_height), new Dimension(GridSizeMode.AutoSize), new Dimension() }; + sortingTabControl.Alpha = 1.0f; + sortingTabControl.Current.Value = ProfileSortCriteria.Local; + + layout.RowDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, username_container_height), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }; }); if (token.IsCancellationRequested) @@ -284,7 +325,7 @@ private void calculateProfile(string username) loadingLayer.Hide(); calculationButton.State.Value = ButtonState.Done; }); - }, token); + }, TaskContinuationOptions.None); } protected override void Dispose(bool isDisposing) @@ -295,5 +336,46 @@ protected override void Dispose(bool isDisposing) calculationCancellatonToken?.Dispose(); calculationCancellatonToken = null; } + + protected override bool OnKeyDown(KeyDownEvent e) + { + if (e.Key == Key.Escape && !calculationCancellatonToken.IsCancellationRequested) + { + calculationCancellatonToken?.Cancel(); + } + + return base.OnKeyDown(e); + } + + private void updateSorting(ProfileSortCriteria sortCriteria) + { + if (!scores.Children.Any()) + return; + + ExtendedProfileScore[] sortedScores; + + switch (sortCriteria) + { + case ProfileSortCriteria.Live: + sortedScores = scores.Children.OrderByDescending(x => x.Score.LivePP).ToArray(); + break; + + case ProfileSortCriteria.Local: + sortedScores = scores.Children.OrderByDescending(x => x.Score.PerformanceAttributes.Total).ToArray(); + break; + + case ProfileSortCriteria.Difference: + sortedScores = scores.Children.OrderByDescending(x => x.Score.PerformanceAttributes.Total - x.Score.LivePP).ToArray(); + break; + + default: + throw new ArgumentOutOfRangeException(nameof(sortCriteria), sortCriteria, null); + } + + for (int i = 0; i < sortedScores.Length; i++) + { + scores.SetLayoutPosition(sortedScores[i], i); + } + } } }