Skip to content

Commit

Permalink
Merge pull request karaoke-dev#2131 from andy840119/create-popover-fo…
Browse files Browse the repository at this point in the history
…r-ruby-blueprint

Create popover for able to edit ruby text.
  • Loading branch information
andy840119 authored Sep 24, 2023
2 parents 10de4b8 + 188eae8 commit aa67f3f
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 86 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Input.Events;
using osu.Game.Rulesets.Karaoke.Objects;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States.Modes;

namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Components.Lyrics.Blueprints;

public abstract partial class LyricPropertyBlueprintContainer<T> : BindableBlueprintContainer<T> where T : class
{
[Resolved]
private ILyricCaretState lyricCaretState { get; set; } = null!;

private readonly BindableList<T> lyricListProperties;

protected readonly Lyric Lyric;

protected LyricPropertyBlueprintContainer(Lyric lyric)
{
lyricListProperties = GetProperties(lyric);
Lyric = lyric;
}

protected abstract BindableList<T> GetProperties(Lyric lyric);

[BackgroundDependencyLoader]
private void load()
{
// Make it auto create or remove the blueprint by the list.
RegisterBindable(lyricListProperties);
}

protected override bool OnClick(ClickEvent e)
{
lyricCaretState.MoveCaretToTargetPosition(Lyric);
return base.OnClick(e);
}

protected override bool OnDragStart(DragStartEvent e)
{
lyricCaretState.MoveCaretToTargetPosition(Lyric);
return base.OnDragStart(e);
}

protected abstract partial class LyricPropertySelectionHandler<TModeState> : BindableSelectionHandler
where TModeState : IHasBlueprintSelection<T>
{
[BackgroundDependencyLoader]
private void load(TModeState modeState)
{
SelectedItems.BindTo(modeState.SelectedItems);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text.

using System.Collections.Generic;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Rulesets.Edit;
Expand All @@ -15,39 +14,25 @@ namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Components.Lyri

public partial class RomajiBlueprintContainer : TextTagBlueprintContainer<RomajiTag>
{
[UsedImplicitly]
private readonly BindableList<RomajiTag> romajiTags;

public RomajiBlueprintContainer(Lyric lyric)
: base(lyric)
{
romajiTags = lyric.RomajiTagsBindable.GetBoundCopy();
}

[BackgroundDependencyLoader]
private void load()
{
// Add romaji tag into blueprint container
RegisterBindable(romajiTags);
}
protected override BindableList<RomajiTag> GetProperties(Lyric lyric)
=> lyric.RomajiTagsBindable.GetBoundCopy();

protected override SelectionHandler<RomajiTag> CreateSelectionHandler()
=> new RomajiTagSelectionHandler();

protected override SelectionBlueprint<RomajiTag> CreateBlueprintFor(RomajiTag item)
=> new RomajiTagSelectionBlueprint(item);

protected partial class RomajiTagSelectionHandler : TextTagSelectionHandler
protected partial class RomajiTagSelectionHandler : TextTagSelectionHandler<IEditRomajiModeState>
{
[Resolved]
private ILyricRomajiTagsChangeHandler romajiTagsChangeHandler { get; set; } = null!;

[BackgroundDependencyLoader]
private void load(IEditRomajiModeState editRomajiModeState)
{
SelectedItems.BindTo(editRomajiModeState.SelectedItems);
}

protected override void DeleteItems(IEnumerable<RomajiTag> items)
=> romajiTagsChangeHandler.RemoveRange(items);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text.

using System.Collections.Generic;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Rulesets.Edit;
Expand All @@ -15,39 +14,25 @@ namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Components.Lyri

public partial class RubyBlueprintContainer : TextTagBlueprintContainer<RubyTag>
{
[UsedImplicitly]
private readonly BindableList<RubyTag> rubyTags;

public RubyBlueprintContainer(Lyric lyric)
: base(lyric)
{
rubyTags = lyric.RubyTagsBindable.GetBoundCopy();
}

[BackgroundDependencyLoader]
private void load()
{
// Add ruby tag into blueprint container
RegisterBindable(rubyTags);
}
protected override BindableList<RubyTag> GetProperties(Lyric lyric)
=> lyric.RubyTagsBindable.GetBoundCopy();

protected override SelectionHandler<RubyTag> CreateSelectionHandler()
=> new RubyTagSelectionHandler();

protected override SelectionBlueprint<RubyTag> CreateBlueprintFor(RubyTag item)
=> new RubyTagSelectionBlueprint(item);

protected partial class RubyTagSelectionHandler : TextTagSelectionHandler
protected partial class RubyTagSelectionHandler : TextTagSelectionHandler<IEditRubyModeState>
{
[Resolved]
private ILyricRubyTagsChangeHandler rubyTagsChangeHandler { get; set; } = null!;

[BackgroundDependencyLoader]
private void load(IEditRubyModeState editRubyModeState)
{
SelectedItems.BindTo(editRubyModeState.SelectedItems);
}

protected override void DeleteItems(IEnumerable<RubyTag> items)
=> rubyTagsChangeHandler.RemoveRange(items);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,26 @@
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics;
using osu.Game.Rulesets.Karaoke.Objects;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States.Modes;
using osuTK;

namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Components.Lyrics.Blueprints;

public partial class RubyTagSelectionBlueprint : TextTagSelectionBlueprint<RubyTag>
public partial class RubyTagSelectionBlueprint : TextTagSelectionBlueprint<RubyTag>, IHasPopover
{
[Resolved]
private IEditRubyModeState editRubyModeState { get; set; } = null!;

[UsedImplicitly]
private readonly Bindable<string> text;

Expand All @@ -35,4 +49,91 @@ private void load()
startIndex.BindValueChanged(_ => UpdatePositionAndSize());
endIndex.BindValueChanged(_ => UpdatePositionAndSize());
}

public Popover GetPopover() => new RubyEditPopover(Item);

protected override bool OnClick(ClickEvent e)
{
Schedule(() =>
{
// should select the current item after popover opened, or other popover closed.
editRubyModeState.Select(Item);
});

this.ShowPopover();
return base.OnClick(e);
}

private partial class RubyEditPopover : OsuPopover
{
[Resolved]
private ILyricRubyTagsChangeHandler lyricRubyTagsChangeHandler { get; set; } = null!;

private readonly LabelledTextBox labelledRubyTextBox;

public RubyEditPopover(RubyTag rubyTag)
{
AllowableAnchors = new[] { Anchor.TopCentre, Anchor.BottomCentre };
Child = new FillFlowContainer
{
Width = 200,
Direction = FillDirection.Vertical,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0, 10),
Children = new Drawable[]
{
labelledRubyTextBox = new LabelledTextBox
{
Label = "Ruby",
Current =
{
Value = rubyTag.Text,
},
},
new DeleteRubyButton
{
Text = "Delete",
Action = deleteRubyText,
},
},
};

labelledRubyTextBox.OnCommit += (_, newText) =>
{
if (newText)
{
editRubyText();
}
};

return;

void editRubyText()
{
lyricRubyTagsChangeHandler.SetText(rubyTag, labelledRubyTextBox.Text);
this.HidePopover();
}

void deleteRubyText()
{
lyricRubyTagsChangeHandler.Remove(rubyTag);
this.HidePopover();
}
}

protected override void LoadComplete()
{
base.LoadComplete();
ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(labelledRubyTextBox));
}

private partial class DeleteRubyButton : EditorSectionButton
{
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
BackgroundColour = colours.Pink3;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,29 @@
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Input.Events;
using osu.Framework.Logging;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Karaoke.Objects;
using osu.Game.Rulesets.Karaoke.Objects.Types;
using osu.Game.Rulesets.Karaoke.Objects.Utils;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States.Modes;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;

namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Components.Lyrics.Blueprints;

public abstract partial class TextTagBlueprintContainer<T> : BindableBlueprintContainer<T> where T : class, ITextTag
public abstract partial class TextTagBlueprintContainer<T> : LyricPropertyBlueprintContainer<T> where T : class, ITextTag
{
[Resolved]
private ILyricCaretState lyricCaretState { get; set; } = null!;

protected readonly Lyric Lyric;

protected TextTagBlueprintContainer(Lyric lyric)
: base(lyric)
{
Lyric = lyric;
}

protected override bool OnMouseDown(MouseDownEvent e)
{
lyricCaretState.MoveCaretToTargetPosition(Lyric);
return base.OnMouseDown(e);
}

protected override IEnumerable<SelectionBlueprint<T>> SortForMovement(IReadOnlyList<SelectionBlueprint<T>> blueprints)
=> blueprints.OrderBy(b => b.Item.StartIndex);

protected abstract partial class TextTagSelectionHandler : BindableSelectionHandler
protected abstract partial class TextTagSelectionHandler<TModeState> : LyricPropertySelectionHandler<TModeState>
where TModeState : IHasBlueprintSelection<T>
{
[Resolved]
private IPreviewLyricPositionProvider previewLyricPositionProvider { get; set; } = null!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,37 @@
// See the LICENCE file in the repository root for full licence text.

using System.Collections.Generic;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Input.Events;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics;
using osu.Game.Rulesets.Karaoke.Objects;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States.Modes;
using osu.Game.Screens.Edit.Compose.Components;

namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Components.Lyrics.Blueprints;

public partial class TimeTagBlueprintContainer : BindableBlueprintContainer<TimeTag>
public partial class TimeTagBlueprintContainer : LyricPropertyBlueprintContainer<TimeTag>
{
[Resolved]
private ILyricCaretState lyricCaretState { get; set; } = null!;

[UsedImplicitly]
private readonly BindableList<TimeTag> timeTags;

protected readonly Lyric Lyric;

public TimeTagBlueprintContainer(Lyric lyric)
: base(lyric)
{
Lyric = lyric;
timeTags = lyric.TimeTagsBindable.GetBoundCopy();
}

protected override bool OnMouseDown(MouseDownEvent e)
{
lyricCaretState.MoveCaretToTargetPosition(Lyric);
return base.OnMouseDown(e);
}

[BackgroundDependencyLoader]
private void load()
{
// Add time tag into blueprint container
RegisterBindable(timeTags);
}
protected override BindableList<TimeTag> GetProperties(Lyric lyric)
=> lyric.TimeTagsBindable.GetBoundCopy();

protected override SelectionHandler<TimeTag> CreateSelectionHandler()
=> new TimeTagSelectionHandler();

protected override SelectionBlueprint<TimeTag> CreateBlueprintFor(TimeTag item)
=> new TimeTagSelectionBlueprint(item);

protected partial class TimeTagSelectionHandler : BindableSelectionHandler
protected partial class TimeTagSelectionHandler : LyricPropertySelectionHandler<ITimeTagModeState>
{
[Resolved]
private ILyricTimeTagsChangeHandler lyricTimeTagsChangeHandler { get; set; } = null!;

[BackgroundDependencyLoader]
private void load(ITimeTagModeState timeTagModeState)
{
SelectedItems.BindTo(timeTagModeState.SelectedItems);
}

// for now we always allow movement. snapping is provided by the Timeline's "distance" snap implementation
public override bool HandleMovement(MoveSelectionEvent<TimeTag> moveEvent) => true;

Expand Down
Loading

0 comments on commit aa67f3f

Please sign in to comment.