diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/EditorTable.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/EditorTable.cs new file mode 100644 index 000000000..28643e787 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/EditorTable.cs @@ -0,0 +1,188 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Diagnostics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Karaoke.Screens.Edit; + +public abstract partial class EditorTable : TableContainer +{ + public event Action? OnRowSelected; + + private const float horizontal_inset = 20; + + protected const float ROW_HEIGHT = 25; + + public const int TEXT_SIZE = 14; + + protected readonly FillFlowContainer BackgroundFlow; + + // We can avoid potentially thousands of objects being added to the input sub-tree since item selection is being handled by the BackgroundFlow + // and no items in the underlying table are clickable. + protected override bool ShouldBeConsideredForInput(Drawable child) => child == BackgroundFlow && base.ShouldBeConsideredForInput(child); + + protected EditorTable() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Padding = new MarginPadding { Horizontal = horizontal_inset }; + RowSize = new Dimension(GridSizeMode.Absolute, ROW_HEIGHT); + + AddInternal(BackgroundFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Depth = 1f, + Padding = new MarginPadding { Horizontal = -horizontal_inset }, + Margin = new MarginPadding { Top = ROW_HEIGHT } + }); + } + + protected int GetIndexForObject(object? item) + { + for (int i = 0; i < BackgroundFlow.Count; i++) + { + if (BackgroundFlow[i].Item == item) + return i; + } + + return -1; + } + + protected virtual bool SetSelectedRow(object? item) + { + bool foundSelection = false; + + foreach (var b in BackgroundFlow) + { + b.Selected = ReferenceEquals(b.Item, item); + + if (b.Selected) + { + Debug.Assert(!foundSelection); + OnRowSelected?.Invoke(b); + foundSelection = true; + } + } + + return foundSelection; + } + + protected object? GetObjectAtIndex(int index) + { + if (index < 0 || index > BackgroundFlow.Count - 1) + return null; + + return BackgroundFlow[index].Item; + } + + protected override Drawable CreateHeader(int index, TableColumn? column) => new HeaderText(column?.Header ?? default); + + private partial class HeaderText : OsuSpriteText + { + public HeaderText(LocalisableString text) + { + Text = text.ToUpper(); + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold); + } + } + + public partial class RowBackground : OsuClickableContainer + { + public readonly object Item; + + private const int fade_duration = 100; + + private readonly Box hoveredBackground; + + public RowBackground(object item) + { + Item = item; + + RelativeSizeAxes = Axes.X; + Height = 25; + + AlwaysPresent = true; + + CornerRadius = 3; + Masking = true; + + Children = new Drawable[] + { + hoveredBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + }; + } + + private Color4 colourHover; + private Color4 colourSelected; + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colours) + { + colourHover = colours.Background1; + colourSelected = colours.Colour3; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + updateState(); + FinishTransforms(true); + } + + private bool selected; + + public bool Selected + { + get => selected; + set + { + if (value == selected) + return; + + selected = value; + updateState(); + } + } + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateState(); + base.OnHoverLost(e); + } + + private void updateState() + { + hoveredBackground.FadeColour(selected ? colourSelected : colourHover, 450, Easing.OutQuint); + + if (selected || IsHovered) + hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + else + hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/IssueTable.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/IssueTable.cs index 5eda81662..4ee4919d4 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/IssueTable.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/IssueTable.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Edit.Checks.Components; -using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Karaoke.Screens.Edit;