/// <summary> /// Searches the specified fields. /// </summary> /// <param name="fields">The fields.</param> /// <param name="filters">The filters.</param> public void Search(IEnumerable <SearchField> fields, IEnumerable <ICmObject> filters) { // If we abort this search (because the user typed), but somehow the system becomes idle before we complete a new // search, go ahead and complete the original one. m_pendingFields = fields; m_pendingFilters = filters; m_mediator.IdleQueue.Add(IdleQueuePriority.High, DoPendingSearchWhenIdle); CreateSearchers(); var results = new HashSet <ICmObject>(); ITsString firstSearchStr = null; foreach (SearchField field in fields) { if (ShouldAbort()) { return; } if (firstSearchStr == null) { firstSearchStr = field.String; } results.UnionWith(m_searcher.Search(field.Flid, field.String)); } if (filters != null) { results.ExceptWith(filters); } if (ShouldAbort()) { return; } // The following fixes LT-10293. RecordSorter sorter = null; if (firstSearchStr != null) { int ws = firstSearchStr.get_WritingSystemAt(0); bool isVern = m_cache.ServiceLocator.WritingSystems.VernacularWritingSystems.Contains(ws); sorter = m_bvMatches.CreateSorterForFirstColumn(isVern, ws); } if (sorter != null) { // Convert each ICmObject in results to a IManyOnePathSortItem, and sort // using the sorter. var records = new ArrayList(results.Count); foreach (ICmObject obj in results) { records.Add(new ManyOnePathSortItem(obj)); } sorter.Sort(records); var hvos = new int[records.Count]; for (int i = 0; i < records.Count; ++i) { hvos[i] = (((IManyOnePathSortItem)records[i]).KeyObject); } UpdateResults(hvos); } else { UpdateResults(results.Select(obj => obj.Hvo).ToArray()); } // Completed successfully, don't want to do again. m_pendingFields = null; m_mediator.IdleQueue.Remove(DoPendingSearchWhenIdle); }
private void UpdateResults(SearchField firstField, IEnumerable <int> results) { ITsString firstSearchStr = firstField.String; // if the firstSearchStr is null we can't get its writing system RecordSorter sorter = null; if (firstSearchStr != null) { int ws = firstSearchStr.get_WritingSystemAt(0); sorter = CreateFindResultSorter(firstSearchStr, ws); } int[] hvos; if (sorter != null) { // Convert each ICmObject in results to a IManyOnePathSortItem, and sort // using the sorter. var records = new ArrayList(); foreach (int hvo in results.Where(hvo => StartingObject == null || StartingObject.Hvo != hvo)) { records.Add(new ManyOnePathSortItem(hvo, null, null)); } sorter.Sort(records); hvos = records.Cast <IManyOnePathSortItem>().Select(i => i.KeyObject).ToArray(); } else { hvos = results.Where(hvo => StartingObject == null || StartingObject.Hvo != hvo).ToArray(); } int count = hvos.Length; int prevIndex = m_bvMatches.SelectedIndex; int prevHvo = prevIndex == -1 ? 0 : m_bvMatches.AllItems[prevIndex]; m_listPublisher.CacheVecProp(m_cache.LanguageProject.LexDbOA.Hvo, hvos); TabStop = count > 0; // Disable the list so that it doesn't steal the focus (LT-9481) m_bvMatches.Enabled = false; try { // LT-6366 if (count == 0) { if (m_bvMatches.BrowseView.IsHandleCreated) { m_bvMatches.SelectedIndex = -1; } m_selObject = null; } else { int newIndex = 0; var allItems = m_bvMatches.AllItems; // This is an important optimization; each call marshals the whole list! for (int i = 0; i < allItems.Count; i++) { if (allItems[i] == prevHvo) { newIndex = i; break; } } if (m_bvMatches.BrowseView.IsHandleCreated) { m_bvMatches.SelectedIndex = newIndex; } m_selObject = m_cache.ServiceLocator.GetObject(allItems[newIndex]); FireSelectionChanged(); } } finally { m_bvMatches.Enabled = true; } if (!m_searchEngine.IsBusy && SearchCompleted != null) { SearchCompleted(this, new EventArgs()); } }