From cc9bed9b84aa8bf1ab1714d9416c0f53ea66204f Mon Sep 17 00:00:00 2001 From: andy840119 Date: Tue, 17 Jan 2023 21:37:08 +0800 Subject: [PATCH 1/6] Implement section editor for able to edit the list of items in the section. Also, naming some methods by follow how RearrangeableListContainer did. --- .../Edit/ISectionItemsEditorProvider.cs | 11 ++ .../Screens/Edit/SectionItemsEditor.cs | 121 ++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 osu.Game.Rulesets.Karaoke/Screens/Edit/ISectionItemsEditorProvider.cs create mode 100644 osu.Game.Rulesets.Karaoke/Screens/Edit/SectionItemsEditor.cs diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/ISectionItemsEditorProvider.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/ISectionItemsEditorProvider.cs new file mode 100644 index 000000000..f8b5e067f --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/ISectionItemsEditorProvider.cs @@ -0,0 +1,11 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; + +namespace osu.Game.Rulesets.Karaoke.Screens.Edit; + +public interface ISectionItemsEditorProvider +{ + void UpdateDisplayOrder(Drawable drawable, int order); +} diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/SectionItemsEditor.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/SectionItemsEditor.cs new file mode 100644 index 000000000..6440827d8 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/SectionItemsEditor.cs @@ -0,0 +1,121 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Diagnostics; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; + +namespace osu.Game.Rulesets.Karaoke.Screens.Edit; + +/// +/// This section handle display the list of . +/// And able to create or remove the in here. +/// +/// +[Cached(typeof(ISectionItemsEditorProvider))] +public abstract partial class SectionItemsEditor : CompositeDrawable, ISectionItemsEditorProvider where TModel : class +{ + protected readonly IBindableList Items = new BindableList(); + + private readonly Dictionary itemMap = new(); + + private readonly FillFlowContainer content; + + protected SectionItemsEditor() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChild = content = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10), + LayoutEasing = Easing.Out, + }; + + Items.BindCollectionChanged((_, args) => + { + switch (args.Action) + { + case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null); + addItems(args.NewItems); + + break; + + case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null); + removeItems(args.OldItems); + + break; + } + }); + + addCreateButton(); + } + + public void RedrewContent() + { + clearDrawable(); + + addItems(Items.ToList()); + + addCreateButton(); + } + + private void clearDrawable() + { + content.Clear(); + itemMap.Clear(); + } + + private void addItems(IList items) + { + bool enableAddAnimation = items.Count == 1; + content.LayoutDuration = enableAddAnimation ? 100 : 0; + + foreach (var item in items.Cast()) + { + var drawable = CreateDrawable(item); + content.Add(drawable); + itemMap.Add(item, drawable); + } + } + + private void removeItems(IList items) + { + foreach (var item in items.Cast()) + { + var drawable = itemMap[item]; + content.Remove(drawable, true); + itemMap.Remove(item); + } + } + + private void addCreateButton() + { + var button = CreateCreateNewItemButton(); + if (button == null) + return; + + content.Insert(int.MaxValue, button); + } + + public void UpdateDisplayOrder(Drawable drawable, int order) + { + float newPosition = order; + content.SetLayoutPosition(drawable, newPosition); + } + + protected abstract Drawable CreateDrawable(TModel item); + + protected abstract EditorSectionButton? CreateCreateNewItemButton(); +} From ca6d9da353432d403583c5cb38b705cf8cbec25f Mon Sep 17 00:00:00 2001 From: andy840119 Date: Tue, 17 Jan 2023 21:51:43 +0800 Subject: [PATCH 2/6] Implement the base section editor for timing info. --- .../Edit/SectionTimingInfoItemsEditor.cs | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 osu.Game.Rulesets.Karaoke/Screens/Edit/SectionTimingInfoItemsEditor.cs diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/SectionTimingInfoItemsEditor.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/SectionTimingInfoItemsEditor.cs new file mode 100644 index 000000000..f2a6933c4 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/SectionTimingInfoItemsEditor.cs @@ -0,0 +1,94 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Diagnostics.CodeAnalysis; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Components.UserInterface; +using osuTK; + +namespace osu.Game.Rulesets.Karaoke.Screens.Edit; + +public abstract partial class SectionTimingInfoItemsEditor : SectionItemsEditor where TItem : class +{ + protected sealed override Drawable CreateDrawable(TItem item) + => CreateTimingInfoDrawable(item); + + protected abstract DrawableTimingInfoItem CreateTimingInfoDrawable(TItem item); + + protected abstract partial class DrawableTimingInfoItem : CompositeDrawable + { + [Resolved, AllowNull] + private ISectionItemsEditorProvider sectionItemsEditorProvider { get; set; } + + public readonly TItem Item; + + private readonly Box background; + private readonly OsuSpriteText spriteText; + private readonly DeleteIconButton deleteIconButton; + + protected DrawableTimingInfoItem(TItem item) + { + Item = item; + + Masking = true; + CornerRadius = 5; + RelativeSizeAxes = Axes.X; + Height = 28; + InternalChildren = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + spriteText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Padding = new MarginPadding + { + Horizontal = 5, + }, + }, + deleteIconButton = new DeleteIconButton + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + X = -5, + Size = new Vector2(20), + Action = () => + { + RemoveItem(item); + }, + } + }; + } + + protected abstract void RemoveItem(TItem item); + + protected string Text + { + set => spriteText.Text = value; + } + + protected void ChangeDisplayOrder(int order) + { + Schedule(() => + { + sectionItemsEditorProvider.UpdateDisplayOrder(this, order); + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + background.Colour = colour.YellowLight; + spriteText.Colour = colour.YellowDarker; + deleteIconButton.IconColour = colour.YellowDarker; + } + } +} From 6d8260921b07add3951d098f9b4882a4a9f3c2c6 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Tue, 17 Jan 2023 22:16:09 +0800 Subject: [PATCH 3/6] Apply the base class for the page section. --- .../Beatmaps/Pages/Settings/PagesSection.cs | 192 +++++------------- 1 file changed, 48 insertions(+), 144 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Pages/Settings/PagesSection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Pages/Settings/PagesSection.cs index 2183cdba6..e03fe7b4d 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Pages/Settings/PagesSection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Pages/Settings/PagesSection.cs @@ -1,25 +1,14 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Specialized; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; using osu.Game.Extensions; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps; -using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Components.UserInterface; using osu.Game.Screens.Edit; -using osuTK; namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Pages.Settings; @@ -27,160 +16,75 @@ public partial class PagesSection : EditorSection { protected override LocalisableString Title => "Pages"; - private readonly IBindableList bindablePages = new BindableList(); - - private FillFlowContainer? fillFlowContainer => Content as FillFlowContainer; - public PagesSection() { - if (fillFlowContainer != null) - { - fillFlowContainer.LayoutDuration = 100; - fillFlowContainer.LayoutEasing = Easing.Out; - } - - bindablePages.BindCollectionChanged((_, args) => - { - switch (args.Action) - { - case NotifyCollectionChangedAction.Add: - Debug.Assert(args.NewItems != null); - - foreach (var obj in args.NewItems.OfType()) - { - Add(new LabelledPage(obj) - { - DepthChanged = updatePagePosition - }); - } - - break; - - case NotifyCollectionChangedAction.Remove: - Debug.Assert(args.OldItems != null); - - foreach (var obj in args.OldItems.OfType()) - { - var drawable = Children.OfType().FirstOrDefault(x => x.Page == obj); - if (drawable == null) - return; - - Remove(drawable, true); - } - - break; - } - }); - - addCreateButton(); - } - - private void addCreateButton() - { - fillFlowContainer?.Insert(int.MaxValue, new CreateNewPageButton()); - } - - private void updatePagePosition(Drawable drawable, float newPosition) - { - fillFlowContainer?.SetLayoutPosition(drawable, newPosition); - } - - [BackgroundDependencyLoader] - private void load(IPageStateProvider pageStateProvider) - { - bindablePages.BindTo(pageStateProvider.PageInfo.Pages); + Add(new SectionPageInfoEditor()); } - private partial class LabelledPage : CompositeDrawable + private partial class SectionPageInfoEditor : SectionTimingInfoItemsEditor { - public readonly Page Page; - - public Action? DepthChanged; - - private readonly IBindable pagesVersion = new Bindable(); + [BackgroundDependencyLoader] + private void load(IPageStateProvider pageStateProvider) + { + Items.BindTo(pageStateProvider.PageInfo.Pages); + } - [Resolved, AllowNull] - private IBeatmapPagesChangeHandler beatmapPagesChangeHandler { get; set; } + protected override DrawableTimingInfoItem CreateTimingInfoDrawable(Page item) => new DrawablePage(item); - private readonly Box background; - private readonly OsuSpriteText spriteText; - private readonly DeleteIconButton deleteIconButton; + protected override EditorSectionButton? CreateCreateNewItemButton() => new CreateNewPageButton(); - public LabelledPage(Page page) + private partial class DrawablePage : DrawableTimingInfoItem { - Page = page; + private readonly IBindable pagesVersion = new Bindable(); + + [Resolved, AllowNull] + private IBeatmapPagesChangeHandler beatmapPagesChangeHandler { get; set; } - Masking = true; - CornerRadius = 5; - RelativeSizeAxes = Axes.X; - Height = 28; - InternalChildren = new Drawable[] + public DrawablePage(Page item) + : base(item) { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - spriteText = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Padding = new MarginPadding - { - Horizontal = 5, - }, - }, - deleteIconButton = new DeleteIconButton - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - X = -5, - Size = new Vector2(20), - Action = () => - { - beatmapPagesChangeHandler.Remove(page); - }, - } - }; - } + } - [BackgroundDependencyLoader] - private void load(OsuColour colour, IPageStateProvider pageStateProvider) - { - background.Colour = colour.YellowLight; - spriteText.Colour = colour.YellowDarker; - deleteIconButton.IconColour = colour.YellowDarker; + protected override void RemoveItem(Page item) + { + beatmapPagesChangeHandler.Remove(item); + } - pagesVersion.BindTo(pageStateProvider.PageInfo.PagesVersion); - pagesVersion.BindValueChanged(_ => + [BackgroundDependencyLoader] + private void load(IPageStateProvider pageStateProvider) { - int? order = pageStateProvider.PageInfo.GetPageOrder(Page); - double time = Page.Time; + pagesVersion.BindTo(pageStateProvider.PageInfo.PagesVersion); + pagesVersion.BindValueChanged(_ => + { + int? order = pageStateProvider.PageInfo.GetPageOrder(Item); + double time = Item.Time; - DepthChanged?.Invoke(this, (float)time); - spriteText.Text = $"#{order} {time.ToEditorFormattedString()}"; - }, true); + ChangeDisplayOrder((int)time); + Text = $"#{order} {time.ToEditorFormattedString()}"; + }, true); + } } - } - private partial class CreateNewPageButton : EditorSectionButton - { - [Resolved, AllowNull] - private IBeatmapPagesChangeHandler beatmapPagesChangeHandler { get; set; } + private partial class CreateNewPageButton : EditorSectionButton + { + [Resolved, AllowNull] + private IBeatmapPagesChangeHandler beatmapPagesChangeHandler { get; set; } - [Resolved, AllowNull] - private EditorClock clock { get; set; } + [Resolved, AllowNull] + private EditorClock clock { get; set; } - public CreateNewPageButton() - { - Text = "Create new page"; - Action = () => + public CreateNewPageButton() { - double currentTime = clock.CurrentTime; - beatmapPagesChangeHandler.Add(new Page + Text = "Create new page"; + Action = () => { - Time = currentTime - }); - }; + double currentTime = clock.CurrentTime; + beatmapPagesChangeHandler.Add(new Page + { + Time = currentTime + }); + }; + } } } } From 5390acd5a11ec96799fba67bf324ed6657eefaf0 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Wed, 18 Jan 2023 00:31:42 +0800 Subject: [PATCH 4/6] Implement lyric properties section for able to display list of items in the lyric at the same time. --- .../Lyrics/Settings/LyricPropertiesSection.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/LyricPropertiesSection.cs diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/LyricPropertiesSection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/LyricPropertiesSection.cs new file mode 100644 index 000000000..41db5216a --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/LyricPropertiesSection.cs @@ -0,0 +1,44 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Bindables; +using osu.Game.Rulesets.Karaoke.Objects; + +namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Settings; + +public abstract partial class LyricPropertiesSection : LyricPropertySection where TModel : class +{ + private readonly LyricPropertiesEditor itemsEditor; + + protected LyricPropertiesSection() + { + Add(itemsEditor = CreateLyricPropertiesEditor()); + } + + protected sealed override void OnLyricChanged(Lyric? lyric) + { + itemsEditor.OnLyricChanged(lyric); + } + + protected abstract LyricPropertiesEditor CreateLyricPropertiesEditor(); + + protected abstract partial class LyricPropertiesEditor : SectionItemsEditor + { + private Lyric? currentLyric; + + protected Lyric CurrentLyric => currentLyric ?? throw new InvalidOperationException(); + + public void OnLyricChanged(Lyric? lyric) + { + currentLyric = lyric; + + Items.UnbindBindings(); + + if (lyric != null) + Items.BindTo(GetItems(lyric)); + } + + protected abstract IBindableList GetItems(Lyric lyric); + } +} From 357cc30a669dbf7579bb1ac738ce3c2e80a7353b Mon Sep 17 00:00:00 2001 From: andy840119 Date: Wed, 18 Jan 2023 00:34:17 +0800 Subject: [PATCH 5/6] Use the new base class in the note edit property section. --- .../Settings/Notes/NoteEditPropertySection.cs | 121 +++++++++--------- 1 file changed, 57 insertions(+), 64 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Notes/NoteEditPropertySection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Notes/NoteEditPropertySection.cs index bc84135a4..7d86eacf8 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Notes/NoteEditPropertySection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/Notes/NoteEditPropertySection.cs @@ -4,85 +4,24 @@ #nullable disable using System; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; -using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Notes; using osu.Game.Rulesets.Karaoke.Edit.Utils; +using osu.Game.Rulesets.Karaoke.Extensions; using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States.Modes; using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Settings.Notes { - public partial class NoteEditPropertySection : LyricPropertySection + public partial class NoteEditPropertySection : LyricPropertiesSection { protected override LocalisableString Title => "Properties"; - private readonly Bindable notes = new(); - private readonly Bindable bindableNoteEditPropertyMode = new(); - - [Resolved] - private EditorBeatmap beatmap { get; set; } - - public NoteEditPropertySection() - { - bindableNoteEditPropertyMode.BindValueChanged(e => - { - reCreateEditComponents(); - }); - - notes.BindValueChanged(e => - { - reCreateEditComponents(); - }); - - void reCreateEditComponents() - { - RemoveAll(x => x is LabelledObjectFieldTextBox, true); - RemoveAll(x => x is LabelledSwitchButton, true); - - if (notes.Value == null) - return; - - AddRange(notes.Value.Select(x => - { - int index = Array.IndexOf(notes.Value, x); - return bindableNoteEditPropertyMode.Value switch - { - NoteEditPropertyMode.Text => new LabelledNoteTextTextBox(x) - { - Label = $"#{index + 1}", - TabbableContentContainer = this - } as Drawable, - NoteEditPropertyMode.RubyText => new LabelledNoteRubyTextTextBox(x) - { - Label = x.Text, - TabbableContentContainer = this - }, - NoteEditPropertyMode.Display => new LabelledNoteDisplaySwitchButton(x) - { - Label = x.Text, - }, - _ => throw new ArgumentOutOfRangeException(nameof(bindableNoteEditPropertyMode.Value)) - }; - })); - } - } - - [BackgroundDependencyLoader] - private void load(IEditNoteModeState editNoteModeState) - { - bindableNoteEditPropertyMode.BindTo(editNoteModeState.NoteEditPropertyMode); - } - - protected override void OnLyricChanged(Lyric lyric) - { - notes.Value = EditorBeatmapUtils.GetNotesByLyric(beatmap, lyric).ToArray(); - } + protected override LyricPropertiesEditor CreateLyricPropertiesEditor() => new NotePropertiesEditor(); protected override LockLyricPropertyBy? IsWriteLyricPropertyLocked(Lyric lyric) => HitObjectWritableUtils.GetCreateOrRemoveNoteLockedBy(lyric); //todo: should reference by another utils. @@ -103,6 +42,60 @@ protected override LocalisableString GetWriteLyricPropertyLockedTooltip(LockLyri _ => throw new ArgumentOutOfRangeException(nameof(lockLyricPropertyBy), lockLyricPropertyBy, null) }; + private partial class NotePropertiesEditor : LyricPropertiesEditor + { + private readonly Bindable bindableNoteEditPropertyMode = new(); + + [Resolved] + private EditorBeatmap beatmap { get; set; } + + public NotePropertiesEditor() + { + bindableNoteEditPropertyMode.BindValueChanged(e => + { + RedrewContent(); + }); + } + + [BackgroundDependencyLoader] + private void load(IEditNoteModeState editNoteModeState) + { + bindableNoteEditPropertyMode.BindTo(editNoteModeState.NoteEditPropertyMode); + } + + protected override Drawable CreateDrawable(Note item) + { + // todo: deal with create or remove the notes. + int index = Items.IndexOf(item); + return bindableNoteEditPropertyMode.Value switch + { + NoteEditPropertyMode.Text => new LabelledNoteTextTextBox(item) + { + Label = $"#{index + 1}", + TabbableContentContainer = this + }, + NoteEditPropertyMode.RubyText => new LabelledNoteRubyTextTextBox(item) + { + Label = item.Text, + TabbableContentContainer = this + }, + NoteEditPropertyMode.Display => new LabelledNoteDisplaySwitchButton(item) + { + Label = item.Text, + }, + _ => throw new ArgumentOutOfRangeException(nameof(bindableNoteEditPropertyMode.Value)) + }; + } + + protected override EditorSectionButton CreateCreateNewItemButton() => null; + + protected override IBindableList GetItems(Lyric lyric) + { + var notes = EditorBeatmapUtils.GetNotesByLyric(beatmap, lyric); + return new BindableList(notes); + } + } + private partial class LabelledNoteTextTextBox : LabelledObjectFieldTextBox { [Resolved] From ee86be3779c51f33af90e50dc60950fa603c4d9a Mon Sep 17 00:00:00 2001 From: andy840119 Date: Wed, 18 Jan 2023 00:56:58 +0800 Subject: [PATCH 6/6] Apply the base class for the ruby/romaji edit section. --- .../RubyRomaji/RomajiTagEditSection.cs | 45 +++++----- .../Settings/RubyRomaji/RubyTagEditSection.cs | 45 +++++----- .../Settings/RubyRomaji/TextTagEditSection.cs | 90 +++++++------------ 3 files changed, 82 insertions(+), 98 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RomajiTagEditSection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RomajiTagEditSection.cs index 4b91191fa..35ef0e568 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RomajiTagEditSection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RomajiTagEditSection.cs @@ -20,26 +20,7 @@ public partial class RomajiTagEditSection : TextTagEditSection { protected override LocalisableString Title => "Romaji"; - [Resolved] - private ILyricRomajiTagsChangeHandler romajiTagsChangeHandler { get; set; } - - protected override IBindableList GetBindableTextTags(Lyric lyric) - => lyric.RomajiTagsBindable; - - protected override LabelledTextTagTextBox CreateLabelledTextTagTextBox(Lyric lyric, RomajiTag textTag) - => new LabelledRomajiTagTextBox(lyric, textTag); - - protected override void AddTextTag(RomajiTag textTag) - => romajiTagsChangeHandler.Add(textTag); - - protected override LocalisableString CreateNewTextTagButtonText() - => "Create new romaji"; - - protected override LocalisableString CreateNewTextTagTitle() - => "Romaji"; - - protected override LocalisableString CreateNewTextTagDescription() - => "Please enter the romaji."; + protected override LyricPropertiesEditor CreateLyricPropertiesEditor() => new RomajiTagsEditor(); protected override LockLyricPropertyBy? IsWriteLyricPropertyLocked(Lyric lyric) => HitObjectWritableUtils.GetLyricPropertyLockedBy(lyric, nameof(Lyric.RomajiTags)); @@ -60,6 +41,30 @@ protected override LocalisableString GetWriteLyricPropertyLockedTooltip(LockLyri _ => throw new ArgumentOutOfRangeException(nameof(lockLyricPropertyBy), lockLyricPropertyBy, null) }; + private partial class RomajiTagsEditor : TextTagsEditor + { + [Resolved] + private ILyricRomajiTagsChangeHandler romajiTagsChangeHandler { get; set; } + + protected override IBindableList GetItems(Lyric lyric) + => lyric.RomajiTagsBindable; + + protected override LabelledTextTagTextBox CreateLabelledTextTagTextBox(Lyric lyric, RomajiTag textTag) + => new LabelledRomajiTagTextBox(lyric, textTag); + + protected override void AddTextTag(RomajiTag textTag) + => romajiTagsChangeHandler.Add(textTag); + + protected override LocalisableString CreateNewTextTagButtonText() + => "Create new romaji"; + + protected override LocalisableString CreateNewTextTagTitle() + => "Romaji"; + + protected override LocalisableString CreateNewTextTagDescription() + => "Please enter the romaji."; + } + protected partial class LabelledRomajiTagTextBox : LabelledTextTagTextBox { [Resolved] diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RubyTagEditSection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RubyTagEditSection.cs index f078c7e4a..13722735e 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RubyTagEditSection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/RubyTagEditSection.cs @@ -20,26 +20,7 @@ public partial class RubyTagEditSection : TextTagEditSection { protected override LocalisableString Title => "Ruby"; - [Resolved] - private ILyricRubyTagsChangeHandler rubyTagsChangeHandler { get; set; } - - protected override IBindableList GetBindableTextTags(Lyric lyric) - => lyric.RubyTagsBindable; - - protected override LabelledTextTagTextBox CreateLabelledTextTagTextBox(Lyric lyric, RubyTag textTag) - => new LabelledRubyTagTextBox(lyric, textTag); - - protected override void AddTextTag(RubyTag textTag) - => rubyTagsChangeHandler.Add(textTag); - - protected override LocalisableString CreateNewTextTagButtonText() - => "Create new ruby"; - - protected override LocalisableString CreateNewTextTagTitle() - => "Ruby"; - - protected override LocalisableString CreateNewTextTagDescription() - => "Please enter the ruby."; + protected override LyricPropertiesEditor CreateLyricPropertiesEditor() => new RubyTagsEditor(); protected override LockLyricPropertyBy? IsWriteLyricPropertyLocked(Lyric lyric) => HitObjectWritableUtils.GetLyricPropertyLockedBy(lyric, nameof(Lyric.RubyTags)); @@ -60,6 +41,30 @@ protected override LocalisableString GetWriteLyricPropertyLockedTooltip(LockLyri _ => throw new ArgumentOutOfRangeException(nameof(lockLyricPropertyBy), lockLyricPropertyBy, null) }; + private partial class RubyTagsEditor : TextTagsEditor + { + [Resolved] + private ILyricRubyTagsChangeHandler rubyTagsChangeHandler { get; set; } + + protected override IBindableList GetItems(Lyric lyric) + => lyric.RubyTagsBindable; + + protected override LabelledTextTagTextBox CreateLabelledTextTagTextBox(Lyric lyric, RubyTag textTag) + => new LabelledRubyTagTextBox(lyric, textTag); + + protected override void AddTextTag(RubyTag textTag) + => rubyTagsChangeHandler.Add(textTag); + + protected override LocalisableString CreateNewTextTagButtonText() + => "Create new ruby"; + + protected override LocalisableString CreateNewTextTagTitle() + => "Ruby"; + + protected override LocalisableString CreateNewTextTagDescription() + => "Please enter the ruby."; + } + protected partial class LabelledRubyTagTextBox : LabelledTextTagTextBox { [Resolved] diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/TextTagEditSection.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/TextTagEditSection.cs index 6a4c28045..0ba911e6b 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/TextTagEditSection.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Settings/RubyRomaji/TextTagEditSection.cs @@ -3,10 +3,8 @@ #nullable disable -using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Objects.Types; @@ -15,72 +13,48 @@ namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Settings.RubyRomaji { - public abstract partial class TextTagEditSection : LyricPropertySection where TTextTag : class, ITextTag, new() + public abstract partial class TextTagEditSection : LyricPropertiesSection where TTextTag : class, ITextTag, new() { - protected readonly IBindableList TextTags = new BindableList(); - - private Lyric lyric; - - protected TextTagEditSection() + protected abstract partial class TextTagsEditor : LyricPropertiesEditor { - // add create button. - addCreateButton(); - - // create list of text-tag text-box if bindable changed. - TextTags.BindCollectionChanged((_, _) => + protected sealed override Drawable CreateDrawable(TTextTag item) { - RemoveAll(x => x is LabelledTextTagTextBox, true); - AddRange(TextTags.Select(x => - { - string relativeToLyricText = TextTagUtils.GetTextFromLyric(x, lyric.Text); - string range = TextTagUtils.PositionFormattedString(x); - - return CreateLabelledTextTagTextBox(lyric, x).With(t => - { - t.Label = relativeToLyricText; - t.Description = range; - t.TabbableContentContainer = this; - }); - })); - }); - } - - protected override void OnLyricChanged(Lyric lyric) - { - TextTags.UnbindBindings(); - - if (lyric == null) - return; - - this.lyric = lyric; + string relativeToLyricText = TextTagUtils.GetTextFromLyric(item, CurrentLyric.Text); + string range = TextTagUtils.PositionFormattedString(item); - TextTags.BindTo(GetBindableTextTags(lyric)); - } + return CreateLabelledTextTagTextBox(CurrentLyric, item).With(t => + { + t.Label = relativeToLyricText; + t.Description = range; + t.TabbableContentContainer = this; + }); + } - private void addCreateButton() - { - var fillFlowContainer = Content as FillFlowContainer; + protected abstract LabelledTextTagTextBox CreateLabelledTextTagTextBox(Lyric lyric, TTextTag textTag); - // create new button. - fillFlowContainer?.Insert(int.MaxValue, new CreateNewTextTagButton + protected override EditorSectionButton CreateCreateNewItemButton() { - Text = CreateNewTextTagButtonText(), - LabelledTextBoxLabel = CreateNewTextTagTitle(), - LabelledTextBoxDescription = CreateNewTextTagDescription(), - Action = AddTextTag - }); - } - - protected abstract IBindableList GetBindableTextTags(Lyric lyric); - - protected abstract LabelledTextTagTextBox CreateLabelledTextTagTextBox(Lyric lyric, TTextTag textTag); + return new CreateNewTextTagButton + { + Text = CreateNewTextTagButtonText(), + LabelledTextBoxLabel = CreateNewTextTagTitle(), + LabelledTextBoxDescription = CreateNewTextTagDescription(), + Action = AddTextTag + }; + } + + protected override IBindableList GetItems(Lyric lyric) + { + throw new System.NotImplementedException(); + } - protected abstract void AddTextTag(TTextTag textTag); + protected abstract LocalisableString CreateNewTextTagButtonText(); - protected abstract LocalisableString CreateNewTextTagButtonText(); + protected abstract LocalisableString CreateNewTextTagTitle(); - protected abstract LocalisableString CreateNewTextTagTitle(); + protected abstract LocalisableString CreateNewTextTagDescription(); - protected abstract LocalisableString CreateNewTextTagDescription(); + protected abstract void AddTextTag(TTextTag textTag); + } } }