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