зеркало из https://github.com/mozilla/gecko-dev.git
Fixing bug 171605. Implementing deletion of individual autocomplete results by pressing Shift+Delete on a selected autocomplete item. r=ben@bengoodger.com
This commit is contained in:
Родитель
4e4d1c2647
Коммит
af28dd355c
|
@ -116,6 +116,12 @@ interface nsIAutoCompleteController : nsISupports
|
||||||
*/
|
*/
|
||||||
boolean handleKeyNavigation(in unsigned short key);
|
boolean handleKeyNavigation(in unsigned short key);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify the controller that the user chose to delete the current
|
||||||
|
* auto-complete result.
|
||||||
|
*/
|
||||||
|
boolean handleDelete();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the value of the result at a given index in the last completed search
|
* Get the value of the result at a given index in the last completed search
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -73,7 +73,7 @@ interface nsIAutoCompleteMdbResult : nsIAutoCompleteBaseResult
|
||||||
|
|
||||||
void addRow(in nsIMdbRow row);
|
void addRow(in nsIMdbRow row);
|
||||||
|
|
||||||
void removeRowAt(in unsigned long rowIndex);
|
void removeRowAt(in unsigned long rowIndex, in boolean removeFromDb);
|
||||||
|
|
||||||
nsIMdbRow getRowAt(in unsigned long rowIndex);
|
nsIMdbRow getRowAt(in unsigned long rowIndex);
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,13 @@ MODULE = autocomplete
|
||||||
LIBRARY_NAME = autocomplete_s
|
LIBRARY_NAME = autocomplete_s
|
||||||
FORCE_STATIC_LIB = 1
|
FORCE_STATIC_LIB = 1
|
||||||
|
|
||||||
REQUIRES = xpcom \
|
REQUIRES = xpcom \
|
||||||
string \
|
string \
|
||||||
dom \
|
dom \
|
||||||
layout \
|
layout \
|
||||||
mork \
|
mork \
|
||||||
$(NULL)
|
unicharutil \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
CPPSRCS = nsAutoCompleteController.cpp \
|
CPPSRCS = nsAutoCompleteController.cpp \
|
||||||
nsAutoCompleteMdbResult.cpp \
|
nsAutoCompleteMdbResult.cpp \
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
*
|
*
|
||||||
* The contents of this file are subject to the Netscape Public License
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
@ -20,6 +21,8 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Joe Hewitt <hewitt@netscape.com> (Original Author)
|
* Joe Hewitt <hewitt@netscape.com> (Original Author)
|
||||||
|
* Dean Tessman <dean_tessman@hotmail.com>
|
||||||
|
* Johnny Stenback <jst@mozilla.jstenback.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
@ -37,12 +40,12 @@
|
||||||
|
|
||||||
#include "nsAutoCompleteController.h"
|
#include "nsAutoCompleteController.h"
|
||||||
|
|
||||||
|
#include "nsIAutoCompleteResultTypes.h"
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
#include "nsIDOMKeyEvent.h"
|
#include "nsIDOMElement.h"
|
||||||
#include "nsIDOMNode.h"
|
|
||||||
#include "nsIDOMEventTarget.h"
|
|
||||||
#include "nsIAtomService.h"
|
#include "nsIAtomService.h"
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
|
#include "nsUnicharUtils.h"
|
||||||
|
|
||||||
static const char *kAutoCompleteSearchCID = "@mozilla.org/autocomplete/search;1?name=";
|
static const char *kAutoCompleteSearchCID = "@mozilla.org/autocomplete/search;1?name=";
|
||||||
|
|
||||||
|
@ -52,7 +55,6 @@ NS_IMPL_ISUPPORTS4(nsAutoCompleteController, nsIAutoCompleteController, nsIAutoC
|
||||||
|
|
||||||
nsAutoCompleteController::nsAutoCompleteController() :
|
nsAutoCompleteController::nsAutoCompleteController() :
|
||||||
mEnterAfterSearch(PR_FALSE),
|
mEnterAfterSearch(PR_FALSE),
|
||||||
mNeedToComplete(PR_FALSE),
|
|
||||||
mDefaultIndexCompleted(PR_FALSE),
|
mDefaultIndexCompleted(PR_FALSE),
|
||||||
mBackspaced(PR_FALSE),
|
mBackspaced(PR_FALSE),
|
||||||
mSearchStatus(0),
|
mSearchStatus(0),
|
||||||
|
@ -120,7 +122,6 @@ nsAutoCompleteController::SetInput(nsIAutoCompleteInput *aInput)
|
||||||
// Reset all search state members to default values
|
// Reset all search state members to default values
|
||||||
mSearchString = newValue;
|
mSearchString = newValue;
|
||||||
mEnterAfterSearch = PR_FALSE;
|
mEnterAfterSearch = PR_FALSE;
|
||||||
mNeedToComplete = PR_FALSE;
|
|
||||||
mDefaultIndexCompleted = PR_FALSE;
|
mDefaultIndexCompleted = PR_FALSE;
|
||||||
mBackspaced = PR_FALSE;
|
mBackspaced = PR_FALSE;
|
||||||
mSearchStatus = nsIAutoCompleteController::STATUS_NONE;
|
mSearchStatus = nsIAutoCompleteController::STATUS_NONE;
|
||||||
|
@ -163,7 +164,7 @@ nsAutoCompleteController::StartSearch(const nsAString &aSearchString)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsAutoCompleteController::HandleText()
|
nsAutoCompleteController::HandleText()
|
||||||
{
|
{
|
||||||
// Stop current search in case it's async.
|
// Stop current search in case it's async.
|
||||||
StopSearch();
|
StopSearch();
|
||||||
// Stop the queued up search on a timer
|
// Stop the queued up search on a timer
|
||||||
|
@ -173,8 +174,6 @@ nsAutoCompleteController::HandleText()
|
||||||
mInput->GetDisableAutoComplete(&disabled);
|
mInput->GetDisableAutoComplete(&disabled);
|
||||||
NS_ENSURE_TRUE(!disabled, NS_OK;);
|
NS_ENSURE_TRUE(!disabled, NS_OK;);
|
||||||
|
|
||||||
mNeedToComplete = PR_TRUE;
|
|
||||||
|
|
||||||
nsAutoString newValue;
|
nsAutoString newValue;
|
||||||
mInput->GetTextValue(newValue);
|
mInput->GetTextValue(newValue);
|
||||||
|
|
||||||
|
@ -264,8 +263,6 @@ nsAutoCompleteController::HandleKeyNavigation(PRUint16 aKey, PRBool *_retval)
|
||||||
// By default, don't cancel the event
|
// By default, don't cancel the event
|
||||||
*_retval = PR_FALSE;
|
*_retval = PR_FALSE;
|
||||||
|
|
||||||
mNeedToComplete = PR_FALSE;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIAutoCompletePopup> popup;
|
nsCOMPtr<nsIAutoCompletePopup> popup;
|
||||||
mInput->GetPopup(getter_AddRefs(popup));
|
mInput->GetPopup(getter_AddRefs(popup));
|
||||||
NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE);
|
||||||
|
@ -325,6 +322,80 @@ nsAutoCompleteController::HandleKeyNavigation(PRUint16 aKey, PRBool *_retval)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAutoCompleteController::HandleDelete(PRBool *_retval)
|
||||||
|
{
|
||||||
|
*_retval = PR_FALSE;
|
||||||
|
PRBool isOpen = PR_FALSE;
|
||||||
|
mInput->GetPopupOpen(&isOpen);
|
||||||
|
if (!isOpen || mRowCount <= 0) {
|
||||||
|
// Nothing left to delete, proceed as normal
|
||||||
|
HandleText();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAutoCompletePopup> popup;
|
||||||
|
mInput->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);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAutoCompleteResult> result;
|
||||||
|
mResults->GetElementAt(searchIndex, getter_AddRefs(result));
|
||||||
|
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nsAutoString search;
|
||||||
|
mInput->GetSearchParam(search);
|
||||||
|
|
||||||
|
nsAutoString value;
|
||||||
|
result->GetValueAt(rowIndex, value);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAutoCompleteMdbResult> mdbResult(do_QueryInterface(result));
|
||||||
|
if (mdbResult) {
|
||||||
|
// Clear the row in our result and in the DB.
|
||||||
|
mdbResult->RemoveRowAt(rowIndex, PR_TRUE);
|
||||||
|
|
||||||
|
--mRowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
nsAutoString value;
|
||||||
|
if (NS_SUCCEEDED(GetResultValueAt(index, PR_TRUE, value))) {
|
||||||
|
CompleteValue(value);
|
||||||
|
|
||||||
|
// Make sure we cancel the event that triggerd this call.
|
||||||
|
*_retval = PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsAutoCompleteController::GetValueAt(PRInt32 aIndex, nsAString & _retval)
|
nsAutoCompleteController::GetValueAt(PRInt32 aIndex, nsAString & _retval)
|
||||||
{
|
{
|
||||||
|
@ -803,7 +874,7 @@ nsAutoCompleteController::EnterMatch()
|
||||||
|
|
||||||
if (!value.IsEmpty()) {
|
if (!value.IsEmpty()) {
|
||||||
mInput->SetTextValue(value);
|
mInput->SetTextValue(value);
|
||||||
mInput->SelectTextRange(-1, -1);
|
mInput->SelectTextRange(value.Length(), value.Length());
|
||||||
mSearchString = value;
|
mSearchString = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -827,7 +898,6 @@ nsAutoCompleteController::RevertTextValue()
|
||||||
mInput->SetTextValue(oldValue);
|
mInput->SetTextValue(oldValue);
|
||||||
|
|
||||||
mSearchString.Truncate(0);
|
mSearchString.Truncate(0);
|
||||||
mNeedToComplete = PR_FALSE;
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -958,13 +1028,23 @@ nsAutoCompleteController::CompleteDefaultIndex(PRInt32 aSearchIndex)
|
||||||
nsresult
|
nsresult
|
||||||
nsAutoCompleteController::CompleteValue(nsString &aValue)
|
nsAutoCompleteController::CompleteValue(nsString &aValue)
|
||||||
{
|
{
|
||||||
PRInt32 findIndex = aValue.Find(mSearchString, PR_FALSE);
|
nsString::const_iterator start, end, iter;
|
||||||
if (findIndex == 0 || mSearchString.IsEmpty()) {
|
aValue.BeginReading(start);
|
||||||
// The textbox value matches the beginning of the default value, so we can just
|
aValue.EndReading(end);
|
||||||
// append the latter portion
|
iter = start;
|
||||||
|
|
||||||
|
FindInReadable(mSearchString, iter, end,
|
||||||
|
nsCaseInsensitiveStringComparator());
|
||||||
|
|
||||||
|
if (iter == start) {
|
||||||
|
// The textbox value matches the beginning of the default value,
|
||||||
|
// or the default value is empty, so we can just append the latter
|
||||||
|
// portion
|
||||||
mInput->SetTextValue(aValue);
|
mInput->SetTextValue(aValue);
|
||||||
mInput->SelectTextRange(mSearchString.Length(), aValue.Length());
|
mInput->SelectTextRange(mSearchString.Length(), aValue.Length());
|
||||||
} else {
|
} else {
|
||||||
|
PRInt32 findIndex = iter.get() - start.get();
|
||||||
|
|
||||||
mInput->SetTextValue(mSearchString + Substring(aValue, mSearchString.Length()+findIndex, aValue.Length()));
|
mInput->SetTextValue(mSearchString + Substring(aValue, mSearchString.Length()+findIndex, aValue.Length()));
|
||||||
mInput->SelectTextRange(mSearchString.Length(), aValue.Length() - findIndex);
|
mInput->SelectTextRange(mSearchString.Length(), aValue.Length() - findIndex);
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,6 @@ protected:
|
||||||
|
|
||||||
nsString mSearchString;
|
nsString mSearchString;
|
||||||
PRPackedBool mEnterAfterSearch;
|
PRPackedBool mEnterAfterSearch;
|
||||||
PRPackedBool mNeedToComplete;
|
|
||||||
PRPackedBool mDefaultIndexCompleted;
|
PRPackedBool mDefaultIndexCompleted;
|
||||||
PRPackedBool mBackspaced;
|
PRPackedBool mBackspaced;
|
||||||
PRUint16 mSearchStatus;
|
PRUint16 mSearchStatus;
|
||||||
|
|
|
@ -210,9 +210,18 @@ nsAutoCompleteMdbResult::AddRow(nsIMdbRow *aRow)
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsAutoCompleteMdbResult::RemoveRowAt(PRUint32 aRowIndex)
|
nsAutoCompleteMdbResult::RemoveRowAt(PRUint32 aRowIndex, PRBool aRemoveFromDb)
|
||||||
{
|
{
|
||||||
|
nsIMdbRow *row = (nsIMdbRow *)mResults.ElementAt(aRowIndex);
|
||||||
|
NS_ENSURE_TRUE(row, NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
mResults.RemoveElementAt(aRowIndex);
|
mResults.RemoveElementAt(aRowIndex);
|
||||||
|
|
||||||
|
if (aRemoveFromDb && mTable && mEnv) {
|
||||||
|
mdb_err err = mTable->CutRow(mEnv, row);
|
||||||
|
NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4154,7 +4154,7 @@ nsGlobalHistory::AutoCompleteSearch(const nsAString &aSearchString,
|
||||||
aPrevResult->GetValueAt(i, url);
|
aPrevResult->GetValueAt(i, url);
|
||||||
|
|
||||||
if (!AutoCompleteCompare(url, aSearchString, aExclude))
|
if (!AutoCompleteCompare(url, aSearchString, aExclude))
|
||||||
aPrevResult->RemoveRowAt(i);
|
aPrevResult->RemoveRowAt(i, PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
*aResult = aPrevResult;
|
*aResult = aPrevResult;
|
||||||
|
|
|
@ -227,12 +227,12 @@ nsFormFillController::GetPopupOpen(PRBool *aPopupOpen)
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::SetPopupOpen(PRBool aPopupOpen)
|
nsFormFillController::SetPopupOpen(PRBool aPopupOpen)
|
||||||
{
|
{
|
||||||
if (aPopupOpen) {
|
if (mFocusedPopup) {
|
||||||
nsRect popupRect = GetScreenOrigin(mFocusedInput);
|
if (aPopupOpen) {
|
||||||
if (mFocusedPopup)
|
nsRect popupRect = GetScreenOrigin(mFocusedInput);
|
||||||
mFocusedPopup->OpenPopup(this, popupRect.x, popupRect.y+popupRect.height, popupRect.width);
|
mFocusedPopup->OpenPopup(this, popupRect.x, popupRect.y+popupRect.height, popupRect.width);
|
||||||
} else {
|
} else
|
||||||
mFocusedPopup->ClosePopup();
|
mFocusedPopup->ClosePopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -562,8 +562,20 @@ nsFormFillController::KeyPress(nsIDOMEvent* aEvent)
|
||||||
PRUint32 k;
|
PRUint32 k;
|
||||||
keyEvent->GetKeyCode(&k);
|
keyEvent->GetKeyCode(&k);
|
||||||
switch (k) {
|
switch (k) {
|
||||||
case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
|
|
||||||
case nsIDOMKeyEvent::DOM_VK_DELETE:
|
case nsIDOMKeyEvent::DOM_VK_DELETE:
|
||||||
|
{
|
||||||
|
PRBool isShift = PR_FALSE;
|
||||||
|
keyEvent->GetShiftKey(&isShift);
|
||||||
|
|
||||||
|
if (isShift) {
|
||||||
|
mController->HandleDelete(&cancel);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
|
||||||
mController->HandleText();
|
mController->HandleText();
|
||||||
break;
|
break;
|
||||||
case nsIDOMKeyEvent::DOM_VK_UP:
|
case nsIDOMKeyEvent::DOM_VK_UP:
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
*
|
*
|
||||||
|
@ -704,7 +705,7 @@ nsFormHistory::AutoCompleteSearch(const nsAString &aInputName,
|
||||||
nsIMdbRow *row;
|
nsIMdbRow *row;
|
||||||
result->GetRowAt(i, &row);
|
result->GetRowAt(i, &row);
|
||||||
if (!RowMatch(row, aInputName, aInputValue, nsnull))
|
if (!RowMatch(row, aInputName, aInputValue, nsnull))
|
||||||
result->RemoveRowAt(i);
|
result->RemoveRowAt(i, PR_FALSE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = do_CreateInstance("@mozilla.org/autocomplete/mdb-result;1");
|
result = do_CreateInstance("@mozilla.org/autocomplete/mdb-result;1");
|
||||||
|
@ -790,11 +791,12 @@ nsFormHistory::SortComparison(const void *v1, const void *v2, void *closureVoid)
|
||||||
PRBool
|
PRBool
|
||||||
nsFormHistory::RowMatch(nsIMdbRow *aRow, const nsAString &aInputName, const nsAString &aInputValue, PRUnichar **aValue)
|
nsFormHistory::RowMatch(nsIMdbRow *aRow, const nsAString &aInputName, const nsAString &aInputValue, PRUnichar **aValue)
|
||||||
{
|
{
|
||||||
nsAutoString name, value;
|
nsAutoString name;
|
||||||
GetRowValue(aRow, kToken_NameColumn, name);
|
GetRowValue(aRow, kToken_NameColumn, name);
|
||||||
GetRowValue(aRow, kToken_ValueColumn, value);
|
|
||||||
|
|
||||||
if (name.Equals(aInputName)) {
|
if (name.Equals(aInputName)) {
|
||||||
|
nsAutoString value;
|
||||||
|
GetRowValue(aRow, kToken_ValueColumn, value);
|
||||||
if (value.Length() != aInputValue.Length() && // ignore exact matches
|
if (value.Length() != aInputValue.Length() && // ignore exact matches
|
||||||
Compare(Substring(value, 0, aInputValue.Length()), aInputValue, nsCaseInsensitiveStringComparator()) == 0)
|
Compare(Substring(value, 0, aInputValue.Length()), aInputValue, nsCaseInsensitiveStringComparator()) == 0)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче