diff options
author | xiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-25 00:16:17 +0000 |
---|---|---|
committer | xiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-25 00:16:17 +0000 |
commit | ef59e6c4064973e58c923fbcfb51e68911cff8d8 (patch) | |
tree | 74b264a7a69765dc3c9b716b4f4b969612ec63e8 /ash/shell/app_list.cc | |
parent | 38ddaff588d764ac6a92ec1e8b6766732ba92efd (diff) | |
download | chromium_src-ef59e6c4064973e58c923fbcfb51e68911cff8d8.zip chromium_src-ef59e6c4064973e58c923fbcfb51e68911cff8d8.tar.gz chromium_src-ef59e6c4064973e58c923fbcfb51e68911cff8d8.tar.bz2 |
app_list: Add search box and search result view for v2.
- Add a SearchBoxModel that represents search box's icon, placeholder text,
user typed text and selection model (current selection and cursor position);
- Add a SearchBoxView that displays SearchBoxModel and observes SearchBoxModel
changes via SearchBoxModelObserver;
When user typed/changed text in search box, the view also fires query changed
notification to its SearchBoxViewDelegate;
- Add a SearchResult that carries an icon, two tagged texts;
- Add a SearchResultView that displays a SearchResult;
- Change AppListModel to be a master model that has three sub models:
apps list, search box and search results;
- Add a SearchResultListView that display search results sub model of
AppListModel using a list of SeachResultView;
The view supports up/down key navigation and when user selects a result
via mouse click or enter key, it asks its SearchResultListViewDelegate to
OpenResult;
- Update AppListViewDelegate:
- Add new methods: StartSearch, StopSearch and OpenResult;
- Deleted no-longer needed UpdateModel method;
- Rename OnAppListItemActivated -> ActivateAppListItem;
- Update ash_shell's app_list to support a simple substr match search;
- Add a SearchBuilder that implements the search via AutoCompleteController;
- Other changes:
- Rename AppListModelBuilder -> AppsModelBuilder;
- Rename AppListModelView -> AppsGridView;
BUG=125964
TEST=Manual. In ash_shell, it searches the 5 example apps. In ash/chrome, it should show similar results as omnibox.
Review URL: https://chromiumcodereview.appspot.com/10386224
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@138938 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/shell/app_list.cc')
-rw-r--r-- | ash/shell/app_list.cc | 148 |
1 files changed, 138 insertions, 10 deletions
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc index 383a450..b9d1174 100644 --- a/ash/shell/app_list.cc +++ b/ash/shell/app_list.cc @@ -2,14 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <string> + #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/shell/example_factory.h" #include "ash/shell/toplevel_window.h" #include "base/basictypes.h" +#include "base/i18n/case_conversion.h" +#include "base/i18n/string_search.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" #include "ui/app_list/app_list_item_model.h" #include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_view_delegate.h" +#include "ui/app_list/search_box_model.h" +#include "ui/app_list/search_result.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/font.h" +#include "ui/gfx/rect.h" #include "ui/views/examples/examples_window.h" namespace ash { @@ -17,6 +28,8 @@ namespace shell { namespace { +// WindowTypeLauncherItem is an app item of app list. It carries a window +// launch type and launches corresponding example window when activated. class WindowTypeLauncherItem : public app_list::AppListItemModel { public: enum Type { @@ -50,6 +63,7 @@ class WindowTypeLauncherItem : public app_list::AppListItemModel { return icon; } + // The text below is not localized as this is an example code. static std::string GetTitle(Type type) { switch (type) { case TOPLEVEL_WINDOW: @@ -67,8 +81,22 @@ class WindowTypeLauncherItem : public app_list::AppListItemModel { } } - void Activate(int event_flags) { - switch (type_) { + // The text below is not localized as this is an example code. + static std::string GetDetails(Type type) { + // Assigns details only to some types so that we see both one-line + // and two-line results. + switch (type) { + case WIDGETS_WINDOW: + return "Creates a window to show example widgets"; + case EXAMPLES_WINDOW: + return "Creates a window to show views example."; + default: + return std::string(); + } + } + + static void Activate(Type type, int event_flags) { + switch (type) { case TOPLEVEL_WINDOW: { ToplevelWindow::CreateParams params; params.can_resize = true; @@ -100,24 +128,125 @@ class WindowTypeLauncherItem : public app_list::AppListItemModel { } } + void Activate(int event_flags) { + Activate(type_, event_flags); + } + private: Type type_; DISALLOW_COPY_AND_ASSIGN(WindowTypeLauncherItem); }; +// ExampleSearchResult is an app list search result. It provides what icon to +// show, what should title and details text look like. It also carries the +// matching window launch type so that AppListViewDelegate knows how to open +// it. +class ExampleSearchResult : public app_list::SearchResult { + public: + ExampleSearchResult(WindowTypeLauncherItem::Type type, + const string16& query) + : type_(type) { + set_icon(WindowTypeLauncherItem::GetIcon(type_)); + + string16 title = UTF8ToUTF16(WindowTypeLauncherItem::GetTitle(type_)); + set_title(title); + + Tags title_tags; + const size_t match_len = query.length(); + + // Highlight matching parts in title with bold. + // Note the following is not a proper way to handle i18n string. + title = base::i18n::ToLower(title); + size_t match_start = title.find(query); + while (match_start != string16::npos) { + title_tags.push_back(Tag(Tag::MATCH, + match_start, + match_start + match_len)); + match_start = title.find(query, match_start + match_len); + } + set_title_tags(title_tags); + + string16 details = UTF8ToUTF16(WindowTypeLauncherItem::GetDetails(type_)); + set_details(details); + Tags details_tags; + details_tags.push_back(Tag(Tag::DIM, 0, details.length())); + set_details_tags(details_tags); + } + + WindowTypeLauncherItem::Type type() const { return type_; } + + private: + WindowTypeLauncherItem::Type type_; + + DISALLOW_COPY_AND_ASSIGN(ExampleSearchResult); +}; + class ExampleAppListViewDelegate : public app_list::AppListViewDelegate { public: ExampleAppListViewDelegate() : model_(NULL) {} private: + void PopulateApps(app_list::AppListModel::Apps* apps) { + for (int i = 0; + i < static_cast<int>(WindowTypeLauncherItem::LAST_TYPE); + ++i) { + WindowTypeLauncherItem::Type type = + static_cast<WindowTypeLauncherItem::Type>(i); + + std::string title = WindowTypeLauncherItem::GetTitle(type); + apps->Add(new WindowTypeLauncherItem(type)); + } + } + + SkBitmap CreateSearchBoxIcon() { + const string16 icon_text = ASCIIToUTF16("ash"); + const gfx::Size icon_size(32, 32); + + gfx::Canvas canvas(icon_size, false /* is_opaque */); + canvas.DrawStringInt(icon_text, + gfx::Font(), + SK_ColorBLACK, + 0, 0, icon_size.width(), icon_size.height(), + gfx::Canvas::TEXT_ALIGN_CENTER | + gfx::Canvas::TEXT_VALIGN_MIDDLE | + gfx::Canvas::NO_SUBPIXEL_RENDERING); + + return canvas.ExtractBitmap(); + } + + void DecorateSearchBox(app_list::SearchBoxModel* search_box_model) { + search_box_model->SetIcon(CreateSearchBoxIcon()); + search_box_model->SetHintText(ASCIIToUTF16("Type to search...")); + } + // Overridden from ash::AppListViewDelegate: virtual void SetModel(app_list::AppListModel* model) OVERRIDE { model_ = model; + PopulateApps(model_->apps()); + DecorateSearchBox(model_->search_box()); + } + + virtual void ActivateAppListItem(app_list::AppListItemModel* item, + int event_flags) OVERRIDE { + static_cast<WindowTypeLauncherItem*>(item)->Activate(event_flags); + } + + virtual void OpenSearchResult(const app_list::SearchResult& result, + int event_flags) OVERRIDE { + const ExampleSearchResult* example_result = + static_cast<const ExampleSearchResult*>(&result); + WindowTypeLauncherItem::Activate(example_result->type(), event_flags); } - virtual void UpdateModel(const std::string& query) OVERRIDE { - DCHECK(model_ && model_->item_count() == 0); + virtual void StartSearch() OVERRIDE { + string16 query; + TrimWhitespace(model_->search_box()->text(), TRIM_ALL, &query); + query = base::i18n::ToLower(query); + + model_->results()->DeleteAll(); + if (query.empty()) + return; for (int i = 0; i < static_cast<int>(WindowTypeLauncherItem::LAST_TYPE); @@ -125,15 +254,14 @@ class ExampleAppListViewDelegate : public app_list::AppListViewDelegate { WindowTypeLauncherItem::Type type = static_cast<WindowTypeLauncherItem::Type>(i); - std::string title = WindowTypeLauncherItem::GetTitle(type); - if (title.find(query) != std::string::npos) - model_->AddItem(new WindowTypeLauncherItem(type)); + string16 title = UTF8ToUTF16(WindowTypeLauncherItem::GetTitle(type)); + if (base::i18n::StringSearchIgnoringCaseAndAccents(query, title)) + model_->results()->Add(new ExampleSearchResult(type, query)); } } - virtual void OnAppListItemActivated(app_list::AppListItemModel* item, - int event_flags) OVERRIDE { - static_cast<WindowTypeLauncherItem*>(item)->Activate(event_flags); + virtual void StopSearch() OVERRIDE { + // Nothing needs to be done. } virtual void Close() OVERRIDE { |