From 30e0231395281e1275f0ebfd09b31605a2ecf4cd Mon Sep 17 00:00:00 2001 From: mukai Date: Tue, 26 Aug 2014 20:37:12 -0700 Subject: [PATCH] Refactor the home card structure and introduce animation. This CL includes the following refactorings: - minimized home is simply a layer instead of views - moves the mouse click handler of minimized home to home card impl - home card now has the same size of the screen. Changing state is now simply changing its position. Then schedule the animation between BOTTOM state and CENTERED state. BUG=398062 R=sadrul@chromium.org, oshima@chromium.org TEST=manually on remote desktop Review URL: https://codereview.chromium.org/478293004 Cr-Commit-Position: refs/heads/master@{#292092} --- athena/home/athena_start_page_view.cc | 177 +++++++++++++------- athena/home/athena_start_page_view.h | 36 ++++- athena/home/home_card_gesture_manager.cc | 1 + athena/home/home_card_impl.cc | 195 +++++++++++------------ athena/home/minimized_home.cc | 52 +++--- athena/home/minimized_home.h | 8 +- 6 files changed, 274 insertions(+), 195 deletions(-) diff --git a/athena/home/athena_start_page_view.cc b/athena/home/athena_start_page_view.cc index b5b8fb955645..1ab634626873 100644 --- a/athena/home/athena_start_page_view.cc +++ b/athena/home/athena_start_page_view.cc @@ -127,17 +127,13 @@ class SearchBoxContainer : public views::View { new views::RoundRectPainter(SK_ColorGRAY, kSearchBoxCornerRadius), gfx::Insets(kSearchBoxBorderWidth, kSearchBoxBorderWidth, kSearchBoxBorderWidth, kSearchBoxBorderWidth))); + SetLayoutManager(new views::FillLayout()); AddChildView(search_box_); } virtual ~SearchBoxContainer() {} private: // views::View: - virtual void Layout() OVERRIDE { - gfx::Rect search_box_bounds = GetContentsBounds(); - search_box_bounds.ClampToCenteredSize(GetPreferredSize()); - search_box_->SetBoundsRect(search_box_bounds); - } virtual gfx::Size GetPreferredSize() const OVERRIDE { return gfx::Size(kSearchBoxWidth, kSearchBoxHeight); } @@ -152,13 +148,30 @@ class SearchBoxContainer : public views::View { namespace athena { +// static +const char AthenaStartPageView::kViewClassName[] = "AthenaStartPageView"; + +AthenaStartPageView::LayoutData::LayoutData() + : logo_opacity(1.0f), + background_opacity(1.0f) { +} + AthenaStartPageView::AthenaStartPageView( app_list::AppListViewDelegate* view_delegate) : delegate_(view_delegate), + layout_state_(0.0f), weak_factory_(this) { + background_ = new views::View(); + background_->set_background( + views::Background::CreateSolidBackground(SK_ColorWHITE)); + background_->SetPaintToLayer(true); + background_->SetFillsBoundsOpaquely(false); + AddChildView(background_); + logo_ = view_delegate->CreateStartPageWebView( gfx::Size(kWebViewWidth, kWebViewHeight)); logo_->SetPaintToLayer(true); + logo_->SetSize(logo_->GetPreferredSize()); AddChildView(logo_); search_results_view_ = new app_list::SearchResultListView( @@ -183,13 +196,7 @@ AthenaStartPageView::AthenaStartPageView( view_delegate->GetModel()->top_level_item_list(); for (size_t i = 0; i < std::min(top_level->item_count(), kMaxIconNum); ++i) app_icon_container_->AddChildView(new AppIconButton(top_level->item_at(i))); - - search_box_view_ = new app_list::SearchBoxView(this, view_delegate); - search_box_view_->set_contents_view(this); - search_box_container_ = new SearchBoxContainer(search_box_view_); - search_box_container_->SetPaintToLayer(true); - search_box_container_->SetFillsBoundsOpaquely(false); - AddChildView(search_box_container_); + app_icon_container_->SetSize(app_icon_container_->GetPreferredSize()); control_icon_container_ = new views::View(); control_icon_container_->SetPaintToLayer(true); @@ -199,6 +206,15 @@ AthenaStartPageView::AthenaStartPageView( views::BoxLayout::kHorizontal, 0, 0, kIconMargin)); for (size_t i = 0; i < kMaxIconNum; ++i) control_icon_container_->AddChildView(new PlaceHolderButton()); + control_icon_container_->SetSize(control_icon_container_->GetPreferredSize()); + + search_box_view_ = new app_list::SearchBoxView(this, view_delegate); + search_box_view_->set_contents_view(this); + search_box_container_ = new SearchBoxContainer(search_box_view_); + search_box_container_->SetPaintToLayer(true); + search_box_container_->SetFillsBoundsOpaquely(false); + search_box_container_->SetSize(search_box_container_->GetPreferredSize()); + AddChildView(search_box_container_); } AthenaStartPageView::~AthenaStartPageView() {} @@ -207,6 +223,69 @@ void AthenaStartPageView::RequestFocusOnSearchBox() { search_box_view_->search_box()->RequestFocus(); } +void AthenaStartPageView::SetLayoutState(float layout_state) { + layout_state_ = layout_state; + Layout(); +} + +void AthenaStartPageView::SetLayoutStateWithAnimation(float layout_state) { + ui::ScopedLayerAnimationSettings logo(logo_->layer()->GetAnimator()); + ui::ScopedLayerAnimationSettings search_box( + search_box_container_->layer()->GetAnimator()); + ui::ScopedLayerAnimationSettings icons( + app_icon_container_->layer()->GetAnimator()); + ui::ScopedLayerAnimationSettings controls( + control_icon_container_->layer()->GetAnimator()); + + logo.SetTweenType(gfx::Tween::EASE_IN_OUT); + search_box.SetTweenType(gfx::Tween::EASE_IN_OUT); + icons.SetTweenType(gfx::Tween::EASE_IN_OUT); + controls.SetTweenType(gfx::Tween::EASE_IN_OUT); + + SetLayoutState(layout_state); +} + +AthenaStartPageView::LayoutData AthenaStartPageView::CreateBottomBounds( + int width) { + LayoutData state; + state.icons.set_size(app_icon_container_->size()); + state.icons.set_x(kIconMargin); + state.icons.set_y(kIconMargin); + + state.controls.set_size(control_icon_container_->size()); + state.controls.set_x(width - kIconMargin - state.controls.width()); + state.controls.set_y(kIconMargin); + + state.search_box.set_size(search_box_container_->size()); + state.search_box.set_x((width - state.search_box.width()) / 2); + state.search_box.set_y((kHomeCardHeight - state.search_box.height()) / 2); + + state.logo_opacity = 0.0f; + state.background_opacity = 0.9f; + return state; +} + +AthenaStartPageView::LayoutData AthenaStartPageView::CreateCenteredBounds( + int width) { + LayoutData state; + + state.search_box.set_size(search_box_container_->size()); + state.search_box.set_x((width - state.search_box.width()) / 2); + state.search_box.set_y(logo_->bounds().bottom() + kInstantContainerSpacing); + + state.icons.set_size(app_icon_container_->size()); + state.icons.set_x(width / 2 - state.icons.width() - kIconMargin / 2); + state.icons.set_y(state.search_box.bottom() + kInstantContainerSpacing); + + state.controls.set_size(control_icon_container_->size()); + state.controls.set_x(width / 2 + kIconMargin / 2 + kIconMargin % 2); + state.controls.set_y(state.icons.y()); + + state.logo_opacity = 1.0f; + state.background_opacity = 1.0f; + return state; +} + void AthenaStartPageView::LayoutSearchResults(bool should_show_search_results) { if (should_show_search_results == search_results_view_->layer()->GetTargetVisibility()) { @@ -276,57 +355,31 @@ void AthenaStartPageView::OnSearchResultLayoutAnimationCompleted( } void AthenaStartPageView::Layout() { - gfx::Rect bounds = GetContentsBounds(); search_results_view_->SetVisible(false); - - if (bounds.height() <= kHomeCardHeight) { - logo_->SetVisible(false); - gfx::Rect icon_bounds(app_icon_container_->GetPreferredSize()); - icon_bounds.set_x(bounds.x() + kIconMargin); - icon_bounds.set_y(bounds.x() + kIconMargin); - app_icon_container_->SetBoundsRect(icon_bounds); - - gfx::Rect control_bounds(control_icon_container_->GetPreferredSize()); - control_bounds.set_x( - bounds.right() - kIconMargin - control_bounds.width()); - control_bounds.set_y(bounds.y() + kIconMargin); - control_icon_container_->SetBoundsRect(control_bounds); - - search_box_container_->SetBounds( - icon_bounds.right(), bounds.y(), - control_bounds.x() - icon_bounds.right(), kHomeCardHeight); - - set_background(views::Background::CreateSolidBackground( - 255, 255, 255, 255 * 0.9)); - } else { - // TODO(mukai): set the intermediate state. - logo_->SetVisible(true); - logo_->layer()->SetOpacity(1.0f); - set_background(views::Background::CreateSolidBackground(SK_ColorWHITE)); - gfx::Rect logo_bounds(bounds.x() + bounds.width() / 2 - kWebViewWidth / 2, - bounds.y() + kTopMargin, - kWebViewWidth, - kWebViewHeight); - logo_->SetBoundsRect(logo_bounds); - - gfx::Rect search_box_bounds(search_box_container_->GetPreferredSize()); - search_box_bounds.set_x( - bounds.x() + bounds.width() / 2 - search_box_bounds.width() / 2); - search_box_bounds.set_y(logo_bounds.bottom() + kInstantContainerSpacing); - search_box_container_->SetBoundsRect(search_box_bounds); - - gfx::Rect icon_bounds(app_icon_container_->GetPreferredSize()); - icon_bounds.set_x(bounds.x() + bounds.width() / 2 - - icon_bounds.width() - kIconMargin / 2); - icon_bounds.set_y(search_box_bounds.bottom() + kInstantContainerSpacing); - app_icon_container_->SetBoundsRect(icon_bounds); - - gfx::Rect control_bounds(control_icon_container_->GetPreferredSize()); - control_bounds.set_x(bounds.x() + bounds.width() / 2 + - kIconMargin / 2 + kIconMargin % 2); - control_bounds.set_y(icon_bounds.y()); - control_icon_container_->SetBoundsRect(control_bounds); - } + gfx::Rect logo_bounds(x() + width() / 2 - kWebViewWidth / 2, y() + kTopMargin, + kWebViewWidth, kWebViewHeight); + logo_->SetBoundsRect(logo_bounds); + + LayoutData bottom_bounds = CreateBottomBounds(width()); + LayoutData centered_bounds = CreateCenteredBounds(width()); + + logo_->layer()->SetOpacity(gfx::Tween::FloatValueBetween( + gfx::Tween::CalculateValue(gfx::Tween::EASE_IN_2, layout_state_), + bottom_bounds.logo_opacity, centered_bounds.logo_opacity)); + logo_->SetVisible(logo_->layer()->GetTargetOpacity() != 0.0f); + + app_icon_container_->SetBoundsRect(gfx::Tween::RectValueBetween( + layout_state_, bottom_bounds.icons, centered_bounds.icons)); + control_icon_container_->SetBoundsRect(gfx::Tween::RectValueBetween( + layout_state_, bottom_bounds.controls, centered_bounds.controls)); + search_box_container_->SetBoundsRect(gfx::Tween::RectValueBetween( + layout_state_, bottom_bounds.search_box, centered_bounds.search_box)); + + background_->SetBoundsRect(bounds()); + background_->layer()->SetOpacity(gfx::Tween::FloatValueBetween( + layout_state_, + bottom_bounds.background_opacity, + centered_bounds.background_opacity)); } bool AthenaStartPageView::OnKeyPressed(const ui::KeyEvent& key_event) { diff --git a/athena/home/athena_start_page_view.h b/athena/home/athena_start_page_view.h index e8a78936a1d0..09c30d7667a3 100644 --- a/athena/home/athena_start_page_view.h +++ b/athena/home/athena_start_page_view.h @@ -17,8 +17,6 @@ class SearchResultListView; namespace athena { -// It will replace app_list::StartPageView in Athena UI in the future. -// Right now it's simply used for VISIBLE_BOTTOM state. class AthenaStartPageView : public views::View, public app_list::SearchBoxViewDelegate { public: @@ -28,7 +26,33 @@ class AthenaStartPageView : public views::View, // Requests the focus on the search box in the start page view. void RequestFocusOnSearchBox(); + // Updates the layout state. See the comment of |layout_state_| field. + void SetLayoutState(float layout_state); + + // Updates the layout state and move the subviews to the target location with + // animation. + void SetLayoutStateWithAnimation(float layout_state); + private: + static const char kViewClassName[]; + + // A struct which bundles the layout data of subviews. + struct LayoutData { + gfx::Rect search_box; + gfx::Rect icons; + gfx::Rect controls; + float logo_opacity; + float background_opacity; + + LayoutData(); + }; + + // Returns the bounds for |VISIBLE_BOTTOM|. + LayoutData CreateBottomBounds(int width); + + // Returns the bounds for |VISIBLE_CENTERED|. + LayoutData CreateCenteredBounds(int width); + // Schedules the animation for the layout the search box and the search // results. void LayoutSearchResults(bool should_show_search_results); @@ -55,9 +79,17 @@ class AthenaStartPageView : public views::View, app_list::SearchBoxView* search_box_view_; app_list::SearchResultListView* search_results_view_; + // Do not use views::Background but a views::View with ui::Layer for gradient + // background opacity update and animation. + views::View* background_; + // The expected height of |search_results_view_| int search_results_height_; + // The state to specify how each of the subviews should be laid out, in the + // range of [0, 1]. 0 means fully BOTTOM state, and 1 is fully CENTERED state. + float layout_state_; + base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(AthenaStartPageView); diff --git a/athena/home/home_card_gesture_manager.cc b/athena/home/home_card_gesture_manager.cc index 755c29cfd791..15a6e3455630 100644 --- a/athena/home/home_card_gesture_manager.cc +++ b/athena/home/home_card_gesture_manager.cc @@ -99,6 +99,7 @@ void HomeCardGestureManager::UpdateScrollState(const ui::GestureEvent& event) { // The finger is between two states. float progress = (last_estimated_height_ - smaller_height) / (bigger_height - smaller_height); + progress = std::min(1.0f, std::max(0.0f, progress)); if (last_state_ == state) { if (event.details().scroll_y() > 0) { diff --git a/athena/home/home_card_impl.cc b/athena/home/home_card_impl.cc index 20783258056c..a6d23ccc5c3b 100644 --- a/athena/home/home_card_impl.cc +++ b/athena/home/home_card_impl.cc @@ -19,22 +19,19 @@ #include "athena/screen/public/screen_manager.h" #include "athena/wm/public/window_manager.h" #include "athena/wm/public/window_manager_observer.h" -#include "base/bind.h" -#include "base/memory/weak_ptr.h" #include "ui/app_list/search_provider.h" #include "ui/app_list/views/app_list_main_view.h" #include "ui/app_list/views/contents_view.h" #include "ui/aura/layout_manager.h" #include "ui/aura/window.h" -#include "ui/compositor/closure_animation_observer.h" +#include "ui/compositor/layer.h" +#include "ui/compositor/layer_owner.h" #include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/views/background.h" -#include "ui/views/layout/box_layout.h" +#include "ui/views/layout/fill_layout.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" #include "ui/wm/core/shadow_types.h" #include "ui/wm/core/visibility_controller.h" -#include "ui/wm/core/window_animations.h" #include "ui/wm/public/activation_change_observer.h" #include "ui/wm/public/activation_client.h" @@ -52,16 +49,18 @@ gfx::Rect GetBoundsForState(const gfx::Rect& screen_bounds, case HomeCard::VISIBLE_CENTERED: return screen_bounds; + // Do not change the home_card's size, only changes the top position + // instead, because size change causes unnecessary re-layouts. case HomeCard::VISIBLE_BOTTOM: return gfx::Rect(0, screen_bounds.bottom() - kHomeCardHeight, screen_bounds.width(), - kHomeCardHeight); + screen_bounds.height()); case HomeCard::VISIBLE_MINIMIZED: return gfx::Rect(0, screen_bounds.bottom() - kHomeCardMinimizedHeight, screen_bounds.width(), - kHomeCardMinimizedHeight); + screen_bounds.height()); } NOTREACHED(); @@ -72,33 +71,51 @@ gfx::Rect GetBoundsForState(const gfx::Rect& screen_bounds, // vertically. class HomeCardLayoutManager : public aura::LayoutManager { public: - explicit HomeCardLayoutManager() - : home_card_(NULL) {} + HomeCardLayoutManager() + : home_card_(NULL), + minimized_layer_(NULL) {} virtual ~HomeCardLayoutManager() {} - void Layout() { + void Layout(bool animate) { // |home_card| could be detached from the root window (e.g. when it is being // destroyed). if (!home_card_ || !home_card_->IsVisible() || !home_card_->GetRootWindow()) return; - { - ui::ScopedLayerAnimationSettings settings( - home_card_->layer()->GetAnimator()); - settings.SetTweenType(gfx::Tween::EASE_IN_OUT); - SetChildBoundsDirect(home_card_, GetBoundsForState( - home_card_->GetRootWindow()->bounds(), HomeCard::Get()->GetState())); + scoped_ptr settings; + if (animate) { + settings.reset(new ui::ScopedLayerAnimationSettings( + home_card_->layer()->GetAnimator())); + settings->SetTweenType(gfx::Tween::EASE_IN_OUT); } + SetChildBoundsDirect(home_card_, GetBoundsForState( + home_card_->GetRootWindow()->bounds(), HomeCard::Get()->GetState())); + } + + void SetMinimizedLayer(ui::Layer* minimized_layer) { + minimized_layer_ = minimized_layer; + UpdateMinimizedHomeBounds(); } private: + void UpdateMinimizedHomeBounds() { + gfx::Rect minimized_bounds = minimized_layer_->parent()->bounds(); + minimized_bounds.set_y( + minimized_bounds.bottom() - kHomeCardMinimizedHeight); + minimized_bounds.set_height(kHomeCardMinimizedHeight); + minimized_layer_->SetBounds(minimized_bounds); + } + // aura::LayoutManager: - virtual void OnWindowResized() OVERRIDE { Layout(); } + virtual void OnWindowResized() OVERRIDE { + Layout(false); + UpdateMinimizedHomeBounds(); + } virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE { if (!home_card_) { home_card_ = child; - Layout(); + Layout(false); } } virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE { @@ -106,11 +123,11 @@ class HomeCardLayoutManager : public aura::LayoutManager { home_card_ = NULL; } virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE { - Layout(); + Layout(false); } virtual void OnChildWindowVisibilityChanged(aura::Window* child, bool visible) OVERRIDE { - Layout(); + Layout(false); } virtual void SetChildBounds(aura::Window* child, const gfx::Rect& requested_bounds) OVERRIDE { @@ -118,6 +135,7 @@ class HomeCardLayoutManager : public aura::LayoutManager { } aura::Window* home_card_; + ui::Layer* minimized_layer_; DISALLOW_COPY_AND_ASSIGN(HomeCardLayoutManager); }; @@ -128,47 +146,28 @@ class HomeCardView : public views::WidgetDelegateView { HomeCardView(app_list::AppListViewDelegate* view_delegate, aura::Window* container, HomeCardGestureManager::Delegate* gesture_delegate) - : gesture_delegate_(gesture_delegate), - weak_factory_(this) { + : gesture_delegate_(gesture_delegate) { + SetLayoutManager(new views::FillLayout()); // Ideally AppListMainView should be used here and have AthenaStartPageView // as its child view, so that custom pages and apps grid are available in // the home card. // TODO(mukai): make it so after the detailed UI has been fixed. main_view_ = new AthenaStartPageView(view_delegate); AddChildView(main_view_); - - minimized_view_ = CreateMinimizedHome(); - minimized_view_->SetPaintToLayer(true); - AddChildView(minimized_view_); } void SetStateProgress(HomeCard::State from_state, HomeCard::State to_state, float progress) { - if (from_state == HomeCard::VISIBLE_BOTTOM && - to_state == HomeCard::VISIBLE_MINIMIZED) { - SetStateProgress(to_state, from_state, 1.0 - progress); - return; - } - - // View from minimized to bottom. - if (from_state == HomeCard::VISIBLE_MINIMIZED && - to_state == HomeCard::VISIBLE_BOTTOM) { - main_view_->SetVisible(true); - minimized_view_->SetVisible(true); - minimized_view_->layer()->SetOpacity(1.0f - progress); - return; - } - - SetState(to_state); + if (from_state == HomeCard::VISIBLE_CENTERED) + main_view_->SetLayoutState(1.0f - progress); + else if (to_state == HomeCard::VISIBLE_CENTERED) + main_view_->SetLayoutState(progress); + else + SetState(to_state); } void SetState(HomeCard::State state) { - main_view_->SetVisible(state == HomeCard::VISIBLE_BOTTOM || - state == HomeCard::VISIBLE_CENTERED); - minimized_view_->SetVisible(state == HomeCard::VISIBLE_MINIMIZED); - if (minimized_view_->visible()) - minimized_view_->layer()->SetOpacity(1.0f); if (state == HomeCard::VISIBLE_CENTERED) main_view_->RequestFocusOnSearchBox(); else @@ -177,31 +176,16 @@ class HomeCardView : public views::WidgetDelegateView { state == HomeCard::VISIBLE_MINIMIZED ? wm::SHADOW_TYPE_NONE : wm::SHADOW_TYPE_RECTANGULAR); + main_view_->SetLayoutState( + (state == HomeCard::VISIBLE_CENTERED) ? 1.0f : 0.0f); } - void SetStateWithAnimation(HomeCard::State from_state, - HomeCard::State to_state) { - if ((from_state == HomeCard::VISIBLE_MINIMIZED && - to_state == HomeCard::VISIBLE_BOTTOM) || - (from_state == HomeCard::VISIBLE_BOTTOM && - to_state == HomeCard::VISIBLE_MINIMIZED)) { - minimized_view_->SetVisible(true); - main_view_->SetVisible(true); - { - ui::ScopedLayerAnimationSettings settings( - minimized_view_->layer()->GetAnimator()); - settings.SetTweenType(gfx::Tween::EASE_IN_OUT); - settings.AddObserver(new ui::ClosureAnimationObserver( - base::Bind(&HomeCardView::SetState, - weak_factory_.GetWeakPtr(), - to_state))); - minimized_view_->layer()->SetOpacity( - (to_state == HomeCard::VISIBLE_MINIMIZED) ? 1.0f : 0.0f); - } - } else { - // TODO(mukai): Take care of other transition. - SetState(to_state); - } + void SetStateWithAnimation(HomeCard::State state) { + if (state == HomeCard::VISIBLE_MINIMIZED) + return; + + main_view_->SetLayoutStateWithAnimation( + (state == HomeCard::VISIBLE_CENTERED) ? 1.0f : 0.0f); } void ClearGesture() { @@ -209,22 +193,6 @@ class HomeCardView : public views::WidgetDelegateView { } // views::View: - virtual void Layout() OVERRIDE { - for (int i = 0; i < child_count(); ++i) { - views::View* child = child_at(i); - if (child->visible()) { - if (child == minimized_view_) { - gfx::Rect minimized_bounds = bounds(); - minimized_bounds.set_y( - minimized_bounds.bottom() - kHomeCardMinimizedHeight); - minimized_bounds.set_height(kHomeCardMinimizedHeight); - child->SetBoundsRect(minimized_bounds); - } else { - child->SetBoundsRect(bounds()); - } - } - } - } virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { if (!gesture_manager_ && event->type() == ui::ET_GESTURE_SCROLL_BEGIN) { @@ -236,6 +204,14 @@ class HomeCardView : public views::WidgetDelegateView { if (gesture_manager_) gesture_manager_->ProcessGestureEvent(event); } + virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { + if (HomeCard::Get()->GetState() == HomeCard::VISIBLE_MINIMIZED && + event.IsLeftMouseButton() && event.GetClickCount() == 1) { + athena::WindowManager::GetInstance()->ToggleOverview(); + return true; + } + return false; + } private: // views::WidgetDelegate: @@ -244,10 +220,8 @@ class HomeCardView : public views::WidgetDelegateView { } AthenaStartPageView* main_view_; - views::View* minimized_view_; scoped_ptr gesture_manager_; HomeCardGestureManager::Delegate* gesture_delegate_; - base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(HomeCardView); }; @@ -268,6 +242,7 @@ class HomeCardImpl : public HomeCard, COMMAND_SHOW_HOME_CARD, }; void InstallAccelerators(); + void UpdateMinimizedHomeBounds(); // Overridden from HomeCard: virtual void SetState(State state) OVERRIDE; @@ -308,6 +283,7 @@ class HomeCardImpl : public HomeCard, scoped_ptr view_delegate_; HomeCardLayoutManager* layout_manager_; aura::client::ActivationClient* activation_client_; // Not owned + scoped_ptr minimized_home_; // Right now HomeCard allows only one search provider. // TODO(mukai): port app-list's SearchController and Mixer. @@ -366,6 +342,11 @@ void HomeCardImpl::Init() { widget_params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; home_card_widget_->Init(widget_params); + minimized_home_ = CreateMinimizedHome(); + container->layer()->Add(minimized_home_->layer()); + container->layer()->StackAtTop(minimized_home_->layer()); + layout_manager_->SetMinimizedLayer(minimized_home_->layer()); + SetState(VISIBLE_MINIMIZED); home_card_view_->Layout(); @@ -374,11 +355,8 @@ void HomeCardImpl::Init() { if (activation_client_) activation_client_->AddObserver(this); - int work_area_bottom_inset = - GetBoundsForState(home_card_widget_->GetNativeWindow()->bounds(), - HomeCard::VISIBLE_MINIMIZED).height(); AthenaEnv::Get()->SetDisplayWorkAreaInsets( - gfx::Insets(0, 0, work_area_bottom_inset, 0)); + gfx::Insets(0, 0, kHomeCardMinimizedHeight, 0)); } void HomeCardImpl::InstallAccelerators() { @@ -399,6 +377,18 @@ void HomeCardImpl::SetState(HomeCard::State state) { HomeCard::State old_state = state_; state_ = state; original_state_ = state; + + if (old_state == VISIBLE_MINIMIZED || + state_ == VISIBLE_MINIMIZED) { + minimized_home_->layer()->SetVisible(true); + { + ui::ScopedLayerAnimationSettings settings( + minimized_home_->layer()->GetAnimator()); + minimized_home_->layer()->SetVisible(state_ == VISIBLE_MINIMIZED); + minimized_home_->layer()->SetOpacity( + state_ == VISIBLE_MINIMIZED ? 1.0f : 0.0f); + } + } if (state_ == HIDDEN) { home_card_widget_->Hide(); } else { @@ -406,8 +396,8 @@ void HomeCardImpl::SetState(HomeCard::State state) { home_card_widget_->Show(); else home_card_widget_->ShowInactive(); - home_card_view_->SetStateWithAnimation(old_state, state); - layout_manager_->Layout(); + home_card_view_->SetStateWithAnimation(state); + layout_manager_->Layout(true); } } @@ -453,17 +443,20 @@ void HomeCardImpl::OnGestureEnded(State final_state) { SetState(final_state); WindowManager::GetInstance()->ToggleOverview(); } else { - HomeCard::State old_state = state_; state_ = final_state; - home_card_view_->SetStateWithAnimation(old_state, final_state); - layout_manager_->Layout(); + home_card_view_->SetStateWithAnimation(state_); + layout_manager_->Layout(true); } } void HomeCardImpl::OnGestureProgressed( State from_state, State to_state, float progress) { - home_card_view_->SetStateProgress(from_state, to_state, progress); - + if (from_state == VISIBLE_MINIMIZED || to_state == VISIBLE_MINIMIZED) { + minimized_home_->layer()->SetVisible(true); + float opacity = + (from_state == VISIBLE_MINIMIZED) ? 1.0f - progress : progress; + minimized_home_->layer()->SetOpacity(opacity); + } gfx::Rect screen_bounds = home_card_widget_->GetNativeWindow()->GetRootWindow()->bounds(); home_card_widget_->SetBounds(gfx::Tween::RectValueBetween( @@ -471,6 +464,8 @@ void HomeCardImpl::OnGestureProgressed( GetBoundsForState(screen_bounds, from_state), GetBoundsForState(screen_bounds, to_state))); + home_card_view_->SetStateProgress(from_state, to_state, progress); + // TODO(mukai): signals the update to the window manager so that it shows the // intermediate visual state of overview mode. } diff --git a/athena/home/minimized_home.cc b/athena/home/minimized_home.cc index 3ffd65b1cf84..2b0bafb8d663 100644 --- a/athena/home/minimized_home.cc +++ b/athena/home/minimized_home.cc @@ -4,24 +4,30 @@ #include "athena/home/minimized_home.h" -#include "athena/wm/public/window_manager.h" +#include "ui/compositor/layer.h" +#include "ui/compositor/layer_owner.h" #include "ui/gfx/canvas.h" -#include "ui/views/background.h" -#include "ui/views/view.h" namespace { const int kDragHandleWidth = 112; const int kDragHandleHeight = 2; +const char kMinimizedHomeLayerName[] = "MinimizedHome"; -class MinimizedHomeBackground : public views::Background { +class MinimizedHomePainter : public ui::LayerDelegate, + public ui::LayerOwner { public: - MinimizedHomeBackground() {} - virtual ~MinimizedHomeBackground() {} + explicit MinimizedHomePainter(ui::Layer* layer) { + layer->set_name(kMinimizedHomeLayerName); + layer->set_delegate(this); + SetLayer(layer); + } + virtual ~MinimizedHomePainter() {} private: - virtual void Paint(gfx::Canvas* canvas, views::View* view) const OVERRIDE { - gfx::Rect bounds = view->GetLocalBounds(); + // ui::LayerDelegate: + virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE { + gfx::Rect bounds(layer()->GetTargetBounds().size()); canvas->FillRect(bounds, SK_ColorBLACK); canvas->FillRect(gfx::Rect((bounds.width() - kDragHandleWidth) / 2, bounds.bottom() - kDragHandleHeight, @@ -30,37 +36,27 @@ class MinimizedHomeBackground : public views::Background { SK_ColorWHITE); } - DISALLOW_COPY_AND_ASSIGN(MinimizedHomeBackground); -}; + virtual void OnDelegatedFrameDamage( + const gfx::Rect& damage_rect_in_dip) OVERRIDE { + } -// This View shows an instance of SmallBarView in the middle, and reacts to -// mouse and touch-gesture events. -class MinimizedHomeView : public views::View { - public: - MinimizedHomeView() { - set_background(new MinimizedHomeBackground()); + virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE { } - virtual ~MinimizedHomeView() {} - private: - // views::View: - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { - if (event.IsLeftMouseButton() && event.GetClickCount() == 1) { - athena::WindowManager::GetInstance()->ToggleOverview(); - return true; - } - return false; + virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE { + return base::Closure(); } - DISALLOW_COPY_AND_ASSIGN(MinimizedHomeView); + DISALLOW_COPY_AND_ASSIGN(MinimizedHomePainter); }; } // namespace namespace athena { -views::View* CreateMinimizedHome() { - return new MinimizedHomeView(); +scoped_ptr CreateMinimizedHome() { + return scoped_ptr( + new MinimizedHomePainter(new ui::Layer(ui::LAYER_TEXTURED))); } } // namespace athena diff --git a/athena/home/minimized_home.h b/athena/home/minimized_home.h index 4427f45732d4..8763a8f16d4b 100644 --- a/athena/home/minimized_home.h +++ b/athena/home/minimized_home.h @@ -5,13 +5,15 @@ #ifndef ATHENA_HOME_MINIMIZED_HOME_H_ #define ATHENA_HOME_MINIMIZED_HOME_H_ -namespace views { -class View; +#include "base/memory/scoped_ptr.h" + +namespace ui { +class LayerOwner; } namespace athena { -views::View* CreateMinimizedHome(); +scoped_ptr CreateMinimizedHome(); } // namespace athena