app_list.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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.
4
5#include <string>
6
7#include "ash/session_state_delegate.h"
8#include "ash/shell.h"
9#include "ash/shell/example_factory.h"
10#include "ash/shell/toplevel_window.h"
11#include "base/basictypes.h"
12#include "base/i18n/case_conversion.h"
13#include "base/i18n/string_search.h"
14#include "base/strings/string_util.h"
15#include "base/strings/utf_string_conversions.h"
16#include "ui/app_list/app_list_item_model.h"
17#include "ui/app_list/app_list_model.h"
18#include "ui/app_list/app_list_view_delegate.h"
19#include "ui/app_list/search_box_model.h"
20#include "ui/app_list/search_result.h"
21#include "ui/gfx/canvas.h"
22#include "ui/gfx/font.h"
23#include "ui/gfx/image/image_skia.h"
24#include "ui/gfx/rect.h"
25#include "ui/views/examples/examples_window_with_content.h"
26
27namespace ash {
28namespace shell {
29
30namespace {
31
32// WindowTypeLauncherItem is an app item of app list. It carries a window
33// launch type and launches corresponding example window when activated.
34class WindowTypeLauncherItem : public app_list::AppListItemModel {
35 public:
36  enum Type {
37    TOPLEVEL_WINDOW = 0,
38    NON_RESIZABLE_WINDOW,
39    LOCK_SCREEN,
40    WIDGETS_WINDOW,
41    EXAMPLES_WINDOW,
42    LAST_TYPE,
43  };
44
45  explicit WindowTypeLauncherItem(Type type) : type_(type) {
46    SetIcon(GetIcon(type), false);
47    SetTitle(GetTitle(type));
48  }
49
50  static gfx::ImageSkia GetIcon(Type type) {
51    static const SkColor kColors[] = {
52        SK_ColorRED,
53        SK_ColorGREEN,
54        SK_ColorBLUE,
55        SK_ColorYELLOW,
56        SK_ColorCYAN,
57    };
58
59    const int kIconSize = 128;
60    SkBitmap icon;
61    icon.setConfig(SkBitmap::kARGB_8888_Config, kIconSize, kIconSize);
62    icon.allocPixels();
63    icon.eraseColor(kColors[static_cast<int>(type) % arraysize(kColors)]);
64    return gfx::ImageSkia::CreateFrom1xBitmap(icon);
65  }
66
67  // The text below is not localized as this is an example code.
68  static std::string GetTitle(Type type) {
69    switch (type) {
70      case TOPLEVEL_WINDOW:
71        return "Create Window";
72      case NON_RESIZABLE_WINDOW:
73        return "Create Non-Resizable Window";
74      case LOCK_SCREEN:
75        return "Lock Screen";
76      case WIDGETS_WINDOW:
77        return "Show Example Widgets";
78      case EXAMPLES_WINDOW:
79        return "Open Views Examples Window";
80      default:
81        return "Unknown window type.";
82    }
83  }
84
85  // The text below is not localized as this is an example code.
86  static std::string GetDetails(Type type) {
87    // Assigns details only to some types so that we see both one-line
88    // and two-line results.
89    switch (type) {
90      case WIDGETS_WINDOW:
91        return "Creates a window to show example widgets";
92      case EXAMPLES_WINDOW:
93        return "Creates a window to show views example.";
94      default:
95        return std::string();
96    }
97  }
98
99  static void Activate(Type type, int event_flags) {
100     switch (type) {
101      case TOPLEVEL_WINDOW: {
102        ToplevelWindow::CreateParams params;
103        params.can_resize = true;
104        ToplevelWindow::CreateToplevelWindow(params);
105        break;
106      }
107      case NON_RESIZABLE_WINDOW: {
108        ToplevelWindow::CreateToplevelWindow(ToplevelWindow::CreateParams());
109        break;
110      }
111      case LOCK_SCREEN: {
112        Shell::GetInstance()->session_state_delegate()->LockScreen();
113        break;
114      }
115      case WIDGETS_WINDOW: {
116        CreateWidgetsWindow();
117        break;
118      }
119      case EXAMPLES_WINDOW: {
120#if !defined(OS_MACOSX)
121        views::examples::ShowExamplesWindowWithContent(
122            views::examples::DO_NOTHING_ON_CLOSE,
123            ash::Shell::GetInstance()->browser_context());
124#endif
125        break;
126      }
127      default:
128        break;
129    }
130  }
131
132  void Activate(int event_flags) {
133    Activate(type_, event_flags);
134  }
135
136 private:
137  Type type_;
138
139  DISALLOW_COPY_AND_ASSIGN(WindowTypeLauncherItem);
140};
141
142// ExampleSearchResult is an app list search result. It provides what icon to
143// show, what should title and details text look like. It also carries the
144// matching window launch type so that AppListViewDelegate knows how to open
145// it.
146class ExampleSearchResult : public app_list::SearchResult {
147 public:
148  ExampleSearchResult(WindowTypeLauncherItem::Type type,
149                      const base::string16& query)
150      : type_(type) {
151    SetIcon(WindowTypeLauncherItem::GetIcon(type_));
152
153    base::string16 title = UTF8ToUTF16(WindowTypeLauncherItem::GetTitle(type_));
154    set_title(title);
155
156    Tags title_tags;
157    const size_t match_len = query.length();
158
159    // Highlight matching parts in title with bold.
160    // Note the following is not a proper way to handle i18n string.
161    title = base::i18n::ToLower(title);
162    size_t match_start = title.find(query);
163    while (match_start != base::string16::npos) {
164      title_tags.push_back(Tag(Tag::MATCH,
165                               match_start,
166                               match_start + match_len));
167      match_start = title.find(query, match_start + match_len);
168    }
169    set_title_tags(title_tags);
170
171    base::string16 details =
172        UTF8ToUTF16(WindowTypeLauncherItem::GetDetails(type_));
173    set_details(details);
174    Tags details_tags;
175    details_tags.push_back(Tag(Tag::DIM, 0, details.length()));
176    set_details_tags(details_tags);
177  }
178
179  WindowTypeLauncherItem::Type type() const { return type_; }
180
181 private:
182  WindowTypeLauncherItem::Type type_;
183
184  DISALLOW_COPY_AND_ASSIGN(ExampleSearchResult);
185};
186
187class ExampleAppListViewDelegate : public app_list::AppListViewDelegate {
188 public:
189  ExampleAppListViewDelegate() : model_(NULL) {}
190
191 private:
192  void PopulateApps(app_list::AppListModel::Apps* apps) {
193    for (int i = 0;
194         i < static_cast<int>(WindowTypeLauncherItem::LAST_TYPE);
195         ++i) {
196      WindowTypeLauncherItem::Type type =
197          static_cast<WindowTypeLauncherItem::Type>(i);
198      apps->Add(new WindowTypeLauncherItem(type));
199    }
200  }
201
202  gfx::ImageSkia CreateSearchBoxIcon() {
203    const base::string16 icon_text = ASCIIToUTF16("ash");
204    const gfx::Size icon_size(32, 32);
205
206    gfx::Canvas canvas(icon_size, ui::SCALE_FACTOR_100P,
207                       false /* is_opaque */);
208    canvas.DrawStringInt(icon_text,
209                         gfx::Font(),
210                         SK_ColorBLACK,
211                         0, 0, icon_size.width(), icon_size.height(),
212                         gfx::Canvas::TEXT_ALIGN_CENTER |
213                             gfx::Canvas::NO_SUBPIXEL_RENDERING);
214
215    return gfx::ImageSkia(canvas.ExtractImageRep());
216  }
217
218  void DecorateSearchBox(app_list::SearchBoxModel* search_box_model) {
219    search_box_model->SetIcon(CreateSearchBoxIcon());
220    search_box_model->SetHintText(ASCIIToUTF16("Type to search..."));
221  }
222
223  // Overridden from ash::AppListViewDelegate:
224  virtual void SetModel(app_list::AppListModel* model) OVERRIDE {
225    model_ = model;
226    PopulateApps(model_->apps());
227    DecorateSearchBox(model_->search_box());
228  }
229
230  virtual app_list::SigninDelegate* GetSigninDelegate() OVERRIDE {
231    return NULL;
232  }
233
234  virtual void ActivateAppListItem(app_list::AppListItemModel* item,
235                                   int event_flags) OVERRIDE {
236    static_cast<WindowTypeLauncherItem*>(item)->Activate(event_flags);
237  }
238
239  virtual void OpenSearchResult(app_list::SearchResult* result,
240                                int event_flags) OVERRIDE {
241    const ExampleSearchResult* example_result =
242        static_cast<const ExampleSearchResult*>(result);
243    WindowTypeLauncherItem::Activate(example_result->type(), event_flags);
244  }
245
246  virtual void InvokeSearchResultAction(app_list::SearchResult* result,
247                                        int action_index,
248                                        int event_flags) OVERRIDE {
249    NOTIMPLEMENTED();
250  }
251
252  virtual void StartSearch() OVERRIDE {
253    base::string16 query;
254    TrimWhitespace(model_->search_box()->text(), TRIM_ALL, &query);
255    query = base::i18n::ToLower(query);
256
257    model_->results()->DeleteAll();
258    if (query.empty())
259      return;
260
261    for (int i = 0;
262         i < static_cast<int>(WindowTypeLauncherItem::LAST_TYPE);
263         ++i) {
264      WindowTypeLauncherItem::Type type =
265          static_cast<WindowTypeLauncherItem::Type>(i);
266
267      base::string16 title =
268          UTF8ToUTF16(WindowTypeLauncherItem::GetTitle(type));
269      if (base::i18n::StringSearchIgnoringCaseAndAccents(
270              query, title, NULL, NULL)) {
271        model_->results()->Add(new ExampleSearchResult(type, query));
272      }
273    }
274  }
275
276  virtual void StopSearch() OVERRIDE {
277    // Nothing needs to be done.
278  }
279
280  virtual void Dismiss() OVERRIDE {
281    DCHECK(ash::Shell::HasInstance());
282    if (Shell::GetInstance()->GetAppListTargetVisibility())
283      Shell::GetInstance()->ToggleAppList(NULL);
284  }
285
286  virtual void ViewClosing() OVERRIDE {
287    // Nothing needs to be done.
288  }
289
290  virtual void ViewActivationChanged(bool active) OVERRIDE {
291    // Nothing needs to be done.
292  }
293
294  virtual gfx::ImageSkia GetWindowIcon() OVERRIDE {
295    return gfx::ImageSkia();
296  }
297
298  virtual base::string16 GetCurrentUserName() OVERRIDE {
299    return base::string16();
300  }
301
302  virtual base::string16 GetCurrentUserEmail() OVERRIDE {
303    return base::string16();
304  }
305
306  virtual void OpenSettings() OVERRIDE {
307    // Nothing needs to be done.
308  }
309
310  virtual void OpenHelp() OVERRIDE {
311    // Nothing needs to be done.
312  }
313
314  virtual void OpenFeedback() OVERRIDE {
315    // Nothing needs to be done.
316  }
317
318  app_list::AppListModel* model_;
319
320  DISALLOW_COPY_AND_ASSIGN(ExampleAppListViewDelegate);
321};
322
323}  // namespace
324
325app_list::AppListViewDelegate* CreateAppListViewDelegate() {
326  return new ExampleAppListViewDelegate;
327}
328
329}  // namespace shell
330}  // namespace ash
331