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