1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 #include "ash/session/session_state_delegate.h"
10 #include "ash/shell/example_factory.h"
11 #include "ash/shell/toplevel_window.h"
12 #include "ash/shell_delegate.h"
13 #include "base/basictypes.h"
14 #include "base/callback.h"
15 #include "base/files/file_path.h"
16 #include "base/i18n/case_conversion.h"
17 #include "base/i18n/string_search.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "ui/app_list/app_list_item.h"
22 #include "ui/app_list/app_list_item_list.h"
23 #include "ui/app_list/app_list_model.h"
24 #include "ui/app_list/app_list_view_delegate.h"
25 #include "ui/app_list/search_box_model.h"
26 #include "ui/app_list/search_result.h"
27 #include "ui/app_list/speech_ui_model.h"
28 #include "ui/gfx/canvas.h"
29 #include "ui/gfx/font_list.h"
30 #include "ui/gfx/geometry/rect.h"
31 #include "ui/gfx/image/image_skia.h"
32 #include "ui/views/examples/examples_window_with_content.h"
39 // WindowTypeShelfItem is an app item of app list. It carries a window
40 // launch type and launches corresponding example window when activated.
41 class WindowTypeShelfItem
: public app_list::AppListItem
{
52 WindowTypeShelfItem(const std::string
& id
, Type type
);
53 ~WindowTypeShelfItem() override
;
55 static gfx::ImageSkia
GetIcon(Type type
) {
56 static const SkColor kColors
[] = {
64 const int kIconSize
= 128;
66 icon
.allocN32Pixels(kIconSize
, kIconSize
);
67 icon
.eraseColor(kColors
[static_cast<int>(type
) % arraysize(kColors
)]);
68 return gfx::ImageSkia::CreateFrom1xBitmap(icon
);
71 // The text below is not localized as this is an example code.
72 static std::string
GetTitle(Type type
) {
75 return "Create Window";
76 case NON_RESIZABLE_WINDOW
:
77 return "Create Non-Resizable Window";
81 return "Show Example Widgets";
83 return "Open Views Examples Window";
85 return "Unknown window type.";
89 // The text below is not localized as this is an example code.
90 static std::string
GetDetails(Type type
) {
91 // Assigns details only to some types so that we see both one-line
92 // and two-line results.
95 return "Creates a window to show example widgets";
97 return "Creates a window to show views example.";
103 static void ActivateItem(Type type
, int event_flags
) {
105 case TOPLEVEL_WINDOW
: {
106 ToplevelWindow::CreateParams params
;
107 params
.can_resize
= true;
108 ToplevelWindow::CreateToplevelWindow(params
);
111 case NON_RESIZABLE_WINDOW
: {
112 ToplevelWindow::CreateToplevelWindow(ToplevelWindow::CreateParams());
116 Shell::GetInstance()->session_state_delegate()->LockScreen();
119 case WIDGETS_WINDOW
: {
120 CreateWidgetsWindow();
123 case EXAMPLES_WINDOW
: {
124 views::examples::ShowExamplesWindowWithContent(
125 views::examples::DO_NOTHING_ON_CLOSE
,
126 Shell::GetInstance()->delegate()->GetActiveBrowserContext(),
136 void Activate(int event_flags
) override
{ ActivateItem(type_
, event_flags
); }
141 DISALLOW_COPY_AND_ASSIGN(WindowTypeShelfItem
);
144 WindowTypeShelfItem::WindowTypeShelfItem(const std::string
& id
, Type type
)
145 : app_list::AppListItem(id
), type_(type
) {
146 std::string
title(GetTitle(type
));
147 SetIcon(GetIcon(type
), false);
151 WindowTypeShelfItem::~WindowTypeShelfItem() {
154 // ExampleSearchResult is an app list search result. It provides what icon to
155 // show, what should title and details text look like. It also carries the
156 // matching window launch type so that AppListViewDelegate knows how to open
158 class ExampleSearchResult
: public app_list::SearchResult
{
160 ExampleSearchResult(WindowTypeShelfItem::Type type
,
161 const base::string16
& query
)
163 SetIcon(WindowTypeShelfItem::GetIcon(type_
));
165 base::string16 title
=
166 base::UTF8ToUTF16(WindowTypeShelfItem::GetTitle(type_
));
170 const size_t match_len
= query
.length();
172 // Highlight matching parts in title with bold.
173 // Note the following is not a proper way to handle i18n string.
174 title
= base::i18n::ToLower(title
);
175 size_t match_start
= title
.find(query
);
176 while (match_start
!= base::string16::npos
) {
177 title_tags
.push_back(Tag(Tag::MATCH
,
179 match_start
+ match_len
));
180 match_start
= title
.find(query
, match_start
+ match_len
);
182 set_title_tags(title_tags
);
184 base::string16 details
=
185 base::UTF8ToUTF16(WindowTypeShelfItem::GetDetails(type_
));
186 set_details(details
);
188 details_tags
.push_back(Tag(Tag::DIM
, 0, details
.length()));
189 set_details_tags(details_tags
);
192 WindowTypeShelfItem::Type
type() const { return type_
; }
194 // app_list::SearchResult:
195 scoped_ptr
<SearchResult
> Duplicate() const override
{
196 return scoped_ptr
<SearchResult
>();
200 WindowTypeShelfItem::Type type_
;
202 DISALLOW_COPY_AND_ASSIGN(ExampleSearchResult
);
205 class ExampleAppListViewDelegate
: public app_list::AppListViewDelegate
{
207 ExampleAppListViewDelegate()
208 : model_(new app_list::AppListModel
) {
210 DecorateSearchBox(model_
->search_box());
214 void PopulateApps() {
215 for (int i
= 0; i
< static_cast<int>(WindowTypeShelfItem::LAST_TYPE
); ++i
) {
216 WindowTypeShelfItem::Type type
=
217 static_cast<WindowTypeShelfItem::Type
>(i
);
218 std::string id
= base::StringPrintf("%d", i
);
219 scoped_ptr
<WindowTypeShelfItem
> shelf_item(
220 new WindowTypeShelfItem(id
, type
));
221 model_
->AddItem(shelf_item
.Pass());
225 gfx::ImageSkia
CreateSearchBoxIcon() {
226 const base::string16 icon_text
= base::ASCIIToUTF16("ash");
227 const gfx::Size
icon_size(32, 32);
229 gfx::Canvas
canvas(icon_size
, 1.0f
, false /* is_opaque */);
230 canvas
.DrawStringRectWithFlags(
234 gfx::Rect(icon_size
),
235 gfx::Canvas::TEXT_ALIGN_CENTER
| gfx::Canvas::NO_SUBPIXEL_RENDERING
);
237 return gfx::ImageSkia(canvas
.ExtractImageRep());
240 void DecorateSearchBox(app_list::SearchBoxModel
* search_box_model
) {
241 search_box_model
->SetIcon(CreateSearchBoxIcon());
242 search_box_model
->SetHintText(base::ASCIIToUTF16("Type to search..."));
245 // Overridden from app_list::AppListViewDelegate:
246 bool ForceNativeDesktop() const override
{ return false; }
248 void SetProfileByPath(const base::FilePath
& profile_path
) override
{
249 // Nothing needs to be done.
252 const Users
& GetUsers() const override
{ return users_
; }
254 bool ShouldCenterWindow() const override
{ return false; }
256 app_list::AppListModel
* GetModel() override
{ return model_
.get(); }
258 app_list::SpeechUIModel
* GetSpeechUI() override
{ return &speech_ui_
; }
260 void GetShortcutPathForApp(
261 const std::string
& app_id
,
262 const base::Callback
<void(const base::FilePath
&)>& callback
) override
{
263 callback
.Run(base::FilePath());
266 void OpenSearchResult(app_list::SearchResult
* result
,
268 int event_flags
) override
{
269 const ExampleSearchResult
* example_result
=
270 static_cast<const ExampleSearchResult
*>(result
);
271 WindowTypeShelfItem::ActivateItem(example_result
->type(), event_flags
);
274 void InvokeSearchResultAction(app_list::SearchResult
* result
,
276 int event_flags
) override
{
280 base::TimeDelta
GetAutoLaunchTimeout() override
{ return base::TimeDelta(); }
282 void AutoLaunchCanceled() override
{}
284 void StartSearch() override
{
285 base::string16 query
;
286 base::TrimWhitespace(model_
->search_box()->text(), base::TRIM_ALL
, &query
);
287 query
= base::i18n::ToLower(query
);
289 model_
->results()->DeleteAll();
293 for (int i
= 0; i
< static_cast<int>(WindowTypeShelfItem::LAST_TYPE
); ++i
) {
294 WindowTypeShelfItem::Type type
=
295 static_cast<WindowTypeShelfItem::Type
>(i
);
297 base::string16 title
=
298 base::UTF8ToUTF16(WindowTypeShelfItem::GetTitle(type
));
299 if (base::i18n::StringSearchIgnoringCaseAndAccents(
300 query
, title
, NULL
, NULL
)) {
301 model_
->results()->Add(new ExampleSearchResult(type
, query
));
306 void StopSearch() override
{
307 // Nothing needs to be done.
310 void ViewInitialized() override
{
311 // Nothing needs to be done.
314 void Dismiss() override
{
315 DCHECK(ash::Shell::HasInstance());
316 Shell::GetInstance()->DismissAppList();
319 void ViewClosing() override
{
320 // Nothing needs to be done.
323 gfx::ImageSkia
GetWindowIcon() override
{ return gfx::ImageSkia(); }
325 void OpenSettings() override
{
326 // Nothing needs to be done.
329 void OpenHelp() override
{
330 // Nothing needs to be done.
333 void OpenFeedback() override
{
334 // Nothing needs to be done.
337 void ToggleSpeechRecognition() override
{ NOTIMPLEMENTED(); }
339 void ShowForProfileByPath(const base::FilePath
& profile_path
) override
{
340 // Nothing needs to be done.
343 views::View
* CreateStartPageWebView(const gfx::Size
& size
) override
{
347 std::vector
<views::View
*> CreateCustomPageWebViews(
348 const gfx::Size
& size
) override
{
349 return std::vector
<views::View
*>();
352 void CustomLauncherPageAnimationChanged(double progress
) override
{}
354 void CustomLauncherPagePopSubpage() override
{}
356 bool IsSpeechRecognitionEnabled() override
{ return false; }
358 scoped_ptr
<app_list::AppListModel
> model_
;
359 app_list::SpeechUIModel speech_ui_
;
362 DISALLOW_COPY_AND_ASSIGN(ExampleAppListViewDelegate
);
367 app_list::AppListViewDelegate
* CreateAppListViewDelegate() {
368 return new ExampleAppListViewDelegate
;