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;
}
示例#2
0
 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);
}
示例#5
0
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;
}
示例#8
0
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;
}
示例#9
0
    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);
    }
示例#10
0
 void OpenPopup(IPopup* ppopup, const Point& point, bool bCloseAll, IPopup* ppopupOwner)
 {
     OpenPopup(ppopup, new PointValue(point), bCloseAll, ppopupOwner);
 }