| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <string> |
| |
| #include "ash/session/session_state_delegate.h" |
| #include "ash/shell.h" |
| #include "ash/shell/example_factory.h" |
| #include "ash/shell/toplevel_window.h" |
| #include "ash/shell_delegate.h" |
| #include "base/basictypes.h" |
| #include "base/callback.h" |
| #include "base/files/file_path.h" |
| #include "base/i18n/case_conversion.h" |
| #include "base/i18n/string_search.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "ui/app_list/app_list_item.h" |
| #include "ui/app_list/app_list_item_list.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/app_list/speech_ui_model.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/font_list.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/views/examples/examples_window_with_content.h" |
| |
| namespace ash { |
| namespace shell { |
| |
| namespace { |
| |
| // WindowTypeShelfItem is an app item of app list. It carries a window |
| // launch type and launches corresponding example window when activated. |
| class WindowTypeShelfItem : public app_list::AppListItem { |
| public: |
| enum Type { |
| TOPLEVEL_WINDOW = 0, |
| NON_RESIZABLE_WINDOW, |
| LOCK_SCREEN, |
| WIDGETS_WINDOW, |
| EXAMPLES_WINDOW, |
| LAST_TYPE, |
| }; |
| |
| explicit WindowTypeShelfItem(const std::string& id, Type type) |
| : app_list::AppListItem(id), |
| type_(type) { |
| std::string title(GetTitle(type)); |
| SetIcon(GetIcon(type), false); |
| SetName(title); |
| } |
| |
| static gfx::ImageSkia GetIcon(Type type) { |
| static const SkColor kColors[] = { |
| SK_ColorRED, |
| SK_ColorGREEN, |
| SK_ColorBLUE, |
| SK_ColorYELLOW, |
| SK_ColorCYAN, |
| }; |
| |
| const int kIconSize = 128; |
| SkBitmap icon; |
| icon.allocN32Pixels(kIconSize, kIconSize); |
| icon.eraseColor(kColors[static_cast<int>(type) % arraysize(kColors)]); |
| return gfx::ImageSkia::CreateFrom1xBitmap(icon); |
| } |
| |
| // The text below is not localized as this is an example code. |
| static std::string GetTitle(Type type) { |
| switch (type) { |
| case TOPLEVEL_WINDOW: |
| return "Create Window"; |
| case NON_RESIZABLE_WINDOW: |
| return "Create Non-Resizable Window"; |
| case LOCK_SCREEN: |
| return "Lock Screen"; |
| case WIDGETS_WINDOW: |
| return "Show Example Widgets"; |
| case EXAMPLES_WINDOW: |
| return "Open Views Examples Window"; |
| default: |
| return "Unknown window 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 ActivateItem(Type type, int event_flags) { |
| switch (type) { |
| case TOPLEVEL_WINDOW: { |
| ToplevelWindow::CreateParams params; |
| params.can_resize = true; |
| ToplevelWindow::CreateToplevelWindow(params); |
| break; |
| } |
| case NON_RESIZABLE_WINDOW: { |
| ToplevelWindow::CreateToplevelWindow(ToplevelWindow::CreateParams()); |
| break; |
| } |
| case LOCK_SCREEN: { |
| Shell::GetInstance()->session_state_delegate()->LockScreen(); |
| break; |
| } |
| case WIDGETS_WINDOW: { |
| CreateWidgetsWindow(); |
| break; |
| } |
| case EXAMPLES_WINDOW: { |
| views::examples::ShowExamplesWindowWithContent( |
| views::examples::DO_NOTHING_ON_CLOSE, |
| Shell::GetInstance()->delegate()->GetActiveBrowserContext(), |
| NULL); |
| break; |
| } |
| default: |
| break; |
| } |
| } |
| |
| // AppListItem |
| virtual void Activate(int event_flags) OVERRIDE { |
| ActivateItem(type_, event_flags); |
| } |
| |
| private: |
| Type type_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WindowTypeShelfItem); |
| }; |
| |
| // 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(WindowTypeShelfItem::Type type, |
| const base::string16& query) |
| : type_(type) { |
| SetIcon(WindowTypeShelfItem::GetIcon(type_)); |
| |
| base::string16 title = |
| base::UTF8ToUTF16(WindowTypeShelfItem::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 != base::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); |
| |
| base::string16 details = |
| base::UTF8ToUTF16(WindowTypeShelfItem::GetDetails(type_)); |
| set_details(details); |
| Tags details_tags; |
| details_tags.push_back(Tag(Tag::DIM, 0, details.length())); |
| set_details_tags(details_tags); |
| } |
| |
| WindowTypeShelfItem::Type type() const { return type_; } |
| |
| private: |
| WindowTypeShelfItem::Type type_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ExampleSearchResult); |
| }; |
| |
| class ExampleAppListViewDelegate : public app_list::AppListViewDelegate { |
| public: |
| ExampleAppListViewDelegate() |
| : model_(new app_list::AppListModel), |
| speech_ui_(app_list::SPEECH_RECOGNITION_OFF) { |
| PopulateApps(); |
| DecorateSearchBox(model_->search_box()); |
| } |
| |
| private: |
| void PopulateApps() { |
| for (int i = 0; i < static_cast<int>(WindowTypeShelfItem::LAST_TYPE); ++i) { |
| WindowTypeShelfItem::Type type = |
| static_cast<WindowTypeShelfItem::Type>(i); |
| std::string id = base::StringPrintf("%d", i); |
| scoped_ptr<WindowTypeShelfItem> shelf_item( |
| new WindowTypeShelfItem(id, type)); |
| model_->AddItem(shelf_item.PassAs<app_list::AppListItem>()); |
| } |
| } |
| |
| gfx::ImageSkia CreateSearchBoxIcon() { |
| const base::string16 icon_text = base::ASCIIToUTF16("ash"); |
| const gfx::Size icon_size(32, 32); |
| |
| gfx::Canvas canvas(icon_size, 1.0f, false /* is_opaque */); |
| canvas.DrawStringRectWithFlags( |
| icon_text, |
| gfx::FontList(), |
| SK_ColorBLACK, |
| gfx::Rect(icon_size), |
| gfx::Canvas::TEXT_ALIGN_CENTER | gfx::Canvas::NO_SUBPIXEL_RENDERING); |
| |
| return gfx::ImageSkia(canvas.ExtractImageRep()); |
| } |
| |
| void DecorateSearchBox(app_list::SearchBoxModel* search_box_model) { |
| search_box_model->SetIcon(CreateSearchBoxIcon()); |
| search_box_model->SetHintText(base::ASCIIToUTF16("Type to search...")); |
| } |
| |
| // Overridden from app_list::AppListViewDelegate: |
| virtual bool ForceNativeDesktop() const OVERRIDE { |
| return false; |
| } |
| |
| virtual void SetProfileByPath(const base::FilePath& profile_path) OVERRIDE { |
| // Nothing needs to be done. |
| } |
| |
| virtual const Users& GetUsers() const OVERRIDE { |
| return users_; |
| } |
| |
| virtual bool ShouldCenterWindow() const OVERRIDE { |
| return false; |
| } |
| |
| virtual app_list::AppListModel* GetModel() OVERRIDE { return model_.get(); } |
| |
| virtual app_list::SpeechUIModel* GetSpeechUI() OVERRIDE { |
| return &speech_ui_; |
| } |
| |
| virtual void GetShortcutPathForApp( |
| const std::string& app_id, |
| const base::Callback<void(const base::FilePath&)>& callback) OVERRIDE { |
| callback.Run(base::FilePath()); |
| } |
| |
| virtual void OpenSearchResult(app_list::SearchResult* result, |
| bool auto_launch, |
| int event_flags) OVERRIDE { |
| const ExampleSearchResult* example_result = |
| static_cast<const ExampleSearchResult*>(result); |
| WindowTypeShelfItem::ActivateItem(example_result->type(), event_flags); |
| } |
| |
| virtual void InvokeSearchResultAction(app_list::SearchResult* result, |
| int action_index, |
| int event_flags) OVERRIDE { |
| NOTIMPLEMENTED(); |
| } |
| |
| virtual base::TimeDelta GetAutoLaunchTimeout() OVERRIDE { |
| return base::TimeDelta(); |
| } |
| |
| virtual void AutoLaunchCanceled() OVERRIDE { |
| } |
| |
| virtual void StartSearch() OVERRIDE { |
| base::string16 query; |
| base::TrimWhitespace(model_->search_box()->text(), base::TRIM_ALL, &query); |
| query = base::i18n::ToLower(query); |
| |
| model_->results()->DeleteAll(); |
| if (query.empty()) |
| return; |
| |
| for (int i = 0; i < static_cast<int>(WindowTypeShelfItem::LAST_TYPE); ++i) { |
| WindowTypeShelfItem::Type type = |
| static_cast<WindowTypeShelfItem::Type>(i); |
| |
| base::string16 title = |
| base::UTF8ToUTF16(WindowTypeShelfItem::GetTitle(type)); |
| if (base::i18n::StringSearchIgnoringCaseAndAccents( |
| query, title, NULL, NULL)) { |
| model_->results()->Add(new ExampleSearchResult(type, query)); |
| } |
| } |
| } |
| |
| virtual void StopSearch() OVERRIDE { |
| // Nothing needs to be done. |
| } |
| |
| virtual void ViewInitialized() OVERRIDE { |
| // Nothing needs to be done. |
| } |
| |
| virtual void Dismiss() OVERRIDE { |
| DCHECK(ash::Shell::HasInstance()); |
| if (Shell::GetInstance()->GetAppListTargetVisibility()) |
| Shell::GetInstance()->ToggleAppList(NULL); |
| } |
| |
| virtual void ViewClosing() OVERRIDE { |
| // Nothing needs to be done. |
| } |
| |
| virtual gfx::ImageSkia GetWindowIcon() OVERRIDE { |
| return gfx::ImageSkia(); |
| } |
| |
| virtual void OpenSettings() OVERRIDE { |
| // Nothing needs to be done. |
| } |
| |
| virtual void OpenHelp() OVERRIDE { |
| // Nothing needs to be done. |
| } |
| |
| virtual void OpenFeedback() OVERRIDE { |
| // Nothing needs to be done. |
| } |
| |
| virtual void ToggleSpeechRecognition() OVERRIDE { |
| NOTIMPLEMENTED(); |
| } |
| |
| virtual void ShowForProfileByPath( |
| const base::FilePath& profile_path) OVERRIDE { |
| // Nothing needs to be done. |
| } |
| |
| virtual views::View* CreateStartPageWebView(const gfx::Size& size) OVERRIDE { |
| return NULL; |
| } |
| |
| virtual views::View* CreateCustomPageWebView(const gfx::Size& size) OVERRIDE { |
| return NULL; |
| } |
| |
| virtual bool IsSpeechRecognitionEnabled() OVERRIDE { |
| return false; |
| } |
| |
| scoped_ptr<app_list::AppListModel> model_; |
| app_list::SpeechUIModel speech_ui_; |
| Users users_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ExampleAppListViewDelegate); |
| }; |
| |
| } // namespace |
| |
| app_list::AppListViewDelegate* CreateAppListViewDelegate() { |
| return new ExampleAppListViewDelegate; |
| } |
| |
| } // namespace shell |
| } // namespace ash |