Commit f20513c8 authored by Alan Cutter's avatar Alan Cutter Committed by Commit Bot

Add URL origin opening animation to hosted app title bar

This CL implements a title bar animation for hosted apps on chromeOS
that shows the URL's origin for a few seconds when the window opens.
This CL omits the menu button highlight animation as that will be
implemented in a follow up CL.

See bug for screencasts.

Bug: 809794
Change-Id: Ied16c5720722f994fa73cafd15c2f42e3d671e50
Reviewed-on: https://chromium-review.googlesource.com/942722
Commit-Queue: Alan Cutter <alancutter@chromium.org>
Reviewed-by: default avatarTrent Apted <tapted@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#542763}
parent 8fc53474
...@@ -205,6 +205,8 @@ component("ash") { ...@@ -205,6 +205,8 @@ component("ash") {
"frame/frame_border_hit_test.cc", "frame/frame_border_hit_test.cc",
"frame/frame_border_hit_test.h", "frame/frame_border_hit_test.h",
"frame/frame_header.h", "frame/frame_header.h",
"frame/frame_header_origin_text.cc",
"frame/frame_header_origin_text.h",
"frame/frame_header_util.cc", "frame/frame_header_util.cc",
"frame/frame_header_util.h", "frame/frame_header_util.h",
"frame/header_view.cc", "frame/header_view.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/frame/frame_header_origin_text.h"
#include "base/i18n/rtl.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/fill_layout.h"
namespace ash {
namespace {
constexpr base::TimeDelta kOriginSlideInDuration =
base::TimeDelta::FromMilliseconds(800);
constexpr base::TimeDelta kOriginPauseDuration =
base::TimeDelta::FromMilliseconds(2500);
constexpr base::TimeDelta kOriginSlideOutDuration =
base::TimeDelta::FromMilliseconds(500);
constexpr gfx::Tween::Type kTweenType = gfx::Tween::FAST_OUT_SLOW_IN_2;
} // namespace
FrameHeaderOriginText::FrameHeaderOriginText(const base::string16& origin,
SkColor active_color,
SkColor inactive_color,
SkColor active_background_color,
SkColor inactive_background_color)
: active_color_(active_color),
inactive_color_(inactive_color),
active_background_color_(active_background_color),
inactive_background_color_(inactive_background_color) {
SetLayoutManager(std::make_unique<views::FillLayout>());
label_ = std::make_unique<views::Label>(origin).release();
label_->SetElideBehavior(gfx::ELIDE_HEAD);
label_->SetSubpixelRenderingEnabled(false);
label_->SetEnabledColor(active_color);
label_->SetBackgroundColor(active_background_color);
label_->SetPaintToLayer();
label_->layer()->SetFillsBoundsOpaquely(false);
label_->layer()->SetOpacity(0);
AddChildView(label_);
// Clip child views to this view.
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
layer()->SetMasksToBounds(true);
}
FrameHeaderOriginText::~FrameHeaderOriginText() = default;
void FrameHeaderOriginText::SetPaintAsActive(bool active) {
label_->SetEnabledColor(active ? active_color_ : inactive_color_);
label_->SetBackgroundColor(active ? active_background_color_
: inactive_background_color_);
}
void FrameHeaderOriginText::StartSlideAnimation() {
ui::Layer* label_layer = label_->layer();
// Current state will become the first animation keyframe.
DCHECK_EQ(label_layer->opacity(), 0);
gfx::Transform out_of_frame;
out_of_frame.Translate(
label_->bounds().width() * (base::i18n::IsRTL() ? -1 : 1), 0);
label_layer->SetTransform(out_of_frame);
auto opacity_sequence = std::make_unique<ui::LayerAnimationSequence>();
auto transform_sequence = std::make_unique<ui::LayerAnimationSequence>();
// Slide in.
auto opacity_keyframe = ui::LayerAnimationElement::CreateOpacityElement(
1, kOriginSlideInDuration);
opacity_keyframe->set_tween_type(kTweenType);
opacity_sequence->AddElement(std::move(opacity_keyframe));
auto transform_keyframe = ui::LayerAnimationElement::CreateTransformElement(
gfx::Transform(), kOriginSlideInDuration);
transform_keyframe->set_tween_type(kTweenType);
transform_sequence->AddElement(std::move(transform_keyframe));
// Pause.
opacity_sequence->AddElement(
ui::LayerAnimationElement::CreatePauseElement(0, kOriginPauseDuration));
transform_sequence->AddElement(
ui::LayerAnimationElement::CreatePauseElement(0, kOriginPauseDuration));
// Slide out.
opacity_keyframe = ui::LayerAnimationElement::CreateOpacityElement(
0, kOriginSlideOutDuration);
opacity_keyframe->set_tween_type(kTweenType);
opacity_sequence->AddElement(std::move(opacity_keyframe));
transform_keyframe = ui::LayerAnimationElement::CreateTransformElement(
out_of_frame, kOriginSlideOutDuration);
transform_keyframe->set_tween_type(kTweenType);
transform_sequence->AddElement(std::move(transform_keyframe));
label_layer->GetAnimator()->StartTogether(
{opacity_sequence.release(), transform_sequence.release()});
}
base::TimeDelta FrameHeaderOriginText::AnimationDuration() {
return kOriginSlideInDuration + kOriginPauseDuration +
kOriginSlideOutDuration;
}
} // namespace ash
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_
#define ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_
#include "ash/ash_export.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/views/view.h"
namespace views {
class Label;
}
namespace ash {
// A URL's origin text with a slide in/out animation.
class ASH_EXPORT FrameHeaderOriginText : public views::View {
public:
FrameHeaderOriginText(const base::string16& origin,
SkColor active_color,
SkColor inactive_color,
SkColor active_background_color,
SkColor inactive_background_color);
~FrameHeaderOriginText() override;
// Sets whether to paint the text with the active/inactive color.
void SetPaintAsActive(bool active);
// Slides the text in and out.
void StartSlideAnimation();
// How long the slide in+out animation takes.
static base::TimeDelta AnimationDuration();
private:
// Owned by the views hierarchy.
views::Label* label_ = nullptr;
const SkColor active_color_;
const SkColor inactive_color_;
const SkColor active_background_color_;
const SkColor inactive_background_color_;
DISALLOW_COPY_AND_ASSIGN(FrameHeaderOriginText);
};
} // namespace ash
#endif // ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "ui/gfx/favicon_size.h" #include "ui/gfx/favicon_size.h"
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -200,10 +199,8 @@ std::string HostedAppBrowserController::GetAppShortName() const { ...@@ -200,10 +199,8 @@ std::string HostedAppBrowserController::GetAppShortName() const {
return GetExtension()->short_name(); return GetExtension()->short_name();
} }
std::string HostedAppBrowserController::GetDomainAndRegistry() const { url::Origin HostedAppBrowserController::GetUrlOrigin() const {
return net::registry_controlled_domains::GetDomainAndRegistry( return url::Origin::Create(AppLaunchInfo::GetLaunchWebURL(GetExtension()));
AppLaunchInfo::GetLaunchWebURL(GetExtension()),
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
} }
void HostedAppBrowserController::OnEngagementEvent( void HostedAppBrowserController::OnEngagementEvent(
......
...@@ -63,8 +63,8 @@ class HostedAppBrowserController : public SiteEngagementObserver { ...@@ -63,8 +63,8 @@ class HostedAppBrowserController : public SiteEngagementObserver {
// Gets the short name of the app. // Gets the short name of the app.
std::string GetAppShortName() const; std::string GetAppShortName() const;
// Gets the domain and registry of the app start url (e.g example.com.au). // Gets the origin of the app start url (e.g www.example.com.au).
std::string GetDomainAndRegistry() const; url::Origin GetUrlOrigin() const;
// Gets the extension for this controller. // Gets the extension for this controller.
const Extension* GetExtension() const; const Extension* GetExtension() const;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "ash/frame/caption_buttons/frame_caption_button_container_view.h" #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
#include "ash/frame/default_frame_header.h" #include "ash/frame/default_frame_header.h"
#include "ash/frame/frame_border_hit_test.h" #include "ash/frame/frame_border_hit_test.h"
#include "ash/frame/frame_header_origin_text.h"
#include "ash/frame/frame_header_util.h" #include "ash/frame/frame_header_util.h"
#include "ash/public/cpp/app_types.h" #include "ash/public/cpp/app_types.h"
#include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/ash_switches.h"
...@@ -22,6 +23,10 @@ ...@@ -22,6 +23,10 @@
#include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/window_util.h" #include "ash/wm/window_util.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "chrome/app/chrome_command_ids.h" #include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
...@@ -67,6 +72,10 @@ constexpr int kTabShadowHeight = 4; ...@@ -67,6 +72,10 @@ constexpr int kTabShadowHeight = 4;
constexpr SkColor kMdWebUIFrameColor = constexpr SkColor kMdWebUIFrameColor =
SkColorSetARGBMacro(0xff, 0x25, 0x4f, 0xae); SkColorSetARGBMacro(0xff, 0x25, 0x4f, 0xae);
// How long to wait before starting the titlebar animation.
constexpr base::TimeDelta kTitlebarAnimationDelay =
base::TimeDelta::FromMilliseconds(750);
bool IsV1AppBackButtonEnabled() { bool IsV1AppBackButtonEnabled() {
return base::CommandLine::ForCurrentProcess()->HasSwitch( return base::CommandLine::ForCurrentProcess()->HasSwitch(
ash::switches::kAshEnableV1AppBackButton); ash::switches::kAshEnableV1AppBackButton);
...@@ -93,6 +102,16 @@ bool IsSnappedInSplitView(aura::Window* window, ...@@ -93,6 +102,16 @@ bool IsSnappedInSplitView(aura::Window* window,
} }
} }
void SetRightSide(gfx::Rect* rect, int x) {
rect->set_x(x - rect->width());
DCHECK_EQ(rect->right(), x);
}
void AlignVerticalCenterWith(gfx::Rect* rect, const gfx::Rect& sibling) {
rect->set_y(sibling.y() + (sibling.height() - rect->height()) / 2);
DCHECK_EQ(rect->CenterPoint().y(), sibling.CenterPoint().y());
}
} // namespace } // namespace
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -106,7 +125,8 @@ BrowserNonClientFrameViewAsh::BrowserNonClientFrameViewAsh( ...@@ -106,7 +125,8 @@ BrowserNonClientFrameViewAsh::BrowserNonClientFrameViewAsh(
back_button_(nullptr), back_button_(nullptr),
window_icon_(nullptr), window_icon_(nullptr),
hosted_app_button_container_(nullptr), hosted_app_button_container_(nullptr),
observer_binding_(this) { observer_binding_(this),
weak_factory_(this) {
ash::wm::InstallResizeHandleWindowTargeterForWindow(frame->GetNativeWindow(), ash::wm::InstallResizeHandleWindowTargeterForWindow(frame->GetNativeWindow(),
nullptr); nullptr);
ash::Shell::Get()->AddShellObserver(this); ash::Shell::Get()->AddShellObserver(this);
...@@ -332,6 +352,9 @@ void BrowserNonClientFrameViewAsh::OnPaint(gfx::Canvas* canvas) { ...@@ -332,6 +352,9 @@ void BrowserNonClientFrameViewAsh::OnPaint(gfx::Canvas* canvas) {
if (hosted_app_button_container_) if (hosted_app_button_container_)
hosted_app_button_container_->SetPaintAsActive(should_paint_as_active); hosted_app_button_container_->SetPaintAsActive(should_paint_as_active);
if (frame_header_origin_text_)
frame_header_origin_text_->SetPaintAsActive(should_paint_as_active);
if (browser_view()->IsToolbarVisible() && if (browser_view()->IsToolbarVisible() &&
!browser_view()->toolbar()->GetPreferredSize().IsEmpty() && !browser_view()->toolbar()->GetPreferredSize().IsEmpty() &&
browser_view()->IsTabStripVisible()) { browser_view()->IsTabStripVisible()) {
...@@ -361,6 +384,21 @@ void BrowserNonClientFrameViewAsh::Layout() { ...@@ -361,6 +384,21 @@ void BrowserNonClientFrameViewAsh::Layout() {
const int inset = const int inset =
(tab_strip_visible || immersive) ? 0 : GetTopInset(/*restored=*/false); (tab_strip_visible || immersive) ? 0 : GetTopInset(/*restored=*/false);
frame()->GetNativeWindow()->SetProperty(aura::client::kTopViewInset, inset); frame()->GetNativeWindow()->SetProperty(aura::client::kTopViewInset, inset);
if (frame_header_origin_text_) {
// Align the right side of the text with the left side of the caption
// buttons.
gfx::Size origin_text_preferred_size =
frame_header_origin_text_->GetPreferredSize();
int origin_text_width =
std::min(width() - caption_button_container_->width(),
origin_text_preferred_size.width());
gfx::Rect text_bounds(origin_text_width,
origin_text_preferred_size.height());
SetRightSide(&text_bounds, caption_button_container_->x());
AlignVerticalCenterWith(&text_bounds, caption_button_container_->bounds());
frame_header_origin_text_->SetBoundsRect(text_bounds);
}
} }
const char* BrowserNonClientFrameViewAsh::GetClassName() const { const char* BrowserNonClientFrameViewAsh::GetClassName() const {
...@@ -557,6 +595,8 @@ BrowserNonClientFrameViewAsh::CreateFrameHeader() { ...@@ -557,6 +595,8 @@ BrowserNonClientFrameViewAsh::CreateFrameHeader() {
std::unique_ptr<ash::DefaultFrameHeader> default_frame_header = std::unique_ptr<ash::DefaultFrameHeader> default_frame_header =
std::make_unique<ash::DefaultFrameHeader>(frame(), this, std::make_unique<ash::DefaultFrameHeader>(frame(), this,
caption_button_container_); caption_button_container_);
// TODO(alancutter): Move this branch into a new HostedAppFrameHeader class.
if (extensions::HostedAppBrowserController::IsForExperimentalHostedAppBrowser( if (extensions::HostedAppBrowserController::IsForExperimentalHostedAppBrowser(
browser)) { browser)) {
// Hosted apps apply a theme color if specified by the extension. // Hosted apps apply a theme color if specified by the extension.
...@@ -570,14 +610,33 @@ BrowserNonClientFrameViewAsh::CreateFrameHeader() { ...@@ -570,14 +610,33 @@ BrowserNonClientFrameViewAsh::CreateFrameHeader() {
} }
// Add the container for extra hosted app buttons (e.g app menu button). // Add the container for extra hosted app buttons (e.g app menu button).
SkColor button_color = ash::FrameCaptionButton::GetButtonColor( SkColor active_color = ash::FrameCaptionButton::GetButtonColor(
default_frame_header->ShouldUseLightImages()); default_frame_header->ShouldUseLightImages());
const float inactive_alpha_ratio = const float inactive_alpha_ratio =
ash::FrameCaptionButton::GetInactiveButtonColorAlphaRatio(); ash::FrameCaptionButton::GetInactiveButtonColorAlphaRatio();
SkColor inactive_color =
SkColorSetA(active_color, 255 * inactive_alpha_ratio);
hosted_app_button_container_ = new HostedAppButtonContainer( hosted_app_button_container_ = new HostedAppButtonContainer(
browser_view(), button_color, browser_view(), active_color, inactive_color);
SkColorSetA(button_color, 255 * inactive_alpha_ratio));
caption_button_container_->AddChildViewAt(hosted_app_button_container_, 0); caption_button_container_->AddChildViewAt(hosted_app_button_container_, 0);
// Add the origin text.
frame_header_origin_text_ =
std::make_unique<ash::FrameHeaderOriginText>(
base::UTF8ToUTF16(
browser->hosted_app_controller()->GetUrlOrigin().host()),
active_color, inactive_color,
default_frame_header->GetActiveFrameColor(),
default_frame_header->GetInactiveFrameColor())
.release();
AddChildView(frame_header_origin_text_);
// Schedule the title bar animation.
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&BrowserNonClientFrameViewAsh::StartHostedAppAnimation,
weak_factory_.GetWeakPtr()),
kTitlebarAnimationDelay);
} else if (!browser->is_app()) { } else if (!browser->is_app()) {
// For non app (i.e. WebUI) windows (e.g. Settings) use MD frame color. // For non app (i.e. WebUI) windows (e.g. Settings) use MD frame color.
default_frame_header->SetFrameColors(kMdWebUIFrameColor, default_frame_header->SetFrameColors(kMdWebUIFrameColor,
...@@ -592,3 +651,9 @@ BrowserNonClientFrameViewAsh::CreateFrameHeader() { ...@@ -592,3 +651,9 @@ BrowserNonClientFrameViewAsh::CreateFrameHeader() {
return default_frame_header; return default_frame_header;
} }
void BrowserNonClientFrameViewAsh::StartHostedAppAnimation() {
frame_header_origin_text_->StartSlideAnimation();
hosted_app_button_container_->StartTitlebarAnimation(
frame_header_origin_text_->AnimationDuration());
}
...@@ -24,6 +24,7 @@ namespace ash { ...@@ -24,6 +24,7 @@ namespace ash {
class FrameCaptionButton; class FrameCaptionButton;
class FrameCaptionButtonContainerView; class FrameCaptionButtonContainerView;
class FrameHeader; class FrameHeader;
class FrameHeaderOriginText;
} }
// Provides the BrowserNonClientFrameView for Chrome OS. // Provides the BrowserNonClientFrameView for Chrome OS.
...@@ -128,6 +129,10 @@ class BrowserNonClientFrameViewAsh : public BrowserNonClientFrameView, ...@@ -128,6 +129,10 @@ class BrowserNonClientFrameViewAsh : public BrowserNonClientFrameView,
// Creates the frame header for the browser window. // Creates the frame header for the browser window.
std::unique_ptr<ash::FrameHeader> CreateFrameHeader(); std::unique_ptr<ash::FrameHeader> CreateFrameHeader();
// Triggers the hosted app origin and icon animations, assumes the hosted app
// UI elements exist.
void StartHostedAppAnimation();
// View which contains the window controls. // View which contains the window controls.
ash::FrameCaptionButtonContainerView* caption_button_container_; ash::FrameCaptionButtonContainerView* caption_button_container_;
...@@ -143,6 +148,10 @@ class BrowserNonClientFrameViewAsh : public BrowserNonClientFrameView, ...@@ -143,6 +148,10 @@ class BrowserNonClientFrameViewAsh : public BrowserNonClientFrameView,
// Owned by views hierarchy. // Owned by views hierarchy.
HostedAppButtonContainer* hosted_app_button_container_; HostedAppButtonContainer* hosted_app_button_container_;
// URL origin text for hosted app windows.
// Owned by views hierarchy.
ash::FrameHeaderOriginText* frame_header_origin_text_ = nullptr;
// Ash's mojom::SplitViewController. // Ash's mojom::SplitViewController.
ash::mojom::SplitViewControllerPtr split_view_controller_; ash::mojom::SplitViewControllerPtr split_view_controller_;
...@@ -159,6 +168,8 @@ class BrowserNonClientFrameViewAsh : public BrowserNonClientFrameView, ...@@ -159,6 +168,8 @@ class BrowserNonClientFrameViewAsh : public BrowserNonClientFrameView,
ash::mojom::SplitViewState split_view_state_ = ash::mojom::SplitViewState split_view_state_ =
ash::mojom::SplitViewState::NO_SNAP; ash::mojom::SplitViewState::NO_SNAP;
base::WeakPtrFactory<BrowserNonClientFrameViewAsh> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameViewAsh); DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameViewAsh);
}; };
......
...@@ -568,8 +568,8 @@ IN_PROC_BROWSER_TEST_P(HostedAppNonClientFrameViewAshTest, HostedAppFrame) { ...@@ -568,8 +568,8 @@ IN_PROC_BROWSER_TEST_P(HostedAppNonClientFrameViewAshTest, HostedAppFrame) {
EXPECT_EQ(expected_active_icon_color, button_container->active_icon_color_); EXPECT_EQ(expected_active_icon_color, button_container->active_icon_color_);
// Show a content setting icon. // Show a content setting icon.
auto& content_setting_views = auto& content_setting_views = frame_view->hosted_app_button_container_
frame_view->hosted_app_button_container_->content_setting_views_; ->GetContentSettingViewsForTesting();
for (auto* v : content_setting_views) for (auto* v : content_setting_views)
EXPECT_FALSE(v->visible()); EXPECT_FALSE(v->visible());
......
...@@ -18,9 +18,13 @@ ...@@ -18,9 +18,13 @@
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/color_palette.h" #include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h" #include "ui/gfx/color_utils.h"
#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/paint_vector_icon.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
#include "ui/views/widget/native_widget_aura.h" #include "ui/views/widget/native_widget_aura.h"
...@@ -29,6 +33,9 @@ namespace { ...@@ -29,6 +33,9 @@ namespace {
// Padding around content setting icons. // Padding around content setting icons.
constexpr int kContentSettingIconInteriorPadding = 4; constexpr int kContentSettingIconInteriorPadding = 4;
constexpr base::TimeDelta kContentSettingsFadeInDuration =
base::TimeDelta::FromMilliseconds(500);
class HostedAppToolbarActionsBar : public ToolbarActionsBar { class HostedAppToolbarActionsBar : public ToolbarActionsBar {
public: public:
using ToolbarActionsBar::ToolbarActionsBar; using ToolbarActionsBar::ToolbarActionsBar;
...@@ -45,6 +52,99 @@ class HostedAppToolbarActionsBar : public ToolbarActionsBar { ...@@ -45,6 +52,99 @@ class HostedAppToolbarActionsBar : public ToolbarActionsBar {
} // namespace } // namespace
class HostedAppButtonContainer::ContentSettingsContainer
: public views::View,
public ContentSettingImageView::Delegate {
public:
ContentSettingsContainer(BrowserView* browser_view, SkColor icon_color);
~ContentSettingsContainer() override = default;
// Updates the visibility of each content setting.
void RefreshContentSettingViews() {
for (auto* v : content_setting_views_)
v->Update();
}
// Sets the color of the content setting icons.
void SetIconColor(SkColor icon_color) {
for (auto* v : content_setting_views_)
v->SetIconColor(icon_color);
}
void FadeIn() {
SetVisible(true);
DCHECK_EQ(layer()->opacity(), 0);
ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
settings.SetTransitionDuration(kContentSettingsFadeInDuration);
layer()->SetOpacity(1);
}
const std::vector<ContentSettingImageView*>&
GetContentSettingViewsForTesting() const {
return content_setting_views_;
}
private:
// views::View:
void ChildVisibilityChanged(views::View* child) override {
PreferredSizeChanged();
}
// ContentSettingsImageView::Delegate:
content::WebContents* GetContentSettingWebContents() override {
return browser_view_->GetActiveWebContents();
}
ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate()
override {
return browser_view_->browser()->content_setting_bubble_model_delegate();
}
void OnContentSettingImageBubbleShown(
ContentSettingImageModel::ImageType type) const override {
UMA_HISTOGRAM_ENUMERATION(
"HostedAppFrame.ContentSettings.ImagePressed", type,
ContentSettingImageModel::ImageType::NUM_IMAGE_TYPES);
}
// Owned by the views hierarchy.
std::vector<ContentSettingImageView*> content_setting_views_;
BrowserView* browser_view_;
DISALLOW_COPY_AND_ASSIGN(ContentSettingsContainer);
};
const std::vector<ContentSettingImageView*>&
HostedAppButtonContainer::GetContentSettingViewsForTesting() const {
return content_settings_container_->GetContentSettingViewsForTesting();
}
HostedAppButtonContainer::ContentSettingsContainer::ContentSettingsContainer(
BrowserView* browser_view,
SkColor icon_color)
: browser_view_(browser_view) {
SetLayoutManager(
std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal));
SetVisible(false);
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
layer()->SetOpacity(0);
std::vector<std::unique_ptr<ContentSettingImageModel>> models =
ContentSettingImageModel::GenerateContentSettingImageModels();
for (auto& model : models) {
auto image_view = std::make_unique<ContentSettingImageView>(
std::move(model), this,
views::NativeWidgetAura::GetWindowTitleFontList());
image_view->SetIconColor(icon_color);
image_view->set_next_element_interior_padding(
kContentSettingIconInteriorPadding);
image_view->disable_animation();
content_setting_views_.push_back(image_view.get());
AddChildView(image_view.release());
}
}
HostedAppButtonContainer::AppMenuButton::AppMenuButton( HostedAppButtonContainer::AppMenuButton::AppMenuButton(
BrowserView* browser_view) BrowserView* browser_view)
: views::MenuButton(base::string16(), this, false), : views::MenuButton(base::string16(), this, false),
...@@ -81,6 +181,13 @@ void HostedAppButtonContainer::AppMenuButton::OnMenuButtonClicked( ...@@ -81,6 +181,13 @@ void HostedAppButtonContainer::AppMenuButton::OnMenuButtonClicked(
menu_->RunMenu(this); menu_->RunMenu(this);
} }
void HostedAppButtonContainer::StartTitlebarAnimation(
base::TimeDelta origin_text_slide_duration) {
fade_in_content_setting_buttons_timer_.Start(
FROM_HERE, origin_text_slide_duration, content_settings_container_,
&ContentSettingsContainer::FadeIn);
}
HostedAppButtonContainer::HostedAppButtonContainer(BrowserView* browser_view, HostedAppButtonContainer::HostedAppButtonContainer(BrowserView* browser_view,
SkColor active_icon_color, SkColor active_icon_color,
SkColor inactive_icon_color) SkColor inactive_icon_color)
...@@ -100,20 +207,10 @@ HostedAppButtonContainer::HostedAppButtonContainer(BrowserView* browser_view, ...@@ -100,20 +207,10 @@ HostedAppButtonContainer::HostedAppButtonContainer(BrowserView* browser_view,
views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
SetLayoutManager(std::move(layout)); SetLayoutManager(std::move(layout));
std::vector<std::unique_ptr<ContentSettingImageModel>> models = auto content_settings_container = std::make_unique<ContentSettingsContainer>(
ContentSettingImageModel::GenerateContentSettingImageModels(); browser_view, active_icon_color);
for (auto& model : models) { content_settings_container_ = content_settings_container.get();
auto image_view = std::make_unique<ContentSettingImageView>( AddChildView(content_settings_container.release());
std::move(model), this,
views::NativeWidgetAura::GetWindowTitleFontList());
image_view->SetIconColor(active_icon_color);
image_view->set_next_element_interior_padding(
kContentSettingIconInteriorPadding);
image_view->SetVisible(false);
image_view->disable_animation();
content_setting_views_.push_back(image_view.get());
AddChildView(image_view.release());
}
AddChildView(browser_actions_container_); AddChildView(browser_actions_container_);
...@@ -126,37 +223,22 @@ HostedAppButtonContainer::HostedAppButtonContainer(BrowserView* browser_view, ...@@ -126,37 +223,22 @@ HostedAppButtonContainer::HostedAppButtonContainer(BrowserView* browser_view,
HostedAppButtonContainer::~HostedAppButtonContainer() {} HostedAppButtonContainer::~HostedAppButtonContainer() {}
void HostedAppButtonContainer::RefreshContentSettingViews() { void HostedAppButtonContainer::RefreshContentSettingViews() {
for (auto* v : content_setting_views_) content_settings_container_->RefreshContentSettingViews();
v->Update();
} }
void HostedAppButtonContainer::SetPaintAsActive(bool active) { void HostedAppButtonContainer::SetPaintAsActive(bool active) {
for (auto* v : content_setting_views_) content_settings_container_->SetIconColor(active ? active_icon_color_
v->SetIconColor(active ? active_icon_color_ : inactive_icon_color_); : inactive_icon_color_);
app_menu_button_->SetIconColor(active ? active_icon_color_ app_menu_button_->SetIconColor(active ? active_icon_color_
: inactive_icon_color_); : inactive_icon_color_);
} }
content::WebContents* HostedAppButtonContainer::GetContentSettingWebContents() {
return browser_view_->GetActiveWebContents();
}
ContentSettingBubbleModelDelegate*
HostedAppButtonContainer::GetContentSettingBubbleModelDelegate() {
return browser_view_->browser()->content_setting_bubble_model_delegate();
}
void HostedAppButtonContainer::OnContentSettingImageBubbleShown(
ContentSettingImageModel::ImageType type) const {
UMA_HISTOGRAM_ENUMERATION(
"HostedAppFrame.ContentSettings.ImagePressed", type,
ContentSettingImageModel::ImageType::NUM_IMAGE_TYPES);
}
void HostedAppButtonContainer::ChildPreferredSizeChanged(views::View* child) { void HostedAppButtonContainer::ChildPreferredSizeChanged(views::View* child) {
if (child != browser_actions_container_) if (child != browser_actions_container_ &&
child != content_settings_container_) {
return; return;
}
PreferredSizeChanged(); PreferredSizeChanged();
} }
......
...@@ -21,7 +21,6 @@ class BrowserView; ...@@ -21,7 +21,6 @@ class BrowserView;
// A container for hosted app buttons in the title bar. // A container for hosted app buttons in the title bar.
class HostedAppButtonContainer : public views::View, class HostedAppButtonContainer : public views::View,
public ContentSettingImageView::Delegate,
public BrowserActionsContainer::Delegate, public BrowserActionsContainer::Delegate,
public BrowserViewButtonProvider { public BrowserViewButtonProvider {
public: public:
...@@ -32,15 +31,24 @@ class HostedAppButtonContainer : public views::View, ...@@ -32,15 +31,24 @@ class HostedAppButtonContainer : public views::View,
SkColor inactive_icon_color); SkColor inactive_icon_color);
~HostedAppButtonContainer() override; ~HostedAppButtonContainer() override;
// Updates the visibility of each content setting view. // Updates the visibility of each content setting.
void RefreshContentSettingViews(); void RefreshContentSettingViews();
// Sets the container to paints its buttons the active/inactive color. // Sets the container to paints its buttons the active/inactive color.
void SetPaintAsActive(bool active); void SetPaintAsActive(bool active);
// Animates the menu button and content setting icons. Intended to run in sync
// with a FrameHeaderOriginText slide animation.
void StartTitlebarAnimation(base::TimeDelta origin_text_slide_duration);
private: private:
FRIEND_TEST_ALL_PREFIXES(HostedAppNonClientFrameViewAshTest, HostedAppFrame); FRIEND_TEST_ALL_PREFIXES(HostedAppNonClientFrameViewAshTest, HostedAppFrame);
class ContentSettingsContainer;
const std::vector<ContentSettingImageView*>&
GetContentSettingViewsForTesting() const;
// The 'app menu' button for the hosted app. // The 'app menu' button for the hosted app.
class AppMenuButton : public views::MenuButton, class AppMenuButton : public views::MenuButton,
public views::MenuButtonListener { public views::MenuButtonListener {
...@@ -71,12 +79,7 @@ class HostedAppButtonContainer : public views::View, ...@@ -71,12 +79,7 @@ class HostedAppButtonContainer : public views::View,
DISALLOW_COPY_AND_ASSIGN(AppMenuButton); DISALLOW_COPY_AND_ASSIGN(AppMenuButton);
}; };
// ContentSettingsImageView::Delegate: void FadeInContentSettingButtons();
content::WebContents* GetContentSettingWebContents() override;
ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate()
override;
void OnContentSettingImageBubbleShown(
ContentSettingImageModel::ImageType type) const override;
// views::View: // views::View:
void ChildPreferredSizeChanged(views::View* child) override; void ChildPreferredSizeChanged(views::View* child) override;
...@@ -101,11 +104,15 @@ class HostedAppButtonContainer : public views::View, ...@@ -101,11 +104,15 @@ class HostedAppButtonContainer : public views::View,
const SkColor active_icon_color_; const SkColor active_icon_color_;
const SkColor inactive_icon_color_; const SkColor inactive_icon_color_;
base::OneShotTimer fade_in_content_setting_buttons_timer_;
// Owned by the views hierarchy. // Owned by the views hierarchy.
AppMenuButton* app_menu_button_; AppMenuButton* app_menu_button_;
std::vector<ContentSettingImageView*> content_setting_views_; ContentSettingsContainer* content_settings_container_;
BrowserActionsContainer* browser_actions_container_; BrowserActionsContainer* browser_actions_container_;
base::OneShotTimer opening_animation_timer_;
DISALLOW_COPY_AND_ASSIGN(HostedAppButtonContainer); DISALLOW_COPY_AND_ASSIGN(HostedAppButtonContainer);
}; };
......
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