A game framework written with osu! in mind.
at master 222 lines 7.6 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System.Collections.Generic; 5using System.Linq; 6using NUnit.Framework; 7using osu.Framework.Graphics; 8using osu.Framework.Graphics.Containers; 9using osu.Framework.Graphics.Sprites; 10using osu.Framework.Graphics.UserInterface; 11using osuTK; 12 13namespace osu.Framework.Tests.Visual.UserInterface 14{ 15 public class TestSceneSearchContainer : FrameworkTestScene 16 { 17 private SearchContainer search; 18 private BasicTextBox textBox; 19 20 [SetUp] 21 public void SetUp() => Schedule(() => 22 { 23 Children = new Drawable[] 24 { 25 textBox = new BasicTextBox 26 { 27 Size = new Vector2(300, 40), 28 }, 29 search = new SearchContainer 30 { 31 AutoSizeAxes = Axes.Both, 32 Margin = new MarginPadding { Top = 40 }, 33 Children = new[] 34 { 35 new HeaderContainer 36 { 37 AutoSizeAxes = Axes.Both, 38 Children = new[] 39 { 40 new HeaderContainer("Subsection 1") 41 { 42 AutoSizeAxes = Axes.Both, 43 Children = new Drawable[] 44 { 45 new SearchableText { Text = "test", }, 46 new SearchableText { Text = "TEST", }, 47 new SearchableText { Text = "123", }, 48 new SearchableText { Text = "444", }, 49 new FilterableFlowContainer 50 { 51 Direction = FillDirection.Horizontal, 52 AutoSizeAxes = Axes.Both, 53 Children = new[] 54 { 55 new SpriteText { Text = "multi", }, 56 new SpriteText { Text = "piece", }, 57 new SpriteText { Text = "container", }, 58 } 59 }, 60 new SearchableText { Text = "öüäéèêáàâ", } 61 } 62 }, 63 new HeaderContainer("Subsection 2") 64 { 65 AutoSizeAxes = Axes.Both, 66 Children = new[] 67 { 68 new SearchableText { Text = "?!()[]{}" }, 69 new SearchableText { Text = "@€$" }, 70 }, 71 }, 72 }, 73 } 74 } 75 } 76 }; 77 78 textBox.Current.ValueChanged += e => search.SearchTerm = e.NewValue; 79 }); 80 81 [TestCase("test", 2)] 82 [TestCase("sUbSeCtIoN 1", 6)] 83 [TestCase("€", 1)] 84 [TestCase("èê", 1)] 85 [TestCase("321", 0)] 86 [TestCase("mul pi", 1)] 87 [TestCase("header", 8)] 88 public void TestFiltering(string term, int count) 89 { 90 setTerm(term); 91 checkCount(count); 92 } 93 94 [TestCase] 95 public void TestRefilterAfterNewChild() 96 { 97 setTerm("multi"); 98 checkCount(1); 99 AddStep("Add new filtered item", () => search.Add(new SearchableText { Text = "not visible" })); 100 checkCount(1); 101 AddStep("Add new unfiltered item", () => search.Add(new SearchableText { Text = "multi visible" })); 102 checkCount(2); 103 } 104 105 private void checkCount(int count) 106 { 107 AddAssert("Visible children: " + count, () => count == countSearchableText(search)); 108 } 109 110 private int countSearchableText(CompositeDrawable container) 111 { 112 return container.InternalChildren.Where(t => t is SearchableText || t is FilterableFlowContainer).Count(c => c.IsPresent) 113 + container.InternalChildren.Where(c => c.IsPresent).OfType<CompositeDrawable>().Sum(countSearchableText); 114 } 115 116 private void setTerm(string term) 117 { 118 AddStep("Search term: " + term, () => textBox.Text = term); 119 } 120 121 private class HeaderContainer : Container, IHasFilterableChildren 122 { 123 public IEnumerable<string> FilterTerms => header.FilterTerms; 124 125 public bool MatchingFilter 126 { 127 set 128 { 129 if (value) 130 this.FadeIn(); 131 else 132 this.FadeOut(); 133 } 134 } 135 136 public bool FilteringActive 137 { 138 set { } 139 } 140 141 public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>(); 142 143 protected override Container<Drawable> Content => flowContainer; 144 145 private readonly HeaderText header; 146 private readonly FillFlowContainer flowContainer; 147 148 public HeaderContainer(string headerText = "Header") 149 { 150 AddInternal(header = new HeaderText 151 { 152 Text = headerText, 153 }); 154 AddInternal(flowContainer = new FillFlowContainer 155 { 156 Margin = new MarginPadding { Top = header.Font.Size, Left = 30 }, 157 AutoSizeAxes = Axes.Both, 158 Direction = FillDirection.Vertical, 159 }); 160 } 161 } 162 163 private class FilterableFlowContainer : FillFlowContainer, IFilterable 164 { 165 public IEnumerable<string> FilterTerms => Children.OfType<IHasFilterTerms>().SelectMany(d => d.FilterTerms); 166 167 public bool MatchingFilter 168 { 169 set 170 { 171 if (value) 172 Show(); 173 else 174 Hide(); 175 } 176 } 177 178 public bool FilteringActive 179 { 180 set { } 181 } 182 } 183 184 private class HeaderText : SpriteText, IFilterable 185 { 186 public bool MatchingFilter 187 { 188 set 189 { 190 if (value) 191 Show(); 192 else 193 Hide(); 194 } 195 } 196 197 public bool FilteringActive 198 { 199 set { } 200 } 201 } 202 203 private class SearchableText : SpriteText, IFilterable 204 { 205 public bool MatchingFilter 206 { 207 set 208 { 209 if (value) 210 Show(); 211 else 212 Hide(); 213 } 214 } 215 216 public bool FilteringActive 217 { 218 set { } 219 } 220 } 221 } 222}