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; }
void OpenPopup(IPopup* ppopup, bool bCloseAll, IPopup* ppopupOwner) { OpenPopup( ppopup, new CenterRectPoint(m_prectValue, new RectValue(ppopup->GetRect())), bCloseAll, ppopupOwner ); }
void FGlobalEditorCommonCommands::OnPressedCtrlTab(TSharedPtr<FUICommandInfo> TriggeringCommand) { if (!SGlobalTabSwitchingDialog::IsAlreadyOpen()) { const FVector2D TabListSize(700.0f, 486.0f); // Create the contents of the popup TSharedRef<SWidget> ActualWidget = SNew(SGlobalTabSwitchingDialog, TabListSize, *TriggeringCommand->GetActiveChord()); TSharedPtr<SWindow> NewWindow = OpenPopup(ActualWidget, TabListSize); } }
void FGlobalEditorCommonCommands::OnSummonedAssetPicker() { const FVector2D AssetPickerSize(600.0f, 586.0f); // Create the contents of the popup TSharedRef<SWidget> ActualWidget = SNew(SGlobalOpenAssetDialog, AssetPickerSize); // Wrap the picker widget in a multibox-style menu body FMenuBuilder MenuBuilder(/*BShouldCloseAfterSelection=*/ false, /*CommandList=*/ nullptr); MenuBuilder.BeginSection("AssetPickerOpenAsset", NSLOCTEXT("GlobalAssetPicker", "WindowTitle", "Open Asset")); MenuBuilder.AddWidget(ActualWidget, FText::GetEmpty(), /*bNoIndent=*/ true); MenuBuilder.EndSection(); OpenPopup(MenuBuilder.MakeWidget(), AssetPickerSize); }
NS_IMETHODIMP nsPopupSetFrame::DestroyPopup(nsIFrame* aPopup, PRBool aDestroyEntireChain) { if (!mPopupList) return NS_OK; // No active popups nsPopupFrameList* entry = mPopupList->GetEntryByFrame(aPopup); if (entry && entry->mCreateHandlerSucceeded) { // ensure the popup was created before we try to destroy it nsWeakFrame weakFrame(this); OpenPopup(entry, PR_FALSE); nsCOMPtr<nsIContent> popupContent = entry->mPopupContent; if (weakFrame.IsAlive()) { if (aDestroyEntireChain && entry->mElementContent && entry->mPopupType.EqualsLiteral("context")) { // If we are a context menu, and if we are attached to a // menupopup, then destroying us should also dismiss the parent // menu popup. if (entry->mElementContent->Tag() == nsXULAtoms::menupopup) { nsIFrame* popupFrame = nsnull; mPresContext->PresShell()->GetPrimaryFrameFor(entry->mElementContent, &popupFrame); if (popupFrame) { nsIMenuParent *menuParent; if (NS_SUCCEEDED(CallQueryInterface(popupFrame, &menuParent))) { menuParent->DismissChain(); } } } } // clear things out for next time entry->mPopupType.Truncate(); entry->mCreateHandlerSucceeded = PR_FALSE; entry->mElementContent = nsnull; entry->mXPos = entry->mYPos = 0; entry->mLastPref.width = -1; entry->mLastPref.height = -1; } // ungenerate the popup. popupContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menugenerated, PR_TRUE); } 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; }
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 nsPopupSetFrame::ShowPopup(nsIContent* aElementContent, nsIContent* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment) { NS_ASSERTION(aElementContent != aPopupContent, "self referential popup"); if (!MayOpenPopup(this)) return NS_OK; nsWeakFrame weakFrame(this); // First fire the popupshowing event. if (!OnCreate(aXPos, aYPos, aPopupContent) || !weakFrame.IsAlive()) return NS_OK; // See if we already have an entry in our list. We must create a new one on a miss. nsPopupFrameList* entry = nsnull; if (mPopupList) entry = mPopupList->GetEntry(aPopupContent); if (!entry) { entry = new nsPopupFrameList(aPopupContent, mPopupList); if (!entry) return NS_ERROR_OUT_OF_MEMORY; mPopupList = entry; } // Cache the element content we're supposed to sync to entry->mPopupType = aPopupType; entry->mElementContent = aElementContent; entry->mPopupAlign = aPopupAlignment; entry->mPopupAnchor = anAnchorAlignment; entry->mXPos = aXPos; entry->mYPos = aYPos; // If a frame exists already, go ahead and use it. mPresContext->PresShell()->GetPrimaryFrameFor(aPopupContent, &entry->mPopupFrame); #ifdef DEBUG_PINK printf("X Pos: %d\n", mXPos); printf("Y Pos: %d\n", mYPos); #endif // Generate the popup. entry->mCreateHandlerSucceeded = PR_TRUE; entry->mIsOpen = PR_TRUE; // This may destroy or change entry->mPopupFrame or remove the entry from // mPopupList. |this| may also get deleted. MarkAsGenerated(aPopupContent); if (!weakFrame.IsAlive()) { return NS_OK; } nsPopupFrameList* newEntry = mPopupList ? mPopupList->GetEntry(aPopupContent) : nsnull; if (!newEntry || newEntry != entry) { NS_WARNING("The popup entry for aPopupContent has changed!"); return NS_OK; } // determine if this menu is a context menu and flag it nsIMenuParent* childPopup = nsnull; if (entry->mPopupFrame) CallQueryInterface(entry->mPopupFrame, &childPopup); if ( childPopup && aPopupType.EqualsLiteral("context") ) childPopup->SetIsContextMenu(PR_TRUE); // Now open the popup. OpenPopup(entry, PR_TRUE); if (!weakFrame.IsAlive()) { return NS_OK; } // Now fire the popupshown event. OnCreated(aXPos, aYPos, aPopupContent); return NS_OK; }
void OpenPopup(IPopup* ppopup, const Rect& rect, bool bCloseAll, bool bCascadeDown, IPopup* ppopupOwner) { // // Figure out where the popup should go // Rect rectPopup = ppopup->GetRect(); Rect rectContainer = m_prectValue->GetValue(); Point point; // // x position // if (m_bCascadeRight) { if (rect.XMax() + rectPopup.XSize() > rectContainer.XMax()) { point.SetX(rect.XMin() - rectPopup.XSize()); } else { point.SetX(rect.XMax()); } } else { if (rect.XMin() - rectPopup.XSize() < 0) { point.SetX(rect.XMax()); } else { point.SetX(rect.XMin() - rectPopup.XSize()); } } // // Make sure we actually stay on the screen // if (point.X() + rectPopup.XSize() > rectContainer.XMax()) { point.SetX(rectContainer.XMax() - rectPopup.XSize()); } if (point.X() < 0) { point.SetX(0); } // // Check if going up or down would go off the screen // if (bCascadeDown) { if (rect.YMax() - rectPopup.YSize() < 0) { bCascadeDown = false; } } else { if (rect.YMin() + rectPopup.YSize() > rectContainer.YMax()) { bCascadeDown = true; } } // // y position // if (bCascadeDown) { if (rect.YMax() - rectPopup.YSize() < 0) { point.SetY(0); } else { point.SetY(rect.YMax() - rectPopup.YSize()); } } else { if (rect.YMin() + rectPopup.YSize() > rectContainer.YMax()) { point.SetY(rectContainer.YMax() - rectPopup.YSize()); } else { point.SetY(rect.YMin()); } } // // Open the popup // OpenPopup(ppopup, point, bCloseAll, ppopupOwner); }
void OpenPopup(IPopup* ppopup, const Point& point, bool bCloseAll, IPopup* ppopupOwner) { OpenPopup(ppopup, new PointValue(point), bCloseAll, ppopupOwner); }