// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; namespace Microsoft.Plugin.WindowWalker.Components { /// /// Responsible for searching and finding matches for the strings provided. /// Essentially the UI independent model of the application /// internal class SearchController { /// /// the current search text /// private string searchText; /// /// Open window search results /// private List searchMatches; /// /// Singleton pattern /// private static SearchController instance; /// /// Gets or sets the current search text /// internal string SearchText { get { return searchText; } set { // Using CurrentCulture since this is user facing searchText = value.ToLower(CultureInfo.CurrentCulture).Trim(); } } /// /// Gets the open window search results /// internal List SearchMatches { get { return new List(searchMatches).OrderByDescending(x => x.Score).ToList(); } } /// /// Gets singleton Pattern /// internal static SearchController Instance { get { if (instance == null) { instance = new SearchController(); } return instance; } } /// /// Initializes a new instance of the class. /// Initializes the search controller object /// private SearchController() { searchText = string.Empty; } /// /// Event handler for when the search text has been updated /// internal void UpdateSearchText(string searchText) { SearchText = searchText; SyncOpenWindowsWithModel(); } /// /// Syncs the open windows with the OpenWindows Model /// internal void SyncOpenWindowsWithModel() { System.Diagnostics.Debug.Print("Syncing WindowSearch result with OpenWindows Model"); List snapshotOfOpenWindows = OpenWindows.Instance.Windows; if (string.IsNullOrWhiteSpace(SearchText)) { searchMatches = AllOpenWindows(snapshotOfOpenWindows); } else { searchMatches = FuzzySearchOpenWindows(snapshotOfOpenWindows); } } /// /// Search method that matches the title of windows with the user search text /// /// what windows are open /// Returns search results private List FuzzySearchOpenWindows(List openWindows) { List result = new List(); var searchStrings = new SearchString(searchText, SearchResult.SearchType.Fuzzy); foreach (var window in openWindows) { var titleMatch = FuzzyMatching.FindBestFuzzyMatch(window.Title, searchStrings.SearchText); var processMatch = FuzzyMatching.FindBestFuzzyMatch(window.Process.Name, searchStrings.SearchText); if ((titleMatch.Count != 0 || processMatch.Count != 0) && window.Title.Length != 0) { result.Add(new SearchResult(window, titleMatch, processMatch, searchStrings.SearchType)); } } System.Diagnostics.Debug.Print("Found " + result.Count + " windows that match the search text"); return result; } /// /// Search method that matches all the windows with a title /// /// what windows are open /// Returns search results private List AllOpenWindows(List openWindows) { List result = new List(); foreach (var window in openWindows) { if (window.Title.Length != 0) { result.Add(new SearchResult(window)); } } return result.OrderBy(w => w.Result.Title).ToList(); } /// /// Event args for a window list update event /// internal class SearchResultUpdateEventArgs : EventArgs { } } }