| // Copyright 2015 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/overlay_panel_layer.h" |
| |
| #include "cc/layers/layer.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 "third_party/skia/include/core/SkColor.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/color_utils.h" |
| |
| namespace android { |
| |
| scoped_refptr<cc::Layer> OverlayPanelLayer::GetIconLayer() { |
| if (panel_icon_resource_id_ == kInvalidResourceID) |
| return nullptr; |
| ui::Resource* panel_icon_resource = resource_manager_->GetResource( |
| ui::ANDROID_RESOURCE_TYPE_STATIC, panel_icon_resource_id_); |
| DCHECK(panel_icon_resource); |
| |
| if (panel_icon_->parent() != layer_) { |
| layer_->AddChild(panel_icon_); |
| } |
| |
| panel_icon_->SetUIResourceId(panel_icon_resource->ui_resource()->id()); |
| panel_icon_->SetBounds(panel_icon_resource->size()); |
| |
| return panel_icon_; |
| } |
| |
| void OverlayPanelLayer::AddBarTextLayer(scoped_refptr<cc::Layer> text_layer) { |
| if (text_container_->parent() != layer_) |
| layer_->AddChild(text_container_); |
| if (text_layer->parent() != text_container_) |
| text_container_->AddChild(text_layer); |
| } |
| |
| void OverlayPanelLayer::SetResourceIds(int bar_text_resource_id, |
| int panel_shadow_resource_id, |
| int rounded_bar_top_resource_id, |
| int bar_shadow_resource_id, |
| int panel_icon_resource_id, |
| int drag_handlebar_resource_id, |
| int open_tab_icon_resource_id, |
| int close_icon_resource_id) { |
| bar_text_resource_id_ = bar_text_resource_id; |
| panel_shadow_resource_id_ = panel_shadow_resource_id; |
| rounded_bar_top_resource_id_ = rounded_bar_top_resource_id; |
| bar_shadow_resource_id_ = bar_shadow_resource_id; |
| panel_icon_resource_id_ = panel_icon_resource_id; |
| drag_handlebar_resource_id_ = drag_handlebar_resource_id; |
| open_tab_icon_resource_id_ = open_tab_icon_resource_id; |
| close_icon_resource_id_ = close_icon_resource_id; |
| } |
| |
| void OverlayPanelLayer::SetProperties( |
| float dp_to_px, |
| const scoped_refptr<cc::Layer>& content_layer, |
| float content_offset_y, |
| float panel_x, |
| float panel_y, |
| float panel_width, |
| float panel_height, |
| int bar_background_color, |
| float bar_margin_side, |
| float bar_margin_top, |
| float bar_height, |
| float bar_offset_y, |
| float bar_text_opacity, |
| bool bar_border_visible, |
| float bar_border_height, |
| bool bar_shadow_visible, |
| int icon_tint, |
| int drag_handlebar_tint, |
| float icon_opacity, |
| int separator_line_color) { |
| // Round values to avoid pixel gap between layers. |
| bar_height = floor(bar_height); |
| |
| float bar_top_y = bar_offset_y; |
| float bar_bottom = bar_top_y + bar_height; |
| |
| bool is_rtl = l10n_util::IsLayoutRtl(); |
| |
| // --------------------------------------------------------------------------- |
| // Panel Shadow |
| // --------------------------------------------------------------------------- |
| if (panel_shadow_resource_id_ != kInvalidResourceID) { |
| if (panel_shadow_->parent() != layer_) { |
| layer_->AddChild(panel_shadow_); |
| } |
| ui::NinePatchResource* panel_shadow_resource = |
| ui::NinePatchResource::From(resource_manager_->GetResource( |
| ui::ANDROID_RESOURCE_TYPE_STATIC, panel_shadow_resource_id_)); |
| DCHECK(panel_shadow_resource); |
| |
| gfx::Size shadow_res_size = panel_shadow_resource->size(); |
| gfx::Rect shadow_res_padding = panel_shadow_resource->padding(); |
| gfx::Size shadow_bounds(panel_width + shadow_res_size.width() - |
| shadow_res_padding.size().width(), |
| panel_height + shadow_res_size.height() - |
| shadow_res_padding.size().height()); |
| panel_shadow_->SetUIResourceId(panel_shadow_resource->ui_resource()->id()); |
| panel_shadow_->SetBorder(panel_shadow_resource->Border(shadow_bounds)); |
| panel_shadow_->SetAperture(panel_shadow_resource->aperture()); |
| panel_shadow_->SetBounds(shadow_bounds); |
| gfx::PointF shadow_position(-shadow_res_padding.origin().x(), |
| -shadow_res_padding.origin().y()); |
| panel_shadow_->SetPosition(shadow_position); |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Content setup, to center in space below drag handle (when present). |
| // --------------------------------------------------------------------------- |
| int content_top_y = bar_top_y; |
| int content_height = bar_height; |
| int rounded_top_adjust = 0; |
| if (rounded_bar_top_resource_id_ != kInvalidResourceID) { |
| content_top_y += bar_margin_top; |
| content_height -= bar_margin_top; |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Rounded Bar Top |
| // --------------------------------------------------------------------------- |
| if (rounded_bar_top_resource_id_ != kInvalidResourceID) { |
| rounded_bar_top_->SetIsDrawable(true); |
| |
| ui::NinePatchResource* rounded_bar_top_resource = |
| ui::NinePatchResource::From(resource_manager_->GetResource( |
| ui::ANDROID_RESOURCE_TYPE_STATIC, rounded_bar_top_resource_id_)); |
| |
| DCHECK(rounded_bar_top_resource); |
| |
| const gfx::Size rounded_bar_top_size( |
| rounded_bar_top_resource->size().width() - |
| rounded_bar_top_resource->padding().width(), |
| rounded_bar_top_resource->size().height() - |
| rounded_bar_top_resource->padding().height()); |
| |
| // TODO(donnd): fix correctly. |
| const int vertical_fudge_factor = 2; // Create an overlap to avoid a seam. |
| rounded_top_adjust = rounded_bar_top_size.height() - vertical_fudge_factor; |
| |
| gfx::PointF rounded_bar_top_position( |
| -rounded_bar_top_resource->padding().x(), |
| bar_top_y - rounded_top_adjust); |
| |
| gfx::Size bounds(panel_width - rounded_bar_top_size.width(), |
| rounded_bar_top_resource->size().height()); |
| |
| rounded_bar_top_->SetUIResourceId( |
| rounded_bar_top_resource->ui_resource()->id()); |
| rounded_bar_top_->SetBounds(bounds); |
| rounded_bar_top_->SetAperture(rounded_bar_top_resource->aperture()); |
| rounded_bar_top_->SetBorder(rounded_bar_top_resource->Border(bounds)); |
| rounded_bar_top_->SetPosition(rounded_bar_top_position); |
| rounded_bar_top_->SetOpacity(1.0f); |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Bar Background |
| // --------------------------------------------------------------------------- |
| // If we have a rounded_bar_top then it draws the top part of the bar |
| // background. |
| gfx::Size background_size(panel_width, bar_height - rounded_top_adjust); |
| bar_background_->SetBounds(background_size); |
| bar_background_->SetPosition( |
| gfx::PointF(0.f, bar_top_y + rounded_top_adjust)); |
| bar_background_->SetBackgroundColor(bar_background_color); |
| |
| // --------------------------------------------------------------------------- |
| // Bar Text |
| // --------------------------------------------------------------------------- |
| ui::Resource* bar_text_resource = resource_manager_->GetResource( |
| ui::ANDROID_RESOURCE_TYPE_DYNAMIC, bar_text_resource_id_); |
| |
| if (bar_text_resource) { |
| // Centers the text vertically in the section of the Search Bar below the |
| // drag handle. |
| float bar_padding_top = content_top_y + content_height / 2 - |
| bar_text_resource->size().height() / 2; |
| bar_text_->SetUIResourceId(bar_text_resource->ui_resource()->id()); |
| bar_text_->SetBounds(bar_text_resource->size()); |
| bar_text_->SetPosition(gfx::PointF(0.f, bar_padding_top)); |
| bar_text_->SetOpacity(bar_text_opacity); |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Panel Icon |
| // --------------------------------------------------------------------------- |
| scoped_refptr<cc::Layer> icon_layer = GetIconLayer(); |
| if (icon_layer) { |
| // If the icon is not the default width, add or remove padding so it appears |
| // centered. |
| float icon_padding = (kDefaultIconWidthDp * dp_to_px - |
| icon_layer->bounds().width()) / 2.0f; |
| |
| // Positions the Icon at the start of the bar. |
| float icon_x; |
| if (is_rtl) { |
| icon_x = panel_width - icon_layer->bounds().width() - |
| (bar_margin_side + icon_padding); |
| } else { |
| icon_x = bar_margin_side + icon_padding; |
| } |
| |
| // Centers the Icon vertically in the bar. |
| float icon_y = |
| content_top_y + content_height / 2 - icon_layer->bounds().height() / 2; |
| |
| icon_layer->SetPosition(gfx::PointF(icon_x, icon_y)); |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Drag Handlebar |
| // --------------------------------------------------------------------------- |
| if (drag_handlebar_resource_id_ != kInvalidResourceID) { |
| if (drag_handlebar_->parent() != layer_) |
| layer_->AddChild(drag_handlebar_); |
| |
| ui::Resource* drag_handlebar_resource = |
| resource_manager_->GetStaticResourceWithTint( |
| drag_handlebar_resource_id_, drag_handlebar_tint); |
| drag_handlebar_->SetUIResourceId( |
| drag_handlebar_resource->ui_resource()->id()); |
| drag_handlebar_->SetBounds(drag_handlebar_resource->size()); |
| float drag_handlebar_left = |
| panel_width / 2 - drag_handlebar_resource->size().width() / 2; |
| float drag_handlebar_top = bar_top_y + bar_margin_top - |
| drag_handlebar_resource->size().height() / 2; |
| drag_handlebar_->SetPosition( |
| gfx::PointF(drag_handlebar_left, drag_handlebar_top)); |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Close Icon |
| // --------------------------------------------------------------------------- |
| int close_icon_width = 0; |
| float close_icon_left = 0.f; |
| // Positions the icon at the end of the bar. |
| if (is_rtl) { |
| close_icon_left = bar_margin_side; |
| } else { |
| close_icon_left = panel_width - bar_margin_side; |
| } |
| if (close_icon_resource_id_ != kInvalidResourceID) { |
| // Grab the Close Icon resource. |
| ui::Resource* close_icon_resource = |
| resource_manager_->GetStaticResourceWithTint(close_icon_resource_id_, |
| icon_tint); |
| |
| // Positions the icon at the end of the bar. |
| close_icon_width = close_icon_resource->size().width(); |
| if (!is_rtl) { |
| close_icon_left = close_icon_left - close_icon_width; |
| } |
| |
| // Centers the Close Icon vertically in the bar. |
| float close_icon_top = content_top_y + content_height / 2 - |
| close_icon_resource->size().height() / 2; |
| close_icon_->SetUIResourceId(close_icon_resource->ui_resource()->id()); |
| close_icon_->SetBounds(close_icon_resource->size()); |
| close_icon_->SetPosition(gfx::PointF(close_icon_left, close_icon_top)); |
| close_icon_->SetOpacity(icon_opacity); |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Open Tab icon |
| // --------------------------------------------------------------------------- |
| if (open_tab_icon_resource_id_ != kInvalidResourceID) { |
| ui::Resource* open_tab_icon_resource = |
| resource_manager_->GetStaticResourceWithTint(open_tab_icon_resource_id_, |
| icon_tint); |
| // Positions the icon at the end of the bar. |
| float open_tab_top = content_top_y + content_height / 2 - |
| open_tab_icon_resource->size().height() / 2; |
| float open_tab_left; |
| float spacing_between_icons = 2 * bar_margin_side; |
| float margin_from_close_icon = close_icon_width + spacing_between_icons; |
| if (is_rtl) { |
| open_tab_left = close_icon_left + margin_from_close_icon; |
| } else { |
| open_tab_left = close_icon_left - margin_from_close_icon; |
| } |
| |
| open_tab_icon_->SetUIResourceId( |
| open_tab_icon_resource->ui_resource()->id()); |
| open_tab_icon_->SetBounds(open_tab_icon_resource->size()); |
| open_tab_icon_->SetPosition(gfx::PointF(open_tab_left, open_tab_top)); |
| open_tab_icon_->SetOpacity(icon_opacity); |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Overlay Web Content |
| // --------------------------------------------------------------------------- |
| content_container_->SetPosition( |
| gfx::PointF(0.f, content_offset_y)); |
| content_container_->SetBounds(gfx::Size(panel_width, panel_height)); |
| content_container_->SetBackgroundColor(bar_background_color); |
| if (content_layer) { |
| if (content_layer->parent() != content_container_) |
| content_container_->AddChild(content_layer); |
| } else { |
| content_container_->RemoveAllChildren(); |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Bar Shadow |
| // --------------------------------------------------------------------------- |
| if (bar_shadow_visible) { |
| ui::Resource* bar_shadow_resource = resource_manager_->GetResource( |
| ui::ANDROID_RESOURCE_TYPE_STATIC, bar_shadow_resource_id_); |
| |
| if (bar_shadow_resource) { |
| if (bar_shadow_->parent() != layer_) |
| layer_->AddChild(bar_shadow_); |
| |
| int shadow_height = bar_shadow_resource->size().height(); |
| gfx::Size shadow_size(panel_width, shadow_height); |
| |
| bar_shadow_->SetUIResourceId(bar_shadow_resource->ui_resource()->id()); |
| bar_shadow_->SetBounds(shadow_size); |
| bar_shadow_->SetPosition(gfx::PointF(0.f, bar_bottom)); |
| bar_shadow_->SetOpacity(1.0f); |
| } |
| } else { |
| if (bar_shadow_.get() && bar_shadow_->parent()) |
| bar_shadow_->RemoveFromParent(); |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Panel |
| // --------------------------------------------------------------------------- |
| layer_->SetPosition(gfx::PointF(panel_x, panel_y)); |
| |
| // --------------------------------------------------------------------------- |
| // Bar border |
| // --------------------------------------------------------------------------- |
| if (bar_border_visible) { |
| gfx::Size bar_border_size(panel_width, |
| bar_border_height); |
| float border_y = bar_bottom - bar_border_height; |
| bar_border_->SetBounds(bar_border_size); |
| bar_border_->SetPosition( |
| gfx::PointF(0.f, border_y)); |
| bar_border_->SetBackgroundColor(separator_line_color); |
| if (bar_border_->parent() != layer_) |
| layer_->AddChild(bar_border_); |
| } else if (bar_border_.get() && bar_border_->parent()) { |
| bar_border_->RemoveFromParent(); |
| } |
| } |
| |
| void OverlayPanelLayer::SetProgressBar(int progress_bar_background_resource_id, |
| int progress_bar_resource_id, |
| bool progress_bar_visible, |
| float progress_bar_position_y, |
| float progress_bar_height, |
| float progress_bar_opacity, |
| int progress_bar_completion, |
| float panel_width) { |
| bool should_render_progress_bar = |
| progress_bar_visible && progress_bar_opacity > 0.f; |
| |
| 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 = progress_bar_position_y - 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(); |
| } |
| } |
| |
| OverlayPanelLayer::OverlayPanelLayer(ui::ResourceManager* resource_manager) |
| : resource_manager_(resource_manager), |
| layer_(cc::Layer::Create()), |
| panel_shadow_(cc::NinePatchLayer::Create()), |
| rounded_bar_top_(cc::NinePatchLayer::Create()), |
| bar_background_(cc::SolidColorLayer::Create()), |
| bar_text_(cc::UIResourceLayer::Create()), |
| bar_shadow_(cc::UIResourceLayer::Create()), |
| panel_icon_(cc::UIResourceLayer::Create()), |
| drag_handlebar_(cc::UIResourceLayer::Create()), |
| open_tab_icon_(cc::UIResourceLayer::Create()), |
| close_icon_(cc::UIResourceLayer::Create()), |
| content_container_(cc::SolidColorLayer::Create()), |
| text_container_(cc::Layer::Create()), |
| bar_border_(cc::SolidColorLayer::Create()), |
| progress_bar_(cc::NinePatchLayer::Create()), |
| progress_bar_background_(cc::NinePatchLayer::Create()) { |
| // Background colors for each widget are set in SetProperties, where variable |
| // colors are available. |
| layer_->SetMasksToBounds(false); |
| layer_->SetIsDrawable(true); |
| |
| // Panel Shadow |
| panel_shadow_->SetIsDrawable(true); |
| panel_shadow_->SetFillCenter(false); |
| |
| // Rounded Bar Top |
| // Puts the layer near the bottom -- we'll decide if it's actually drawable |
| // later. |
| rounded_bar_top_->SetIsDrawable(false); |
| layer_->AddChild(rounded_bar_top_); |
| |
| // Bar Background |
| bar_background_->SetIsDrawable(true); |
| layer_->AddChild(bar_background_); |
| |
| // Bar Text |
| bar_text_->SetIsDrawable(true); |
| AddBarTextLayer(bar_text_); |
| |
| // Panel Icon |
| panel_icon_->SetIsDrawable(true); |
| |
| // The container that any text in the bar will be added to. |
| text_container_->SetIsDrawable(true); |
| |
| // Drag Handlebar |
| drag_handlebar_->SetIsDrawable(true); |
| |
| // Open Tab Icon |
| open_tab_icon_->SetIsDrawable(true); |
| layer_->AddChild(open_tab_icon_); |
| |
| // Close Icon |
| close_icon_->SetIsDrawable(true); |
| layer_->AddChild(close_icon_); |
| |
| // Content Container |
| content_container_->SetIsDrawable(true); |
| layer_->AddChild(content_container_); |
| |
| // Bar Border |
| bar_border_->SetIsDrawable(true); |
| |
| // Bar Shadow |
| bar_shadow_->SetIsDrawable(true); |
| |
| // Progress Bar Background |
| progress_bar_background_->SetIsDrawable(true); |
| progress_bar_background_->SetFillCenter(true); |
| |
| // Progress Bar |
| progress_bar_->SetIsDrawable(true); |
| progress_bar_->SetFillCenter(true); |
| } |
| |
| OverlayPanelLayer::~OverlayPanelLayer() { |
| } |
| |
| scoped_refptr<cc::Layer> OverlayPanelLayer::layer() { |
| return layer_; |
| } |
| |
| } // namespace android |