From c377ec0eeff787988254fcf4bac85a9b1b0a8360 Mon Sep 17 00:00:00 2001 From: Flamefire Date: Thu, 28 Feb 2013 00:47:46 +0100 Subject: [PATCH] Added Classes for categorizing, filtering and sorting --- .gitignore | 2 + .../PartyModeChallenge/PartyModeChallenge.cs | 2 +- .../PartyModeChallenge.cs | 4 +- .../PartyModeTicTacToe/PartyModeTicTacToe.cs | 2 +- Vocaluxe/Base/CMain.cs | 8 +- Vocaluxe/Base/CObservable.cs | 21 + Vocaluxe/Base/CSongCategorizer.cs | 173 +++++++ Vocaluxe/Base/CSongFilter.cs | 93 ++++ Vocaluxe/Base/CSongSorter.cs | 201 +++++++++ Vocaluxe/Base/CSongs.cs | 421 ++---------------- Vocaluxe/Screens/CScreenOptionsGame.cs | 23 +- Vocaluxe/Screens/CScreenOptionsTheme.cs | 4 +- Vocaluxe/Screens/CScreenSong.cs | 6 +- Vocaluxe/Vocaluxe.csproj | 4 + VocaluxeLib/Menu/IMenu.cs | 9 +- VocaluxeLib/PartyModes/CPartyModeNone.cs | 2 +- VocaluxeLib/PartyModes/IPartyMode.cs | 2 +- 17 files changed, 566 insertions(+), 411 deletions(-) create mode 100644 Vocaluxe/Base/CObservable.cs create mode 100644 Vocaluxe/Base/CSongCategorizer.cs create mode 100644 Vocaluxe/Base/CSongFilter.cs create mode 100644 Vocaluxe/Base/CSongSorter.cs diff --git a/.gitignore b/.gitignore index 1ea3fff8..7afc1fe5 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ Output/Songs *.ipch *.log + +/Output/Playlists/*.xml diff --git a/PartyModes/PartyModeChallenge/PartyModeChallenge.cs b/PartyModes/PartyModeChallenge/PartyModeChallenge.cs index 600024c2..6314434e 100644 --- a/PartyModes/PartyModeChallenge/PartyModeChallenge.cs +++ b/PartyModes/PartyModeChallenge/PartyModeChallenge.cs @@ -153,7 +153,7 @@ namespace Vocaluxe.PartyModes _ScreenSongOptions.Sorting.SearchString = String.Empty; _ScreenSongOptions.Sorting.SearchActive = false; - _ScreenSongOptions.Sorting.ShowDuetSongs = false; + _ScreenSongOptions.Sorting.DuetOptions = EDuetOptions.NoDuets; _Stage = EStage.NotStarted; diff --git a/PartyModes/PartyModeChallengeMedley/PartyModeChallenge.cs b/PartyModes/PartyModeChallengeMedley/PartyModeChallenge.cs index 86d86ee3..441d839a 100644 --- a/PartyModes/PartyModeChallengeMedley/PartyModeChallenge.cs +++ b/PartyModes/PartyModeChallengeMedley/PartyModeChallenge.cs @@ -155,7 +155,7 @@ namespace Vocaluxe.PartyModes _ScreenSongOptions.Sorting.SearchString = String.Empty; _ScreenSongOptions.Sorting.SearchActive = false; - _ScreenSongOptions.Sorting.ShowDuetSongs = false; + _ScreenSongOptions.Sorting.DuetOptions = EDuetOptions.NoDuets; _Stage = EStage.NotStarted; @@ -188,7 +188,7 @@ namespace Vocaluxe.PartyModes ToScreenMain.ResultTable = new List(); GameData.ResultTable = new List(); - CBase.Songs.SortSongs(ESongSorting.TR_CONFIG_NONE, EOffOn.TR_CONFIG_OFF, EOffOn.TR_CONFIG_OFF, String.Empty, false); + CBase.Songs.SortSongs(ESongSorting.TR_CONFIG_NONE, EOffOn.TR_CONFIG_OFF, EOffOn.TR_CONFIG_OFF, String.Empty, EDuetOptions.NoDuets); CBase.Songs.SetCategory(0); return true; diff --git a/PartyModes/PartyModeTicTacToe/PartyModeTicTacToe.cs b/PartyModes/PartyModeTicTacToe/PartyModeTicTacToe.cs index 6bb9b5de..f2f120f8 100644 --- a/PartyModes/PartyModeTicTacToe/PartyModeTicTacToe.cs +++ b/PartyModes/PartyModeTicTacToe/PartyModeTicTacToe.cs @@ -168,7 +168,7 @@ namespace Vocaluxe.PartyModes _ScreenSongOptions.Sorting.SearchString = String.Empty; _ScreenSongOptions.Sorting.SearchActive = false; - _ScreenSongOptions.Sorting.ShowDuetSongs = false; + _ScreenSongOptions.Sorting.DuetOptions = EDuetOptions.NoDuets; _Stage = EStage.NotStarted; diff --git a/Vocaluxe/Base/CMain.cs b/Vocaluxe/Base/CMain.cs index a77459f6..339eaa39 100644 --- a/Vocaluxe/Base/CMain.cs +++ b/Vocaluxe/Base/CMain.cs @@ -585,12 +585,12 @@ namespace Vocaluxe.Base public EOffOn GetTabs() { - return CSongs.Tabs; + return CSongs.Categorizer.Tabs; } public string GetSearchFilter() { - return CSongs.SearchFilter; + return CSongs.Filter.SearchString; } public void SetCategory(int CategoryIndex) @@ -646,9 +646,9 @@ namespace Vocaluxe.Base CSongs.ResetPartySongSung(CatIndex); } - public void SortSongs(ESongSorting Sorting, EOffOn Tabs, EOffOn IgnoreArticles, String SearchString, bool ShowDuetSongs) + public void SortSongs(ESongSorting Sorting, EOffOn Tabs, EOffOn IgnoreArticles, String SearchString, EDuetOptions DuetOptions) { - CSongs.Sort(Sorting, Tabs, IgnoreArticles, SearchString, ShowDuetSongs); + CSongs.Sort(Sorting, Tabs, IgnoreArticles, SearchString, DuetOptions); } public void NextCategory() diff --git a/Vocaluxe/Base/CObservable.cs b/Vocaluxe/Base/CObservable.cs new file mode 100644 index 00000000..60bfc1bb --- /dev/null +++ b/Vocaluxe/Base/CObservable.cs @@ -0,0 +1,21 @@ +using System; + +namespace Vocaluxe.Base +{ + class CObservable + { + public event EventHandler ObjectChanged = delegate { }; + protected bool _Changed = true; + + protected void NotifyObservers() + { + ObjectChanged.Invoke(this, null); + } + + protected void _SetChanged() + { + _Changed = true; + NotifyObservers(); + } + } +} diff --git a/Vocaluxe/Base/CSongCategorizer.cs b/Vocaluxe/Base/CSongCategorizer.cs new file mode 100644 index 00000000..3a930a87 --- /dev/null +++ b/Vocaluxe/Base/CSongCategorizer.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using Vocaluxe.Menu; +using Vocaluxe.Menu.SongMenu; + +namespace Vocaluxe.Base +{ + class CSongCategorizer : CObservable + { + private List _Categories = new List(); + private EOffOn _Tabs = CConfig.Tabs; + + public CSongCategorizer() + { + CSongs.Filter.ObjectChanged += HandleSortedSongsChanged; + } + + public List Categories + { + get { _FillCategories(); return _Categories; } + } + + public EOffOn Tabs + { + get { return _Tabs; } + set + { + if (value != _Tabs) + { + _Tabs = value; + _SetChanged(); + } + } + } + + private void HandleSortedSongsChanged(object sender, EventArgs args) + { + _SetChanged(); + } + + private void _CreateCategoriesLetter() + { + string category = ""; + int NotLetterCat = -1; + for (int i = 0; i < CSongs.Sorter.SortedSongs.Length; i++) + { + Char firstLetter = Char.ToUpper(CSongs.Sorter.SortedSongs[i].SortString.Normalize(NormalizationForm.FormD)[0]); + + if (!Char.IsLetter(firstLetter)) + { + firstLetter = '#'; + } + if (firstLetter.ToString() != category) + { + if (firstLetter != '#' || NotLetterCat == -1) + { + category = firstLetter.ToString(); + _Categories.Add(new CCategory(category)); + + CSongs.Sorter.SortedSongs[i].CatIndex = _Categories.Count - 1; + + if (firstLetter == '#') + NotLetterCat = CSongs.Sorter.SortedSongs[i].CatIndex; + } + else + CSongs.Sorter.SortedSongs[i].CatIndex = NotLetterCat; + } + else + CSongs.Sorter.SortedSongs[i].CatIndex = _Categories.Count - 1; + } + } + + private void _CreateCategoriesNormal(string NoCategoryName) + { + string category = ""; + int NoCategoryIndex = -1; + for (int i = 0; i < CSongs.Sorter.SortedSongs.Length; i++) + { + if (CSongs.Sorter.SortedSongs[i].SortString.Length > 0) + { + if (CSongs.Sorter.SortedSongs[i].SortString != category) + { + category = CSongs.Sorter.SortedSongs[i].SortString; + _Categories.Add(new CCategory(category)); + } + CSongs.Sorter.SortedSongs[i].CatIndex = _Categories.Count - 1; + } + else + { + if (NoCategoryIndex < 0) + { + category = NoCategoryName; + _Categories.Add(new CCategory(category)); + NoCategoryIndex = _Categories.Count - 1; + } + CSongs.Sorter.SortedSongs[i].CatIndex = NoCategoryIndex; + } + } + + } + + private void _CreateCategories() + { + string NoCategoryName = ""; + + ESongSorting Sorting = CSongs.Sorter.SongSorting; + + switch (Sorting) + { + case ESongSorting.TR_CONFIG_EDITION: + NoCategoryName = CLanguage.Translate("TR_SCREENSONG_NOEDITION"); + break; + case ESongSorting.TR_CONFIG_GENRE: + NoCategoryName = CLanguage.Translate("TR_SCREENSONG_NOGENRE"); + break; + case ESongSorting.TR_CONFIG_DECADE: + case ESongSorting.TR_CONFIG_YEAR: + NoCategoryName = CLanguage.Translate("TR_SCREENSONG_NOYEAR"); + break; + case ESongSorting.TR_CONFIG_LANGUAGE: + NoCategoryName = CLanguage.Translate("TR_SCREENSONG_NOLANGUAGE"); + break; + case ESongSorting.TR_CONFIG_NONE: + NoCategoryName = CLanguage.Translate("TR_SCREENSONG_ALLSONGS"); + break; + } + if (Sorting == ESongSorting.TR_CONFIG_ARTIST_LETTER || Sorting == ESongSorting.TR_CONFIG_TITLE_LETTER) + _CreateCategoriesLetter(); + else + { + if (Sorting == ESongSorting.TR_CONFIG_DECADE) + for (int i = 0; i < CSongs.Sorter.SortedSongs.Length; i++) + { + string Year = CSongs.Sorter.SortedSongs[i].SortString; + if (Year.Length > 0) + { + Year = Year.Substring(0, 3); + CSongs.Sorter.SortedSongs[i].SortString = Year + "0 - " + Year + "9"; + } + } + _CreateCategoriesNormal(NoCategoryName); + } + } + + private void _FillCategories() + { + if (!_Changed) + return; + + _Categories.Clear(); + + if (_Tabs == EOffOn.TR_CONFIG_OFF) + { + //No categories. So don't create them! + _Categories.Add(new CCategory("")); + for (int i = 0; i < CSongs.Sorter.SortedSongs.Length; i++) + { + CSongs.Sorter.SortedSongs[i].CatIndex = 0; + } + } + else + _CreateCategories(); + + foreach (CCategory cat in _Categories) + { + cat.CoverTextureSmall = CCover.Cover(cat.Name); + } + _Changed = false; + } + } +} diff --git a/Vocaluxe/Base/CSongFilter.cs b/Vocaluxe/Base/CSongFilter.cs new file mode 100644 index 00000000..b3444700 --- /dev/null +++ b/Vocaluxe/Base/CSongFilter.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; + +using Vocaluxe.Menu; +using Vocaluxe.Menu.SongMenu; + +namespace Vocaluxe.Base +{ + class CSongFilter : CObservable + { + private readonly List _FilteredSongs = new List(); + + private String _SearchString = String.Empty; + private EDuetOptions _DuetOptions = EDuetOptions.All; + + public List FilteredSongs + { + get { _FilterSongs(); return _FilteredSongs; } + } + + public String SearchString + { + get { return _SearchString; } + set + { + if (value != _SearchString) + { + _SetChanged(); + _SearchString = value; + } + } + } + + public EDuetOptions DuetOptions + { + get { return _DuetOptions; } + set + { + if (value != _DuetOptions) + { + _SetChanged(); + _DuetOptions = value; + } + } + } + + public void SetOptions(String searchString, EDuetOptions duetOptions) + { + if (searchString != _SearchString || duetOptions != _DuetOptions) + { + _SearchString = searchString; + _DuetOptions = duetOptions; + _SetChanged(); + } + } + + private void _FilterSongs() + { + if (!_Changed) + return; + + _FilteredSongs.Clear(); + + string[] searchStrings = null; + if (_SearchString.Length > 0) + searchStrings = _SearchString.ToUpper().Split(new char[] { ' ' }); + + foreach (CSong song in CSongs.Songs) + { + if ((song.IsDuet && _DuetOptions != EDuetOptions.NoDuets) || (!song.IsDuet && _DuetOptions != EDuetOptions.Duets)) + { + if (searchStrings == null) + _FilteredSongs.Add(song); + else + { + string search = song.Title.ToUpper() + " " + song.Artist.ToUpper() + " " + song.FolderName.ToUpper() + " " + song.FileName.ToUpper(); + + bool contains = true; + + foreach (string str in searchStrings) + { + contains &= search.Contains(str); + } + if (contains) + _FilteredSongs.Add(song); + } + } + } + _Changed = false; + } + + } +} \ No newline at end of file diff --git a/Vocaluxe/Base/CSongSorter.cs b/Vocaluxe/Base/CSongSorter.cs new file mode 100644 index 00000000..b58b3bfe --- /dev/null +++ b/Vocaluxe/Base/CSongSorter.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; + +using Vocaluxe.Menu; +using Vocaluxe.Menu.SongMenu; + +namespace Vocaluxe.Base +{ + class CSongSorter:CObservable + { + private SongPointer[] _SortedSongs = new SongPointer[0]; + private EOffOn _IgnoreArticles = CConfig.IgnoreArticles; + private ESongSorting _SongSorting = CConfig.SongSorting; + + public CSongSorter() + { + CSongs.Filter.ObjectChanged += HandleFilteredSongsChanged; + } + + public SongPointer[] SortedSongs + { + get { _SortSongs(); return _SortedSongs; } + } + + public EOffOn IgnoreArticles + { + get { return _IgnoreArticles; } + set + { + if (value != _IgnoreArticles) + { + _IgnoreArticles = value; + _SetChanged(); + } + } + } + + public ESongSorting SongSorting + { + get { return _SongSorting; } + set + { + if (value != _SongSorting) + { + _SongSorting = value; + _SetChanged(); + } + } + } + + public void SetOptions(ESongSorting songSorting, EOffOn ignoreArticles) + { + if (songSorting != _SongSorting || ignoreArticles != _IgnoreArticles) + { + _SongSorting = songSorting; + _IgnoreArticles = ignoreArticles; + _SetChanged(); + } + } + + private void HandleFilteredSongsChanged(object sender, EventArgs args) + { + _SetChanged(); + } + + private int _SortByFieldArtistTitle(SongPointer s1, SongPointer s2) + { + int res = s1.SortString.ToUpper().CompareTo(s2.SortString.ToUpper()); + if (res == 0) + { + if (_IgnoreArticles == EOffOn.TR_CONFIG_ON) + { + res = CSongs.Songs[s1.SongID].ArtistSorting.ToUpper().CompareTo(CSongs.Songs[s2.SongID].ArtistSorting.ToUpper()); + if (res == 0) + { + return CSongs.Songs[s1.SongID].TitleSorting.ToUpper().CompareTo(CSongs.Songs[s2.SongID].TitleSorting.ToUpper()); + } + return res; + } + else + { + res = CSongs.Songs[s1.SongID].Artist.ToUpper().CompareTo(CSongs.Songs[s2.SongID].Artist.ToUpper()); + if (res == 0) + { + return CSongs.Songs[s1.SongID].Title.ToUpper().CompareTo(CSongs.Songs[s2.SongID].Title.ToUpper()); + } + return res; + } + } + return res; + } + + private int _SortByFieldTitle(SongPointer s1, SongPointer s2) + { + int res = s1.SortString.ToUpper().CompareTo(s2.SortString.ToUpper()); + if (res == 0) + { + if (_IgnoreArticles == EOffOn.TR_CONFIG_ON) + return CSongs.Songs[s1.SongID].TitleSorting.ToUpper().CompareTo(CSongs.Songs[s2.SongID].TitleSorting.ToUpper()); + else + return CSongs.Songs[s1.SongID].Title.ToUpper().CompareTo(CSongs.Songs[s2.SongID].Title.ToUpper()); + } + return res; + } + + private List _CreateSortList(string fieldName) + { + FieldInfo field = null; + bool isString = false; + List SortList = new List(); + if (fieldName.Length == 0) + CSongs.Filter.FilteredSongs.ForEach((song) => SortList.Add(new SongPointer(song.ID, ""))); + { + field = Type.GetType("Vocaluxe.Menu.SongMenu.CSong,VocaluxeLib").GetField(fieldName, BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public); + isString = field.FieldType == typeof(string); + if (!isString && field.FieldType != typeof(List)) + throw new Exception("Unkown sort field type"); + foreach (CSong song in CSongs.Filter.FilteredSongs) + { + object value = field.GetValue(song); + if (isString) + SortList.Add(new SongPointer(song.ID, (String)value)); + else + { + List values = (List)value; + if (values.Count == 0) + { + SortList.Add(new SongPointer(song.ID, "")); + } + else + { + foreach (String sortString in (List)value) + { + SortList.Add(new SongPointer(song.ID, sortString)); + } + } + } + } + } + return SortList; + } + + private void _SortSongs() + { + if (!_Changed) + return; + String fieldName; + switch (_SongSorting) + { + case ESongSorting.TR_CONFIG_EDITION: + fieldName = "Edition"; + break; + case ESongSorting.TR_CONFIG_GENRE: + fieldName = "Genre"; + break; + case ESongSorting.TR_CONFIG_FOLDER: + fieldName = "FolderName"; + break; + case ESongSorting.TR_CONFIG_ARTIST_LETTER: + case ESongSorting.TR_CONFIG_ARTIST: + if (_IgnoreArticles == EOffOn.TR_CONFIG_ON) + fieldName = "ArtistSorting"; + else + fieldName = "Artist"; + break; + case ESongSorting.TR_CONFIG_TITLE_LETTER: + if (_IgnoreArticles == EOffOn.TR_CONFIG_ON) + fieldName = "TitleSorting"; + else + fieldName = "Title"; + break; + case ESongSorting.TR_CONFIG_YEAR: + case ESongSorting.TR_CONFIG_DECADE: + fieldName = "Year"; + break; + case ESongSorting.TR_CONFIG_LANGUAGE: + fieldName = "Language"; + break; + default: + fieldName = ""; + break; + } + List SortList = _CreateSortList(fieldName); + switch (_SongSorting) + { + case ESongSorting.TR_CONFIG_ARTIST_LETTER: + case ESongSorting.TR_CONFIG_ARTIST: + case ESongSorting.TR_CONFIG_NONE: + SortList.Sort(_SortByFieldTitle); + break; + default: + SortList.Sort(_SortByFieldArtistTitle); + break; + } + _SortedSongs = SortList.ToArray(); + _Changed = false; + } + } +} \ No newline at end of file diff --git a/Vocaluxe/Base/CSongs.cs b/Vocaluxe/Base/CSongs.cs index 7ef5a4ba..93527f8a 100644 --- a/Vocaluxe/Base/CSongs.cs +++ b/Vocaluxe/Base/CSongs.cs @@ -1,14 +1,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; -using System.IO; using System.Text; -using System.Text.RegularExpressions; -using System.Threading; using System.Reflection; -using Vocaluxe.Lib.Draw; using Vocaluxe.Menu; using Vocaluxe.Menu.SongMenu; @@ -37,8 +32,6 @@ namespace Vocaluxe.Base static class CSongs { private static List _Songs = new List(); - private static List _FilteredSongs = new List(); - private static SongPointer[] _SongsSortList = new SongPointer[0]; private static List _SongsForRandom = new List(); private static bool _SongsLoaded = false; @@ -46,41 +39,17 @@ namespace Vocaluxe.Base private static int _CoverLoadIndex = 0; private static int _CatIndex = -1; private static bool _Init = false; - private static List _Categories = new List(); private static List _CategoriesForRandom = new List(); private static Stopwatch _CoverLoadTimer = new Stopwatch(); - private static string _SearchFilter = String.Empty; - private static EOffOn _Tabs = CConfig.Tabs; - private static EOffOn _IgnoreArticles = CConfig.IgnoreArticles; - private static ESongSorting _SongSorting = CConfig.SongSorting; - private static bool _ShowDuetSongs = true; - - public static string SearchFilter - { - get { return _SearchFilter; } - set - { - if (value.Length > 0) - { - _Sort(_SongSorting, EOffOn.TR_CONFIG_OFF, _IgnoreArticles, value, false, _ShowDuetSongs); - } - else - { - _Sort(_SongSorting, _Tabs, _IgnoreArticles, value, false, _ShowDuetSongs); - } - } - } + public static CSongFilter Filter = new CSongFilter(); + public static CSongSorter Sorter = new CSongSorter(); + public static CSongCategorizer Categorizer = new CSongCategorizer(); - public static EOffOn Tabs + public static List Songs { - get { return _Tabs; } - } - - public static EOffOn IgnoreArticles - { - get { return _IgnoreArticles; } + get { return _Songs; } } public static bool SongsLoaded @@ -108,7 +77,7 @@ namespace Vocaluxe.Base get { int Result = 0; - foreach (SongPointer sp in _SongsSortList) + foreach (SongPointer sp in Sorter.SortedSongs) { if (sp.Visible) Result++; @@ -119,7 +88,7 @@ namespace Vocaluxe.Base public static int NumCategories { - get { return _Categories.Count; } + get { return Categorizer.Categories.Count; } } public static int Category @@ -127,13 +96,13 @@ namespace Vocaluxe.Base get { return _CatIndex; } set { - if ((_Categories.Count > value) && (value >= -1)) + if (value >= -1 && value < Categorizer.Categories.Count) { _CatIndex = value; - for (int i = 0; i < _SongsSortList.Length; i++) + for (int i = 0; i < Sorter.SortedSongs.Length; i++) { - _SongsSortList[i].Visible = (_SongsSortList[i].CatIndex == _CatIndex && !_SongsSortList[i].PartyHidden); + Sorter.SortedSongs[i].Visible = (Sorter.SortedSongs[i].CatIndex == _CatIndex && !Sorter.SortedSongs[i].PartyHidden); } } } @@ -146,13 +115,13 @@ namespace Vocaluxe.Base /// public static int NumSongsInCategory(int CatIndex) { - if (_Categories.Count <= CatIndex || CatIndex < 0) + if (Categorizer.Categories.Count <= CatIndex || CatIndex < 0) return 0; int num = 0; - for (int i = 0; i < _SongsSortList.Length; i++) + for (int i = 0; i < Sorter.SortedSongs.Length; i++) { - if (_SongsSortList[i].CatIndex == CatIndex && !_SongsSortList[i].PartyHidden) + if (Sorter.SortedSongs[i].CatIndex == CatIndex && !Sorter.SortedSongs[i].PartyHidden) num++; } return num; @@ -160,7 +129,7 @@ namespace Vocaluxe.Base public static void NextCategory() { - if (Category == _Categories.Count - 1) + if (Category == Categorizer.Categories.Count - 1) Category = 0; else Category++; @@ -168,7 +137,7 @@ namespace Vocaluxe.Base public static void PrevCategory() { if (Category == 0) - Category = _Categories.Count - 1; + Category = Categorizer.Categories.Count - 1; else Category--; } @@ -213,8 +182,8 @@ namespace Vocaluxe.Base public static string GetCurrentCategoryName() { - if ((_Categories.Count > 0) && (_CatIndex >= 0) && (_Categories.Count > _CatIndex)) - return _Categories[_CatIndex].Name; + if ((Categorizer.Categories.Count > 0) && (_CatIndex >= 0) && (Categorizer.Categories.Count > _CatIndex)) + return Categorizer.Categories[_CatIndex].Name; else return String.Empty; } @@ -232,13 +201,13 @@ namespace Vocaluxe.Base public static void AddPartySongSung(int SongID) { int cat = -1; - for (int i = 0; i < _SongsSortList.Length; i++) + for (int i = 0; i < Sorter.SortedSongs.Length; i++) { - if (SongID == _SongsSortList[i].SongID) + if (SongID == Sorter.SortedSongs[i].SongID) { - _SongsSortList[i].PartyHidden = true; - _SongsSortList[i].Visible = false; - cat = _SongsSortList[i].CatIndex; + Sorter.SortedSongs[i].PartyHidden = true; + Sorter.SortedSongs[i].Visible = false; + cat = Sorter.SortedSongs[i].CatIndex; break; } } @@ -252,21 +221,21 @@ namespace Vocaluxe.Base public static void ResetPartySongSung() { - for (int i = 0; i < _SongsSortList.Length; i++) + for (int i = 0; i < Sorter.SortedSongs.Length; i++) { - _SongsSortList[i].PartyHidden = false; - _SongsSortList[i].Visible = (_SongsSortList[i].CatIndex == _CatIndex && !_SongsSortList[i].PartyHidden); + Sorter.SortedSongs[i].PartyHidden = false; + Sorter.SortedSongs[i].Visible = (Sorter.SortedSongs[i].CatIndex == _CatIndex && !Sorter.SortedSongs[i].PartyHidden); } } public static void ResetPartySongSung(int CatIndex) { - for (int i = 0; i < _SongsSortList.Length; i++) + for (int i = 0; i < Sorter.SortedSongs.Length; i++) { - if (_SongsSortList[i].CatIndex == CatIndex) + if (Sorter.SortedSongs[i].CatIndex == CatIndex) { - _SongsSortList[i].PartyHidden = false; - _SongsSortList[i].Visible = (_SongsSortList[i].CatIndex == _CatIndex && !_SongsSortList[i].PartyHidden); + Sorter.SortedSongs[i].PartyHidden = false; + Sorter.SortedSongs[i].Visible = (Sorter.SortedSongs[i].CatIndex == _CatIndex && !Sorter.SortedSongs[i].PartyHidden); } } } @@ -343,7 +312,7 @@ namespace Vocaluxe.Base get { List songs = new List(); - foreach (SongPointer sp in _SongsSortList) + foreach (SongPointer sp in Sorter.SortedSongs) { if (sp.Visible) songs.Add(_Songs[sp.SongID]); @@ -357,7 +326,7 @@ namespace Vocaluxe.Base get { List songs = new List(); - foreach (SongPointer sp in _SongsSortList) + foreach (SongPointer sp in Sorter.SortedSongs) { if (sp.Visible) songs.Add(_Songs[sp.SongID]); @@ -368,7 +337,7 @@ namespace Vocaluxe.Base public static CCategory[] Categories { - get { return _Categories.ToArray(); } + get { return Categorizer.Categories.ToArray(); } } public static CSong GetVisibleSongByIndex(int index) @@ -376,7 +345,7 @@ namespace Vocaluxe.Base if (index < 0) return null; - foreach (SongPointer sp in _SongsSortList) + foreach (SongPointer sp in Sorter.SortedSongs) { if (sp.Visible) { @@ -388,320 +357,19 @@ namespace Vocaluxe.Base return null; } - private static void _FilterSongs(String SearchFilter, bool ShowDuetSongs) + private static void HandleCategoriesChanged(object sender, EventArgs args) { - if (_Init && _SearchFilter == SearchFilter && _ShowDuetSongs == ShowDuetSongs) - return; - - _Init = true; - _SearchFilter = SearchFilter; - _ShowDuetSongs = ShowDuetSongs; - _FilteredSongs.Clear(); - - string[] searchStrings = null; - if (_SearchFilter.Length > 0) - searchStrings = _SearchFilter.ToUpper().Split(new char[] { ' ' }); - - foreach (CSong song in _Songs) - { - if (!song.IsDuet || _ShowDuetSongs) - { - if (_SearchFilter.Length == 0) - _FilteredSongs.Add(song); - else if (searchStrings != null) - { - string search = song.Title.ToUpper() + " " + song.Artist.ToUpper() + " " + song.FolderName.ToUpper() + " " + song.FileName.ToUpper(); - - bool contains = true; - - foreach (string str in searchStrings) - { - contains &= search.Contains(str); - } - if (contains) - _FilteredSongs.Add(song); - } - } - } - } - - private static int _SortByFieldArtistTitle(SongPointer s1, SongPointer s2) - { - int res = s1.SortString.ToUpper().CompareTo(s2.SortString.ToUpper()); - if (res == 0) - { - if (_IgnoreArticles == EOffOn.TR_CONFIG_ON) - { - res = _Songs[s1.SongID].ArtistSorting.ToUpper().CompareTo(_Songs[s2.SongID].ArtistSorting.ToUpper()); - if (res == 0) - { - return _Songs[s1.SongID].TitleSorting.ToUpper().CompareTo(_Songs[s2.SongID].TitleSorting.ToUpper()); - } - return res; - } - else - { - res = _Songs[s1.SongID].Artist.ToUpper().CompareTo(_Songs[s2.SongID].Artist.ToUpper()); - if (res == 0) - { - return _Songs[s1.SongID].Title.ToUpper().CompareTo(_Songs[s2.SongID].Title.ToUpper()); - } - return res; - } - } - return res; - } - - private static int _SortByFieldTitle(SongPointer s1, SongPointer s2) - { - int res = s1.SortString.ToUpper().CompareTo(s2.SortString.ToUpper()); - if (res == 0) - { - if (_IgnoreArticles == EOffOn.TR_CONFIG_ON) - return _Songs[s1.SongID].TitleSorting.ToUpper().CompareTo(_Songs[s2.SongID].TitleSorting.ToUpper()); - else - return _Songs[s1.SongID].Title.ToUpper().CompareTo(_Songs[s2.SongID].Title.ToUpper()); - } - return res; - } - - private static List _CreateSortList(string fieldName) - { - FieldInfo field = null; - bool isString = false; - List SortList = new List(); - if (fieldName.Length == 0) - _FilteredSongs.ForEach((song) => SortList.Add(new SongPointer(song.ID, ""))); - { - field = Type.GetType("Vocaluxe.Menu.SongMenu.CSong,VocaluxeLib").GetField(fieldName, BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public); - isString = field.FieldType == typeof(string); - if (!isString && field.FieldType != typeof(List)) - throw new Exception("Unkown sort field type"); - foreach (CSong song in _FilteredSongs) - { - object value = field.GetValue(song); - if (isString) - SortList.Add(new SongPointer(song.ID, (String)value)); - else - { - List values = (List)value; - if (values.Count == 0) - { - SortList.Add(new SongPointer(song.ID, "")); - } - else - { - foreach (String sortString in (List)value) - { - SortList.Add(new SongPointer(song.ID, sortString)); - } - } - } - } - } - return SortList; - } - - private static void SortSongs() - { - String fieldName; - switch (_SongSorting) - { - case ESongSorting.TR_CONFIG_EDITION: - fieldName = "Edition"; - break; - case ESongSorting.TR_CONFIG_GENRE: - fieldName = "Genre"; - break; - case ESongSorting.TR_CONFIG_FOLDER: - fieldName = "FolderName"; - break; - case ESongSorting.TR_CONFIG_ARTIST_LETTER: - case ESongSorting.TR_CONFIG_ARTIST: - if (_IgnoreArticles == EOffOn.TR_CONFIG_ON) - fieldName = "ArtistSorting"; - else - fieldName = "Artist"; - break; - case ESongSorting.TR_CONFIG_TITLE_LETTER: - if (_IgnoreArticles == EOffOn.TR_CONFIG_ON) - fieldName = "TitleSorting"; - else - fieldName = "Title"; - break; - case ESongSorting.TR_CONFIG_YEAR: - case ESongSorting.TR_CONFIG_DECADE: - fieldName = "Year"; - break; - case ESongSorting.TR_CONFIG_LANGUAGE: - fieldName = "Language"; - break; - default: - fieldName = ""; - break; - } - List SortList = _CreateSortList(fieldName); - switch (_SongSorting) - { - case ESongSorting.TR_CONFIG_ARTIST_LETTER: - case ESongSorting.TR_CONFIG_ARTIST: - case ESongSorting.TR_CONFIG_NONE: - SortList.Sort(_SortByFieldTitle); - break; - default: - SortList.Sort(_SortByFieldArtistTitle); - break; - } - _SongsSortList = SortList.ToArray(); - } - - private static void _CreateCategoriesLetter() - { - string category = ""; - int NotLetterCat = -1; - for (int i = 0; i < _SongsSortList.Length; i++) - { - Char firstLetter = Char.ToUpper(_SongsSortList[i].SortString.Normalize(NormalizationForm.FormD)[0]); - - if (!Char.IsLetter(firstLetter)) - { - firstLetter = '#'; - } - if (firstLetter.ToString() != category) - { - if (firstLetter != '#' || NotLetterCat == -1) - { - category = firstLetter.ToString(); - _Categories.Add(new CCategory(category)); - - _SongsSortList[i].CatIndex = _Categories.Count - 1; - - if (firstLetter == '#') - NotLetterCat = _SongsSortList[i].CatIndex; - } - else - _SongsSortList[i].CatIndex = NotLetterCat; - } - else - _SongsSortList[i].CatIndex = _Categories.Count - 1; - } - } - - private static void _CreateCategoriesNormal(string NoCategoryName) - { - string category = ""; - int NoCategoryIndex = -1; - for (int i = 0; i < _SongsSortList.Length; i++) - { - if (_SongsSortList[i].SortString.Length > 0) - { - if (_SongsSortList[i].SortString != category) - { - category = _SongsSortList[i].SortString; - _Categories.Add(new CCategory(category)); - } - _SongsSortList[i].CatIndex = _Categories.Count - 1; - } - else - { - if (NoCategoryIndex < 0) - { - category = NoCategoryName; - _Categories.Add(new CCategory(category)); - NoCategoryIndex = _Categories.Count - 1; - } - _SongsSortList[i].CatIndex = NoCategoryIndex; - } - } - - } - - private static void _FillCategories() - { - string NoCategoryName = ""; - - switch (_SongSorting) - { - case ESongSorting.TR_CONFIG_EDITION: - NoCategoryName = CLanguage.Translate("TR_SCREENSONG_NOEDITION"); - break; - case ESongSorting.TR_CONFIG_GENRE: - NoCategoryName = CLanguage.Translate("TR_SCREENSONG_NOGENRE"); - break; - case ESongSorting.TR_CONFIG_DECADE: - case ESongSorting.TR_CONFIG_YEAR: - NoCategoryName = CLanguage.Translate("TR_SCREENSONG_NOYEAR"); - break; - case ESongSorting.TR_CONFIG_LANGUAGE: - NoCategoryName = CLanguage.Translate("TR_SCREENSONG_NOLANGUAGE"); - break; - case ESongSorting.TR_CONFIG_NONE: - NoCategoryName = CLanguage.Translate("TR_SCREENSONG_ALLSONGS"); - break; - } - if (_SongSorting == ESongSorting.TR_CONFIG_ARTIST_LETTER || _SongSorting == ESongSorting.TR_CONFIG_TITLE_LETTER) - _CreateCategoriesLetter(); - else - { - if(_SongSorting==ESongSorting.TR_CONFIG_DECADE) - for (int i = 0; i < _SongsSortList.Length; i++) - { - string Year = _SongsSortList[i].SortString; - if (Year.Length > 0) - { - Year = Year.Substring(0, 3); - _SongsSortList[i].SortString = Year + "0 - " + Year + "9"; - } - } - _CreateCategoriesNormal(NoCategoryName); - } - - } - - public static void Sort(ESongSorting Sorting, EOffOn Tabs, EOffOn IgnoreArticles, String SearchString) - { - _Sort(Sorting, Tabs, IgnoreArticles, SearchString, false, _ShowDuetSongs); - } - - public static void Sort(ESongSorting Sorting, EOffOn Tabs, EOffOn IgnoreArticles, String SearchString, bool ShowDuetSongs) - { - _Sort(Sorting, Tabs, IgnoreArticles, SearchString, false, ShowDuetSongs); - } - - private static void _Sort(ESongSorting Sorting, EOffOn Tabs, EOffOn IgnoreArticles, string SearchString, bool force, bool ShowDuetSongs) - { - if (_Songs.Count == 0) - return; - - if (!force && Sorting == _SongSorting && Tabs == _Tabs && IgnoreArticles == _IgnoreArticles && SearchString == _SearchFilter && ShowDuetSongs == _ShowDuetSongs) - return; //nothing to do - - _IgnoreArticles = IgnoreArticles; - _SongSorting = Sorting; - _Tabs = Tabs; - - _FilterSongs(SearchString, ShowDuetSongs); - SortSongs(); - _Categories.Clear(); - - if (_Tabs == EOffOn.TR_CONFIG_OFF) - { - //No categories. So don't create them! - _Categories.Add(new CCategory("")); - for (int i = 0; i < _SongsSortList.Length; i++) - { - _SongsSortList[i].CatIndex = 0; - } - }else - _FillCategories(); - - foreach (CCategory cat in _Categories) - { - cat.CoverTextureSmall = CCover.Cover(cat.Name); - } + _CategoriesForRandom.Clear(); Category = _CatIndex; } + public static void Sort(ESongSorting Sorting, EOffOn Tabs, EOffOn IgnoreArticles, String SearchString, EDuetOptions DuetOptions) + { + Filter.SetOptions(SearchString, DuetOptions); + Sorter.SetOptions(Sorting, IgnoreArticles); + Categorizer.Tabs = Tabs; + } + public static void LoadSongs() { CLog.StartBenchmark(1, "Load Songs"); @@ -734,7 +402,10 @@ namespace Vocaluxe.Base CLog.StopBenchmark(2, "Read TXTs"); CLog.StartBenchmark(2, "Sort Songs"); - _Sort(CConfig.SongSorting, CConfig.Tabs, CConfig.IgnoreArticles, String.Empty, true, true); + Sorter.SongSorting = CConfig.SongSorting; + Sorter.IgnoreArticles = CConfig.IgnoreArticles; + Categorizer.Tabs = CConfig.Tabs; + Categorizer.ObjectChanged += HandleCategoriesChanged; CLog.StopBenchmark(2, "Sort Songs"); Category = -1; _SongsLoaded = true; diff --git a/Vocaluxe/Screens/CScreenOptionsGame.cs b/Vocaluxe/Screens/CScreenOptionsGame.cs index b2c597ce..3bb48d0d 100644 --- a/Vocaluxe/Screens/CScreenOptionsGame.cs +++ b/Vocaluxe/Screens/CScreenOptionsGame.cs @@ -24,9 +24,6 @@ namespace Vocaluxe.Screens private const string ButtonExit = "ButtonExit"; - private ESongSorting _SongSortingOld; - private EOffOn _TabsOld; - private string _LanguageOld; private string[] _Languages; private int _CurrentLang = -1; @@ -133,15 +130,6 @@ namespace Vocaluxe.Screens return true; } - public override void OnShow() - { - base.OnShow(); - - _SongSortingOld = CConfig.SongSorting; - _TabsOld = CConfig.Tabs; - _LanguageOld = CConfig.Language; - } - public override bool UpdateGame() { return true; @@ -164,17 +152,10 @@ namespace Vocaluxe.Screens CConfig.SaveConfig(); - if (_SongSortingOld != CConfig.SongSorting || _TabsOld != CConfig.Tabs || _LanguageOld != CConfig.Language) - { - CSongs.Sort(CConfig.SongSorting, CConfig.Tabs, CConfig.IgnoreArticles, String.Empty); - CSongs.Category = -1; - } + CSongs.Sorter.SongSorting = CConfig.SongSorting; + CSongs.Categorizer.Tabs = CConfig.Tabs; CLanguage.SetLanguage(CConfig.Language); - - _SongSortingOld = CConfig.SongSorting; - _TabsOld = CConfig.Tabs; - _LanguageOld = CConfig.Language; } } } diff --git a/Vocaluxe/Screens/CScreenOptionsTheme.cs b/Vocaluxe/Screens/CScreenOptionsTheme.cs index 53fa7aa0..57d41052 100644 --- a/Vocaluxe/Screens/CScreenOptionsTheme.cs +++ b/Vocaluxe/Screens/CScreenOptionsTheme.cs @@ -178,7 +178,9 @@ namespace Vocaluxe.Screens if (_OldCoverTheme != SelectSlides[htSelectSlides(SelectSlideCover)].Selection) { CCover.ReloadCover(); - CSongs.Sort(CConfig.SongSorting, CConfig.Tabs, CConfig.IgnoreArticles, String.Empty); + CSongs.Filter.SearchString = String.Empty; + CSongs.Sorter.SetOptions(CConfig.SongSorting, CConfig.IgnoreArticles); + CSongs.Categorizer.Tabs = CConfig.Tabs; } if (_OldTheme != SelectSlides[htSelectSlides(SelectSlideTheme)].Selection) diff --git a/Vocaluxe/Screens/CScreenSong.cs b/Vocaluxe/Screens/CScreenSong.cs index ecbfdad2..a70f217d 100644 --- a/Vocaluxe/Screens/CScreenSong.cs +++ b/Vocaluxe/Screens/CScreenSong.cs @@ -674,7 +674,7 @@ namespace Vocaluxe.Screens SelectedCategoryIndex = -2; _sso = CParty.GetSongSelectionOptions(); - CSongs.Sort(_sso.Sorting.SongSorting, _sso.Sorting.Tabs, _sso.Sorting.IgnoreArticles, _sso.Sorting.SearchString, _sso.Sorting.ShowDuetSongs); + CSongs.Sort(_sso.Sorting.SongSorting, _sso.Sorting.Tabs, _sso.Sorting.IgnoreArticles, _sso.Sorting.SearchString, _sso.Sorting.DuetOptions); _SearchActive = _sso.Sorting.SearchActive; _SearchText = _sso.Sorting.SearchString; @@ -807,7 +807,7 @@ namespace Vocaluxe.Screens if (_sso.Selection.PartyMode) { - CSongs.Sort(_sso.Sorting.SongSorting, _sso.Sorting.Tabs, _sso.Sorting.IgnoreArticles, _sso.Sorting.SearchString, _sso.Sorting.ShowDuetSongs); + CSongs.Sort(_sso.Sorting.SongSorting, _sso.Sorting.Tabs, _sso.Sorting.IgnoreArticles, _sso.Sorting.SearchString, _sso.Sorting.DuetOptions); _SearchActive = _sso.Sorting.SearchActive; _SearchText = _sso.Sorting.SearchString; @@ -1117,7 +1117,7 @@ namespace Vocaluxe.Screens refresh = true; } - CSongs.Sort(_sso.Sorting.SongSorting, _sso.Sorting.Tabs, _sso.Sorting.IgnoreArticles, NewFilterString, _sso.Sorting.ShowDuetSongs); + CSongs.Sort(_sso.Sorting.SongSorting, _sso.Sorting.Tabs, _sso.Sorting.IgnoreArticles, NewFilterString, _sso.Sorting.DuetOptions); if (SongID == -1 || CSongs.NumVisibleSongs == 0 || CSongs.NumVisibleSongs <= SongIndex || CSongs.VisibleSongs[SongIndex].ID != SongID) refresh = true; diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj index 062512ba..b546ebad 100644 --- a/Vocaluxe/Vocaluxe.csproj +++ b/Vocaluxe/Vocaluxe.csproj @@ -182,9 +182,13 @@ + + + + diff --git a/VocaluxeLib/Menu/IMenu.cs b/VocaluxeLib/Menu/IMenu.cs index 8fb425db..87261c52 100644 --- a/VocaluxeLib/Menu/IMenu.cs +++ b/VocaluxeLib/Menu/IMenu.cs @@ -248,7 +248,7 @@ namespace Vocaluxe.Menu void ResetPartySongSung(); void ResetPartySongSung(int CatIndex); - void SortSongs(ESongSorting Sorting, EOffOn Tabs, EOffOn IgnoreArticles, String SearchString, bool ShowDuetSongs); + void SortSongs(ESongSorting Sorting, EOffOn Tabs, EOffOn IgnoreArticles, String SearchString, EDuetOptions DuetOptions); void NextCategory(); void PrevCategory(); @@ -667,6 +667,13 @@ namespace Vocaluxe.Menu //TR_CONFIG_BOOK //for playlists } + public enum EDuetOptions + { + All, + Duets, + NoDuets + } + public enum ESongSorting { TR_CONFIG_NONE, diff --git a/VocaluxeLib/PartyModes/CPartyModeNone.cs b/VocaluxeLib/PartyModes/CPartyModeNone.cs index 10d33c7c..df073bc6 100644 --- a/VocaluxeLib/PartyModes/CPartyModeNone.cs +++ b/VocaluxeLib/PartyModes/CPartyModeNone.cs @@ -20,7 +20,7 @@ namespace Vocaluxe.PartyModes _ScreenSongOptions.Sorting.SearchString = String.Empty; _ScreenSongOptions.Sorting.SearchActive = false; - _ScreenSongOptions.Sorting.ShowDuetSongs = true; + _ScreenSongOptions.Sorting.DuetOptions = EDuetOptions.All; } public override ScreenSongOptions GetScreenSongOptions() diff --git a/VocaluxeLib/PartyModes/IPartyMode.cs b/VocaluxeLib/PartyModes/IPartyMode.cs index 99c3e532..7b4289c3 100644 --- a/VocaluxeLib/PartyModes/IPartyMode.cs +++ b/VocaluxeLib/PartyModes/IPartyMode.cs @@ -20,7 +20,7 @@ namespace Vocaluxe.PartyModes public EOffOn IgnoreArticles; public string SearchString; public bool SearchActive; - public bool ShowDuetSongs; + public EDuetOptions DuetOptions; } ///