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