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