mirror of https://github.com/ppy/osu
76 lines
2.4 KiB
C#
76 lines
2.4 KiB
C#
// 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.
|
|
|
|
#nullable disable
|
|
|
|
using System;
|
|
using osu.Framework.Graphics;
|
|
|
|
namespace osu.Game.Screens.Edit
|
|
{
|
|
/// <summary>
|
|
/// A component that tracks a batch change, only applying after all active changes are completed.
|
|
/// </summary>
|
|
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;
|
|
|
|
private int bulkChangesStarted;
|
|
|
|
/// <summary>
|
|
/// Signal the beginning of a change.
|
|
/// </summary>
|
|
public void BeginChange()
|
|
{
|
|
if (bulkChangesStarted++ == 0)
|
|
TransactionBegan?.Invoke();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Signal the end of a change.
|
|
/// </summary>
|
|
/// <exception cref="InvalidOperationException">Throws if <see cref="BeginChange"/> was not first called.</exception>
|
|
public void EndChange()
|
|
{
|
|
if (bulkChangesStarted == 0)
|
|
throw new InvalidOperationException($"Cannot call {nameof(EndChange)} without a previous call to {nameof(BeginChange)}.");
|
|
|
|
if (--bulkChangesStarted == 0)
|
|
{
|
|
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()
|
|
{
|
|
if (bulkChangesStarted > 0)
|
|
return;
|
|
|
|
SaveStateTriggered?.Invoke();
|
|
UpdateState();
|
|
}
|
|
|
|
protected abstract void UpdateState();
|
|
}
|
|
}
|