@@ -18,9 +18,10 @@ namespace ComponentSelectorAdditions
1818 /// Use the <see cref="AddExcludedCategory(string)"/> and <see cref="RemoveExcludedCategory(string)"/>
1919 /// methods to add categories which shouldn't be searched into because they're added.
2020 /// </summary>
21- public sealed class SearchConfig : ConfigSection
21+ public sealed class SearchConfig : SingletonConfigSection < SearchConfig >
2222 {
2323 private static readonly DefiningConfigKey < bool > _alwaysSearchRoot = new ( "AlwaysSearchRoot" , "Always starts searching from the root category, regardless of the current one." , ( ) => false ) ;
24+
2425 private static readonly Dictionary < string , bool > _excludedCategories = new ( StringComparer . OrdinalIgnoreCase ) ;
2526
2627 private static readonly DefiningConfigKey < int > _maxResultCount = new ( "MaxResultCount" , "The maximum number of component / node results to display. 'Better' results are listed first. Categories don't count." , ( ) => 64 )
@@ -37,50 +38,62 @@ public sealed class SearchConfig : ConfigSection
3738 private static readonly char [ ] _userExclusionSeparator = new [ ] { ';' } ;
3839
3940 /// <summary>
40- /// Gets this config's instance .
41+ /// Gets whether the search always searches from the root category of the component selector / node browser .
4142 /// </summary>
42- public static SearchConfig Instance { get ; private set ; } = null ! ;
43+ public bool AlwaysSearchRoot => _alwaysSearchRoot ;
4344
4445 /// <inheritdoc/>
4546 public override string Description => "Contains settings for the Component Selector Search." ;
4647
4748 /// <inheritdoc/>
4849 public override string Id => "Search" ;
4950
51+ /// <summary>
52+ /// Gets how many results will be listed at most.
53+ /// </summary>
54+ public int MaxResultCount => _maxResultCount ;
55+
56+ /// <summary>
57+ /// Gets how many milliseconds to wait after the last change in the search input before actually searching.
58+ /// </summary>
59+ public int SearchRefreshDelay => ( int ) ( 1000 * _searchRefreshDelay ) ;
60+
5061 /// <inheritdoc/>
5162 public override Version Version { get ; } = new ( 1 , 0 , 0 ) ;
5263
53- internal bool AlwaysSearchRoot => _alwaysSearchRoot ;
54- internal int MaxResultCount => _maxResultCount ;
55- internal int SearchRefreshDelay => ( int ) ( 1000 * _searchRefreshDelay ) ;
56-
5764 static SearchConfig ( )
5865 {
5966 _userExcludedCategories . Changed += UserExcludedCategoriesChanged ;
6067 }
6168
6269 /// <summary>
63- /// Creates an instance of this config once .
70+ /// Adds the given category path as an excluded category for searches .
6471 /// </summary>
65- /// <exception cref="InvalidOperationException"></exception>
66- public SearchConfig ( )
67- {
68- if ( Instance is not null )
69- throw new InvalidOperationException ( ) ;
70-
71- Instance = this ;
72- }
73-
72+ /// <remarks>
73+ /// This should be used to exclude any categories added by mods.
74+ /// Make sure to <see cref="RemoveExcludedCategory">remove</see> them again when being shutdown without the application being exited.<br/>
75+ /// Searching <i>inside</i> of them is still possible.
76+ /// </remarks>
77+ /// <param name="category">The path of the category to exclude. Must not be null or whitespace.</param>
78+ /// <returns><c>true</c> if the category is excluded now; otherwise, <c>false</c>.</returns>
7479 public bool AddExcludedCategory ( string category )
7580 {
7681 if ( string . IsNullOrWhiteSpace ( category ) )
7782 return false ;
7883
79- _excludedCategories [ category ] = false ;
84+ // Don't override user status of already excluded category
85+ if ( ! HasExcludedCategory ( category ) )
86+ _excludedCategories [ category ] = false ;
8087
8188 return true ;
8289 }
8390
91+ /// <summary>
92+ /// Checks whether the given category path is an excluded category for searches.
93+ /// </summary>
94+ /// <param name="category">The path of the category to check.</param>
95+ /// <param name="isUserCategory">Whether the excluded category was added by the user if it is excluded; otherwise, <c>null</c>.</param>
96+ /// <returns><c>true</c> if the given category is excluded; otherwise, <c>false</c>.</returns>
8497 public bool HasExcludedCategory ( string category , [ NotNullWhen ( true ) ] out bool ? isUserCategory )
8598 {
8699 if ( _excludedCategories . TryGetValue ( category , out var userCategory ) )
@@ -93,9 +106,20 @@ public bool HasExcludedCategory(string category, [NotNullWhen(true)] out bool? i
93106 return false ;
94107 }
95108
109+ /// <inheritdoc cref="HasExcludedCategory(string, out bool?)"/>
96110 public bool HasExcludedCategory ( string category )
97111 => _excludedCategories . ContainsKey ( category ) ;
98112
113+ /// <summary>
114+ /// Removes the given category path from being an excluded category for searches,
115+ /// if it wasn't added by the user.
116+ /// </summary>
117+ /// <remarks>
118+ /// This should be used to remove any excluded categories added by mods again
119+ /// when they're being shutdown without the application being exited.
120+ /// </remarks>
121+ /// <param name="category">The path of the category to remove from being excluded. Must not be null or whitespace.</param>
122+ /// <returns><c>true</c> if the category is not excluded anymore; otherwise, <c>false</c>.</returns>
99123 public bool RemoveExcludedCategory ( string category )
100124 {
101125 if ( ! _excludedCategories . TryGetValue ( category , out var userCategory ) )
@@ -114,7 +138,6 @@ protected override void OnLoad(JObject source, JsonSerializer jsonSerializer)
114138 {
115139 base . OnLoad ( source , jsonSerializer ) ;
116140
117- Instance = this ;
118141 LoadUserExcludedCategories ( _userExcludedCategories ) ;
119142 }
120143
0 commit comments