A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using osu.Framework.Allocation;
6using osu.Framework.Graphics.Containers;
7using osu.Framework.Graphics.Shapes;
8using osu.Framework.Graphics.Sprites;
9using osu.Framework.Input.Events;
10using osuTK;
11using osuTK.Graphics;
12
13namespace osu.Framework.Graphics.UserInterface
14{
15 public class BasicRearrangeableListContainer<TModel> : RearrangeableListContainer<TModel>
16 {
17 protected override FillFlowContainer<RearrangeableListItem<TModel>> CreateListFillFlowContainer() => base.CreateListFillFlowContainer().With(d =>
18 {
19 d.LayoutDuration = 160;
20 d.LayoutEasing = Easing.OutQuint;
21 d.Spacing = new Vector2(1);
22 });
23
24 protected override ScrollContainer<Drawable> CreateScrollContainer() => new BasicScrollContainer().With(d =>
25 {
26 d.RelativeSizeAxes = Axes.Both;
27 d.ScrollbarOverlapsContent = false;
28 d.Padding = new MarginPadding(5);
29 });
30
31 protected sealed override RearrangeableListItem<TModel> CreateDrawable(TModel item) => CreateBasicItem(item).With(d =>
32 {
33 d.RequestRemoval += _ => Items.Remove(item);
34 });
35
36 protected virtual BasicRearrangeableListItem<TModel> CreateBasicItem(TModel item) => new BasicRearrangeableListItem<TModel>(item);
37 }
38
39 public class BasicRearrangeableListItem<TModel> : RearrangeableListItem<TModel>
40 {
41 internal Action<RearrangeableListItem<TModel>> RequestRemoval;
42
43 private readonly bool removable;
44 private Drawable dragHandle;
45
46 public BasicRearrangeableListItem(TModel item, bool removable = false)
47 : base(item)
48 {
49 this.removable = removable;
50 }
51
52 [BackgroundDependencyLoader]
53 private void load()
54 {
55 Height = 25;
56 RelativeSizeAxes = Axes.X;
57
58 InternalChild = new GridContainer
59 {
60 RelativeSizeAxes = Axes.Both,
61 Content = new[]
62 {
63 new[]
64 {
65 dragHandle = new Button(FontAwesome.Solid.Bars)
66 {
67 RelativeSizeAxes = Axes.Y,
68 Width = 25,
69 },
70 new Container
71 {
72 RelativeSizeAxes = Axes.Both,
73 CornerRadius = 2,
74 Masking = true,
75 Children = new Drawable[]
76 {
77 new Box
78 {
79 RelativeSizeAxes = Axes.Both,
80 Colour = Color4.DarkSlateGray,
81 },
82 new SpriteText
83 {
84 Anchor = Anchor.CentreLeft,
85 Origin = Anchor.CentreLeft,
86 AllowMultiline = false,
87 Padding = new MarginPadding(5),
88 Text = Model.ToString(),
89 }
90 },
91 },
92 new Button(FontAwesome.Solid.Times)
93 {
94 RelativeSizeAxes = Axes.Y,
95 Width = removable ? 25 : 0, // https://github.com/ppy/osu-framework/issues/3214
96 Colour = Color4.DarkRed,
97 Alpha = removable ? 1 : 0,
98 Action = () => RequestRemoval?.Invoke(this),
99 },
100 },
101 },
102 ColumnDimensions = new[]
103 {
104 new Dimension(GridSizeMode.AutoSize),
105 new Dimension(GridSizeMode.Distributed),
106 new Dimension(GridSizeMode.AutoSize),
107 }
108 };
109 }
110
111 protected override bool IsDraggableAt(Vector2 screenSpacePos) => dragHandle.IsHovered;
112
113 protected internal class Button : Container
114 {
115 public Action Action;
116
117 public override bool HandlePositionalInput => true;
118
119 public Button(IconUsage icon)
120 {
121 RelativeSizeAxes = Axes.Both;
122
123 InternalChild = new SpriteIcon
124 {
125 Anchor = Anchor.Centre,
126 Origin = Anchor.Centre,
127 RelativeSizeAxes = Axes.Both,
128 Scale = new Vector2(0.5f),
129 Icon = icon,
130 };
131 }
132
133 protected override bool OnClick(ClickEvent e)
134 {
135 Action?.Invoke();
136 return true;
137 }
138 }
139 }
140}