mirror of
https://github.com/ppy/osu.git
synced 2025-01-27 17:53:15 +08:00
Create a new collection via a placeholder item
This commit is contained in:
parent
1260e30cde
commit
0bf6bfe5ee
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
@ -10,19 +12,94 @@ namespace osu.Game.Collections
|
|||||||
{
|
{
|
||||||
public class DrawableCollectionList : OsuRearrangeableListContainer<BeatmapCollection>
|
public class DrawableCollectionList : OsuRearrangeableListContainer<BeatmapCollection>
|
||||||
{
|
{
|
||||||
protected override ScrollContainer<Drawable> CreateScrollContainer() => base.CreateScrollContainer().With(d =>
|
private Scroll scroll;
|
||||||
{
|
|
||||||
d.ScrollbarVisible = false;
|
|
||||||
d.Padding = new MarginPadding(10);
|
|
||||||
});
|
|
||||||
|
|
||||||
protected override FillFlowContainer<RearrangeableListItem<BeatmapCollection>> CreateListFillFlowContainer() => new FillFlowContainer<RearrangeableListItem<BeatmapCollection>>
|
protected override ScrollContainer<Drawable> CreateScrollContainer() => scroll = new Scroll();
|
||||||
|
|
||||||
|
protected override FillFlowContainer<RearrangeableListItem<BeatmapCollection>> CreateListFillFlowContainer() => new Flow
|
||||||
{
|
{
|
||||||
LayoutDuration = 200,
|
DragActive = { BindTarget = DragActive }
|
||||||
LayoutEasing = Easing.OutQuint,
|
|
||||||
Spacing = new Vector2(0, 5)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override OsuRearrangeableListItem<BeatmapCollection> CreateOsuDrawable(BeatmapCollection item) => new DrawableCollectionListItem(item);
|
protected override OsuRearrangeableListItem<BeatmapCollection> CreateOsuDrawable(BeatmapCollection item)
|
||||||
|
{
|
||||||
|
if (item == scroll.PlaceholderItem.Model)
|
||||||
|
return scroll.ReplacePlaceholder();
|
||||||
|
|
||||||
|
return new DrawableCollectionListItem(item, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Scroll : OsuScrollContainer
|
||||||
|
{
|
||||||
|
public DrawableCollectionListItem PlaceholderItem { get; private set; }
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
||||||
|
public DrawableCollectionListItem ReplacePlaceholder()
|
||||||
|
{
|
||||||
|
var previous = PlaceholderItem;
|
||||||
|
|
||||||
|
placeholderContainer.Clear(false);
|
||||||
|
placeholderContainer.Add(PlaceholderItem = new DrawableCollectionListItem(new BeatmapCollection(), false));
|
||||||
|
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Flow : FillFlowContainer<RearrangeableListItem<BeatmapCollection>>
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -21,20 +22,33 @@ namespace osu.Game.Collections
|
|||||||
public class DrawableCollectionListItem : OsuRearrangeableListItem<BeatmapCollection>
|
public class DrawableCollectionListItem : OsuRearrangeableListItem<BeatmapCollection>
|
||||||
{
|
{
|
||||||
private const float item_height = 35;
|
private const float item_height = 35;
|
||||||
|
|
||||||
private const float button_width = item_height * 0.75f;
|
private const float button_width = item_height * 0.75f;
|
||||||
|
|
||||||
public DrawableCollectionListItem(BeatmapCollection item)
|
private readonly Bindable<bool> isCreated = new Bindable<bool>();
|
||||||
|
|
||||||
|
public DrawableCollectionListItem(BeatmapCollection item, bool isCreated)
|
||||||
: base(item)
|
: base(item)
|
||||||
{
|
{
|
||||||
|
this.isCreated.Value = isCreated;
|
||||||
|
|
||||||
|
ShowDragHandle.BindTo(this.isCreated);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Drawable CreateContent() => new ItemContent(Model);
|
protected override Drawable CreateContent() => new ItemContent(Model)
|
||||||
|
{
|
||||||
|
IsCreated = { BindTarget = isCreated }
|
||||||
|
};
|
||||||
|
|
||||||
private class ItemContent : CircularContainer
|
private class ItemContent : CircularContainer
|
||||||
{
|
{
|
||||||
|
public readonly Bindable<bool> IsCreated = new Bindable<bool>();
|
||||||
|
|
||||||
|
private readonly IBindable<string> collectionName;
|
||||||
private readonly BeatmapCollection collection;
|
private readonly BeatmapCollection collection;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private BeatmapCollectionManager collectionManager { get; set; }
|
||||||
|
|
||||||
private ItemTextBox textBox;
|
private ItemTextBox textBox;
|
||||||
|
|
||||||
public ItemContent(BeatmapCollection collection)
|
public ItemContent(BeatmapCollection collection)
|
||||||
@ -44,6 +58,8 @@ namespace osu.Game.Collections
|
|||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Height = item_height;
|
Height = item_height;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
|
|
||||||
|
collectionName = collection.Name.GetBoundCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -55,6 +71,7 @@ namespace osu.Game.Collections
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.CentreRight,
|
Anchor = Anchor.CentreRight,
|
||||||
Origin = Anchor.CentreRight,
|
Origin = Anchor.CentreRight,
|
||||||
|
IsCreated = { BindTarget = IsCreated },
|
||||||
IsTextBoxHovered = v => textBox.ReceivePositionalInputAt(v)
|
IsTextBoxHovered = v => textBox.ReceivePositionalInputAt(v)
|
||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
@ -68,12 +85,37 @@ namespace osu.Game.Collections
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Size = Vector2.One,
|
Size = Vector2.One,
|
||||||
CornerRadius = item_height / 2,
|
CornerRadius = item_height / 2,
|
||||||
Current = collection.Name
|
Current = collection.Name,
|
||||||
|
PlaceholderText = IsCreated.Value ? string.Empty : "Create a new collection"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
collectionName.BindValueChanged(_ => createNewCollection(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNewCollection()
|
||||||
|
{
|
||||||
|
if (IsCreated.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(collectionName.Value))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Add the new collection and disable our placeholder. If all text is removed, the placeholder should not show back again.
|
||||||
|
collectionManager.Collections.Add(collection);
|
||||||
|
textBox.PlaceholderText = string.Empty;
|
||||||
|
|
||||||
|
// When this item changes from placeholder to non-placeholder (via changing containers), its textbox will lose focus, so it needs to be re-focused.
|
||||||
|
Schedule(() => GetContainingInputManager().ChangeFocus(textBox));
|
||||||
|
|
||||||
|
IsCreated.Value = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ItemTextBox : OsuTextBox
|
private class ItemTextBox : OsuTextBox
|
||||||
@ -90,6 +132,8 @@ namespace osu.Game.Collections
|
|||||||
|
|
||||||
public class DeleteButton : CompositeDrawable
|
public class DeleteButton : CompositeDrawable
|
||||||
{
|
{
|
||||||
|
public readonly IBindable<bool> IsCreated = new Bindable<bool>();
|
||||||
|
|
||||||
public Func<Vector2, bool> IsTextBoxHovered;
|
public Func<Vector2, bool> IsTextBoxHovered;
|
||||||
|
|
||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
@ -100,6 +144,7 @@ namespace osu.Game.Collections
|
|||||||
|
|
||||||
private readonly BeatmapCollection collection;
|
private readonly BeatmapCollection collection;
|
||||||
|
|
||||||
|
private Drawable fadeContainer;
|
||||||
private Drawable background;
|
private Drawable background;
|
||||||
|
|
||||||
public DeleteButton(BeatmapCollection collection)
|
public DeleteButton(BeatmapCollection collection)
|
||||||
@ -108,42 +153,51 @@ namespace osu.Game.Collections
|
|||||||
RelativeSizeAxes = Axes.Y;
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
|
||||||
Width = button_width + item_height / 2; // add corner radius to cover with fill
|
Width = button_width + item_height / 2; // add corner radius to cover with fill
|
||||||
|
|
||||||
Alpha = 0.1f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
InternalChildren = new[]
|
InternalChild = fadeContainer = new Container
|
||||||
{
|
{
|
||||||
background = new Box
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0.1f,
|
||||||
|
Children = new[]
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
background = new Box
|
||||||
Colour = colours.Red
|
{
|
||||||
},
|
RelativeSizeAxes = Axes.Both,
|
||||||
new SpriteIcon
|
Colour = colours.Red
|
||||||
{
|
},
|
||||||
Anchor = Anchor.CentreRight,
|
new SpriteIcon
|
||||||
Origin = Anchor.Centre,
|
{
|
||||||
X = -button_width * 0.6f,
|
Anchor = Anchor.CentreRight,
|
||||||
Size = new Vector2(10),
|
Origin = Anchor.Centre,
|
||||||
Icon = FontAwesome.Solid.Trash
|
X = -button_width * 0.6f,
|
||||||
|
Size = new Vector2(10),
|
||||||
|
Icon = FontAwesome.Solid.Trash
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
IsCreated.BindValueChanged(created => Alpha = created.NewValue ? 1 : 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) && !IsTextBoxHovered(screenSpacePos);
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) && !IsTextBoxHovered(screenSpacePos);
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
{
|
{
|
||||||
this.FadeTo(1f, 100, Easing.Out);
|
fadeContainer.FadeTo(1f, 100, Easing.Out);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
{
|
{
|
||||||
this.FadeTo(0.1f, 100);
|
fadeContainer.FadeTo(0.1f, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
protected override bool OnClick(ClickEvent e)
|
||||||
|
@ -8,7 +8,6 @@ using osu.Framework.Graphics.Shapes;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Collections
|
namespace osu.Game.Collections
|
||||||
@ -51,9 +50,7 @@ namespace osu.Game.Collections
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
RowDimensions = new[]
|
RowDimensions = new[]
|
||||||
{
|
{
|
||||||
new Dimension(GridSizeMode.Absolute, 50),
|
new Dimension(GridSizeMode.AutoSize),
|
||||||
new Dimension(),
|
|
||||||
new Dimension(GridSizeMode.Absolute, 50),
|
|
||||||
},
|
},
|
||||||
Content = new[]
|
Content = new[]
|
||||||
{
|
{
|
||||||
@ -65,6 +62,7 @@ namespace osu.Game.Collections
|
|||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Text = "Manage collections",
|
Text = "Manage collections",
|
||||||
Font = OsuFont.GetFont(size: 30),
|
Font = OsuFont.GetFont(size: 30),
|
||||||
|
Padding = new MarginPadding { Vertical = 10 },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Drawable[]
|
new Drawable[]
|
||||||
@ -87,19 +85,6 @@ namespace osu.Game.Collections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Drawable[]
|
|
||||||
{
|
|
||||||
new OsuButton
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Size = Vector2.One,
|
|
||||||
Padding = new MarginPadding(10),
|
|
||||||
Text = "Create new collection",
|
|
||||||
Action = () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "My new collection" } })
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user