Merge branch 'master' into enable-multiple-templates

This commit is contained in:
Dean Herbert
2020-02-18 15:24:40 +09:00
9 changed files with 467 additions and 96 deletions

View File

@@ -3,9 +3,11 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions;
namespace osu.Framework.Tests.Bindables
{
@@ -118,16 +120,25 @@ namespace osu.Framework.Tests.Bindables
{
bindableStringList.Add("0");
#pragma warning disable 618 can be removed 20200817
IEnumerable<string> addedItem = null;
IEnumerable<string> removedItem = null;
bindableStringList.ItemsAdded += v => addedItem = v;
bindableStringList.ItemsRemoved += v => removedItem = v;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList[0] = "1";
Assert.AreEqual(removedItem.Single(), "0");
Assert.AreEqual(addedItem.Single(), "1");
Assert.That(removedItem.Single(), Is.EqualTo("0"));
Assert.That(addedItem.Single(), Is.EqualTo("1"));
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Replace));
Assert.That(triggeredArgs.OldItems, Is.EquivalentTo("0".Yield()));
Assert.That(triggeredArgs.NewItems, Is.EquivalentTo("1".Yield()));
Assert.That(triggeredArgs.OldStartingIndex, Is.Zero);
Assert.That(triggeredArgs.NewStartingIndex, Is.Zero);
}
[Test]
@@ -135,18 +146,28 @@ namespace osu.Framework.Tests.Bindables
{
bindableStringList.Add("0");
IEnumerable<string> addedItem = null;
IEnumerable<string> removedItem = null;
var list = new BindableList<string>();
list.BindTo(bindableStringList);
#pragma warning disable 618 can be removed 20200817
IEnumerable<string> addedItem = null;
IEnumerable<string> removedItem = null;
list.ItemsAdded += v => addedItem = v;
list.ItemsRemoved += v => removedItem = v;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
list.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList[0] = "1";
Assert.AreEqual(removedItem.Single(), "0");
Assert.AreEqual(addedItem.Single(), "1");
Assert.That(removedItem.Single(), Is.EqualTo("0"));
Assert.That(addedItem.Single(), Is.EqualTo("1"));
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Replace));
Assert.That(triggeredArgs.OldItems, Is.EquivalentTo("0".Yield()));
Assert.That(triggeredArgs.NewItems, Is.EquivalentTo("1".Yield()));
Assert.That(triggeredArgs.OldStartingIndex, Is.Zero);
Assert.That(triggeredArgs.NewStartingIndex, Is.Zero);
}
#endregion
@@ -168,12 +189,20 @@ namespace osu.Framework.Tests.Bindables
[TestCase(null)]
public void TestAddWithStringNotifiesSubscriber(string str)
{
#pragma warning disable 618 can be removed 20200817
string addedString = null;
bindableStringList.ItemsAdded += s => addedString = s.SingleOrDefault();
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.Add(str);
Assert.AreEqual(str, addedString);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Add));
Assert.That(triggeredArgs.NewItems, Is.EquivalentTo(str.Yield()));
Assert.That(triggeredArgs.NewStartingIndex, Is.Zero);
}
[TestCase("a random string")]
@@ -181,12 +210,18 @@ namespace osu.Framework.Tests.Bindables
[TestCase(null)]
public void TestAddWithStringNotifiesSubscriberOnce(string str)
{
#pragma warning disable 618 can be removed 20200817
int notificationCount = 0;
bindableStringList.ItemsAdded += s => notificationCount++;
#pragma warning restore 618
var triggeredArgs = new List<NotifyCollectionChangedEventArgs>();
bindableStringList.CollectionChanged += (_, args) => triggeredArgs.Add(args);
bindableStringList.Add(str);
Assert.AreEqual(1, notificationCount);
Assert.That(triggeredArgs, Has.Count.EqualTo(1));
}
[TestCase("a random string")]
@@ -194,18 +229,30 @@ namespace osu.Framework.Tests.Bindables
[TestCase(null)]
public void TestAddWithStringNotifiesMultipleSubscribers(string str)
{
#pragma warning disable 618 can be removed 20200817
bool subscriberANotified = false;
bool subscriberBNotified = false;
bool subscriberCNotified = false;
bindableStringList.ItemsAdded += s => subscriberANotified = true;
bindableStringList.ItemsAdded += s => subscriberBNotified = true;
bindableStringList.ItemsAdded += s => subscriberCNotified = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgsA = null;
NotifyCollectionChangedEventArgs triggeredArgsB = null;
NotifyCollectionChangedEventArgs triggeredArgsC = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsA = args;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsB = args;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsC = args;
bindableStringList.Add(str);
Assert.IsTrue(subscriberANotified);
Assert.IsTrue(subscriberBNotified);
Assert.IsTrue(subscriberCNotified);
Assert.That(triggeredArgsA, Is.Not.Null);
Assert.That(triggeredArgsB, Is.Not.Null);
Assert.That(triggeredArgsC, Is.Not.Null);
}
[TestCase("a random string")]
@@ -213,17 +260,29 @@ namespace osu.Framework.Tests.Bindables
[TestCase(null)]
public void TestAddWithStringNotifiesMultipleSubscribersOnlyAfterTheAdd(string str)
{
#pragma warning disable 618 can be removed 20200817
bool subscriberANotified = false;
bool subscriberBNotified = false;
bool subscriberCNotified = false;
bindableStringList.ItemsAdded += s => subscriberANotified = true;
bindableStringList.ItemsAdded += s => subscriberBNotified = true;
bindableStringList.ItemsAdded += s => subscriberCNotified = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgsA = null;
NotifyCollectionChangedEventArgs triggeredArgsB = null;
NotifyCollectionChangedEventArgs triggeredArgsC = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsA = args;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsB = args;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsC = args;
Assert.IsFalse(subscriberANotified);
Assert.IsFalse(subscriberBNotified);
Assert.IsFalse(subscriberCNotified);
Assert.That(triggeredArgsA, Is.Null);
Assert.That(triggeredArgsB, Is.Null);
Assert.That(triggeredArgsC, Is.Null);
bindableStringList.Add(str);
}
@@ -309,8 +368,13 @@ namespace osu.Framework.Tests.Bindables
string[] items = { "test1", "test2", "test3" };
var list = new BindableList<string>();
bindableStringList.BindTo(list);
#pragma warning disable 618 can be removed 20200817
IEnumerable<string> addedItems = null;
list.ItemsAdded += e => addedItems = e;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
list.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.AddRange(items);
@@ -320,6 +384,9 @@ namespace osu.Framework.Tests.Bindables
CollectionAssert.AreEquivalent(items, addedItems);
CollectionAssert.AreEquivalent(items, list);
});
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Add));
Assert.That(triggeredArgs.NewItems, Is.EquivalentTo(items));
}
[Test]
@@ -329,9 +396,6 @@ namespace osu.Framework.Tests.Bindables
BindableList<int> list2 = new BindableList<int>();
list2.BindTo(list1);
int addeditem = 0;
list1.ItemsAdded += items => addeditem = items.Single();
int counter = 0;
IEnumerable<int> valueEnumerable()
@@ -341,9 +405,9 @@ namespace osu.Framework.Tests.Bindables
list1.AddRange(valueEnumerable());
Assert.That(list1[0], Is.EqualTo(0));
Assert.That(list2[0], Is.EqualTo(0));
Assert.That(addeditem, Is.EqualTo(0));
Assert.That(list1, Is.EquivalentTo(0.Yield()));
Assert.That(list2, Is.EquivalentTo(0.Yield()));
Assert.That(counter, Is.EqualTo(1));
}
#endregion
@@ -372,12 +436,20 @@ namespace osu.Framework.Tests.Bindables
bindableStringList.Add("0");
bindableStringList.Add("2");
#pragma warning disable 618 can be removed 20200817
bool wasAdded = false;
bindableStringList.ItemsAdded += _ => wasAdded = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.Insert(1, "1");
Assert.IsTrue(wasAdded);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Add));
Assert.That(triggeredArgs.NewItems, Has.One.Items.EqualTo("1"));
Assert.That(triggeredArgs.NewStartingIndex, Is.EqualTo(1));
}
[Test]
@@ -386,15 +458,23 @@ namespace osu.Framework.Tests.Bindables
bindableStringList.Add("0");
bindableStringList.Add("2");
bool wasAdded = false;
var list = new BindableList<string>();
list.BindTo(bindableStringList);
#pragma warning disable 618 can be removed 20200817
bool wasAdded = false;
list.ItemsAdded += _ => wasAdded = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
list.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.Insert(1, "1");
Assert.IsTrue(wasAdded);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Add));
Assert.That(triggeredArgs.NewItems, Has.One.Items.EqualTo("1"));
Assert.That(triggeredArgs.NewStartingIndex, Is.EqualTo(1));
}
[Test]
@@ -464,12 +544,21 @@ namespace osu.Framework.Tests.Bindables
{
const string item = "item";
bindableStringList.Add(item);
#pragma warning disable 618 can be removed 20200817
bool updated = false;
bindableStringList.ItemsRemoved += s => updated = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.Remove(item);
Assert.True(updated);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.OldItems, Has.One.Items.EqualTo(item));
Assert.That(triggeredArgs.OldStartingIndex, Is.EqualTo(0));
}
[Test]
@@ -477,12 +566,21 @@ namespace osu.Framework.Tests.Bindables
{
const string item = "item";
bindableStringList.Add(item);
#pragma warning disable 618 can be removed 20200817
bool updatedA = false;
bool updatedB = false;
bool updatedC = false;
bindableStringList.ItemsRemoved += s => updatedA = true;
bindableStringList.ItemsRemoved += s => updatedB = true;
bindableStringList.ItemsRemoved += s => updatedC = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgsA = null;
NotifyCollectionChangedEventArgs triggeredArgsB = null;
NotifyCollectionChangedEventArgs triggeredArgsC = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsA = args;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsB = args;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsC = args;
bindableStringList.Remove(item);
@@ -492,6 +590,10 @@ namespace osu.Framework.Tests.Bindables
Assert.True(updatedB);
Assert.True(updatedC);
});
Assert.That(triggeredArgsA, Is.Not.Null);
Assert.That(triggeredArgsB, Is.Not.Null);
Assert.That(triggeredArgsC, Is.Not.Null);
}
[Test]
@@ -536,12 +638,21 @@ namespace osu.Framework.Tests.Bindables
bindableStringList.Add(item);
var list = new BindableList<string>();
list.BindTo(bindableStringList);
#pragma warning disable 618 can be removed 20200817
bool wasRemoved = false;
list.ItemsRemoved += s => wasRemoved = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
list.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.Remove(item);
Assert.True(wasRemoved);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.OldItems, Has.One.Items.EqualTo(item));
Assert.That(triggeredArgs.OldStartingIndex, Is.EqualTo(0));
}
[Test]
@@ -551,16 +662,31 @@ namespace osu.Framework.Tests.Bindables
bindableStringList.Add(item);
var listA = new BindableList<string>();
listA.BindTo(bindableStringList);
#pragma warning disable 618 can be removed 20200817
bool wasRemovedA1 = false;
bool wasRemovedA2 = false;
listA.ItemsRemoved += s => wasRemovedA1 = true;
listA.ItemsRemoved += s => wasRemovedA2 = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgsA1 = null;
NotifyCollectionChangedEventArgs triggeredArgsA2 = null;
listA.CollectionChanged += (_, args) => triggeredArgsA1 = args;
listA.CollectionChanged += (_, args) => triggeredArgsA2 = args;
var listB = new BindableList<string>();
listB.BindTo(bindableStringList);
#pragma warning disable 618 can be removed 20200817
bool wasRemovedB1 = false;
bool wasRemovedB2 = false;
listB.ItemsRemoved += s => wasRemovedB1 = true;
listB.ItemsRemoved += s => wasRemovedB2 = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgsB1 = null;
NotifyCollectionChangedEventArgs triggeredArgsB2 = null;
listB.CollectionChanged += (_, args) => triggeredArgsB1 = args;
listB.CollectionChanged += (_, args) => triggeredArgsB2 = args;
bindableStringList.Remove(item);
@@ -571,6 +697,11 @@ namespace osu.Framework.Tests.Bindables
Assert.IsTrue(wasRemovedB1);
Assert.IsTrue(wasRemovedB2);
});
Assert.That(triggeredArgsA1, Is.Not.Null);
Assert.That(triggeredArgsA2, Is.Not.Null);
Assert.That(triggeredArgsB1, Is.Not.Null);
Assert.That(triggeredArgsB2, Is.Not.Null);
}
[Test]
@@ -615,17 +746,27 @@ namespace osu.Framework.Tests.Bindables
bindableStringList.Add("0");
bindableStringList.Add("1");
#pragma warning disable 618 can be removed 20200817
List<string> itemsRemoved = null;
bindableStringList.ItemsRemoved += i => itemsRemoved = i.ToList();
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.RemoveRange(1, 1);
Assert.AreEqual(1, bindableStringList.Count);
Assert.AreEqual("0", bindableStringList.FirstOrDefault());
Assert.Multiple(() =>
{
Assert.AreEqual(1, bindableStringList.Count);
Assert.AreEqual("0", bindableStringList.FirstOrDefault());
Assert.AreEqual(1, itemsRemoved.Count);
Assert.AreEqual("1", itemsRemoved.FirstOrDefault());
});
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.OldItems, Has.One.Items.EqualTo("1"));
Assert.That(triggeredArgs.OldStartingIndex, Is.EqualTo(1));
}
[Test]
@@ -634,10 +775,15 @@ namespace osu.Framework.Tests.Bindables
bindableStringList.Add("0");
bindableStringList.Add("1");
List<string> itemsRemoved = null;
var list = new BindableList<string>();
list.BindTo(bindableStringList);
#pragma warning disable 618 can be removed 20200817
List<string> itemsRemoved = null;
list.ItemsRemoved += i => itemsRemoved = i.ToList();
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
list.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.RemoveRange(0, 1);
@@ -646,6 +792,10 @@ namespace osu.Framework.Tests.Bindables
Assert.AreEqual(1, itemsRemoved.Count);
Assert.AreEqual("0", itemsRemoved.FirstOrDefault());
});
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.OldItems, Has.One.Items.EqualTo("0"));
Assert.That(triggeredArgs.OldStartingIndex, Is.EqualTo(0));
}
[Test]
@@ -653,14 +803,21 @@ namespace osu.Framework.Tests.Bindables
{
bindableStringList.Add("0");
bool notified = false;
var list = new BindableList<string>();
list.BindTo(bindableStringList);
#pragma warning disable 618 can be removed 20200817
bool notified = false;
list.ItemsRemoved += i => notified = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
list.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.RemoveRange(0, 0);
Assert.IsFalse(notified);
Assert.That(triggeredArgs, Is.Null);
}
#endregion
@@ -692,14 +849,22 @@ namespace osu.Framework.Tests.Bindables
[Test]
public void TestRemoveAtNotifiesSubscribers()
{
bool wasRemoved = false;
bindableStringList.Add("abc");
#pragma warning disable 618 can be removed 20200817
bool wasRemoved = false;
bindableStringList.ItemsRemoved += _ => wasRemoved = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.RemoveAt(0);
Assert.IsTrue(wasRemoved);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.OldItems, Has.One.Items.EqualTo("abc"));
Assert.That(triggeredArgs.OldStartingIndex, Is.EqualTo(0));
}
[Test]
@@ -707,15 +872,23 @@ namespace osu.Framework.Tests.Bindables
{
bindableStringList.Add("abc");
bool wasRemoved = false;
var list = new BindableList<string>();
list.BindTo(bindableStringList);
#pragma warning disable 618 can be removed 20200817
bool wasRemoved = false;
list.ItemsRemoved += s => wasRemoved = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
list.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.RemoveAt(0);
Assert.IsTrue(wasRemoved);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.OldItems, Has.One.Items.EqualTo("abc"));
Assert.That(triggeredArgs.OldStartingIndex, Is.EqualTo(0));
}
#endregion
@@ -747,11 +920,19 @@ namespace osu.Framework.Tests.Bindables
bindableStringList.Add("0");
bindableStringList.Add("0");
#pragma warning disable 618 can be removed 20200817
List<string> itemsRemoved = null;
bindableStringList.ItemsRemoved += i => itemsRemoved = i.ToList();
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.RemoveAll(m => m == "0");
Assert.AreEqual(2, itemsRemoved.Count);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.OldItems, Is.EquivalentTo(new[] { "0", "0" }));
}
[Test]
@@ -760,14 +941,22 @@ namespace osu.Framework.Tests.Bindables
bindableStringList.Add("0");
bindableStringList.Add("0");
List<string> itemsRemoved = null;
var list = new BindableList<string>();
list.BindTo(bindableStringList);
#pragma warning disable 618 can be removed 20200817
List<string> itemsRemoved = null;
list.ItemsRemoved += i => itemsRemoved = i.ToList();
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
list.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.RemoveAll(m => m == "0");
Assert.AreEqual(2, itemsRemoved.Count);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.OldItems, Is.EquivalentTo(new[] { "0", "0" }));
}
#endregion
@@ -819,24 +1008,40 @@ namespace osu.Framework.Tests.Bindables
{
for (int i = 0; i < 5; i++)
bindableStringList.Add("testA");
#pragma warning disable 618 can be removed 20200817
bool wasNotified = false;
bindableStringList.ItemsRemoved += items => wasNotified = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.Clear();
Assert.IsTrue(wasNotified);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.OldItems, Is.EquivalentTo(new[] { "testA", "testA", "testA", "testA", "testA" }));
Assert.That(triggeredArgs.OldStartingIndex, Is.EqualTo(0));
}
[Test]
public void TestClearDoesNotNotifySubscriberBeforeClear()
{
bool wasNotified = false;
bindableStringList.ItemsRemoved += items => wasNotified = true;
for (int i = 0; i < 5; i++)
bindableStringList.Add("testA");
#pragma warning disable 618 can be removed 20200817
bool wasNotified = false;
bindableStringList.ItemsRemoved += items => wasNotified = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgs = args;
Assert.IsFalse(wasNotified);
Assert.That(triggeredArgs, Is.Null);
bindableStringList.Clear();
}
@@ -845,12 +1050,21 @@ namespace osu.Framework.Tests.Bindables
{
for (int i = 0; i < 5; i++)
bindableStringList.Add("testA");
#pragma warning disable 618 can be removed 20200817
bool wasNotifiedA = false;
bindableStringList.ItemsRemoved += items => wasNotifiedA = true;
bool wasNotifiedB = false;
bindableStringList.ItemsRemoved += items => wasNotifiedB = true;
bool wasNotifiedC = false;
bindableStringList.ItemsRemoved += items => wasNotifiedA = true;
bindableStringList.ItemsRemoved += items => wasNotifiedB = true;
bindableStringList.ItemsRemoved += items => wasNotifiedC = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgsA = null;
NotifyCollectionChangedEventArgs triggeredArgsB = null;
NotifyCollectionChangedEventArgs triggeredArgsC = null;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsA = args;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsB = args;
bindableStringList.CollectionChanged += (_, args) => triggeredArgsC = args;
bindableStringList.Clear();
@@ -860,6 +1074,10 @@ namespace osu.Framework.Tests.Bindables
Assert.IsTrue(wasNotifiedB);
Assert.IsTrue(wasNotifiedC);
});
Assert.That(triggeredArgsA, Is.Not.Null);
Assert.That(triggeredArgsB, Is.Not.Null);
Assert.That(triggeredArgsC, Is.Not.Null);
}
[Test]
@@ -1114,6 +1332,8 @@ namespace osu.Framework.Tests.Bindables
{
string[] strings = { "testA", "testB", "testC" };
bindableStringList.AddRange(strings);
#pragma warning disable 618 can be removed 20200817
bool itemsGotCleared = false;
IEnumerable<string> clearedItems = null;
bindableStringList.ItemsRemoved += items =>
@@ -1121,6 +1341,9 @@ namespace osu.Framework.Tests.Bindables
itemsGotCleared = true;
clearedItems = items;
};
#pragma warning restore 618
var triggeredArgs = new List<NotifyCollectionChangedEventArgs>();
bindableStringList.CollectionChanged += (_, args) => triggeredArgs.Add(args);
bindableStringList.Parse(null);
@@ -1129,14 +1352,20 @@ namespace osu.Framework.Tests.Bindables
CollectionAssert.AreEquivalent(strings, clearedItems);
Assert.IsTrue(itemsGotCleared);
});
Assert.That(triggeredArgs, Has.Count.EqualTo(1));
Assert.That(triggeredArgs.First().Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.First().OldItems, Is.EquivalentTo(strings));
Assert.That(triggeredArgs.First().OldStartingIndex, Is.EqualTo(0));
}
[Test]
public void TestParseWithItemsNotifiesAddRangeAndClearSubscribers()
{
bindableStringList.Add("test123");
IEnumerable<string> strings = new[] { "testA", "testB" };
#pragma warning disable 618 can be removed 20200817
IEnumerable<string> addedItems = null;
bool? itemsWereFirstCleaned = null;
bindableStringList.ItemsAdded += items =>
@@ -1150,6 +1379,9 @@ namespace osu.Framework.Tests.Bindables
if (itemsWereFirstCleaned == null)
itemsWereFirstCleaned = true;
};
#pragma warning restore 618
var triggeredArgs = new List<NotifyCollectionChangedEventArgs>();
bindableStringList.CollectionChanged += (_, args) => triggeredArgs.Add(args);
bindableStringList.Parse(strings);
@@ -1160,6 +1392,14 @@ namespace osu.Framework.Tests.Bindables
Assert.NotNull(itemsWereFirstCleaned);
Assert.IsTrue(itemsWereFirstCleaned ?? false);
});
Assert.That(triggeredArgs, Has.Count.EqualTo(2));
Assert.That(triggeredArgs.First().Action, Is.EqualTo(NotifyCollectionChangedAction.Remove));
Assert.That(triggeredArgs.First().OldItems, Is.EquivalentTo("test123".Yield()));
Assert.That(triggeredArgs.First().OldStartingIndex, Is.EqualTo(0));
Assert.That(triggeredArgs.ElementAt(1).Action, Is.EqualTo(NotifyCollectionChangedAction.Add));
Assert.That(triggeredArgs.ElementAt(1).NewItems, Is.EquivalentTo(strings));
Assert.That(triggeredArgs.ElementAt(1).NewStartingIndex, Is.EqualTo(0));
}
#endregion
@@ -1170,12 +1410,21 @@ namespace osu.Framework.Tests.Bindables
public void TestBoundCopyWithAdd()
{
var boundCopy = bindableStringList.GetBoundCopy();
#pragma warning disable 618 can be removed 20200817
bool boundCopyItemAdded = false;
boundCopy.ItemsAdded += item => boundCopyItemAdded = true;
#pragma warning restore 618
NotifyCollectionChangedEventArgs triggeredArgs = null;
boundCopy.CollectionChanged += (_, args) => triggeredArgs = args;
bindableStringList.Add("test");
Assert.IsTrue(boundCopyItemAdded);
Assert.That(triggeredArgs.Action, Is.EqualTo(NotifyCollectionChangedAction.Add));
Assert.That(triggeredArgs.NewItems, Is.EquivalentTo("test".Yield()));
Assert.That(triggeredArgs.NewStartingIndex, Is.EqualTo(0));
}
#endregion

View File

@@ -0,0 +1,25 @@
// 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 NUnit.Framework;
namespace osu.Framework.Tests.Visual.Testing
{
public class TestSceneIgnore : FrameworkTestScene
{
[Test]
[Ignore("test")]
public void IgnoredTest()
{
AddAssert("Test ignored", () => false);
}
[TestCase(1)]
[TestCase(2)]
[Ignore("test")]
public void IgnoredParameterizedTest(int test)
{
AddAssert("Test ignored", () => false);
}
}
}

View File

@@ -0,0 +1,36 @@
// 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 NUnit.Framework;
using osu.Framework.Input;
using osu.Framework.Testing;
using osuTK;
using osuTK.Input;
namespace osu.Framework.Tests.Visual.Testing
{
public class TestSceneManualInputManagerTestScene : ManualInputManagerTestScene
{
protected override Vector2 InitialMousePosition => new Vector2(10f);
[Test]
public void TestResetInput()
{
AddStep("move mouse", () => InputManager.MoveMouseTo(Vector2.Zero));
AddStep("press mouse", () => InputManager.PressButton(MouseButton.Left));
AddStep("press key", () => InputManager.PressKey(Key.Z));
AddStep("press joystick", () => InputManager.PressJoystickButton(JoystickButton.Button1));
AddStep("reset input", ResetInput);
AddAssert("mouse position reset", () => InputManager.CurrentState.Mouse.Position == InitialMousePosition);
AddAssert("all input states released", () =>
!InputManager.CurrentState.Mouse.Buttons.HasAnyButtonPressed &&
!InputManager.CurrentState.Keyboard.Keys.HasAnyButtonPressed &&
!InputManager.CurrentState.Joystick.Buttons.HasAnyButtonPressed);
}
[Test]
public void TestMousePositionSetToInitial() => AddAssert("mouse position set to initial", () => InputManager.CurrentState.Mouse.Position == InitialMousePosition);
}
}

View File

@@ -4,6 +4,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using osu.Framework.Caching;
using osu.Framework.Lists;
@@ -15,13 +16,20 @@ namespace osu.Framework.Bindables
/// <summary>
/// An event which is raised when any items are added to this <see cref="BindableList{T}"/>.
/// </summary>
[Obsolete("Use CollectionChanged instead.")]
public event Action<IEnumerable<T>> ItemsAdded;
/// <summary>
/// An event which is raised when any items are removed from this <see cref="BindableList{T}"/>.
/// </summary>
[Obsolete("Use CollectionChanged instead.")]
public event Action<IEnumerable<T>> ItemsRemoved;
/// <summary>
/// An event which is raised when this <see cref="BindableList{T}"/> changes.
/// </summary>
public event NotifyCollectionChangedEventHandler CollectionChanged;
/// <summary>
/// An event which is raised when <see cref="Disabled"/>'s state has changed (or manually via <see cref="triggerDisabledChange(bool)"/>).
/// </summary>
@@ -77,8 +85,7 @@ namespace osu.Framework.Bindables
}
}
ItemsRemoved?.Invoke(new[] { lastItem });
ItemsAdded?.Invoke(new[] { item });
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, lastItem, index));
}
/// <summary>
@@ -106,7 +113,7 @@ namespace osu.Framework.Bindables
}
}
ItemsAdded?.Invoke(new[] { item });
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, collection.Count - 1));
}
/// <summary>
@@ -142,7 +149,7 @@ namespace osu.Framework.Bindables
}
}
ItemsAdded?.Invoke(new[] { item });
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
}
/// <summary>
@@ -175,7 +182,7 @@ namespace osu.Framework.Bindables
}
}
ItemsRemoved?.Invoke(clearedItems);
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, clearedItems, 0));
}
/// <summary>
@@ -199,25 +206,27 @@ namespace osu.Framework.Bindables
{
ensureMutationAllowed();
bool removed = collection.Remove(item);
int index = collection.IndexOf(item);
if (removed)
if (index < 0)
return false;
collection.RemoveAt(index);
if (bindings != null)
{
if (bindings != null)
foreach (var b in bindings)
{
foreach (var b in bindings)
{
// prevent re-adding the item back to the callee.
// That would result in a <see cref="StackOverflowException"/>.
if (b != caller)
b.remove(item, this);
}
// prevent re-adding the item back to the callee.
// That would result in a <see cref="StackOverflowException"/>.
if (b != caller)
b.remove(item, this);
}
ItemsRemoved?.Invoke(new[] { item });
}
return removed;
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
return true;
}
/// <summary>
@@ -252,7 +261,7 @@ namespace osu.Framework.Bindables
}
}
ItemsRemoved?.Invoke(removedItems);
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removedItems, index));
}
/// <summary>
@@ -282,7 +291,7 @@ namespace osu.Framework.Bindables
}
}
ItemsRemoved?.Invoke(new[] { item });
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
}
/// <summary>
@@ -312,7 +321,7 @@ namespace osu.Framework.Bindables
}
}
ItemsRemoved?.Invoke(removed);
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed));
return removed.Count;
}
@@ -447,8 +456,12 @@ namespace osu.Framework.Bindables
public void UnbindEvents()
{
#pragma warning disable 618 can be removed 20200817
ItemsAdded = null;
ItemsRemoved = null;
#pragma warning restore 618
CollectionChanged = null;
DisabledChanged = null;
}
@@ -497,13 +510,13 @@ namespace osu.Framework.Bindables
/// <param name="items">The collection whose items should be added to this collection.</param>
/// <exception cref="InvalidOperationException">Thrown if this collection is <see cref="Disabled"/></exception>
public void AddRange(IEnumerable<T> items)
=> addRange(items as ICollection<T> ?? items.ToArray(), null);
=> addRange(items as IList ?? items.ToArray(), null);
private void addRange(ICollection<T> items, BindableList<T> caller)
private void addRange(IList items, BindableList<T> caller)
{
ensureMutationAllowed();
collection.AddRange(items);
collection.AddRange(items.Cast<T>());
if (bindings != null)
{
@@ -516,7 +529,7 @@ namespace osu.Framework.Bindables
}
}
ItemsAdded?.Invoke(items);
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, items, collection.Count - items.Count));
}
void IBindable.BindTo(IBindable them)
@@ -603,6 +616,33 @@ namespace osu.Framework.Bindables
#endregion IEnumerable
private void notifyCollectionChanged(NotifyCollectionChangedEventArgs args)
{
#pragma warning disable 618 can be removed 20200817
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
ItemsAdded?.Invoke(args.NewItems.Cast<T>());
break;
case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Move:
ItemsRemoved?.Invoke(args.OldItems.Cast<T>());
ItemsAdded?.Invoke(args.NewItems.Cast<T>());
break;
case NotifyCollectionChangedAction.Remove:
ItemsRemoved?.Invoke(args.OldItems.Cast<T>());
break;
case NotifyCollectionChangedAction.Reset:
break;
}
#pragma warning restore 618
CollectionChanged?.Invoke(this, args);
}
private void ensureMutationAllowed()
{
if (Disabled)

View File

@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace osu.Framework.Bindables
{
@@ -10,7 +11,7 @@ namespace osu.Framework.Bindables
/// An readonly interface which can be bound to other <see cref="IBindableList{T}"/>s in order to watch for state and content changes.
/// </summary>
/// <typeparam name="T">The type of value encapsulated by this <see cref="IBindableList{T}"/>.</typeparam>
public interface IBindableList<T> : IReadOnlyList<T>, IBindable
public interface IBindableList<T> : IReadOnlyList<T>, IBindable, INotifyCollectionChanged
{
/// <summary>
/// An event which is raised when an range of items get added.

View File

@@ -2,7 +2,10 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Input.Events;
using osuTK;
@@ -68,20 +71,64 @@ namespace osu.Framework.Graphics.Containers
d.Child = ListContainer;
});
Items.ItemsAdded += itemsAdded;
Items.ItemsRemoved += itemsRemoved;
Items.CollectionChanged += collectionChanged;
}
private void itemsAdded(IEnumerable<TModel> items)
private void collectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (isCurrentlyRearranging)
return;
foreach (var item in items)
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
addItems(e.NewItems);
reSort();
break;
case NotifyCollectionChangedAction.Remove:
removeItems(e.OldItems);
reSort();
// Explicitly reset scroll position here so that ScrollContainer doesn't retain our
// scroll position if we quickly add new items after calling a Clear().
ScrollContainer.ScrollToStart();
break;
case NotifyCollectionChangedAction.Reset:
currentlyDraggedItem = null;
ListContainer.Clear();
itemMap.Clear();
break;
case NotifyCollectionChangedAction.Replace:
removeItems(e.OldItems);
addItems(e.NewItems);
reSort();
break;
}
}
private void removeItems(IList items)
{
foreach (var item in items.Cast<TModel>())
{
if (currentlyDraggedItem != null && EqualityComparer<TModel>.Default.Equals(currentlyDraggedItem.Model, item))
currentlyDraggedItem = null;
ListContainer.Remove(itemMap[item]);
itemMap.Remove(item);
}
}
private void addItems(IList items)
{
foreach (var item in items.Cast<TModel>())
{
if (itemMap.ContainsKey(item))
{
throw new InvalidOperationException($"Duplicate items cannot be added to a {nameof(BindableList<TModel>)} that is currently bound with a {nameof(RearrangeableListContainer<TModel>)}.");
throw new InvalidOperationException(
$"Duplicate items cannot be added to a {nameof(BindableList<TModel>)} that is currently bound with a {nameof(RearrangeableListContainer<TModel>)}.");
}
var drawable = CreateDrawable(item).With(d =>
@@ -94,32 +141,6 @@ namespace osu.Framework.Graphics.Containers
ListContainer.Add(drawable);
itemMap[item] = drawable;
}
reSort();
}
private void itemsRemoved(IEnumerable<TModel> items)
{
if (isCurrentlyRearranging)
return;
foreach (var item in items)
{
if (currentlyDraggedItem != null && EqualityComparer<TModel>.Default.Equals(currentlyDraggedItem.Model, item))
currentlyDraggedItem = null;
ListContainer.Remove(itemMap[item]);
itemMap.Remove(item);
}
reSort();
if (Items.Count == 0)
{
// Explicitly reset scroll position here so that ScrollContainer doesn't retain our
// scroll position if we quickly add new items after calling a Clear().
ScrollContainer.ScrollToStart();
}
}
private void reSort()
@@ -220,10 +241,10 @@ namespace osu.Framework.Graphics.Containers
Items.RemoveAt(srcIndex);
Items.Insert(dstIndex, currentlyDraggedItem.Model);
isCurrentlyRearranging = false;
// Todo: this could be optimised, but it's a very simple iteration over all the items
reSort();
isCurrentlyRearranging = false;
}
/// <summary>

View File

@@ -133,13 +133,12 @@ namespace osu.Framework.Testing
var joystick = currentState.Joystick;
joystick.Buttons.ForEach(InputManager.ReleaseJoystickButton);
InputManager.UseParentInput = true;
// schedule after children to ensure pending inputs have been applied before using parent input manager.
ScheduleAfterChildren(returnUserInput);
}
private void returnUserInput() =>
InputManager.UseParentInput = true;
private void returnUserInput() => InputManager.UseParentInput = true;
private void returnTestInput() =>
InputManager.UseParentInput = false;
private void returnTestInput() => InputManager.UseParentInput = false;
}
}

View File

@@ -461,7 +461,7 @@ namespace osu.Framework.Testing
{
var name = m.Name;
if (name == nameof(TestScene.TestConstructor))
if (name == nameof(TestScene.TestConstructor) || m.GetCustomAttribute(typeof(IgnoreAttribute), false) != null)
continue;
if (name.StartsWith("Test"))

View File

@@ -42,6 +42,6 @@
<ItemGroup Condition="$(TargetFrameworkIdentifier) == '.NETCoreApp'">
<!-- DO NOT use ProjectReference for native packaging project.
See https://github.com/NuGet/Home/issues/4514 and https://github.com/dotnet/sdk/issues/765 . -->
<PackageReference Include="ppy.osu.Framework.NativeLibs" Version="2019.1104.0" />
<PackageReference Include="ppy.osu.Framework.NativeLibs" Version="2020.213.0" />
</ItemGroup>
</Project>