Make component and add hooking events

This commit is contained in:
Dean Herbert 2020-10-08 17:17:52 +09:00
parent ce04daf053
commit a9bca671d0

View File

@ -2,14 +2,30 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using osu.Framework.Graphics;
namespace osu.Game.Screens.Edit namespace osu.Game.Screens.Edit
{ {
/// <summary> /// <summary>
/// A component that tracks a batch change, only applying after all active changes are completed. /// A component that tracks a batch change, only applying after all active changes are completed.
/// </summary> /// </summary>
public abstract class TransactionalCommitComponent public abstract class TransactionalCommitComponent : Component
{ {
/// <summary>
/// Fires whenever a transaction begins. Will not fire on nested transactions.
/// </summary>
public event Action TransactionBegan;
/// <summary>
/// Fires when the last transaction completes.
/// </summary>
public event Action TransactionEnded;
/// <summary>
/// Fires when <see cref="SaveState"/> is called and results in a non-transactional state save.
/// </summary>
public event Action SaveStateTriggered;
public bool TransactionActive => bulkChangesStarted > 0; public bool TransactionActive => bulkChangesStarted > 0;
private int bulkChangesStarted; private int bulkChangesStarted;
@ -17,7 +33,11 @@ namespace osu.Game.Screens.Edit
/// <summary> /// <summary>
/// Signal the beginning of a change. /// Signal the beginning of a change.
/// </summary> /// </summary>
public void BeginChange() => bulkChangesStarted++; public void BeginChange()
{
if (bulkChangesStarted++ == 0)
TransactionBegan?.Invoke();
}
/// <summary> /// <summary>
/// Signal the end of a change. /// Signal the end of a change.
@ -29,14 +49,22 @@ namespace osu.Game.Screens.Edit
throw new InvalidOperationException($"Cannot call {nameof(EndChange)} without a previous call to {nameof(BeginChange)}."); throw new InvalidOperationException($"Cannot call {nameof(EndChange)} without a previous call to {nameof(BeginChange)}.");
if (--bulkChangesStarted == 0) if (--bulkChangesStarted == 0)
{
UpdateState(); UpdateState();
TransactionEnded?.Invoke();
}
} }
/// <summary>
/// Force an update of the state with no attached transaction.
/// This is a no-op if a transaction is already active. Should generally be used as a safety measure to ensure granular changes are not left outside a transaction.
/// </summary>
public void SaveState() public void SaveState()
{ {
if (bulkChangesStarted > 0) if (bulkChangesStarted > 0)
return; return;
SaveStateTriggered?.Invoke();
UpdateState(); UpdateState();
} }