blob: eb5938548c9205d69e8d52d288e05e31cb38a391 [file] [log] [blame]
// 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 "chrome/browser/android/compositor/layer/ephemeral_tab_layer.h"
#include "cc/layers/layer.h"
#include "cc/layers/nine_patch_layer.h"
#include "cc/resources/scoped_ui_resource.h"
#include "content/public/browser/android/compositor.h"
#include "ui/android/resources/nine_patch_resource.h"
#include "ui/android/resources/resource_manager.h"
namespace android {
// static
scoped_refptr<EphemeralTabLayer> EphemeralTabLayer::Create(
ui::ResourceManager* resource_manager) {
return base::WrapRefCounted(new EphemeralTabLayer(resource_manager));
}
void EphemeralTabLayer::SetProperties(
int title_view_resource_id,
int caption_view_resource_id,
jfloat caption_animation_percentage,
jfloat text_layer_min_height,
jfloat title_caption_spacing,
jboolean caption_visible,
int progress_bar_background_resource_id,
int progress_bar_resource_id,
float dp_to_px,
const scoped_refptr<cc::Layer>& content_layer,
float panel_x,
float panel_y,
float panel_width,
float panel_height,
float bar_margin_side,
float bar_height,
bool bar_border_visible,
float bar_border_height,
bool bar_shadow_visible,
float bar_shadow_opacity,
bool progress_bar_visible,
float progress_bar_height,
float progress_bar_opacity,
int progress_bar_completion) {
// Round values to avoid pixel gap between layers.
bar_height = floor(bar_height);
float bar_top = 0.f;
float bar_bottom = bar_top + bar_height;
bool should_render_progress_bar =
progress_bar_visible && progress_bar_opacity > 0.f;
// Title needs no rendering in the base layer as it can be rendered
// together with caption below. Make it invisible.
float title_opacity = 0.f;
OverlayPanelLayer::SetProperties(
dp_to_px, content_layer, bar_height, panel_x, panel_y, panel_width,
panel_height, bar_margin_side, bar_height, 0.0f, title_opacity,
bar_border_visible, bar_border_height, bar_shadow_visible,
bar_shadow_opacity, 1.0f /* icon opacity */);
SetupTextLayer(bar_top, bar_height, text_layer_min_height,
caption_view_resource_id, caption_animation_percentage,
caption_visible, title_view_resource_id,
title_caption_spacing);
// ---------------------------------------------------------------------------
// Progress Bar
// ---------------------------------------------------------------------------
if (should_render_progress_bar) {
ui::NinePatchResource* progress_bar_background_resource =
ui::NinePatchResource::From(resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_STATIC,
progress_bar_background_resource_id));
ui::NinePatchResource* progress_bar_resource =
ui::NinePatchResource::From(resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_STATIC, progress_bar_resource_id));
DCHECK(progress_bar_background_resource);
DCHECK(progress_bar_resource);
// Progress Bar Background
if (progress_bar_background_->parent() != layer_)
layer_->AddChild(progress_bar_background_);
float progress_bar_y = bar_bottom - progress_bar_height;
gfx::Size progress_bar_background_size(panel_width, progress_bar_height);
progress_bar_background_->SetUIResourceId(
progress_bar_background_resource->ui_resource()->id());
progress_bar_background_->SetBorder(
progress_bar_background_resource->Border(progress_bar_background_size));
progress_bar_background_->SetAperture(
progress_bar_background_resource->aperture());
progress_bar_background_->SetBounds(progress_bar_background_size);
progress_bar_background_->SetPosition(gfx::PointF(0.f, progress_bar_y));
progress_bar_background_->SetOpacity(progress_bar_opacity);
// Progress Bar
if (progress_bar_->parent() != layer_)
layer_->AddChild(progress_bar_);
float progress_bar_width =
floor(panel_width * progress_bar_completion / 100.f);
gfx::Size progress_bar_size(progress_bar_width, progress_bar_height);
progress_bar_->SetUIResourceId(progress_bar_resource->ui_resource()->id());
progress_bar_->SetBorder(progress_bar_resource->Border(progress_bar_size));
progress_bar_->SetAperture(progress_bar_resource->aperture());
progress_bar_->SetBounds(progress_bar_size);
progress_bar_->SetPosition(gfx::PointF(0.f, progress_bar_y));
progress_bar_->SetOpacity(progress_bar_opacity);
} else {
// Removes Progress Bar and its Background from the Layer Tree.
if (progress_bar_background_.get() && progress_bar_background_->parent())
progress_bar_background_->RemoveFromParent();
if (progress_bar_.get() && progress_bar_->parent())
progress_bar_->RemoveFromParent();
}
}
void EphemeralTabLayer::SetupTextLayer(float bar_top,
float bar_height,
float text_layer_min_height,
int caption_resource_id,
float animation_percentage,
bool caption_visible,
int title_resource_id,
float title_caption_spacing) {
// ---------------------------------------------------------------------------
// Setup the Drawing Hierarchy
// ---------------------------------------------------------------------------
DCHECK(text_layer_.get());
DCHECK(caption_.get());
DCHECK(title_.get());
// Title
ui::Resource* title_resource = resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_DYNAMIC, title_resource_id);
if (title_resource) {
title_->SetUIResourceId(title_resource->ui_resource()->id());
title_->SetBounds(title_resource->size());
}
// Caption
ui::Resource* caption_resource = nullptr;
if (caption_visible) {
// Grabs the dynamic Search Caption resource so we can get a snapshot.
caption_resource = resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_DYNAMIC, caption_resource_id);
}
if (animation_percentage != 0.f) {
if (caption_->parent() != text_layer_) {
text_layer_->AddChild(caption_);
}
if (caption_resource) {
caption_->SetUIResourceId(caption_resource->ui_resource()->id());
caption_->SetBounds(caption_resource->size());
}
} else if (caption_->parent()) {
caption_->RemoveFromParent();
}
// ---------------------------------------------------------------------------
// Calculate Text Layer Size
// ---------------------------------------------------------------------------
// The caption_ may not have had its resource set by this point, if so
// the bounds will be zero and everything will still work.
float title_height = title_->bounds().height();
float caption_height = caption_->bounds().height();
float layer_height =
std::max(text_layer_min_height,
title_height + caption_height + title_caption_spacing);
float layer_width =
std::max(title_->bounds().width(), caption_->bounds().width());
float layer_top = bar_top + (bar_height - layer_height) / 2;
text_layer_->SetBounds(gfx::Size(layer_width, layer_height));
text_layer_->SetPosition(gfx::PointF(0.f, layer_top));
text_layer_->SetMasksToBounds(true);
// ---------------------------------------------------------------------------
// Layout Text Layer
// ---------------------------------------------------------------------------
// ---Top of Panel Bar--- <- bar_top
//
// ---Top of Text Layer--- <- layer_top
// } remaining_height / 2
// Title } title_height
// } title_caption_spacing
// Caption } caption_height
// } remaining_height / 2
// --Bottom of Text Layer-
//
// --Bottom of Panel Bar-
// If the Caption is not visible the Title is centered in this space, when
// the Caption becomes visible it is animated sliding up into it's position
// with the spacings determined by UI.
// If there is no caption, just vertically center the title.
float title_top = (layer_height - title_height) / 2;
// If we aren't displaying the caption we're done.
if (animation_percentage == 0.f || !caption_resource) {
title_->SetPosition(gfx::PointF(0.f, title_top));
return;
}
// Calculate the positions for the Title and Caption when the Caption
// animation is complete.
float remaining_height =
layer_height - title_height - title_caption_spacing - caption_height;
float title_top_end = remaining_height / 2;
float caption_top_end = title_top_end + title_height + title_caption_spacing;
// Interpolate between the animation start and end positions (short cut
// if the animation is at the end or start).
title_top = title_top * (1.f - animation_percentage) +
title_top_end * animation_percentage;
// The Caption starts off the bottom of the Text Layer.
float caption_top = layer_height * (1.f - animation_percentage) +
caption_top_end * animation_percentage;
title_->SetPosition(gfx::PointF(0.f, title_top));
caption_->SetPosition(gfx::PointF(0.f, caption_top));
}
EphemeralTabLayer::EphemeralTabLayer(ui::ResourceManager* resource_manager)
: OverlayPanelLayer(resource_manager),
title_(cc::UIResourceLayer::Create()),
caption_(cc::UIResourceLayer::Create()),
text_layer_(cc::UIResourceLayer::Create()),
progress_bar_(cc::NinePatchLayer::Create()),
progress_bar_background_(cc::NinePatchLayer::Create()) {
progress_bar_background_->SetIsDrawable(true);
progress_bar_background_->SetFillCenter(true);
progress_bar_->SetIsDrawable(true);
progress_bar_->SetFillCenter(true);
// Content layer
text_layer_->SetIsDrawable(true);
title_->SetIsDrawable(true);
caption_->SetIsDrawable(true);
AddBarTextLayer(text_layer_);
text_layer_->AddChild(title_);
}
EphemeralTabLayer::~EphemeralTabLayer() {}
} // namespace android