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