NS_IMETHODIMP nsAutoCompleteController::SetInput(nsIAutoCompleteInput *aInput) { // Don't do anything if the input isn't changing. if (mInput == aInput) return NS_OK; // Clear out the current search context if (mInput) { // Stop all searches in case they are async. StopSearch(); ClearResults(); ClosePopup(); mSearches.Clear(); } mInput = aInput; // Nothing more to do if the input was just being set to null. if (!aInput) return NS_OK; nsAutoString newValue; aInput->GetTextValue(newValue); // Clear out this reference in case the new input's popup has no tree mTree = nsnull; // Reset all search state members to default values mSearchString = newValue; mDefaultIndexCompleted = false; mBackspaced = false; mSearchStatus = nsIAutoCompleteController::STATUS_NONE; mRowCount = 0; mSearchesOngoing = 0; // Initialize our list of search objects PRUint32 searchCount; aInput->GetSearchCount(&searchCount); mResults.SetCapacity(searchCount); mSearches.SetCapacity(searchCount); mMatchCounts.SetLength(searchCount); const char *searchCID = kAutoCompleteSearchCID; for (PRUint32 i = 0; i < searchCount; ++i) { // Use the search name to create the contract id string for the search service nsCAutoString searchName; aInput->GetSearchAt(i, searchName); nsCAutoString cid(searchCID); cid.Append(searchName); // Use the created cid to get a pointer to the search service and store it for later nsCOMPtr<nsIAutoCompleteSearch> search = do_GetService(cid.get()); if (search) mSearches.AppendObject(search); } return NS_OK; }
uint32 CMenuIntel::OnCommand(uint32 nCommand, uint32 nParam1, uint32 nParam2) { if (m_PopupText.IsVisible()) { ClosePopup(); return 1; } switch (nCommand) { case MC_INTEL: { uint16 nID = (uint16) nParam1; CIntelItemList *pList = g_pPlayerStats->GetIntelList(); INTEL_ITEM* pItem = pList->Get(nID); if (pItem) { m_PopupText.Show(pItem->nTextId, pItem->nPopupId); // Disable menu now that popup is visible. g_pInterfaceMgr->GetMenuMgr()->EnableMenuBar(false); } } default: { return CBaseMenu::OnCommand(nCommand,nParam1,nParam2); } } return 1; }
nsresult nsAutoCompleteController::PostSearchCleanup() { NS_ENSURE_STATE(mInput); nsCOMPtr<nsIAutoCompleteInput> input(mInput); PRUint32 minResults; mInput->GetMinResultsForPopup(&minResults); if (mRowCount || minResults == 0) { OpenPopup(); if (mRowCount) mSearchStatus = nsIAutoCompleteController::STATUS_COMPLETE_MATCH; else mSearchStatus = nsIAutoCompleteController::STATUS_COMPLETE_NO_MATCH; } else { mSearchStatus = nsIAutoCompleteController::STATUS_COMPLETE_NO_MATCH; ClosePopup(); } // notify the input that the search is complete input->OnSearchComplete(); return NS_OK; }
NS_IMETHODIMP nsAutoCompleteController::HandleStartComposition() { NS_ENSURE_TRUE(!mIsIMEComposing, NS_OK); mPopupClosedByCompositionStart = false; mIsIMEComposing = true; if (!mInput) return NS_OK; nsCOMPtr<nsIAutoCompleteInput> input(mInput); bool disabled; input->GetDisableAutoComplete(&disabled); if (disabled) return NS_OK; // Stop all searches in case they are async. StopSearch(); bool isOpen = false; input->GetPopupOpen(&isOpen); if (isOpen) { ClosePopup(); bool stillOpen = false; input->GetPopupOpen(&stillOpen); mPopupClosedByCompositionStart = !stillOpen; } return NS_OK; }
bool WgPopupLayer::CloseAllPopups() { WgPopupHook * pHook = m_popupHooks.First(); if( pHook ) ClosePopup( pHook->_widget() ); return true; }
LTBOOL CMenuIntel::OnEscape ( ) { if (m_PopupText.IsVisible()) { ClosePopup(); return LTTRUE; } return CBaseMenu::OnEscape(); }
LTBOOL CMenuIntel::OnLButtonDown(int x, int y) { if (m_PopupText.IsVisible()) { ClosePopup(); return LTTRUE; } return CBaseMenu::OnLButtonDown(x, y); }
LTBOOL CMenuIntel::HandleKeyDown(int key, int rep) { // Close popup if necessary...Use OnEscape // to handle escape key... if (m_PopupText.IsVisible() && (VK_ESCAPE != key)) { ClosePopup(); return LTTRUE; } return CBaseMenu::HandleKeyDown(key, rep); }
void Picked() { // // Picked outside close all the popups // while (m_pdata && m_pdata->m_bCloseAll) { ClosePopup(m_pdata->m_ppopup); } EngineWindow::DoHitTest(); }
bool HwndSourceHookMenuPopup::OnFilterMessage(suic::ObjectPtr sender, suic::MessageParameter& mp) { suic::ElementPtr rootElement = suic::ElementPtr::cast(sender); bool handled = false; HWND hwnd = HandleToHwnd(mp.hwnd); switch (mp.message) { case WM_NCLBUTTONDOWN: case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: HandleMouseDown(hwnd); break; case WM_NCRBUTTONDOWN: case WM_RBUTTONDOWN: HandleMouseDown(hwnd); break; case WM_LBUTTONUP: HandleMouseUp(); handled = true; break; case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: handled = HandleMouseMove(mp); break; case WM_MOUSEACTIVATE: mp.result = MA_NOACTIVATE; handled = true; break; case WM_CLOSE: ClosePopup(rootElement.get()); break; case WM_NCACTIVATE: { if (mp.wParam == 0 && g_trackmenuitem) { g_trackmenuitem->CloseSubmenu(); g_trackmenuitem->InvalidateVisual(true); suic::SystemHelper::RemoveHwndMessageSystemHook(this); } } break; } return handled; }
NS_IMETHODIMP nsAutoCompleteController::HandleEscape(bool *_retval) { *_retval = false; if (!mInput) return NS_OK; // allow the event through if the popup is closed mInput->GetPopupOpen(_retval); // Stop all searches in case they are async. StopSearch(); ClearResults(); RevertTextValue(); ClosePopup(); return NS_OK; }
bool OnButtonLogon() { // Make sure that they have entered a CD Key if (g_bAskForCDKey && trekClient.GetCDKey().IsEmpty()) { TRef<IPopup> ppopupCDKey = CreateCDKeyPopup(); GetWindow()->GetPopupContainer()->OpenPopup(ppopupCDKey, false); } else { // // Grab info from the controls // ZString strName = m_peditName->GetString(); ZString strPassword = m_peditPassword->GetString(); bool fRememberPW = m_pbuttonSavePassword->GetChecked(); if (strName[0] != ' ' && strName[0] != '\0') // give 'em a msg box? { // // Close // TRef<LogonPopup> pthis = this; ClosePopup(NULL); // // Tell the site // m_psite->OnLogon(strName, strPassword, fRememberPW); } } return true; }
void WgPopupLayer::_onEvent( const WgEventPtr& _pEvent, WgEventHandler * pHandler ) { WgLayer::_onEvent(_pEvent,pHandler); WgWidget * pOpener = 0; // Try to find an opener WgWidget * pOrigin = _pEvent->Widget(); if( pOrigin && pOrigin != this ) { WgPopupHook * pHook = m_popupHooks.First(); while( pHook && pHook->_widget() != pOrigin ) pHook = pHook->_next(); if( pHook && pHook->m_pOpener ) pOpener = pHook->m_pOpener.RawPtr(); } // First we try to forward event to opener (if any) if( pOpener ) { pHandler->ForwardEvent( _pEvent, pOpener ); return; } // Secondly we take care of event ourselves if it is addressed to one of our menus or us. switch( _pEvent->Type() ) { /* case WG_EVENT_MOUSE_POSITION: if( !m_popupHooks.IsEmpty() ) // Process only if we have at least one open menu. { WgCoord ofs = _pEvent->PointerPos(); WgWidget * p = _findWidget( ofs, WG_SEARCH_ACTION_TARGET ); if( p != this ) { while( p->Parent() != this ) p = p->Parent(); if( p != m_popupHooks. } } break; */ case WG_EVENT_MOUSE_RELEASE: case WG_EVENT_MOUSE_PRESS: { WgMouseButtonEventPtr pEvent = WgMouseButtonEvent::Cast(_pEvent); WgCoord ofs = pEvent->PointerPos(); WgWidget * p = _findWidget( ofs, WG_SEARCH_ACTION_TARGET ); if( p == this ) { CloseAllPopups(); pHandler->SwallowEvent( _pEvent ); return; } } break; case WG_EVENT_KEY_PRESS: case WG_EVENT_KEY_REPEAT: { WgKeyEventPtr pEvent = WgKeyEvent::Cast(_pEvent); if( pEvent->TranslatedKeyCode() == WG_KEY_ESCAPE ) { if( !m_popupHooks.IsEmpty() ) { ClosePopup( m_popupHooks.Last()->_widget() ); pHandler->SwallowEvent( _pEvent ); return; } } } break; } }
NS_IMETHODIMP nsAutoCompleteController::HandleText() { // We should do nothing during composition. if (mIsIMEComposing) { return NS_OK; } if (!mInput) { // Stop all searches in case they are async. StopSearch(); // Note: if now is after blur and IME end composition, // check mInput before calling. // See https://bugzilla.mozilla.org/show_bug.cgi?id=193544#c31 NS_ERROR("Called before attaching to the control or after detaching from the control"); return NS_OK; } nsAutoString newValue; nsCOMPtr<nsIAutoCompleteInput> input(mInput); input->GetTextValue(newValue); // Note: the events occur in the following order when IME is used. // 1. composition start event(HandleStartComposition) // 2. composition end event(HandleEndComposition) // 3. input event(HandleText) // Note that the input event occurs if IME composition is cancelled, as well. // In HandleEndComposition, we are processing the popup properly. // Therefore, the input event after composition end event should do nothing. // (E.g., calling StopSearch() and ClosePopup().) // If it is not, popup is always closed after composition end. if (mIgnoreHandleText) { mIgnoreHandleText = false; if (newValue.Equals(mSearchString)) return NS_OK; NS_ERROR("Now is after composition end event. But the value was changed."); } // Stop all searches in case they are async. StopSearch(); if (!mInput) { // StopSearch() can call PostSearchCleanup() which might result // in a blur event, which could null out mInput, so we need to check it // again. See bug #395344 for more details return NS_OK; } bool disabled; input->GetDisableAutoComplete(&disabled); NS_ENSURE_TRUE(!disabled, NS_OK); // Don't search again if the new string is the same as the last search if (newValue.Length() > 0 && newValue.Equals(mSearchString)) return NS_OK; // Determine if the user has removed text from the end (probably by backspacing) if (newValue.Length() < mSearchString.Length() && Substring(mSearchString, 0, newValue.Length()).Equals(newValue)) { // We need to throw away previous results so we don't try to search through them again ClearResults(); mBackspaced = true; } else mBackspaced = false; mSearchString = newValue; // Don't search if the value is empty if (newValue.Length() == 0) { ClosePopup(); return NS_OK; } StartSearchTimer(); 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; }
NS_IMETHODIMP nsAutoCompleteController::HandleText() { // Note: the events occur in the following order when IME is used. // 1. a compositionstart event(HandleStartComposition) // 2. some input events (HandleText), eCompositionState_Composing // 3. a compositionend event(HandleEndComposition) // 4. an input event(HandleText), eCompositionState_Committing // We should do nothing during composition. if (mCompositionState == eCompositionState_Composing) { return NS_OK; } bool handlingCompositionCommit = (mCompositionState == eCompositionState_Committing); bool popupClosedByCompositionStart = mPopupClosedByCompositionStart; if (handlingCompositionCommit) { mCompositionState = eCompositionState_None; mPopupClosedByCompositionStart = false; } if (!mInput) { // Stop all searches in case they are async. StopSearch(); // Note: if now is after blur and IME end composition, // check mInput before calling. // See https://bugzilla.mozilla.org/show_bug.cgi?id=193544#c31 NS_ERROR("Called before attaching to the control or after detaching from the control"); return NS_OK; } nsAutoString newValue; nsCOMPtr<nsIAutoCompleteInput> input(mInput); input->GetTextValue(newValue); // Stop all searches in case they are async. StopSearch(); if (!mInput) { // StopSearch() can call PostSearchCleanup() which might result // in a blur event, which could null out mInput, so we need to check it // again. See bug #395344 for more details return NS_OK; } bool disabled; input->GetDisableAutoComplete(&disabled); NS_ENSURE_TRUE(!disabled, NS_OK); // Don't search again if the new string is the same as the last search // However, if this is called immediately after compositionend event, // we need to search the same value again since the search was canceled // at compositionstart event handler. if (!handlingCompositionCommit && newValue.Length() > 0 && newValue.Equals(mSearchString)) { return NS_OK; } // Determine if the user has removed text from the end (probably by backspacing) if (newValue.Length() < mSearchString.Length() && Substring(mSearchString, 0, newValue.Length()).Equals(newValue)) { // We need to throw away previous results so we don't try to search through them again ClearResults(); mBackspaced = true; } else mBackspaced = false; mSearchString = newValue; // Don't search if the value is empty if (newValue.Length() == 0) { // If autocomplete popup was closed by compositionstart event handler, // we should reopen it forcibly even if the value is empty. if (popupClosedByCompositionStart && handlingCompositionCommit) { bool cancel; HandleKeyNavigation(nsIDOMKeyEvent::DOM_VK_DOWN, &cancel); return NS_OK; } ClosePopup(); return NS_OK; } StartSearches(); return NS_OK; }
nsresult nsAutoCompleteController::EnterMatch(bool aIsPopupSelection) { nsCOMPtr<nsIAutoCompleteInput> input(mInput); nsCOMPtr<nsIAutoCompletePopup> popup; input->GetPopup(getter_AddRefs(popup)); NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE); bool forceComplete; input->GetForceComplete(&forceComplete); // Ask the popup if it wants to enter a special value into the textbox nsAutoString value; popup->GetOverrideValue(value); if (value.IsEmpty()) { bool shouldComplete; mInput->GetCompleteDefaultIndex(&shouldComplete); bool completeSelection; input->GetCompleteSelectedIndex(&completeSelection); // If completeselectedindex is false or a row was selected from the popup, // enter it into the textbox. If completeselectedindex is true, or // EnterMatch was called via other means, for instance pressing Enter, // don't fill in the value as it will have already been filled in as needed. PRInt32 selectedIndex; popup->GetSelectedIndex(&selectedIndex); if (selectedIndex >= 0 && (!completeSelection || aIsPopupSelection)) GetResultValueAt(selectedIndex, true, value); else if (shouldComplete) { // We usually try to preserve the casing of what user has typed, but // if he wants to autocomplete, we will replace the value with the // actual autocomplete result. // The user wants explicitely to use that result, so this ensures // association of the result with the autocompleted text. nsAutoString defaultIndexValue; nsAutoString inputValue; input->GetTextValue(inputValue); if (NS_SUCCEEDED(GetDefaultCompleteValue(-1, false, defaultIndexValue)) && defaultIndexValue.Equals(inputValue, nsCaseInsensitiveStringComparator())) value = defaultIndexValue; } if (forceComplete && value.IsEmpty()) { // Since nothing was selected, and forceComplete is specified, that means // we have to find the first default match and enter it instead PRUint32 count = mResults.Count(); for (PRUint32 i = 0; i < count; ++i) { nsIAutoCompleteResult *result = mResults[i]; if (result) { PRInt32 defaultIndex; result->GetDefaultIndex(&defaultIndex); if (defaultIndex >= 0) { result->GetValueAt(defaultIndex, value); break; } } } } } nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService(); NS_ENSURE_STATE(obsSvc); obsSvc->NotifyObservers(input, "autocomplete-will-enter-text", nsnull); if (!value.IsEmpty()) { input->SetTextValue(value); input->SelectTextRange(value.Length(), value.Length()); mSearchString = value; } obsSvc->NotifyObservers(input, "autocomplete-did-enter-text", nsnull); ClosePopup(); bool cancel; input->OnTextEntered(&cancel); return NS_OK; }
NS_IMETHODIMP nsAutoCompleteController::HandleKeyNavigation(PRUint32 aKey, bool *_retval) { // By default, don't cancel the event *_retval = false; if (!mInput) { // Stop all searches in case they are async. StopSearch(); // Note: if now is after blur and IME end composition, // check mInput before calling. // See https://bugzilla.mozilla.org/show_bug.cgi?id=193544#c31 NS_ERROR("Called before attaching to the control or after detaching from the control"); return NS_OK; } nsCOMPtr<nsIAutoCompleteInput> input(mInput); nsCOMPtr<nsIAutoCompletePopup> popup; input->GetPopup(getter_AddRefs(popup)); NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE); bool disabled; input->GetDisableAutoComplete(&disabled); NS_ENSURE_TRUE(!disabled, NS_OK); if (aKey == nsIDOMKeyEvent::DOM_VK_UP || aKey == nsIDOMKeyEvent::DOM_VK_DOWN || aKey == nsIDOMKeyEvent::DOM_VK_PAGE_UP || aKey == nsIDOMKeyEvent::DOM_VK_PAGE_DOWN) { // Prevent the input from handling up/down events, as it may move // the cursor to home/end on some systems *_retval = true; bool isOpen = false; input->GetPopupOpen(&isOpen); if (isOpen) { bool reverse = aKey == nsIDOMKeyEvent::DOM_VK_UP || aKey == nsIDOMKeyEvent::DOM_VK_PAGE_UP ? true : false; bool page = aKey == nsIDOMKeyEvent::DOM_VK_PAGE_UP || aKey == nsIDOMKeyEvent::DOM_VK_PAGE_DOWN ? true : false; // Fill in the value of the textbox with whatever is selected in the popup // if the completeSelectedIndex attribute is set. We check this before // calling SelectBy of an earlier attempt to avoid crashing. bool completeSelection; input->GetCompleteSelectedIndex(&completeSelection); // Instruct the result view to scroll by the given amount and direction popup->SelectBy(reverse, page); if (completeSelection) { PRInt32 selectedIndex; popup->GetSelectedIndex(&selectedIndex); if (selectedIndex >= 0) { // A result is selected, so fill in its value nsAutoString value; if (NS_SUCCEEDED(GetResultValueAt(selectedIndex, true, value))) { input->SetTextValue(value); input->SelectTextRange(value.Length(), value.Length()); } } else { // Nothing is selected, so fill in the last typed value input->SetTextValue(mSearchString); input->SelectTextRange(mSearchString.Length(), mSearchString.Length()); } } } else { #ifdef XP_MACOSX // on Mac, only show the popup if the caret is at the start or end of // the input and there is no selection, so that the default defined key // shortcuts for up and down move to the beginning and end of the field // otherwise. PRInt32 start, end; if (aKey == nsIDOMKeyEvent::DOM_VK_UP) { input->GetSelectionStart(&start); input->GetSelectionEnd(&end); if (start > 0 || start != end) *_retval = false; } else if (aKey == nsIDOMKeyEvent::DOM_VK_DOWN) { nsAutoString text; input->GetTextValue(text); input->GetSelectionStart(&start); input->GetSelectionEnd(&end); if (start != end || end < (PRInt32)text.Length()) *_retval = false; } #endif if (*_retval) { // Open the popup if there has been a previous search, or else kick off a new search if (mResults.Count() > 0) { if (mRowCount) { OpenPopup(); } } else { // Stop all searches in case they are async. StopSearch(); if (!mInput) { // StopSearch() can call PostSearchCleanup() which might result // in a blur event, which could null out mInput, so we need to check it // again. See bug #395344 for more details return NS_OK; } StartSearchTimer(); } } } } else if ( aKey == nsIDOMKeyEvent::DOM_VK_LEFT || aKey == nsIDOMKeyEvent::DOM_VK_RIGHT #ifndef XP_MACOSX || aKey == nsIDOMKeyEvent::DOM_VK_HOME #endif ) { // The user hit a text-navigation key. bool isOpen = false; input->GetPopupOpen(&isOpen); if (isOpen) { PRInt32 selectedIndex; popup->GetSelectedIndex(&selectedIndex); bool shouldComplete; input->GetCompleteDefaultIndex(&shouldComplete); if (selectedIndex >= 0) { // The pop-up is open and has a selection, take its value nsAutoString value; if (NS_SUCCEEDED(GetResultValueAt(selectedIndex, true, value))) { input->SetTextValue(value); input->SelectTextRange(value.Length(), value.Length()); } } else if (shouldComplete) { // We usually try to preserve the casing of what user has typed, but // if he wants to autocomplete, we will replace the value with the // actual autocomplete result. // The user wants explicitely to use that result, so this ensures // association of the result with the autocompleted text. nsAutoString value; nsAutoString inputValue; input->GetTextValue(inputValue); if (NS_SUCCEEDED(GetDefaultCompleteValue(-1, false, value)) && value.Equals(inputValue, nsCaseInsensitiveStringComparator())) { input->SetTextValue(value); input->SelectTextRange(value.Length(), value.Length()); } } // Close the pop-up even if nothing was selected ClearSearchTimer(); ClosePopup(); } // Update last-searched string to the current input, since the input may // have changed. Without this, subsequent backspaces look like text // additions, not text deletions. nsAutoString value; input->GetTextValue(value); mSearchString = value; } return NS_OK; }
bool OnButtonAbort() { m_psite->OnAbort(); ClosePopup(NULL); return true; }
NS_IMETHODIMP nsAutoCompleteController::HandleDelete(bool *_retval) { *_retval = false; if (!mInput) return NS_OK; nsCOMPtr<nsIAutoCompleteInput> input(mInput); bool isOpen = false; input->GetPopupOpen(&isOpen); if (!isOpen || mRowCount <= 0) { // Nothing left to delete, proceed as normal HandleText(); return NS_OK; } nsCOMPtr<nsIAutoCompletePopup> popup; input->GetPopup(getter_AddRefs(popup)); PRInt32 index, searchIndex, rowIndex; popup->GetSelectedIndex(&index); RowIndexToSearch(index, &searchIndex, &rowIndex); NS_ENSURE_TRUE(searchIndex >= 0 && rowIndex >= 0, NS_ERROR_FAILURE); nsIAutoCompleteResult *result = mResults[searchIndex]; NS_ENSURE_TRUE(result, NS_ERROR_FAILURE); nsAutoString search; input->GetSearchParam(search); // Clear the row in our result and in the DB. result->RemoveValueAt(rowIndex, true); --mRowCount; // We removed it, so make sure we cancel the event that triggered this call. *_retval = true; // Unselect the current item. popup->SetSelectedIndex(-1); // Tell the tree that the row count changed. if (mTree) mTree->RowCountChanged(mRowCount, -1); // Adjust index, if needed. if (index >= (PRInt32)mRowCount) index = mRowCount - 1; if (mRowCount > 0) { // There are still rows in the popup, select the current index again. popup->SetSelectedIndex(index); // Complete to the new current value. bool shouldComplete = false; mInput->GetCompleteDefaultIndex(&shouldComplete); if (shouldComplete) { nsAutoString value; if (NS_SUCCEEDED(GetResultValueAt(index, true, value))) { CompleteValue(value); } } // Invalidate the popup. popup->Invalidate(); } else { // Nothing left in the popup, clear any pending search timers and // close the popup. ClearSearchTimer(); ClosePopup(); } return NS_OK; }
nsXULPopupListener::~nsXULPopupListener(void) { ClosePopup(); }