blob: 9ee09013d58d5eace35e4b20f7defa1c3dd545a2 [file] [log] [blame]
// Copyright 2014 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/tab_layer.h"
#include "base/i18n/rtl.h"
#include "base/memory/ptr_util.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_collections.h"
#include "cc/layers/nine_patch_layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/ui_resource_layer.h"
#include "cc/resources/scoped_ui_resource.h"
#include "chrome/browser/android/compositor/decoration_title.h"
#include "chrome/browser/android/compositor/layer/content_layer.h"
#include "chrome/browser/android/compositor/layer/toolbar_layer.h"
#include "chrome/browser/android/compositor/layer_title_cache.h"
#include "chrome/browser/android/compositor/tab_content_manager.h"
#include "content/public/browser/android/compositor.h"
#include "ui/android/resources/nine_patch_resource.h"
#include "ui/android/resources/resource_manager.h"
#include "ui/base/l10n/l10n_util_android.h"
#include "ui/gfx/geometry/insets_f.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/transform.h"
namespace android {
// static
scoped_refptr<TabLayer> TabLayer::Create(
bool incognito,
ui::ResourceManager* resource_manager,
LayerTitleCache* layer_title_cache,
TabContentManager* tab_content_manager) {
return make_scoped_refptr(new TabLayer(
incognito, resource_manager, layer_title_cache, tab_content_manager));
}
// static
void TabLayer::ComputePaddingPositions(const gfx::Size& content_size,
const gfx::Size& desired_size,
gfx::Rect* side_padding_rect,
gfx::Rect* bottom_padding_rect) {
if (content_size.width() < desired_size.width()) {
side_padding_rect->set_x(content_size.width());
side_padding_rect->set_width(desired_size.width() - content_size.width());
// Restrict the side padding height to avoid overdrawing when both the side
// and bottom padding are used.
side_padding_rect->set_height(std::min(content_size.height(),
desired_size.height()));
}
if (content_size.height() < desired_size.height()) {
bottom_padding_rect->set_y(content_size.height());
// The side padding height is restricted to the min of bounds.height() and
// desired_bounds.height(), so it will not extend all the way to the bottom
// of the desired_bounds. The width of the bottom padding is set at
// desired_bounds.width() so that there is not a hole where the side padding
// stops.
bottom_padding_rect->set_width(desired_size.width());
bottom_padding_rect->set_height(
desired_size.height() - content_size.height());
}
}
static void PositionPadding(scoped_refptr<cc::SolidColorLayer> padding_layer,
gfx::Rect padding_rect,
float content_scale,
float alpha,
gfx::PointF content_position,
gfx::RectF descaled_local_content_area) {
if (padding_rect.IsEmpty()) {
padding_layer->SetHideLayerAndSubtree(true);
return;
}
padding_layer->SetHideLayerAndSubtree(false);
padding_layer->SetBounds(padding_rect.size());
padding_layer->SetOpacity(alpha);
gfx::Transform transform;
transform.Scale(content_scale, content_scale);
transform.Translate(padding_rect.x() + content_position.x(),
padding_rect.y() + content_position.y());
transform.Translate(descaled_local_content_area.x(),
descaled_local_content_area.y());
padding_layer->SetTransformOrigin(gfx::Point3F(0.f, 0.f, 0.f));
padding_layer->SetTransform(transform);
}
void TabLayer::SetProperties(int id,
bool can_use_live_layer,
bool browser_controls_at_bottom,
int toolbar_resource_id,
int close_button_resource_id,
int shadow_resource_id,
int contour_resource_id,
int back_logo_resource_id,
int border_resource_id,
int border_inner_shadow_resource_id,
int default_background_color,
int back_logo_color,
bool is_portrait,
float x,
float y,
float width,
float height,
float shadow_x,
float shadow_y,
float shadow_width,
float shadow_height,
float pivot_x,
float pivot_y,
float rotation_x,
float rotation_y,
float alpha,
float border_alpha,
float border_inner_shadow_alpha,
float contour_alpha,
float shadow_alpha,
float close_alpha,
float border_scale,
float saturation,
float brightness,
float close_btn_width,
float static_to_view_blend,
float content_width,
float content_height,
float view_width,
float view_height,
bool show_toolbar,
int default_theme_color,
int toolbar_background_color,
int close_button_color,
bool anonymize_toolbar,
bool show_tab_title,
int toolbar_textbox_resource_id,
int toolbar_textbox_background_color,
float toolbar_textbox_alpha,
float toolbar_alpha,
float toolbar_y_offset,
float side_border_scale,
bool inset_border) {
if (alpha <= 0) {
layer_->SetHideLayerAndSubtree(true);
return;
}
layer_->SetHideLayerAndSubtree(false);
// Grab required resources
ui::NinePatchResource* border_resource =
ui::NinePatchResource::From(resource_manager_->GetStaticResourceWithTint(
border_resource_id, toolbar_background_color));
ui::NinePatchResource* border_inner_shadow_resource =
ui::NinePatchResource::From(resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_STATIC, border_inner_shadow_resource_id));
ui::NinePatchResource* shadow_resource =
ui::NinePatchResource::From(resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_STATIC, shadow_resource_id));
ui::NinePatchResource* contour_resource =
ui::NinePatchResource::From(resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_STATIC, contour_resource_id));
ui::Resource* close_btn_resource =
resource_manager_->GetStaticResourceWithTint(close_button_resource_id,
close_button_color);
ui::Resource* back_logo_resource = nullptr;
DecorationTitle* title_layer = nullptr;
//----------------------------------------------------------------------------
// Handle Border Scaling (Upscale/Downscale everything until final scaling)
//----------------------------------------------------------------------------
width /= border_scale;
height /= border_scale;
shadow_x /= border_scale;
shadow_y /= border_scale;
shadow_width /= border_scale;
shadow_height /= border_scale;
//----------------------------------------------------------------------------
// Precalculate Helper Values
//----------------------------------------------------------------------------
const gfx::RectF border_padding(border_resource->padding());
const gfx::RectF border_inner_shadow_padding(
border_inner_shadow_resource->padding());
const gfx::RectF shadow_padding(shadow_resource->padding());
const gfx::RectF contour_padding(contour_resource->padding());
// If we're in portrait and we're RTL, the close button is on the left.
// Similarly if we're in landscape and we're in LTR, the close button is on
// the left.
const bool close_button_on_left = is_portrait == l10n_util::IsLayoutRtl();
const bool back_visible = cos(rotation_x * SK_MScalarPI / 180.0f) < 0 ||
cos(rotation_y * SK_MScalarPI / 180.0f) < 0;
const float content_scale = width / content_width;
gfx::RectF content_area(0.f, 0.f, content_width, content_height);
gfx::RectF scaled_local_content_area(shadow_x, shadow_y, shadow_width,
shadow_height);
gfx::RectF descaled_local_content_area(
scaled_local_content_area.x() / content_scale,
scaled_local_content_area.y() / content_scale,
scaled_local_content_area.width() / content_scale,
scaled_local_content_area.height() / content_scale);
const gfx::Size shadow_padding_size(
shadow_resource->size().width() - shadow_padding.width(),
shadow_resource->size().height() - shadow_padding.height());
const gfx::Size border_padding_size(
border_resource->size().width() - border_padding.width(),
border_resource->size().height() - border_padding.height());
const gfx::Size border_inner_shadow_padding_size(
border_inner_shadow_resource->size().width() -
border_inner_shadow_padding.width(),
border_inner_shadow_resource->size().height() -
border_inner_shadow_padding.height());
const gfx::Size contour_padding_size(
contour_resource->size().width() - contour_padding.width(),
contour_resource->size().height() - contour_padding.height());
const float close_btn_effective_width = close_btn_width * close_alpha;
//--------------------------------------------------------------------------
// Update Resource Ids For Layers That Impact Layout
//--------------------------------------------------------------------------
// TODO(kkimlabs): Tab switcher doesn't show the progress bar.
toolbar_layer_->PushResource(toolbar_resource_id,
toolbar_background_color,
anonymize_toolbar,
toolbar_textbox_background_color,
toolbar_textbox_resource_id,
toolbar_textbox_alpha,
view_height,
// TODO(mdjones): Feels odd to pass 0 here when
// we have access to toolbar_y_offset.
0,
false,
false,
browser_controls_at_bottom);
toolbar_layer_->UpdateProgressBar(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
float toolbar_impact_height = 0;
if (show_toolbar && !back_visible && !browser_controls_at_bottom)
toolbar_impact_height = toolbar_layer_->layer()->bounds().height();
//----------------------------------------------------------------------------
// Compute Alpha and Visibility
//----------------------------------------------------------------------------
border_alpha *= alpha;
contour_alpha *= alpha;
shadow_alpha *= alpha;
close_alpha *= alpha;
toolbar_alpha *= alpha;
if (back_visible) {
border_alpha = 0.f;
border_inner_shadow_alpha = 0.f;
}
bool border_visible = border_alpha > 0.f;
bool border_inner_shadow_visible = border_inner_shadow_alpha > 0.f;
bool contour_visible = border_alpha < contour_alpha && contour_alpha > 0.f;
bool shadow_visible = shadow_alpha > 0.f && border_alpha > 0.f;
//----------------------------------------------------------------------------
// Compute Layer Sizes
//----------------------------------------------------------------------------
gfx::Size shadow_size(width + shadow_padding_size.width() * side_border_scale,
height + shadow_padding_size.height());
gfx::Size border_size(width + border_padding_size.width() * side_border_scale,
height + border_padding_size.height());
gfx::Size border_inner_shadow_size(
width + border_inner_shadow_padding_size.width(),
height + border_inner_shadow_padding_size.height());
gfx::Size contour_size(
width + contour_padding_size.width() * side_border_scale,
height + contour_padding_size.height());
gfx::Size close_button_size(close_btn_width, border_padding.y());
gfx::Size title_size(width - close_btn_effective_width, border_padding.y());
gfx::Size back_logo_size;
// TODO(clholgat): Figure out why the back logo is null sometimes.
if (back_visible) {
back_logo_resource =
resource_manager_->GetResource(ui::ANDROID_RESOURCE_TYPE_STATIC,
back_logo_resource_id);
if (back_logo_resource)
back_logo_size = back_logo_resource->size();
}
// Store this size at a point as it might go negative during the inset
// calculations.
gfx::Point desired_content_size_pt(
descaled_local_content_area.width(),
descaled_local_content_area.height() - toolbar_impact_height);
// Shrink the toolbar layer so we properly clip if it's offset.
gfx::Size toolbar_size(
toolbar_layer_->layer()->bounds().width(),
toolbar_layer_->layer()->bounds().height() - toolbar_y_offset);
//----------------------------------------------------------------------------
// Compute Layer Positions
//----------------------------------------------------------------------------
gfx::PointF shadow_position(-shadow_padding.x() * side_border_scale,
-shadow_padding.y());
gfx::PointF border_position(-border_padding.x() * side_border_scale,
-border_padding.y());
gfx::PointF border_inner_shadow_position(-border_inner_shadow_padding.x(),
-border_inner_shadow_padding.y());
gfx::PointF contour_position(-contour_padding.x() * side_border_scale,
-contour_padding.y());
gfx::PointF toolbar_position(
0.f, toolbar_layer_->layer()->bounds().height() - toolbar_size.height());
gfx::PointF content_position(0.f, toolbar_impact_height);
gfx::PointF back_logo_position(
((descaled_local_content_area.width() - back_logo_->bounds().width()) *
content_scale) /
2.0f,
((descaled_local_content_area.height() - back_logo_->bounds().height()) *
content_scale) /
2.0f);
gfx::PointF close_button_position;
gfx::PointF title_position;
close_button_position.set_y(-border_padding.y());
title_position.set_y(-border_padding.y());
if (!close_button_on_left)
close_button_position.set_x(width - close_button_size.width());
else
title_position.set_x(close_btn_effective_width);
//----------------------------------------------------------------------------
// Center Specific Assets in the Rects
//----------------------------------------------------------------------------
close_button_position.Offset(
(close_button_size.width() - close_btn_resource->size().width()) / 2.f,
(close_button_size.height() - close_btn_resource->size().height()) / 2.f);
close_button_size.SetSize(close_btn_resource->size().width(),
close_btn_resource->size().height());
//----------------------------------------------------------------------------
// Handle Insetting the Top Border Component
//----------------------------------------------------------------------------
if (inset_border) {
float inset_diff = inset_border ? border_padding.y() : 0.f;
descaled_local_content_area.set_height(
descaled_local_content_area.height() - inset_diff);
scaled_local_content_area.set_height(scaled_local_content_area.height() -
inset_diff * content_scale);
shadow_size.set_height(shadow_size.height() - inset_diff);
border_size.set_height(border_size.height() - inset_diff);
border_inner_shadow_size.set_height(
border_inner_shadow_size.height() - inset_diff);
contour_size.set_height(contour_size.height() - inset_diff);
shadow_position.set_y(shadow_position.y() + inset_diff);
border_position.set_y(border_position.y() + inset_diff);
border_inner_shadow_position.set_y(
border_inner_shadow_position.y() + inset_diff);
contour_position.set_y(contour_position.y() + inset_diff);
close_button_position.set_y(close_button_position.y() + inset_diff);
title_position.set_y(title_position.y() + inset_diff);
// Scaled eventually, so have to descale the size difference first.
toolbar_position.set_y(toolbar_position.y() + inset_diff / content_scale);
content_position.set_y(content_position.y() + inset_diff / content_scale);
desired_content_size_pt.set_y(desired_content_size_pt.y() -
inset_diff / content_scale);
}
const bool inset_toolbar = !inset_border;
if (!inset_toolbar) {
float inset_diff = toolbar_impact_height;
toolbar_position.set_y(toolbar_position.y() - inset_diff);
content_position.set_y(content_position.y() - inset_diff);
desired_content_size_pt.set_y(desired_content_size_pt.y() + inset_diff);
}
// Finally build the sizes that might have calculations that go negative.
gfx::Size desired_content_size(desired_content_size_pt.x(),
desired_content_size_pt.y());
//----------------------------------------------------------------------------
// Calculate Content Visibility
//----------------------------------------------------------------------------
// Check if the rect we are drawing is larger than the content rect.
bool content_visible = desired_content_size.GetArea() > 0.f;
// TODO(dtrainor): Improve these calculations to prune these layers out.
bool title_visible = border_alpha > 0.f && !back_visible && show_tab_title;
bool close_btn_visible = title_visible;
bool toolbar_visible = show_toolbar && toolbar_alpha > 0.f && !back_visible;
//----------------------------------------------------------------------------
// Fix jaggies
//----------------------------------------------------------------------------
border_position.Offset(0.5f, 0.5f);
border_inner_shadow_position.Offset(0.5f, 0.5f);
shadow_position.Offset(0.5f, 0.5f);
contour_position.Offset(0.5f, 0.5f);
title_position.Offset(0.5f, 0.5f);
close_button_position.Offset(0.5f, 0.5f);
toolbar_position.Offset(0.5f, 0.5f);
border_size.Enlarge(-1.f, -1.f);
border_inner_shadow_size.Enlarge(-1.f, -1.f);
shadow_size.Enlarge(-1.f, -1.f);
//----------------------------------------------------------------------------
// Update Resource Ids
//----------------------------------------------------------------------------
shadow_->SetUIResourceId(shadow_resource->ui_resource()->id());
shadow_->SetBorder(shadow_resource->Border(shadow_size));
shadow_->SetAperture(shadow_resource->aperture());
contour_shadow_->SetUIResourceId(contour_resource->ui_resource()->id());
contour_shadow_->SetBorder(contour_resource->Border(contour_size));
contour_shadow_->SetAperture(contour_resource->aperture());
front_border_->SetUIResourceId(border_resource->ui_resource()->id());
front_border_->SetAperture(border_resource->aperture());
front_border_->SetBorder(border_resource->Border(
border_size,
gfx::InsetsF(1.f, side_border_scale, 1.f, side_border_scale)));
front_border_inner_shadow_->SetUIResourceId(
border_inner_shadow_resource->ui_resource()->id());
front_border_inner_shadow_->SetAperture(
border_inner_shadow_resource->aperture());
front_border_inner_shadow_->SetBorder(border_inner_shadow_resource->Border(
border_inner_shadow_size));
side_padding_->SetBackgroundColor(back_visible ? back_logo_color
: default_background_color);
bottom_padding_->SetBackgroundColor(back_visible ? back_logo_color
: default_background_color);
if (title_visible && layer_title_cache_)
title_layer = layer_title_cache_->GetTitleLayer(id);
SetTitle(title_layer);
close_button_->SetUIResourceId(close_btn_resource->ui_resource()->id());
if (!back_visible) {
gfx::Rect rounded_descaled_content_area(
round(descaled_local_content_area.x()),
round(descaled_local_content_area.y()),
round(desired_content_size.width()),
round(desired_content_size.height()));
content_->SetProperties(id, can_use_live_layer, static_to_view_blend,
true, alpha, saturation,
true, rounded_descaled_content_area);
} else if (back_logo_resource) {
back_logo_->SetUIResourceId(back_logo_resource->ui_resource()->id());
}
//----------------------------------------------------------------------------
// Push Size, Position, Alpha and Transformations to Layers
//----------------------------------------------------------------------------
shadow_->SetHideLayerAndSubtree(!shadow_visible);
if (shadow_visible) {
shadow_->SetPosition(shadow_position);
shadow_->SetBounds(shadow_size);
shadow_->SetOpacity(shadow_alpha);
}
contour_shadow_->SetHideLayerAndSubtree(!contour_visible);
if (contour_visible) {
contour_shadow_->SetPosition(contour_position);
contour_shadow_->SetBounds(contour_size);
contour_shadow_->SetOpacity(contour_alpha);
}
front_border_->SetHideLayerAndSubtree(!border_visible);
if (border_visible) {
front_border_->SetPosition(border_position);
front_border_->SetBounds(border_size);
front_border_->SetOpacity(border_alpha);
front_border_->SetNearestNeighbor(toolbar_visible);
}
front_border_inner_shadow_->SetHideLayerAndSubtree(
!border_inner_shadow_visible);
if (border_inner_shadow_visible) {
front_border_inner_shadow_->SetPosition(border_inner_shadow_position);
front_border_inner_shadow_->SetBounds(border_inner_shadow_size);
front_border_inner_shadow_->SetOpacity(border_inner_shadow_alpha);
}
toolbar_layer_->layer()->SetHideLayerAndSubtree(!toolbar_visible);
if (toolbar_visible) {
// toolbar_ Transform
gfx::Transform transform;
transform.Scale(content_scale, content_scale);
transform.Translate(toolbar_position.x(), toolbar_position.y());
toolbar_layer_->layer()->SetTransformOrigin(gfx::Point3F(0.f, 0.f, 0.f));
toolbar_layer_->layer()->SetTransform(transform);
toolbar_layer_->layer()->SetOpacity(toolbar_alpha);
toolbar_layer_->layer()->SetMasksToBounds(
toolbar_layer_->layer()->bounds() != toolbar_size);
toolbar_layer_->layer()->SetBounds(toolbar_size);
}
if (title_layer) {
gfx::PointF vertically_centered_position(
title_position.x(),
title_position.y() +
(title_size.height() - title_layer->size().height()) / 2.f);
title_->SetPosition(vertically_centered_position);
title_layer->setBounds(title_size);
title_layer->setOpacity(border_alpha);
}
close_button_->SetHideLayerAndSubtree(!close_btn_visible);
if (close_btn_visible) {
close_button_->SetPosition(close_button_position);
close_button_->SetBounds(close_button_size);
// Non-linear alpha looks better.
close_button_->SetOpacity(close_alpha * close_alpha * border_alpha);
}
if (content_visible) {
{
// content_ and back_logo_ Transforms
gfx::Transform transform;
transform.Scale(content_scale, content_scale);
transform.Translate(content_position.x(), content_position.y());
transform.Translate(descaled_local_content_area.x(),
descaled_local_content_area.y());
content_->layer()->SetHideLayerAndSubtree(back_visible);
back_logo_->SetHideLayerAndSubtree(!back_visible);
if (!back_visible) {
content_->layer()->SetTransformOrigin(gfx::Point3F(0.f, 0.f, 0.f));
content_->layer()->SetTransform(transform);
} else {
back_logo_->SetPosition(back_logo_position);
back_logo_->SetBounds(back_logo_size);
back_logo_->SetTransformOrigin(gfx::Point3F(0.f, 0.f, 0.f));
back_logo_->SetTransform(transform);
// TODO: Set back logo alpha on leaf.
}
}
{
// padding_ Transform
gfx::Size content_bounds;
if (!back_visible)
content_bounds = content_->ComputeSize(id);
gfx::Rect side_padding_rect;
gfx::Rect bottom_padding_rect;
if (content_bounds.width() == 0 || content_bounds.height() == 0) {
// If content_ has 0 width or height, use the side padding to fill
// the desired_content_size.
side_padding_rect.set_size(desired_content_size);
} else {
ComputePaddingPositions(content_bounds, desired_content_size,
&side_padding_rect, &bottom_padding_rect);
}
PositionPadding(side_padding_, side_padding_rect, content_scale,
alpha, content_position, descaled_local_content_area);
PositionPadding(bottom_padding_, bottom_padding_rect, content_scale,
alpha, content_position, descaled_local_content_area);
}
} else {
back_logo_->SetHideLayerAndSubtree(true);
side_padding_->SetHideLayerAndSubtree(true);
bottom_padding_->SetHideLayerAndSubtree(true);
content_->layer()->SetHideLayerAndSubtree(true);
}
{
// Global Transform
gfx::PointF pivot_origin(pivot_y, pivot_x);
gfx::Transform transform;
if (rotation_x != 0 || rotation_y != 0) {
// Apply screen perspective if there are rotations.
transform.Translate(content_width / 2, content_height / 2);
transform.ApplyPerspectiveDepth(
content_width > content_height ? content_width : content_height);
transform.Translate(-content_width / 2, -content_height / 2);
// Translate to correct position on the screen
transform.Translate(x, y);
// Apply pivot rotations
transform.Translate(pivot_origin.x(), pivot_origin.y());
transform.RotateAboutYAxis(rotation_y);
transform.RotateAboutXAxis(-rotation_x);
transform.Translate(-pivot_origin.x(), -pivot_origin.y());
} else {
// Translate to correct position on the screen
transform.Translate(x, y);
}
transform.Scale(border_scale, border_scale);
layer_->SetTransform(transform);
}
// Only applies the brightness filter if the value has changed and is less
// than 1.
if (brightness != brightness_) {
brightness_ = brightness;
cc::FilterOperations filters;
if (brightness_ < 1.f)
filters.Append(cc::FilterOperation::CreateBrightnessFilter(brightness_));
layer_->SetFilters(filters);
}
}
scoped_refptr<cc::Layer> TabLayer::layer() {
return layer_;
}
TabLayer::TabLayer(bool incognito,
ui::ResourceManager* resource_manager,
LayerTitleCache* layer_title_cache,
TabContentManager* tab_content_manager)
: incognito_(incognito),
resource_manager_(resource_manager),
layer_title_cache_(layer_title_cache),
layer_(cc::Layer::Create()),
toolbar_layer_(ToolbarLayer::Create(resource_manager)),
title_(cc::Layer::Create()),
content_(ContentLayer::Create(tab_content_manager)),
side_padding_(cc::SolidColorLayer::Create()),
bottom_padding_(cc::SolidColorLayer::Create()),
close_button_(cc::UIResourceLayer::Create()),
front_border_(cc::NinePatchLayer::Create()),
front_border_inner_shadow_(cc::NinePatchLayer::Create()),
contour_shadow_(cc::NinePatchLayer::Create()),
shadow_(cc::NinePatchLayer::Create()),
back_logo_(cc::UIResourceLayer::Create()),
brightness_(1.f) {
layer_->AddChild(shadow_);
layer_->AddChild(contour_shadow_);
layer_->AddChild(side_padding_);
layer_->AddChild(bottom_padding_);
layer_->AddChild(content_->layer());
layer_->AddChild(back_logo_);
layer_->AddChild(front_border_inner_shadow_);
layer_->AddChild(front_border_);
layer_->AddChild(title_.get());
layer_->AddChild(close_button_);
layer_->AddChild(toolbar_layer_->layer());
contour_shadow_->SetIsDrawable(true);
side_padding_->SetIsDrawable(true);
bottom_padding_->SetIsDrawable(true);
front_border_->SetIsDrawable(true);
front_border_inner_shadow_->SetIsDrawable(true);
shadow_->SetIsDrawable(true);
close_button_->SetIsDrawable(true);
back_logo_->SetIsDrawable(true);
front_border_->SetFillCenter(false);
}
TabLayer::~TabLayer() {
}
void TabLayer::SetTitle(DecorationTitle* title) {
scoped_refptr<cc::Layer> layer = title ? title->layer() : nullptr;
if (!layer.get()) {
title_->RemoveAllChildren();
} else {
const cc::LayerList& children = title_->children();
if (children.size() == 0 || children[0]->id() != layer->id()) {
title_->RemoveAllChildren();
title_->AddChild(layer);
}
}
if (title)
title->SetUIResourceIds();
}
} // namespace android