mirror of
https://github.com/osukey/osukey.git
synced 2025-07-02 08:49:59 +09:00
Extract common rearrangeable list design
This commit is contained in:
@ -0,0 +1,26 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
public abstract class OsuRearrangeableListContainer<TModel> : RearrangeableListContainer<TModel>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether any item is currently being dragged. Used to hide other items' drag handles.
|
||||||
|
/// </summary>
|
||||||
|
private readonly BindableBool playlistDragActive = new BindableBool();
|
||||||
|
|
||||||
|
protected override ScrollContainer<Drawable> CreateScrollContainer() => new OsuScrollContainer();
|
||||||
|
|
||||||
|
protected sealed override RearrangeableListItem<TModel> CreateDrawable(TModel item) => CreateOsuDrawable(item).With(d =>
|
||||||
|
{
|
||||||
|
d.PlaylistDragActive.BindTo(playlistDragActive);
|
||||||
|
});
|
||||||
|
|
||||||
|
protected abstract OsuRearrangeableListItem<TModel> CreateOsuDrawable(TModel item);
|
||||||
|
}
|
||||||
|
}
|
149
osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs
Normal file
149
osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
public abstract class OsuRearrangeableListItem<TModel> : RearrangeableListItem<TModel>
|
||||||
|
{
|
||||||
|
public const float FADE_DURATION = 100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether any item is currently being dragged. Used to hide other items' drag handles.
|
||||||
|
/// </summary>
|
||||||
|
public readonly BindableBool PlaylistDragActive = new BindableBool();
|
||||||
|
|
||||||
|
private Color4 handleColour = Color4.White;
|
||||||
|
|
||||||
|
protected Color4 HandleColour
|
||||||
|
{
|
||||||
|
get => handleColour;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (handleColour == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
handleColour = value;
|
||||||
|
|
||||||
|
if (handle != null)
|
||||||
|
handle.Colour = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlaylistItemHandle handle;
|
||||||
|
|
||||||
|
protected OsuRearrangeableListItem(TModel item)
|
||||||
|
: base(item)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChild = new GridContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Content = new[]
|
||||||
|
{
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Horizontal = 5 },
|
||||||
|
Child = handle = new PlaylistItemHandle
|
||||||
|
{
|
||||||
|
Size = new Vector2(12),
|
||||||
|
Colour = HandleColour,
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Alpha = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CreateContent()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) },
|
||||||
|
RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnDragStart(DragStartEvent e)
|
||||||
|
{
|
||||||
|
if (!base.OnDragStart(e))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PlaylistDragActive.Value = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDragEnd(DragEndEvent e)
|
||||||
|
{
|
||||||
|
PlaylistDragActive.Value = false;
|
||||||
|
base.OnDragEnd(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsDraggableAt(Vector2 screenSpacePos) => handle.HandlingDrag;
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
handle.UpdateHoverState(IsDragged || !PlaylistDragActive.Value);
|
||||||
|
return base.OnHover(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(HoverLostEvent e) => handle.UpdateHoverState(false);
|
||||||
|
|
||||||
|
protected abstract Drawable CreateContent();
|
||||||
|
|
||||||
|
private class PlaylistItemHandle : SpriteIcon
|
||||||
|
{
|
||||||
|
public bool HandlingDrag { get; private set; }
|
||||||
|
private bool isHovering;
|
||||||
|
|
||||||
|
public PlaylistItemHandle()
|
||||||
|
{
|
||||||
|
Icon = FontAwesome.Solid.Bars;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
|
{
|
||||||
|
base.OnMouseDown(e);
|
||||||
|
|
||||||
|
HandlingDrag = true;
|
||||||
|
UpdateHoverState(isHovering);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseUp(MouseUpEvent e)
|
||||||
|
{
|
||||||
|
base.OnMouseUp(e);
|
||||||
|
|
||||||
|
HandlingDrag = false;
|
||||||
|
UpdateHoverState(isHovering);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateHoverState(bool hovering)
|
||||||
|
{
|
||||||
|
isHovering = hovering;
|
||||||
|
|
||||||
|
if (isHovering || HandlingDrag)
|
||||||
|
this.FadeIn(FADE_DURATION);
|
||||||
|
else
|
||||||
|
this.FadeOut(FADE_DURATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,17 +12,12 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays.Music
|
namespace osu.Game.Overlays.Music
|
||||||
{
|
{
|
||||||
public class Playlist : RearrangeableListContainer<BeatmapSetInfo>
|
public class Playlist : OsuRearrangeableListContainer<BeatmapSetInfo>
|
||||||
{
|
{
|
||||||
public Action<BeatmapSetInfo> RequestSelection;
|
public Action<BeatmapSetInfo> RequestSelection;
|
||||||
|
|
||||||
public readonly Bindable<BeatmapSetInfo> SelectedSet = new Bindable<BeatmapSetInfo>();
|
public readonly Bindable<BeatmapSetInfo> SelectedSet = new Bindable<BeatmapSetInfo>();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether any item is currently being dragged. Used to hide other items' drag handles.
|
|
||||||
/// </summary>
|
|
||||||
private readonly BindableBool playlistDragActive = new BindableBool();
|
|
||||||
|
|
||||||
public new MarginPadding Padding
|
public new MarginPadding Padding
|
||||||
{
|
{
|
||||||
get => base.Padding;
|
get => base.Padding;
|
||||||
@ -33,15 +28,12 @@ namespace osu.Game.Overlays.Music
|
|||||||
|
|
||||||
public BeatmapSetInfo FirstVisibleSet => Items.FirstOrDefault(i => ((PlaylistItem)ItemMap[i]).MatchingFilter);
|
public BeatmapSetInfo FirstVisibleSet => Items.FirstOrDefault(i => ((PlaylistItem)ItemMap[i]).MatchingFilter);
|
||||||
|
|
||||||
protected override RearrangeableListItem<BeatmapSetInfo> CreateDrawable(BeatmapSetInfo item) => new PlaylistItem(item)
|
protected override OsuRearrangeableListItem<BeatmapSetInfo> CreateOsuDrawable(BeatmapSetInfo item) => new PlaylistItem(item)
|
||||||
{
|
{
|
||||||
SelectedSet = { BindTarget = SelectedSet },
|
SelectedSet = { BindTarget = SelectedSet },
|
||||||
PlaylistDragActive = { BindTarget = playlistDragActive },
|
|
||||||
RequestSelection = set => RequestSelection?.Invoke(set)
|
RequestSelection = set => RequestSelection?.Invoke(set)
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override ScrollContainer<Drawable> CreateScrollContainer() => new OsuScrollContainer();
|
|
||||||
|
|
||||||
protected override FillFlowContainer<RearrangeableListItem<BeatmapSetInfo>> CreateListFillFlowContainer() => new SearchContainer<RearrangeableListItem<BeatmapSetInfo>>
|
protected override FillFlowContainer<RearrangeableListItem<BeatmapSetInfo>> CreateListFillFlowContainer() => new SearchContainer<RearrangeableListItem<BeatmapSetInfo>>
|
||||||
{
|
{
|
||||||
Spacing = new Vector2(0, 3),
|
Spacing = new Vector2(0, 3),
|
||||||
|
@ -14,36 +14,27 @@ using osu.Framework.Localisation;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Music
|
namespace osu.Game.Overlays.Music
|
||||||
{
|
{
|
||||||
public class PlaylistItem : RearrangeableListItem<BeatmapSetInfo>, IFilterable
|
public class PlaylistItem : OsuRearrangeableListItem<BeatmapSetInfo>, IFilterable
|
||||||
{
|
{
|
||||||
private const float fade_duration = 100;
|
|
||||||
|
|
||||||
public BindableBool PlaylistDragActive = new BindableBool();
|
|
||||||
|
|
||||||
public readonly Bindable<BeatmapSetInfo> SelectedSet = new Bindable<BeatmapSetInfo>();
|
public readonly Bindable<BeatmapSetInfo> SelectedSet = new Bindable<BeatmapSetInfo>();
|
||||||
|
|
||||||
public Action<BeatmapSetInfo> RequestSelection;
|
public Action<BeatmapSetInfo> RequestSelection;
|
||||||
|
|
||||||
private PlaylistItemHandle handle;
|
|
||||||
private TextFlowContainer text;
|
private TextFlowContainer text;
|
||||||
private IEnumerable<Drawable> titleSprites;
|
private IEnumerable<Drawable> titleSprites;
|
||||||
private ILocalisedBindableString titleBind;
|
private ILocalisedBindableString titleBind;
|
||||||
private ILocalisedBindableString artistBind;
|
private ILocalisedBindableString artistBind;
|
||||||
|
|
||||||
private Color4 hoverColour;
|
private Color4 selectedColour;
|
||||||
private Color4 artistColour;
|
private Color4 artistColour;
|
||||||
|
|
||||||
public PlaylistItem(BeatmapSetInfo item)
|
public PlaylistItem(BeatmapSetInfo item)
|
||||||
: base(item)
|
: base(item)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
|
||||||
AutoSizeAxes = Axes.Y;
|
|
||||||
|
|
||||||
Padding = new MarginPadding { Left = 5 };
|
Padding = new MarginPadding { Left = 5 };
|
||||||
|
|
||||||
FilterTerms = item.Metadata.SearchableTerms;
|
FilterTerms = item.Metadata.SearchableTerms;
|
||||||
@ -52,42 +43,12 @@ namespace osu.Game.Overlays.Music
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours, LocalisationManager localisation)
|
private void load(OsuColour colours, LocalisationManager localisation)
|
||||||
{
|
{
|
||||||
hoverColour = colours.Yellow;
|
selectedColour = colours.Yellow;
|
||||||
artistColour = colours.Gray9;
|
artistColour = colours.Gray9;
|
||||||
|
HandleColour = colours.Gray5;
|
||||||
InternalChild = new GridContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Content = new[]
|
|
||||||
{
|
|
||||||
new Drawable[]
|
|
||||||
{
|
|
||||||
handle = new PlaylistItemHandle
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.CentreLeft,
|
|
||||||
Size = new Vector2(12),
|
|
||||||
Colour = colours.Gray5,
|
|
||||||
AlwaysPresent = true,
|
|
||||||
Alpha = 0
|
|
||||||
},
|
|
||||||
text = new OsuTextFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Padding = new MarginPadding { Left = 5 },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) },
|
|
||||||
RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }
|
|
||||||
};
|
|
||||||
|
|
||||||
titleBind = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.TitleUnicode, Model.Metadata.Title)));
|
titleBind = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.TitleUnicode, Model.Metadata.Title)));
|
||||||
artistBind = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.ArtistUnicode, Model.Metadata.Artist)));
|
artistBind = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.ArtistUnicode, Model.Metadata.Artist)));
|
||||||
|
|
||||||
artistBind.BindValueChanged(_ => recreateText(), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
@ -100,10 +61,18 @@ namespace osu.Game.Overlays.Music
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (Drawable s in titleSprites)
|
foreach (Drawable s in titleSprites)
|
||||||
s.FadeColour(set.NewValue == Model ? hoverColour : Color4.White, fade_duration);
|
s.FadeColour(set.NewValue == Model ? selectedColour : Color4.White, FADE_DURATION);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
artistBind.BindValueChanged(_ => recreateText(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override Drawable CreateContent() => text = new OsuTextFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
};
|
||||||
|
|
||||||
private void recreateText()
|
private void recreateText()
|
||||||
{
|
{
|
||||||
text.Clear();
|
text.Clear();
|
||||||
@ -125,31 +94,6 @@ namespace osu.Game.Overlays.Music
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnDragStart(DragStartEvent e)
|
|
||||||
{
|
|
||||||
if (!base.OnDragStart(e))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
PlaylistDragActive.Value = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDragEnd(DragEndEvent e)
|
|
||||||
{
|
|
||||||
PlaylistDragActive.Value = false;
|
|
||||||
base.OnDragEnd(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool IsDraggableAt(Vector2 screenSpacePos) => handle.HandlingDrag;
|
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
|
||||||
{
|
|
||||||
handle.UpdateHoverState(IsDragged || !PlaylistDragActive.Value);
|
|
||||||
return base.OnHover(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e) => handle.UpdateHoverState(false);
|
|
||||||
|
|
||||||
public IEnumerable<string> FilterTerms { get; }
|
public IEnumerable<string> FilterTerms { get; }
|
||||||
|
|
||||||
private bool matching = true;
|
private bool matching = true;
|
||||||
@ -168,44 +112,5 @@ namespace osu.Game.Overlays.Music
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bool FilteringActive { get; set; }
|
public bool FilteringActive { get; set; }
|
||||||
|
|
||||||
private class PlaylistItemHandle : SpriteIcon
|
|
||||||
{
|
|
||||||
public bool HandlingDrag { get; private set; }
|
|
||||||
private bool isHovering;
|
|
||||||
|
|
||||||
public PlaylistItemHandle()
|
|
||||||
{
|
|
||||||
Icon = FontAwesome.Solid.Bars;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e)
|
|
||||||
{
|
|
||||||
base.OnMouseDown(e);
|
|
||||||
|
|
||||||
HandlingDrag = true;
|
|
||||||
UpdateHoverState(isHovering);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnMouseUp(MouseUpEvent e)
|
|
||||||
{
|
|
||||||
base.OnMouseUp(e);
|
|
||||||
|
|
||||||
HandlingDrag = false;
|
|
||||||
UpdateHoverState(isHovering);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateHoverState(bool hovering)
|
|
||||||
{
|
|
||||||
isHovering = hovering;
|
|
||||||
|
|
||||||
if (isHovering || HandlingDrag)
|
|
||||||
this.FadeIn(fade_duration);
|
|
||||||
else
|
|
||||||
this.FadeOut(fade_duration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user