2020-09-05 02:52:07 +08:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
2022-07-27 18:35:25 +08:00
using System ;
2022-07-27 15:46:23 +08:00
using System.Diagnostics ;
2020-09-08 15:43:07 +08:00
using System.Linq ;
2022-07-27 18:35:25 +08:00
using osu.Framework.Allocation ;
2020-09-08 15:43:07 +08:00
using osu.Framework.Bindables ;
2020-09-05 02:52:07 +08:00
using osu.Framework.Graphics ;
using osu.Framework.Graphics.Containers ;
2022-07-27 18:35:25 +08:00
using osu.Game.Database ;
2020-09-05 02:52:07 +08:00
using osu.Game.Graphics.Containers ;
using osuTK ;
2022-07-27 18:35:25 +08:00
using Realms ;
2020-09-05 02:52:07 +08:00
namespace osu.Game.Collections
{
2020-09-08 15:50:51 +08:00
/// <summary>
2022-07-27 15:46:23 +08:00
/// Visualises a list of <see cref="BeatmapCollection"/>s.
2020-09-08 15:50:51 +08:00
/// </summary>
2022-07-27 18:35:25 +08:00
public class DrawableCollectionList : OsuRearrangeableListContainer < Live < BeatmapCollection > >
2020-09-05 02:52:07 +08:00
{
2020-09-08 15:43:07 +08:00
protected override ScrollContainer < Drawable > CreateScrollContainer ( ) = > scroll = new Scroll ( ) ;
2020-09-05 02:52:07 +08:00
2022-07-27 18:35:25 +08:00
[Resolved]
private RealmAccess realm { get ; set ; } = null ! ;
2022-07-28 12:50:19 +08:00
private Scroll scroll = null ! ;
private IDisposable ? realmSubscription ;
2022-07-27 18:35:25 +08:00
protected override FillFlowContainer < RearrangeableListItem < Live < BeatmapCollection > > > CreateListFillFlowContainer ( ) = > new Flow
2020-09-05 02:52:07 +08:00
{
2020-09-08 15:43:07 +08:00
DragActive = { BindTarget = DragActive }
2020-09-05 02:52:07 +08:00
} ;
2022-07-27 18:35:25 +08:00
protected override void LoadComplete ( )
{
base . LoadComplete ( ) ;
2022-07-28 13:07:42 +08:00
realmSubscription = realm . RegisterForNotifications ( r = > r . All < BeatmapCollection > ( ) . OrderBy ( c = > c . Name ) , collectionsChanged ) ;
2022-07-27 18:35:25 +08:00
}
private void collectionsChanged ( IRealmCollection < BeatmapCollection > collections , ChangeSet ? changes , Exception error )
{
Items . Clear ( ) ;
Items . AddRange ( collections . AsEnumerable ( ) . Select ( c = > c . ToLive ( realm ) ) ) ;
}
2022-07-27 14:59:36 +08:00
2022-07-27 18:35:25 +08:00
protected override OsuRearrangeableListItem < Live < BeatmapCollection > > CreateOsuDrawable ( Live < BeatmapCollection > item )
2020-09-08 15:43:07 +08:00
{
2022-07-27 14:59:36 +08:00
if ( item . ID = = scroll . PlaceholderItem . Model . ID )
2020-09-08 15:43:07 +08:00
return scroll . ReplacePlaceholder ( ) ;
return new DrawableCollectionListItem ( item , true ) ;
}
2022-07-28 12:50:19 +08:00
protected override void Dispose ( bool isDisposing )
{
base . Dispose ( isDisposing ) ;
realmSubscription ? . Dispose ( ) ;
}
2020-09-08 15:50:51 +08:00
/// <summary>
/// The scroll container for this <see cref="DrawableCollectionList"/>.
/// Contains the main flow of <see cref="DrawableCollectionListItem"/> and attaches a placeholder item to the end of the list.
/// </summary>
/// <remarks>
/// Use <see cref="ReplacePlaceholder"/> to transfer the placeholder into the main list.
/// </remarks>
2020-09-08 15:43:07 +08:00
private class Scroll : OsuScrollContainer
{
2020-09-08 15:50:51 +08:00
/// <summary>
/// The currently-displayed placeholder item.
/// </summary>
2022-07-27 15:46:23 +08:00
public DrawableCollectionListItem PlaceholderItem { get ; private set ; } = null ! ;
2020-09-08 15:43:07 +08:00
protected override Container < Drawable > Content = > content ;
private readonly Container content ;
private readonly Container < DrawableCollectionListItem > placeholderContainer ;
public Scroll ( )
{
ScrollbarVisible = false ;
Padding = new MarginPadding ( 10 ) ;
base . Content . Add ( new FillFlowContainer
{
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y ,
LayoutDuration = 200 ,
LayoutEasing = Easing . OutQuint ,
Children = new Drawable [ ]
{
content = new Container { RelativeSizeAxes = Axes . X } ,
placeholderContainer = new Container < DrawableCollectionListItem >
{
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y
}
}
} ) ;
ReplacePlaceholder ( ) ;
2022-07-27 15:46:23 +08:00
Debug . Assert ( PlaceholderItem ! = null ) ;
2020-09-08 15:43:07 +08:00
}
protected override void Update ( )
{
base . Update ( ) ;
// AutoSizeAxes cannot be used as the height should represent the post-layout-transform height at all times, so that the placeholder doesn't bounce around.
content . Height = ( ( Flow ) Child ) . Children . Sum ( c = > c . DrawHeight + 5 ) ;
}
/// <summary>
/// Replaces the current <see cref="PlaceholderItem"/> with a new one, and returns the previous.
/// </summary>
2020-09-08 15:50:51 +08:00
/// <returns>The current <see cref="PlaceholderItem"/>.</returns>
2020-09-08 15:43:07 +08:00
public DrawableCollectionListItem ReplacePlaceholder ( )
{
var previous = PlaceholderItem ;
placeholderContainer . Clear ( false ) ;
2022-07-27 18:35:25 +08:00
placeholderContainer . Add ( PlaceholderItem = new DrawableCollectionListItem ( new BeatmapCollection ( ) . ToLiveUnmanaged ( ) , false ) ) ;
2020-09-08 15:43:07 +08:00
return previous ;
}
}
2020-09-08 15:50:51 +08:00
/// <summary>
/// The flow of <see cref="DrawableCollectionListItem"/>. Disables layout easing unless a drag is in progress.
/// </summary>
2022-07-27 18:35:25 +08:00
private class Flow : FillFlowContainer < RearrangeableListItem < Live < BeatmapCollection > > >
2020-09-08 15:43:07 +08:00
{
public readonly IBindable < bool > DragActive = new Bindable < bool > ( ) ;
public Flow ( )
{
Spacing = new Vector2 ( 0 , 5 ) ;
LayoutEasing = Easing . OutQuint ;
}
protected override void LoadComplete ( )
{
base . LoadComplete ( ) ;
DragActive . BindValueChanged ( active = > LayoutDuration = active . NewValue ? 200 : 0 ) ;
}
}
2020-09-05 02:52:07 +08:00
}
}