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