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