app_list.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/shell.h"
8#include "ash/shell/example_factory.h"
9#include "ash/shell/toplevel_window.h"
10#include "ash/shell_delegate.h"
11#include "base/basictypes.h"
12#include "base/i18n/case_conversion.h"
13#include "base/i18n/string_search.h"
14#include "base/string_util.h"
15#include "base/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()->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 string16& query)
150      : type_(type) {
151    SetIcon(WindowTypeLauncherItem::GetIcon(type_));
152
153    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 != 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    string16 details = UTF8ToUTF16(WindowTypeLauncherItem::GetDetails(type_));
172    set_details(details);
173    Tags details_tags;
174    details_tags.push_back(Tag(Tag::DIM, 0, details.length()));
175    set_details_tags(details_tags);
176  }
177
178  WindowTypeLauncherItem::Type type() const { return type_; }
179
180 private:
181  WindowTypeLauncherItem::Type type_;
182
183  DISALLOW_COPY_AND_ASSIGN(ExampleSearchResult);
184};
185
186class ExampleAppListViewDelegate : public app_list::AppListViewDelegate {
187 public:
188  ExampleAppListViewDelegate() : model_(NULL) {}
189
190 private:
191  void PopulateApps(app_list::AppListModel::Apps* apps) {
192    for (int i = 0;
193         i < static_cast<int>(WindowTypeLauncherItem::LAST_TYPE);
194         ++i) {
195      WindowTypeLauncherItem::Type type =
196          static_cast<WindowTypeLauncherItem::Type>(i);
197      apps->Add(new WindowTypeLauncherItem(type));
198    }
199  }
200
201  gfx::ImageSkia CreateSearchBoxIcon() {
202    const string16 icon_text = ASCIIToUTF16("ash");
203    const gfx::Size icon_size(32, 32);
204
205    gfx::Canvas canvas(icon_size, ui::SCALE_FACTOR_100P,
206                       false /* is_opaque */);
207    canvas.DrawStringInt(icon_text,
208                         gfx::Font(),
209                         SK_ColorBLACK,
210                         0, 0, icon_size.width(), icon_size.height(),
211                         gfx::Canvas::TEXT_ALIGN_CENTER |
212                             gfx::Canvas::NO_SUBPIXEL_RENDERING);
213
214    return gfx::ImageSkia(canvas.ExtractImageRep());
215  }
216
217  void DecorateSearchBox(app_list::SearchBoxModel* search_box_model) {
218    search_box_model->SetIcon(CreateSearchBoxIcon());
219    search_box_model->SetHintText(ASCIIToUTF16("Type to search..."));
220  }
221
222  // Overridden from ash::AppListViewDelegate:
223  virtual void SetModel(app_list::AppListModel* model) OVERRIDE {
224    model_ = model;
225    PopulateApps(model_->apps());
226    DecorateSearchBox(model_->search_box());
227  }
228
229  virtual app_list::SigninDelegate* GetSigninDelegate() OVERRIDE {
230    return NULL;
231  }
232
233  virtual void ActivateAppListItem(app_list::AppListItemModel* item,
234                                   int event_flags) OVERRIDE {
235    static_cast<WindowTypeLauncherItem*>(item)->Activate(event_flags);
236  }
237
238  virtual void OpenSearchResult(const app_list::SearchResult& result,
239                                int event_flags) OVERRIDE {
240    const ExampleSearchResult* example_result =
241        static_cast<const ExampleSearchResult*>(&result);
242    WindowTypeLauncherItem::Activate(example_result->type(), event_flags);
243  }
244
245  virtual void InvokeSearchResultAction(const app_list::SearchResult& result,
246                                        int action_index,
247                                        int event_flags) OVERRIDE {
248    NOTIMPLEMENTED();
249  }
250
251  virtual void StartSearch() OVERRIDE {
252    string16 query;
253    TrimWhitespace(model_->search_box()->text(), TRIM_ALL, &query);
254    query = base::i18n::ToLower(query);
255
256    model_->results()->DeleteAll();
257    if (query.empty())
258      return;
259
260    for (int i = 0;
261         i < static_cast<int>(WindowTypeLauncherItem::LAST_TYPE);
262         ++i) {
263      WindowTypeLauncherItem::Type type =
264          static_cast<WindowTypeLauncherItem::Type>(i);
265
266      string16 title = UTF8ToUTF16(WindowTypeLauncherItem::GetTitle(type));
267      if (base::i18n::StringSearchIgnoringCaseAndAccents(
268              query, title, NULL, NULL)) {
269        model_->results()->Add(new ExampleSearchResult(type, query));
270      }
271    }
272  }
273
274  virtual void StopSearch() OVERRIDE {
275    // Nothing needs to be done.
276  }
277
278  virtual void Dismiss() OVERRIDE {
279    DCHECK(ash::Shell::HasInstance());
280    if (Shell::GetInstance()->GetAppListTargetVisibility())
281      Shell::GetInstance()->ToggleAppList(NULL);
282  }
283
284  virtual void ViewClosing() OVERRIDE {
285    // Nothing needs to be done.
286  }
287
288  virtual void ViewActivationChanged(bool active) OVERRIDE {
289    // Nothing needs to be done.
290  }
291
292  virtual gfx::ImageSkia GetWindowIcon() OVERRIDE {
293    return gfx::ImageSkia();
294  }
295
296  virtual string16 GetCurrentUserName() {
297    return string16();
298  }
299
300  virtual string16 GetCurrentUserEmail() {
301    return string16();
302  }
303
304  virtual void OpenSettings() {
305    // Nothing needs to be done.
306  }
307
308  virtual void OpenFeedback() {
309    // Nothing needs to be done.
310  }
311
312  app_list::AppListModel* model_;
313
314  DISALLOW_COPY_AND_ASSIGN(ExampleAppListViewDelegate);
315};
316
317}  // namespace
318
319app_list::AppListViewDelegate* CreateAppListViewDelegate() {
320  return new ExampleAppListViewDelegate;
321}
322
323}  // namespace shell
324}  // namespace ash
325