1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-15 09:33:02 +08:00

Merge pull request #15545 from bdach/editor-clipboard-refactor

Move clipboard operation implementations to individual editor subscreens
This commit is contained in:
Dean Herbert 2021-11-11 02:09:19 +09:00 committed by GitHub
commit 61225092bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 163 additions and 62 deletions

View File

@ -22,6 +22,9 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
[Resolved]
private SkinManager skins { get; set; }
[Cached]
private EditorClipboard clipboard = new EditorClipboard();
[SetUpSteps]
public void SetUpSteps()
{

View File

@ -26,6 +26,9 @@ namespace osu.Game.Tests.Visual.Editing
}
});
[Cached]
private EditorClipboard clipboard = new EditorClipboard();
[BackgroundDependencyLoader]
private void load()
{

View File

@ -7,29 +7,26 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Extensions;
using osu.Game.IO.Serialization;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Edit;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
namespace osu.Game.Screens.Edit.Compose
{
public class ComposeScreen : EditorScreenWithTimeline, IKeyBindingHandler<PlatformAction>
public class ComposeScreen : EditorScreenWithTimeline
{
[Resolved]
private IBindable<WorkingBeatmap> beatmap { get; set; }
[Resolved]
private GameHost host { get; set; }
[Resolved]
private EditorClock clock { get; set; }
private Bindable<string> clipboard { get; set; }
private HitObjectComposer composer;
public ComposeScreen()
@ -76,18 +73,65 @@ namespace osu.Game.Screens.Edit.Compose
return new EditorSkinProvidingContainer(EditorBeatmap).WithChild(content);
}
#region Input Handling
public bool OnPressed(KeyBindingPressEvent<PlatformAction> e)
[BackgroundDependencyLoader]
private void load(EditorClipboard clipboard)
{
if (e.Action == PlatformAction.Copy)
host.GetClipboard()?.SetText(formatSelectionAsString());
return false;
this.clipboard = clipboard.Content.GetBoundCopy();
}
public void OnReleased(KeyBindingReleaseEvent<PlatformAction> e)
protected override void LoadComplete()
{
base.LoadComplete();
EditorBeatmap.SelectedHitObjects.BindCollectionChanged((_, __) => updateClipboardActionAvailability());
clipboard.BindValueChanged(_ => updateClipboardActionAvailability(), true);
}
#region Clipboard operations
protected override void PerformCut()
{
base.PerformCut();
Copy();
EditorBeatmap.RemoveRange(EditorBeatmap.SelectedHitObjects.ToArray());
}
protected override void PerformCopy()
{
base.PerformCopy();
clipboard.Value = new ClipboardContent(EditorBeatmap).Serialize();
host.GetClipboard()?.SetText(formatSelectionAsString());
}
protected override void PerformPaste()
{
base.PerformPaste();
var objects = clipboard.Value.Deserialize<ClipboardContent>().HitObjects;
Debug.Assert(objects.Any());
double timeOffset = clock.CurrentTime - objects.Min(o => o.StartTime);
foreach (var h in objects)
h.StartTime += timeOffset;
EditorBeatmap.BeginChange();
EditorBeatmap.SelectedHitObjects.Clear();
EditorBeatmap.AddRange(objects);
EditorBeatmap.SelectedHitObjects.AddRange(objects);
EditorBeatmap.EndChange();
}
private void updateClipboardActionAvailability()
{
CanCut.Value = CanCopy.Value = EditorBeatmap.SelectedHitObjects.Any();
CanPaste.Value = !string.IsNullOrEmpty(clipboard.Value);
}
private string formatSelectionAsString()

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
using osu.Framework;
@ -24,7 +23,6 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings;
using osu.Game.IO.Serialization;
using osu.Game.Online.API;
using osu.Game.Overlays;
using osu.Game.Rulesets.Edit;
@ -105,6 +103,9 @@ namespace osu.Game.Screens.Edit
[Resolved]
private MusicController music { get; set; }
[Cached]
public readonly EditorClipboard Clipboard = new EditorClipboard();
public Editor(EditorLoader loader = null)
{
this.loader = loader;
@ -180,10 +181,6 @@ namespace osu.Game.Screens.Edit
OsuMenuItem undoMenuItem;
OsuMenuItem redoMenuItem;
EditorMenuItem cutMenuItem;
EditorMenuItem copyMenuItem;
EditorMenuItem pasteMenuItem;
AddInternal(new OsuContextMenuContainer
{
RelativeSizeAxes = Axes.Both,
@ -299,19 +296,15 @@ namespace osu.Game.Screens.Edit
changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true);
changeHandler.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true);
editorBeatmap.SelectedHitObjects.BindCollectionChanged((_, __) =>
{
bool hasObjects = editorBeatmap.SelectedHitObjects.Count > 0;
cutMenuItem.Action.Disabled = !hasObjects;
copyMenuItem.Action.Disabled = !hasObjects;
}, true);
clipboard.BindValueChanged(content => pasteMenuItem.Action.Disabled = string.IsNullOrEmpty(content.NewValue));
menuBar.Mode.ValueChanged += onModeChanged;
}
protected override void LoadComplete()
{
base.LoadComplete();
setUpClipboardActionAvailability();
}
/// <summary>
/// If the beatmap's track has changed, this method must be called to keep the editor in a valid state.
/// </summary>
@ -324,7 +317,7 @@ namespace osu.Game.Screens.Edit
public void RestoreState([NotNull] EditorState state) => Schedule(() =>
{
clock.Seek(state.Time);
clipboard.Value = state.ClipboardContent;
Clipboard.Content.Value = state.ClipboardContent;
});
protected void Save()
@ -561,45 +554,37 @@ namespace osu.Game.Screens.Edit
this.Exit();
}
private readonly Bindable<string> clipboard = new Bindable<string>();
#region Clipboard support
protected void Cut()
private EditorMenuItem cutMenuItem;
private EditorMenuItem copyMenuItem;
private EditorMenuItem pasteMenuItem;
private readonly BindableWithCurrent<bool> canCut = new BindableWithCurrent<bool>();
private readonly BindableWithCurrent<bool> canCopy = new BindableWithCurrent<bool>();
private readonly BindableWithCurrent<bool> canPaste = new BindableWithCurrent<bool>();
private void setUpClipboardActionAvailability()
{
Copy();
editorBeatmap.RemoveRange(editorBeatmap.SelectedHitObjects.ToArray());
canCut.Current.BindValueChanged(cut => cutMenuItem.Action.Disabled = !cut.NewValue, true);
canCopy.Current.BindValueChanged(copy => copyMenuItem.Action.Disabled = !copy.NewValue, true);
canPaste.Current.BindValueChanged(paste => pasteMenuItem.Action.Disabled = !paste.NewValue, true);
}
protected void Copy()
private void rebindClipboardBindables()
{
if (editorBeatmap.SelectedHitObjects.Count == 0)
return;
clipboard.Value = new ClipboardContent(editorBeatmap).Serialize();
canCut.Current = currentScreen.CanCut;
canCopy.Current = currentScreen.CanCopy;
canPaste.Current = currentScreen.CanPaste;
}
protected void Paste()
{
if (string.IsNullOrEmpty(clipboard.Value))
return;
protected void Cut() => currentScreen?.Cut();
var objects = clipboard.Value.Deserialize<ClipboardContent>().HitObjects;
protected void Copy() => currentScreen?.Copy();
Debug.Assert(objects.Any());
protected void Paste() => currentScreen?.Paste();
double timeOffset = clock.CurrentTime - objects.Min(o => o.StartTime);
foreach (var h in objects)
h.StartTime += timeOffset;
editorBeatmap.BeginChange();
editorBeatmap.SelectedHitObjects.Clear();
editorBeatmap.AddRange(objects);
editorBeatmap.SelectedHitObjects.AddRange(objects);
editorBeatmap.EndChange();
}
#endregion
protected void Undo() => changeHandler.RestoreState(-1);
@ -677,6 +662,7 @@ namespace osu.Game.Screens.Edit
finally
{
updateSampleDisabledState();
rebindClipboardBindables();
}
}
@ -757,7 +743,7 @@ namespace osu.Game.Screens.Edit
protected void SwitchToDifficulty(BeatmapInfo nextBeatmap) => loader?.ScheduleDifficultySwitch(nextBeatmap, new EditorState
{
Time = clock.CurrentTimeAccurate,
ClipboardContent = editorBeatmap.BeatmapInfo.RulesetID == nextBeatmap.RulesetID ? clipboard.Value : string.Empty
ClipboardContent = editorBeatmap.BeatmapInfo.RulesetID == nextBeatmap.RulesetID ? Clipboard.Content.Value : string.Empty
});
private void cancelExit()

View File

@ -0,0 +1,15 @@
// 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.
using osu.Framework.Bindables;
namespace osu.Game.Screens.Edit
{
/// <summary>
/// Wraps the contents of the editor clipboard.
/// </summary>
public class EditorClipboard
{
public Bindable<string> Content { get; } = new Bindable<string>();
}
}

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
@ -49,5 +50,54 @@ namespace osu.Game.Screens.Edit
this.ScaleTo(0.98f, 200, Easing.OutQuint)
.FadeOut(200, Easing.OutQuint);
}
#region Clipboard operations
public BindableBool CanCut { get; } = new BindableBool();
/// <summary>
/// Performs a "cut to clipboard" operation appropriate for the given screen.
/// </summary>
protected virtual void PerformCut()
{
}
public void Cut()
{
if (CanCut.Value)
PerformCut();
}
public BindableBool CanCopy { get; } = new BindableBool();
/// <summary>
/// Performs a "copy to clipboard" operation appropriate for the given screen.
/// </summary>
protected virtual void PerformCopy()
{
}
public virtual void Copy()
{
if (CanCopy.Value)
PerformCopy();
}
public BindableBool CanPaste { get; } = new BindableBool();
/// <summary>
/// Performs a "paste from clipboard" operation appropriate for the given screen.
/// </summary>
protected virtual void PerformPaste()
{
}
public virtual void Paste()
{
if (CanPaste.Value)
PerformPaste();
}
#endregion
}
}