Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / location_bar / content_setting_image_view.cc
blob28410ee8072cf800df647fa337c5e8bba1b7486d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
9 #include "chrome/browser/themes/theme_properties.h"
10 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
11 #include "chrome/browser/ui/content_settings/content_setting_image_model.h"
12 #include "chrome/browser/ui/views/content_setting_bubble_contents.h"
13 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
14 #include "grit/theme_resources.h"
15 #include "ui/base/l10n/l10n_util.h"
16 #include "ui/base/resource/material_design/material_design_controller.h"
17 #include "ui/base/theme_provider.h"
18 #include "ui/gfx/color_utils.h"
19 #include "ui/views/controls/image_view.h"
20 #include "ui/views/controls/label.h"
21 #include "ui/views/widget/widget.h"
24 namespace {
25 // Time spent with animation fully open.
26 const int kStayOpenTimeMS = 3200;
30 // static
31 const int ContentSettingImageView::kOpenTimeMS = 150;
32 const int ContentSettingImageView::kAnimationDurationMS =
33 (kOpenTimeMS * 2) + kStayOpenTimeMS;
35 ContentSettingImageView::ContentSettingImageView(
36 ContentSettingsType content_type,
37 LocationBarView* parent,
38 const gfx::FontList& font_list,
39 SkColor text_color,
40 SkColor parent_background_color)
41 : IconLabelBubbleView(0,
42 font_list,
43 text_color,
44 parent_background_color,
45 false),
46 parent_(parent),
47 content_setting_image_model_(
48 ContentSettingImageModel::CreateContentSettingImageModel(
49 content_type)),
50 slide_animator_(this),
51 pause_animation_(false),
52 pause_animation_state_(0.0),
53 bubble_widget_(NULL) {
54 if (ui::MaterialDesignController::IsModeMaterial()) {
55 // The insets for IDR_OMNIBOX_CONTENT_SETTING_BUBBLE for which to perfom
56 // nine-slicing.
57 static const int kImageInset = 4;
58 gfx::Insets insets(kImageInset, kImageInset, kImageInset, kImageInset);
59 SetBackgroundImageWithInsets(IDR_OMNIBOX_CONTENT_SETTING_BUBBLE, insets);
60 } else {
61 static const int kBackgroundImages[] =
62 IMAGE_GRID(IDR_OMNIBOX_CONTENT_SETTING_BUBBLE);
63 SetBackgroundImageGrid(kBackgroundImages);
66 image()->SetHorizontalAlignment(views::ImageView::LEADING);
67 image()->set_interactive(true);
68 label()->SetElideBehavior(gfx::NO_ELIDE);
70 slide_animator_.SetSlideDuration(kAnimationDurationMS);
71 slide_animator_.SetTweenType(gfx::Tween::LINEAR);
74 ContentSettingImageView::~ContentSettingImageView() {
75 if (bubble_widget_)
76 bubble_widget_->RemoveObserver(this);
79 void ContentSettingImageView::Update(content::WebContents* web_contents) {
80 // Note: We explicitly want to call this even if |web_contents| is NULL, so we
81 // get hidden properly while the user is editing the omnibox.
82 content_setting_image_model_->UpdateFromWebContents(web_contents);
84 if (!content_setting_image_model_->is_visible()) {
85 SetVisible(false);
86 return;
89 SetImage(content_setting_image_model_->icon().AsImageSkia());
90 image()->SetTooltipText(
91 base::UTF8ToUTF16(content_setting_image_model_->get_tooltip()));
92 SetVisible(true);
94 // If the content blockage should be indicated to the user, start the
95 // animation and record that we indicated the blockage.
96 TabSpecificContentSettings* content_settings = web_contents ?
97 TabSpecificContentSettings::FromWebContents(web_contents) : NULL;
98 if (!content_settings || content_settings->IsBlockageIndicated(
99 content_setting_image_model_->get_content_settings_type()))
100 return;
102 // We just ignore this blockage if we're already showing some other string to
103 // the user. If this becomes a problem, we could design some sort of queueing
104 // mechanism to show one after the other, but it doesn't seem important now.
105 int string_id = content_setting_image_model_->explanatory_string_id();
106 if (string_id && !ShouldShowBackground()) {
107 SetLabel(l10n_util::GetStringUTF16(string_id));
108 label()->SetVisible(true);
109 slide_animator_.Show();
112 content_settings->SetBlockageHasBeenIndicated(
113 content_setting_image_model_->get_content_settings_type());
116 bool ContentSettingImageView::ShouldShowBackground() const {
117 return slide_animator_.is_animating() || pause_animation_;
120 double ContentSettingImageView::WidthMultiplier() const {
121 double state = slide_animator_.GetCurrentValue();
122 // The fraction of the animation we'll spend animating the string into view,
123 // which is also the fraction we'll spend animating it closed; total
124 // animation (slide out, show, then slide in) is 1.0.
125 const double kOpenFraction =
126 static_cast<double>(kOpenTimeMS) / kAnimationDurationMS;
127 double size_fraction = 1.0;
128 if (state < kOpenFraction)
129 size_fraction = state / kOpenFraction;
130 if (state > (1.0 - kOpenFraction))
131 size_fraction = (1.0 - state) / kOpenFraction;
132 return size_fraction;
135 void ContentSettingImageView::AnimationEnded(const gfx::Animation* animation) {
136 slide_animator_.Reset();
137 if (!pause_animation_) {
138 label()->SetVisible(false);
139 parent_->Layout();
140 parent_->SchedulePaint();
144 void ContentSettingImageView::AnimationProgressed(
145 const gfx::Animation* animation) {
146 if (!pause_animation_) {
147 parent_->Layout();
148 parent_->SchedulePaint();
152 void ContentSettingImageView::AnimationCanceled(
153 const gfx::Animation* animation) {
154 AnimationEnded(animation);
157 const char* ContentSettingImageView::GetClassName() const {
158 return "ContentSettingsImageView";
161 bool ContentSettingImageView::OnMousePressed(const ui::MouseEvent& event) {
162 // We want to show the bubble on mouse release; that is the standard behavior
163 // for buttons.
164 return true;
167 void ContentSettingImageView::OnMouseReleased(const ui::MouseEvent& event) {
168 if (HitTestPoint(event.location()))
169 OnClick();
172 void ContentSettingImageView::OnGestureEvent(ui::GestureEvent* event) {
173 if (event->type() == ui::ET_GESTURE_TAP)
174 OnClick();
175 if ((event->type() == ui::ET_GESTURE_TAP) ||
176 (event->type() == ui::ET_GESTURE_TAP_DOWN))
177 event->SetHandled();
180 void ContentSettingImageView::OnWidgetDestroying(views::Widget* widget) {
181 DCHECK_EQ(bubble_widget_, widget);
182 bubble_widget_->RemoveObserver(this);
183 bubble_widget_ = NULL;
185 if (pause_animation_) {
186 slide_animator_.Reset(pause_animation_state_);
187 pause_animation_ = false;
188 slide_animator_.Show();
192 void ContentSettingImageView::OnClick() {
193 if (slide_animator_.is_animating()) {
194 if (!pause_animation_) {
195 pause_animation_ = true;
196 pause_animation_state_ = slide_animator_.GetCurrentValue();
198 slide_animator_.Reset();
201 content::WebContents* web_contents = parent_->GetWebContents();
202 if (web_contents && !bubble_widget_) {
203 bubble_widget_ =
204 parent_->delegate()->CreateViewsBubble(new ContentSettingBubbleContents(
205 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
206 parent_->delegate()->GetContentSettingBubbleModelDelegate(),
207 web_contents, parent_->profile(),
208 content_setting_image_model_->get_content_settings_type()),
209 web_contents, this, views::BubbleBorder::TOP_RIGHT));
210 bubble_widget_->AddObserver(this);
211 bubble_widget_->Show();