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:
jst%mozilla.jstenback.com 2004-03-18 01:52:51 +00:00
Родитель 4e4d1c2647
Коммит af28dd355c
9 изменённых файлов: 146 добавлений и 37 удалений

Просмотреть файл

@ -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)
{ {