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