Commit 3fd8c986 authored by mgiuca's avatar mgiuca Committed by Commit bot

App launcher: Spoken feedback reads out details of search results.

This means the grey text under the title, which usually explains what
type the result is (e.g., "Google Search" or "Chrome Web Store").

BUG=450644

Review URL: https://codereview.chromium.org/935523002

Cr-Commit-Position: refs/heads/master@{#316953}
parent 45f92d83
......@@ -6,6 +6,7 @@
#include <map>
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/app_list/app_list_model.h"
#include "ui/app_list/test/app_list_test_view_delegate.h"
......@@ -38,6 +39,10 @@ class SearchResultListViewTest : public views::ViewsTestBase,
protected:
SearchResultListView* view() { return view_.get(); }
SearchResultView* GetResultViewAt(int index) {
return view_->GetResultViewAt(index);
}
AppListModel::SearchResults* GetResults() {
return view_delegate_.GetModel()->results();
}
......@@ -56,6 +61,9 @@ class SearchResultListViewTest : public views::ViewsTestBase,
for (int i = 0; i < kDefaultSearchItems; ++i) {
TestSearchResult* result = new TestSearchResult();
result->set_display_type(SearchResult::DISPLAY_LIST);
result->set_title(base::UTF8ToUTF16(base::StringPrintf("Result %d", i)));
if (i < 2)
result->set_details(base::ASCIIToUTF16("Detail"));
results->Add(result);
}
......@@ -103,12 +111,12 @@ class SearchResultListViewTest : public views::ViewsTestBase,
AppListModel::SearchResults* results = GetResults();
for (size_t i = 0; i < results->item_count(); ++i) {
EXPECT_EQ(results->GetItemAt(i), view_->GetResultViewAt(i)->result());
EXPECT_EQ(results->GetItemAt(i), GetResultViewAt(i)->result());
}
}
ProgressBarView* GetProgressBarAt(size_t index) {
return view()->GetResultViewAt(index)->progress_bar_;
return GetResultViewAt(index)->progress_bar_;
}
private:
......@@ -194,6 +202,19 @@ TEST_F(SearchResultListViewTest, CancelAutoLaunch) {
EXPECT_TRUE(IsAutoLaunching());
}
TEST_F(SearchResultListViewTest, SpokenFeedback) {
SetUpSearchResults();
// Result 0 has a detail text. Expect that the detail is appended to the
// accessibility name.
EXPECT_EQ(base::ASCIIToUTF16("Result 0, Detail"),
GetResultViewAt(0)->ComputeAccessibleName());
// Result 2 has no detail text.
EXPECT_EQ(base::ASCIIToUTF16("Result 2"),
GetResultViewAt(2)->ComputeAccessibleName());
}
TEST_F(SearchResultListViewTest, ModelObservers) {
SetUpSearchResults();
ExpectConsistent();
......
......@@ -6,6 +6,7 @@
#include <algorithm>
#include "base/strings/utf_string_conversions.h"
#include "ui/app_list/app_list_constants.h"
#include "ui/app_list/app_list_switches.h"
#include "ui/app_list/search_result.h"
......@@ -120,12 +121,12 @@ void SearchResultView::ClearSelectedAction() {
void SearchResultView::UpdateTitleText() {
if (!result_ || result_->title().empty()) {
title_text_.reset();
SetAccessibleName(base::string16());
} else {
title_text_.reset(CreateRenderText(result_->title(),
result_->title_tags()));
SetAccessibleName(result_->title());
}
UpdateAccessibleName();
}
void SearchResultView::UpdateDetailsText() {
......@@ -135,6 +136,24 @@ void SearchResultView::UpdateDetailsText() {
details_text_.reset(CreateRenderText(result_->details(),
result_->details_tags()));
}
UpdateAccessibleName();
}
base::string16 SearchResultView::ComputeAccessibleName() const {
if (!result_)
return base::string16();
base::string16 accessible_name = result_->title();
if (!result_->title().empty() && !result_->details().empty())
accessible_name += base::ASCIIToUTF16(", ");
accessible_name += result_->details();
return accessible_name;
}
void SearchResultView::UpdateAccessibleName() {
SetAccessibleName(ComputeAccessibleName());
}
const char* SearchResultView::GetClassName() const {
......
......@@ -9,7 +9,9 @@
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "ui/app_list/search_result_observer.h"
#include "ui/app_list/views/search_result_actions_view_delegate.h"
#include "ui/views/context_menu_controller.h"
......@@ -37,11 +39,12 @@ class SearchResultViewDelegate;
class SearchResultActionsView;
// SearchResultView displays a SearchResult.
class SearchResultView : public views::CustomButton,
public views::ButtonListener,
public views::ContextMenuController,
public SearchResultObserver,
public SearchResultActionsViewDelegate {
class APP_LIST_EXPORT SearchResultView
: public views::CustomButton,
public views::ButtonListener,
public views::ContextMenuController,
public SearchResultObserver,
NON_EXPORTED_BASE(public SearchResultActionsViewDelegate) {
public:
// Internal class name.
static const char kViewClassName[];
......@@ -59,6 +62,9 @@ class SearchResultView : public views::CustomButton,
// Clears the selected action.
void ClearSelectedAction();
// Computes the button's spoken feedback name.
base::string16 ComputeAccessibleName() const;
void set_is_last_result(bool is_last) { is_last_result_ = is_last; }
private:
......@@ -66,6 +72,7 @@ class SearchResultView : public views::CustomButton,
void UpdateTitleText();
void UpdateDetailsText();
void UpdateAccessibleName();
// views::View overrides:
const char* GetClassName() const override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment