Home | History | Annotate | Download | only in home
      1 // Copyright 2014 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 "athena/home/public/home_card.h"
      6 
      7 #include "athena/home/app_list_view_delegate.h"
      8 #include "athena/home/public/app_model_builder.h"
      9 #include "athena/input/public/accelerator_manager.h"
     10 #include "athena/screen/public/screen_manager.h"
     11 #include "ui/app_list/search_provider.h"
     12 #include "ui/app_list/views/app_list_view.h"
     13 #include "ui/aura/layout_manager.h"
     14 #include "ui/aura/window.h"
     15 #include "ui/wm/core/visibility_controller.h"
     16 #include "ui/wm/core/window_animations.h"
     17 
     18 namespace athena {
     19 namespace {
     20 
     21 HomeCard* instance = NULL;
     22 
     23 class HomeCardLayoutManager : public aura::LayoutManager {
     24  public:
     25   explicit HomeCardLayoutManager(aura::Window* container)
     26       : container_(container) {}
     27   virtual ~HomeCardLayoutManager() {}
     28 
     29  private:
     30   // aura::LayoutManager:
     31   virtual void OnWindowResized() OVERRIDE { Layout(); }
     32   virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE { Layout(); }
     33   virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
     34   virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {
     35     Layout();
     36   }
     37   virtual void OnChildWindowVisibilityChanged(aura::Window* child,
     38                                               bool visible) OVERRIDE {
     39     Layout();
     40   }
     41   virtual void SetChildBounds(aura::Window* child,
     42                               const gfx::Rect& requested_bounds) OVERRIDE {
     43     SetChildBoundsDirect(child, gfx::Rect(requested_bounds.size()));
     44   }
     45 
     46   void Layout() {
     47     const int kHomeCardHeight = 150;
     48     const int kHomeCardHorizontalMargin = 50;
     49     // Currently the home card is provided as a bubble and the bounds has to be
     50     // increased to cancel the shadow.
     51     // TODO(mukai): stops using the bubble and remove this.
     52     const int kHomeCardShadowWidth = 30;
     53     if (container_->children().size() < 1)
     54       return;
     55     aura::Window* home_card = container_->children()[0];
     56     if (!home_card->IsVisible())
     57       return;
     58     gfx::Rect screen_bounds = home_card->GetRootWindow()->bounds();
     59     gfx::Rect card_bounds = screen_bounds;
     60     card_bounds.Inset(kHomeCardHorizontalMargin,
     61                       screen_bounds.height() - kHomeCardHeight,
     62                       kHomeCardHorizontalMargin,
     63                       0);
     64     card_bounds.Inset(-kHomeCardShadowWidth, -kHomeCardShadowWidth);
     65     SetChildBoundsDirect(home_card, card_bounds);
     66   }
     67 
     68   aura::Window* container_;
     69 
     70   DISALLOW_COPY_AND_ASSIGN(HomeCardLayoutManager);
     71 };
     72 
     73 class HomeCardImpl : public HomeCard, public AcceleratorHandler {
     74  public:
     75   explicit HomeCardImpl(AppModelBuilder* model_builder);
     76   virtual ~HomeCardImpl();
     77 
     78   void Init();
     79 
     80  private:
     81   enum Command {
     82     COMMAND_SHOW_HOME_CARD,
     83   };
     84   void InstallAccelerators();
     85 
     86   // Overridden from HomeCard:
     87   virtual void RegisterSearchProvider(
     88       app_list::SearchProvider* search_provider) OVERRIDE;
     89 
     90   // AcceleratorHandler:
     91   virtual bool IsCommandEnabled(int command_id) const OVERRIDE { return true; }
     92   virtual bool OnAcceleratorFired(int command_id,
     93                                   const ui::Accelerator& accelerator) OVERRIDE {
     94     DCHECK_EQ(COMMAND_SHOW_HOME_CARD, command_id);
     95     if (home_card_widget_->IsVisible())
     96       home_card_widget_->Hide();
     97     else
     98       home_card_widget_->Show();
     99     return true;
    100   }
    101 
    102   scoped_ptr<AppModelBuilder> model_builder_;
    103 
    104   views::Widget* home_card_widget_;
    105   AppListViewDelegate* view_delegate_;
    106 
    107   // Right now HomeCard allows only one search provider.
    108   // TODO(mukai): port app-list's SearchController and Mixer.
    109   scoped_ptr<app_list::SearchProvider> search_provider_;
    110 
    111   DISALLOW_COPY_AND_ASSIGN(HomeCardImpl);
    112 };
    113 
    114 HomeCardImpl::HomeCardImpl(AppModelBuilder* model_builder)
    115     : model_builder_(model_builder),
    116       home_card_widget_(NULL) {
    117   DCHECK(!instance);
    118   instance = this;
    119 }
    120 
    121 HomeCardImpl::~HomeCardImpl() {
    122   DCHECK(instance);
    123   home_card_widget_->CloseNow();
    124   view_delegate_ = NULL;
    125   instance = NULL;
    126 }
    127 
    128 void HomeCardImpl::RegisterSearchProvider(
    129     app_list::SearchProvider* search_provider) {
    130   DCHECK(!search_provider_);
    131   search_provider_.reset(search_provider);
    132   view_delegate_->RegisterSearchProvider(search_provider_.get());
    133 }
    134 
    135 void HomeCardImpl::Init() {
    136   InstallAccelerators();
    137 
    138   aura::Window* container =
    139       ScreenManager::Get()->CreateContainer("HomeCardContainer");
    140   container->SetLayoutManager(new HomeCardLayoutManager(container));
    141   wm::SetChildWindowVisibilityChangesAnimated(container);
    142 
    143   view_delegate_ = new AppListViewDelegate(model_builder_.get());
    144   if (search_provider_)
    145     view_delegate_->RegisterSearchProvider(search_provider_.get());
    146   app_list::AppListView* view = new app_list::AppListView(view_delegate_);
    147   view->InitAsBubbleAtFixedLocation(
    148       container,
    149       0 /* initial_apps_page */,
    150       gfx::Point(),
    151       views::BubbleBorder::FLOAT,
    152       true /* border_accepts_events */);
    153   home_card_widget_ = view->GetWidget();
    154   view->ShowWhenReady();
    155 }
    156 
    157 void HomeCardImpl::InstallAccelerators() {
    158   const AcceleratorData accelerator_data[] = {
    159       {TRIGGER_ON_PRESS, ui::VKEY_L, ui::EF_CONTROL_DOWN,
    160        COMMAND_SHOW_HOME_CARD, AF_NONE},
    161   };
    162   AcceleratorManager::Get()->RegisterAccelerators(
    163       accelerator_data, arraysize(accelerator_data), this);
    164 }
    165 
    166 }  // namespace
    167 
    168 // static
    169 HomeCard* HomeCard::Create(AppModelBuilder* model_builder) {
    170   (new HomeCardImpl(model_builder))->Init();
    171   DCHECK(instance);
    172   return instance;
    173 }
    174 
    175 // static
    176 void HomeCard::Shutdown() {
    177   DCHECK(instance);
    178   delete instance;
    179   instance = NULL;
    180 }
    181 
    182 // static
    183 HomeCard* HomeCard::Get() {
    184   DCHECK(instance);
    185   return instance;
    186 }
    187 
    188 }  // namespace athena
    189