Bug 720081 - Part 1: backportable solution for autocomplete controller to provide a different final defaultComplete value for typeAheadResults

r=gavin
This commit is contained in:
Marco Bonardo 2012-06-01 14:38:37 +02:00
parent 78a01c60c9
commit f799d28aa7
2 changed files with 111 additions and 30 deletions

View File

@ -491,10 +491,7 @@ nsAutoCompleteController::HandleKeyNavigation(PRUint32 aKey, bool *_retval)
// 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())) {
if (NS_SUCCEEDED(GetFinalDefaultCompleteValue(value))) {
input->SetTextValue(value);
input->SelectTextRange(value.Length(), value.Length());
}
@ -1184,10 +1181,7 @@ nsAutoCompleteController::EnterMatch(bool aIsPopupSelection)
// 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()))
if (NS_SUCCEEDED(GetFinalDefaultCompleteValue(defaultIndexValue)))
value = defaultIndexValue;
}
@ -1444,34 +1438,34 @@ nsAutoCompleteController::CompleteDefaultIndex(PRInt32 aResultIndex)
}
nsresult
nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
bool aPreserveCasing,
nsAString &_retval)
nsAutoCompleteController::GetDefaultCompleteResult(PRInt32 aResultIndex,
nsIAutoCompleteResult** _result,
PRInt32* _defaultIndex)
{
PRInt32 defaultIndex = -1;
PRInt32 index = aResultIndex;
if (index < 0) {
PRUint32 count = mResults.Count();
for (PRUint32 i = 0; i < count; ++i) {
nsIAutoCompleteResult *result = mResults[i];
if (result && NS_SUCCEEDED(result->GetDefaultIndex(&defaultIndex)) &&
defaultIndex >= 0) {
index = i;
break;
}
*_defaultIndex = -1;
PRInt32 resultIndex = aResultIndex;
// If a result index was not provided, find the first defaultIndex result.
for (PRInt32 i = 0; resultIndex < 0 && i < mResults.Count(); ++i) {
nsIAutoCompleteResult *result = mResults[i];
if (result &&
NS_SUCCEEDED(result->GetDefaultIndex(_defaultIndex)) &&
*_defaultIndex >= 0) {
resultIndex = i;
}
}
NS_ENSURE_TRUE(index >= 0, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(resultIndex >= 0, NS_ERROR_FAILURE);
nsIAutoCompleteResult *result = mResults.SafeObjectAt(index);
NS_ENSURE_TRUE(result != nsnull, NS_ERROR_FAILURE);
*_result = mResults.SafeObjectAt(resultIndex);
NS_ENSURE_TRUE(*_result, NS_ERROR_FAILURE);
if (defaultIndex < 0) {
if (*_defaultIndex < 0) {
// The search must explicitly provide a default index in order
// for us to be able to complete.
result->GetDefaultIndex(&defaultIndex);
(*_result)->GetDefaultIndex(_defaultIndex);
}
if (defaultIndex < 0) {
if (*_defaultIndex < 0) {
// We were given a result index, but that result doesn't want to
// be autocompleted.
return NS_ERROR_FAILURE;
@ -1481,10 +1475,24 @@ nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
// provides a defaultIndex greater than its matchCount, avoid trying to
// complete to an empty value.
PRUint32 matchCount = 0;
result->GetMatchCount(&matchCount);
(*_result)->GetMatchCount(&matchCount);
// Here defaultIndex is surely non-negative, so can be cast to unsigned.
if ((PRUint32)defaultIndex >= matchCount)
if ((PRUint32)(*_defaultIndex) >= matchCount) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
bool aPreserveCasing,
nsAString &_retval)
{
nsIAutoCompleteResult *result;
PRInt32 defaultIndex = -1;
nsresult rv = GetDefaultCompleteResult(aResultIndex, &result, &defaultIndex);
if (NS_FAILED(rv)) return rv;
nsAutoString resultValue;
result->GetValueAt(defaultIndex, resultValue);
@ -1512,6 +1520,37 @@ nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
return NS_OK;
}
nsresult
nsAutoCompleteController::GetFinalDefaultCompleteValue(nsAString &_retval)
{
nsIAutoCompleteResult *result;
PRInt32 defaultIndex = -1;
nsresult rv = GetDefaultCompleteResult(-1, &result, &defaultIndex);
if (NS_FAILED(rv)) return rv;
// Hack: For typeAheadResults allow the comment to be used as the final
// defaultComplete value if provided, otherwise fall back to the usual
// value. This allows to provide a different complete text when the user
// confirms the match. Don't rely on this for production code, since it's a
// temporary solution that needs a dedicated API (bug 754265).
bool isTypeAheadResult = false;
if (NS_SUCCEEDED(result->GetTypeAheadResult(&isTypeAheadResult)) &&
isTypeAheadResult &&
NS_SUCCEEDED(result->GetCommentAt(defaultIndex, _retval)) &&
!_retval.IsEmpty()) {
return NS_OK;
}
result->GetValueAt(defaultIndex, _retval);
nsAutoString inputValue;
mInput->GetTextValue(inputValue);
if (!_retval.Equals(inputValue, nsCaseInsensitiveStringComparator())) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
nsAutoCompleteController::CompleteValue(nsString &aValue)
/* mInput contains mSearchString, which we want to autocomplete to aValue. If

View File

@ -66,8 +66,50 @@ private:
nsresult GetResultValueLabelAt(PRInt32 aIndex, bool aValueOnly,
bool aGetValue, nsAString & _retval);
protected:
/**
* Gets and validates the defaultComplete result and the relative
* defaultIndex value.
*
* @param aResultIndex
* Index of the defaultComplete result to be used. Pass -1 to search
* for the first result providing a valid defaultIndex.
* @param _result
* The found result.
* @param _defaultIndex
* The defaultIndex relative to _result.
*/
nsresult GetDefaultCompleteResult(PRInt32 aResultIndex,
nsIAutoCompleteResult** _result,
PRInt32* _defaultIndex);
/**
* Gets the defaultComplete value to be suggested to the user.
*
* @param aResultIndex
* Index of the defaultComplete result to be used.
* @param aPreserveCasing
* Whether user casing should be preserved.
* @param _retval
* The value to be completed.
*/
nsresult GetDefaultCompleteValue(PRInt32 aResultIndex, bool aPreserveCasing,
nsAString &_retval);
/**
* Gets the defaultComplete value to be used when the user navigates or
* confirms the current match.
* The value is returned only if it case-insensitively matches the current
* input text, otherwise the method returns NS_ERROR_FAILURE.
* This happens because we don't want to override user casing in case of a
* navigation key (unless the text is the same), or to replace text if the
* user backspaces just before Enter.
*
* @param _retval
* The value to be completed.
*/
nsresult GetFinalDefaultCompleteValue(nsAString &_retval);
nsresult ClearResults();
nsresult RowIndexToSearch(PRInt32 aRowIndex,