SearchController.cs
  1  // Copyright (c) Microsoft Corporation
  2  // The Microsoft Corporation licenses this file to you under the MIT license.
  3  // See the LICENSE file in the project root for more information.
  4  
  5  // Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
  6  using System;
  7  using System.Collections.Generic;
  8  using System.Globalization;
  9  using System.Linq;
 10  
 11  namespace Microsoft.Plugin.WindowWalker.Components
 12  {
 13      /// <summary>
 14      /// Responsible for searching and finding matches for the strings provided.
 15      /// Essentially the UI independent model of the application
 16      /// </summary>
 17      internal class SearchController
 18      {
 19          /// <summary>
 20          /// the current search text
 21          /// </summary>
 22          private string searchText;
 23  
 24          /// <summary>
 25          /// Open window search results
 26          /// </summary>
 27          private List<SearchResult> searchMatches;
 28  
 29          /// <summary>
 30          /// Singleton pattern
 31          /// </summary>
 32          private static SearchController instance;
 33  
 34          /// <summary>
 35          /// Gets or sets the current search text
 36          /// </summary>
 37          internal string SearchText
 38          {
 39              get
 40              {
 41                  return searchText;
 42              }
 43  
 44              set
 45              {
 46                  // Using CurrentCulture since this is user facing
 47                  searchText = value.ToLower(CultureInfo.CurrentCulture).Trim();
 48              }
 49          }
 50  
 51          /// <summary>
 52          /// Gets the open window search results
 53          /// </summary>
 54          internal List<SearchResult> SearchMatches
 55          {
 56              get { return new List<SearchResult>(searchMatches).OrderByDescending(x => x.Score).ToList(); }
 57          }
 58  
 59          /// <summary>
 60          /// Gets singleton Pattern
 61          /// </summary>
 62          internal static SearchController Instance
 63          {
 64              get
 65              {
 66                  if (instance == null)
 67                  {
 68                      instance = new SearchController();
 69                  }
 70  
 71                  return instance;
 72              }
 73          }
 74  
 75          /// <summary>
 76          /// Initializes a new instance of the <see cref="SearchController"/> class.
 77          /// Initializes the search controller object
 78          /// </summary>
 79          private SearchController()
 80          {
 81              searchText = string.Empty;
 82          }
 83  
 84          /// <summary>
 85          /// Event handler for when the search text has been updated
 86          /// </summary>
 87          internal void UpdateSearchText(string searchText)
 88          {
 89              SearchText = searchText;
 90              SyncOpenWindowsWithModel();
 91          }
 92  
 93          /// <summary>
 94          /// Syncs the open windows with the OpenWindows Model
 95          /// </summary>
 96          internal void SyncOpenWindowsWithModel()
 97          {
 98              System.Diagnostics.Debug.Print("Syncing WindowSearch result with OpenWindows Model");
 99  
100              List<Window> snapshotOfOpenWindows = OpenWindows.Instance.Windows;
101  
102              if (string.IsNullOrWhiteSpace(SearchText))
103              {
104                  searchMatches = AllOpenWindows(snapshotOfOpenWindows);
105              }
106              else
107              {
108                  searchMatches = FuzzySearchOpenWindows(snapshotOfOpenWindows);
109              }
110          }
111  
112          /// <summary>
113          /// Search method that matches the title of windows with the user search text
114          /// </summary>
115          /// <param name="openWindows">what windows are open</param>
116          /// <returns>Returns search results</returns>
117          private List<SearchResult> FuzzySearchOpenWindows(List<Window> openWindows)
118          {
119              List<SearchResult> result = new List<SearchResult>();
120              var searchStrings = new SearchString(searchText, SearchResult.SearchType.Fuzzy);
121  
122              foreach (var window in openWindows)
123              {
124                  var titleMatch = FuzzyMatching.FindBestFuzzyMatch(window.Title, searchStrings.SearchText);
125                  var processMatch = FuzzyMatching.FindBestFuzzyMatch(window.Process.Name, searchStrings.SearchText);
126  
127                  if ((titleMatch.Count != 0 || processMatch.Count != 0) && window.Title.Length != 0)
128                  {
129                      result.Add(new SearchResult(window, titleMatch, processMatch, searchStrings.SearchType));
130                  }
131              }
132  
133              System.Diagnostics.Debug.Print("Found " + result.Count + " windows that match the search text");
134  
135              return result;
136          }
137  
138          /// <summary>
139          /// Search method that matches all the windows with a title
140          /// </summary>
141          /// <param name="openWindows">what windows are open</param>
142          /// <returns>Returns search results</returns>
143          private List<SearchResult> AllOpenWindows(List<Window> openWindows)
144          {
145              List<SearchResult> result = new List<SearchResult>();
146  
147              foreach (var window in openWindows)
148              {
149                  if (window.Title.Length != 0)
150                  {
151                      result.Add(new SearchResult(window));
152                  }
153              }
154  
155              return result.OrderBy(w => w.Result.Title).ToList();
156          }
157  
158          /// <summary>
159          /// Event args for a window list update event
160          /// </summary>
161          internal class SearchResultUpdateEventArgs : EventArgs
162          {
163          }
164      }
165  }