void nsAutoCompleteController::AfterSearches() { mResultCache.Clear(); if (mSearchesFailed == mSearches.Count()) PostSearchCleanup(); }
nsresult nsAutoCompleteController::StartSearch() { NS_ENSURE_STATE(mInput); nsCOMPtr<nsIAutoCompleteInput> input(mInput); mSearchStatus = nsIAutoCompleteController::STATUS_SEARCHING; mDefaultIndexCompleted = PR_FALSE; // Cache the current results so that we can pass these through to all the // searches without losing them nsCOMArray<nsIAutoCompleteResult> resultCache; if (!resultCache.AppendObjects(mResults)) { return NS_ERROR_OUT_OF_MEMORY; } PRUint32 count = mSearches.Count(); mSearchesOngoing = count; mFirstSearchResult = PR_TRUE; // notify the input that the search is beginning input->OnSearchBegin(); PRUint32 searchesFailed = 0; for (PRUint32 i = 0; i < count; ++i) { nsCOMPtr<nsIAutoCompleteSearch> search = mSearches[i]; nsIAutoCompleteResult *result = resultCache.SafeObjectAt(i); if (result) { PRUint16 searchResult; result->GetSearchResult(&searchResult); if (searchResult != nsIAutoCompleteResult::RESULT_SUCCESS && searchResult != nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING && searchResult != nsIAutoCompleteResult::RESULT_NOMATCH) result = nsnull; } nsAutoString searchParam; nsresult rv = input->GetSearchParam(searchParam); if (NS_FAILED(rv)) return rv; rv = search->StartSearch(mSearchString, searchParam, result, static_cast<nsIAutoCompleteObserver *>(this)); if (NS_FAILED(rv)) { ++searchesFailed; --mSearchesOngoing; } } if (searchesFailed == count) PostSearchCleanup(); return NS_OK; }
NS_IMETHODIMP nsAutoCompleteController::StopSearch() { // Stop the timer if there is one ClearSearchTimer(); // Stop any ongoing asynchronous searches if (mSearchStatus == nsIAutoCompleteController::STATUS_SEARCHING) { PRUint32 count = mSearches.Count(); for (PRUint32 i = 0; i < count; ++i) { nsCOMPtr<nsIAutoCompleteSearch> search = mSearches[i]; search->StopSearch(); } mSearchesOngoing = 0; // since we were searching, but now we've stopped, // we need to call PostSearchCleanup() PostSearchCleanup(); } return NS_OK; }
nsresult nsAutoCompleteController::ProcessResult(PRInt32 aSearchIndex, nsIAutoCompleteResult *aResult) { NS_ENSURE_STATE(mInput); nsCOMPtr<nsIAutoCompleteInput> input(mInput); // If this is the first search result we are processing // we should clear out the previously cached results if (mFirstSearchResult) { ClearResults(); mFirstSearchResult = false; } PRUint16 result = 0; if (aResult) aResult->GetSearchResult(&result); // if our results are incremental, the search is still ongoing if (result != nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING && result != nsIAutoCompleteResult::RESULT_NOMATCH_ONGOING) { --mSearchesOngoing; } PRUint32 oldMatchCount = 0; PRUint32 matchCount = 0; if (aResult) aResult->GetMatchCount(&matchCount); PRInt32 resultIndex = mResults.IndexOf(aResult); if (resultIndex == -1) { // cache the result mResults.AppendObject(aResult); mMatchCounts.AppendElement(matchCount); resultIndex = mResults.Count() - 1; } else { oldMatchCount = mMatchCounts[aSearchIndex]; mMatchCounts[resultIndex] = matchCount; } bool isTypeAheadResult = false; if (aResult) { aResult->GetTypeAheadResult(&isTypeAheadResult); } if (!isTypeAheadResult) { PRUint32 oldRowCount = mRowCount; // If the search failed, increase the match count to include the error // description. if (result == nsIAutoCompleteResult::RESULT_FAILURE) { nsAutoString error; aResult->GetErrorDescription(error); if (!error.IsEmpty()) { ++mRowCount; if (mTree) { mTree->RowCountChanged(oldRowCount, 1); } } } else if (result == nsIAutoCompleteResult::RESULT_SUCCESS || result == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) { // Increase the match count for all matches in this result. mRowCount += matchCount - oldMatchCount; if (mTree) { mTree->RowCountChanged(oldRowCount, matchCount - oldMatchCount); } } // Refresh the popup view to display the new search results nsCOMPtr<nsIAutoCompletePopup> popup; input->GetPopup(getter_AddRefs(popup)); NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE); popup->Invalidate(); // Make sure the popup is open, if necessary, since we now have at least one // search result ready to display. Don't force the popup closed if we might // get results in the future to avoid unnecessarily canceling searches. if (mRowCount) { OpenPopup(); } else if (result != nsIAutoCompleteResult::RESULT_NOMATCH_ONGOING) { ClosePopup(); } } if (result == nsIAutoCompleteResult::RESULT_SUCCESS || result == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) { // Try to autocomplete the default index for this search. CompleteDefaultIndex(resultIndex); } if (mSearchesOngoing == 0) { // If this is the last search to return, cleanup. PostSearchCleanup(); } return NS_OK; }
nsresult nsAutoCompleteController::StartSearch() { NS_ENSURE_STATE(mInput); nsCOMPtr<nsIAutoCompleteInput> input(mInput); mSearchStatus = nsIAutoCompleteController::STATUS_SEARCHING; mDefaultIndexCompleted = false; // Cache the current results so that we can pass these through to all the // searches without losing them nsCOMArray<nsIAutoCompleteResult> resultCache; if (!resultCache.AppendObjects(mResults)) { return NS_ERROR_OUT_OF_MEMORY; } PRUint32 count = mSearches.Count(); mSearchesOngoing = count; mFirstSearchResult = true; // notify the input that the search is beginning input->OnSearchBegin(); PRUint32 searchesFailed = 0; for (PRUint32 i = 0; i < count; ++i) { nsCOMPtr<nsIAutoCompleteSearch> search = mSearches[i]; nsIAutoCompleteResult *result = resultCache.SafeObjectAt(i); if (result) { PRUint16 searchResult; result->GetSearchResult(&searchResult); if (searchResult != nsIAutoCompleteResult::RESULT_SUCCESS && searchResult != nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING && searchResult != nsIAutoCompleteResult::RESULT_NOMATCH) result = nsnull; } nsAutoString searchParam; nsresult rv = input->GetSearchParam(searchParam); if (NS_FAILED(rv)) return rv; rv = search->StartSearch(mSearchString, searchParam, result, static_cast<nsIAutoCompleteObserver *>(this)); if (NS_FAILED(rv)) { ++searchesFailed; --mSearchesOngoing; } // Because of the joy of nested event loops (which can easily happen when some // code uses a generator for an asynchronous AutoComplete search), // nsIAutoCompleteSearch::StartSearch might cause us to be detached from our input // field. The next time we iterate, we'd be touching something that we shouldn't // be, and result in a crash. if (!mInput) { // The search operation has been finished. return NS_OK; } } if (searchesFailed == count) PostSearchCleanup(); return NS_OK; }