Commit 30e02313 authored by mukai's avatar mukai Committed by Commit bot

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}
parent bf20fc68
......@@ -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) {
......
......@@ -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<AthenaStartPageView> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(AthenaStartPageView);
......
......@@ -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) {
......
This diff is collapsed.
......@@ -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<ui::LayerOwner> CreateMinimizedHome() {
return scoped_ptr<ui::LayerOwner>(
new MinimizedHomePainter(new ui::Layer(ui::LAYER_TEXTURED)));
}
} // namespace athena
......@@ -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<ui::LayerOwner> CreateMinimizedHome();
} // namespace athena
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment