Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h" | 5 #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h" |
| 6 | 6 |
| 7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
| 8 #include "chrome/browser/ui/layout_constants.h" | 8 #include "chrome/browser/ui/layout_constants.h" |
| 9 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h" | 9 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h" |
| 10 #include "ui/base/material_design/material_design_controller.h" | 10 #include "ui/base/material_design/material_design_controller.h" |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 } | 98 } |
| 99 | 99 |
| 100 bool IconLabelBubbleView::ShouldShowBackground() const { | 100 bool IconLabelBubbleView::ShouldShowBackground() const { |
| 101 return should_show_background_; | 101 return should_show_background_; |
| 102 } | 102 } |
| 103 | 103 |
| 104 double IconLabelBubbleView::WidthMultiplier() const { | 104 double IconLabelBubbleView::WidthMultiplier() const { |
| 105 return 1.0; | 105 return 1.0; |
| 106 } | 106 } |
| 107 | 107 |
| 108 bool IconLabelBubbleView::IsShrinking() const { | |
| 109 return false; | |
| 110 } | |
| 111 | |
| 108 int IconLabelBubbleView::GetImageAndPaddingWidth() const { | 112 int IconLabelBubbleView::GetImageAndPaddingWidth() const { |
| 109 const int image_width = image_->GetPreferredSize().width(); | 113 const int image_width = image_->GetPreferredSize().width(); |
| 110 return image_width | 114 return image_width |
| 111 ? image_width + GetLayoutConstant(ICON_LABEL_VIEW_INTERNAL_PADDING) | 115 ? image_width + GetLayoutConstant(ICON_LABEL_VIEW_INTERNAL_PADDING) |
| 112 : 0; | 116 : 0; |
| 113 } | 117 } |
| 114 | 118 |
| 115 gfx::Size IconLabelBubbleView::GetPreferredSize() const { | 119 gfx::Size IconLabelBubbleView::GetPreferredSize() const { |
| 116 // Height will be ignored by the LocationBarView. | 120 // Height will be ignored by the LocationBarView. |
| 117 return GetSizeForLabelWidth(label_->GetPreferredSize().width()); | 121 return GetSizeForLabelWidth(label_->GetPreferredSize().width()); |
| 118 } | 122 } |
| 119 | 123 |
| 120 void IconLabelBubbleView::Layout() { | 124 void IconLabelBubbleView::Layout() { |
| 121 // In MD mode, both extension icons and Chrome-provided icons are 16px, | 125 // Compute the label bounds. The label gets whatever size is left over after |
| 122 // so it's not necessary to handle them differently. TODO(estade): clean | 126 // accounting for the preferred image width and padding amounts. Note that if |
| 123 // this up when MD is on by default. | 127 // the label has zero size it doesn't actually matter what we compute its X |
| 124 bool icon_has_enough_padding = | 128 // value to be, since it won't be visible, so the X value can be "wrong" |
| 129 // compared to where the right edge of the image is computed to be below. | |
| 130 // This means doing this layout doesn't doesn't depend on any of the layout | |
| 131 // below. That layout, however, may need for this layout to have already | |
| 132 // happened, since the value of ShouldShowBackground() we read below may | |
| 133 // depend on whether the label has nonzero size. Therefore, we do this first. | |
| 134 const int label_x = GetBubbleOuterPadding(true) + GetImageAndPaddingWidth(); | |
| 135 const int label_width = | |
| 136 std::max(0, width() - label_x - GetBubbleOuterPadding(false)); | |
| 137 label_->SetBounds(label_x, 0, label_width, height()); | |
| 138 | |
| 139 // Now compute the image bounds. In non-MD, the leading padding depends on | |
| 140 // whether this is an extension icon, since extension icons and | |
| 141 // Chrome-provided icons are different sizes. In MD, these sizes are the | |
| 142 // same, so it's not necessary to handle the two types differently. | |
| 143 const bool icon_has_enough_padding = | |
| 125 !is_extension_icon_ || ui::MaterialDesignController::IsModeMaterial(); | 144 !is_extension_icon_ || ui::MaterialDesignController::IsModeMaterial(); |
| 126 const int image_width = image_->GetPreferredSize().width(); | 145 int image_x = GetBubbleOuterPadding(icon_has_enough_padding); |
| 127 image_->SetBounds(std::min((width() - image_width) / 2, | |
| 128 GetBubbleOuterPadding(icon_has_enough_padding)), | |
| 129 0, image_->GetPreferredSize().width(), height()); | |
| 130 | 146 |
| 131 int pre_label_width = GetBubbleOuterPadding(true) + GetImageAndPaddingWidth(); | 147 // When animating, there may not be enough space for even just the leading |
| 132 label_->SetBounds(pre_label_width, 0, | 148 // padding, image, and trailing padding. In this case, shrink the trailing |
| 133 width() - pre_label_width - GetBubbleOuterPadding(false), | 149 // padding first, so that as the view animates in the image slides in from the |
| 134 height()); | 150 // trailing edge, and as it animates out it slides all the way to the trailing |
| 151 // edge before slowing or stopping. | |
|
Peter Kasting
2016/03/11 12:05:24
Nit: After your changes this comment no longer des
varkha
2016/03/11 20:04:46
Done.
| |
| 152 const int image_preferred_width = image_->GetPreferredSize().width(); | |
| 153 int bubble_trailing_padding = GetBubbleOuterPadding(false); | |
| 154 | |
| 155 // If ShouldShowBackground() is true, then either we show a background in the | |
| 156 // steady state, or we're not yet in the last portion of the animation. In | |
| 157 // these cases, we leave the leading padding alone, to keep the image pinned | |
| 158 // near the leading edge of the view. If this is false, however, then we're | |
| 159 // only showing the image, and either the view width is the image width, or | |
| 160 // it's animating downwards and getting close to it. In these cases, we want | |
| 161 // to start shrinking the leading padding down to zero once the trailing | |
| 162 // padding has gone down to zero. This is equivalent to checking if the view | |
| 163 // width is not even large enough to accommodate the image preferred width | |
| 164 // and the full leading padding. | |
| 165 if (!ShouldShowBackground()) { | |
| 166 image_x = std::min(image_x, std::max(width() - image_preferred_width, 0)); | |
|
Peter Kasting
2016/03/11 12:05:24
Nit: The std::max() call here is actually unnecess
varkha
2016/03/11 20:04:46
Done.
| |
| 167 bubble_trailing_padding = | |
| 168 std::min(bubble_trailing_padding, | |
| 169 std::max(width() - image_preferred_width - image_x, 0)); | |
|
Peter Kasting
2016/03/11 12:05:24
Nit: Now that this is happening after the image_x
varkha
2016/03/11 20:04:46
Done.
| |
| 170 } | |
| 171 | |
| 172 // Now that we've computed the padding values, give the image all the | |
| 173 // remaining width. This will be less than the image's preferred width during | |
| 174 // the first portion of the animation. | |
| 175 const int image_width = | |
| 176 std::min(image_preferred_width, | |
| 177 std::max(0, width() - image_x - bubble_trailing_padding)); | |
| 178 image_->SetBounds(image_x, 0, image_width, height()); | |
| 135 } | 179 } |
| 136 | 180 |
| 137 void IconLabelBubbleView::OnNativeThemeChanged( | 181 void IconLabelBubbleView::OnNativeThemeChanged( |
| 138 const ui::NativeTheme* native_theme) { | 182 const ui::NativeTheme* native_theme) { |
| 139 label_->SetEnabledColor(GetTextColor()); | 183 label_->SetEnabledColor(GetTextColor()); |
| 140 | 184 |
| 141 if (!ui::MaterialDesignController::IsModeMaterial()) | 185 if (!ui::MaterialDesignController::IsModeMaterial()) |
| 142 return; | 186 return; |
| 143 | 187 |
| 144 bool inverted = color_utils::IsDark(GetParentBackgroundColor()); | 188 bool inverted = color_utils::IsDark(GetParentBackgroundColor()); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 170 return color_utils::DeriveDefaultIconColor(GetTextColor()); | 214 return color_utils::DeriveDefaultIconColor(GetTextColor()); |
| 171 } | 215 } |
| 172 | 216 |
| 173 SkColor IconLabelBubbleView::GetParentBackgroundColor() const { | 217 SkColor IconLabelBubbleView::GetParentBackgroundColor() const { |
| 174 return ui::MaterialDesignController::IsModeMaterial() | 218 return ui::MaterialDesignController::IsModeMaterial() |
| 175 ? GetNativeTheme()->GetSystemColor( | 219 ? GetNativeTheme()->GetSystemColor( |
| 176 ui::NativeTheme::kColorId_TextfieldDefaultBackground) | 220 ui::NativeTheme::kColorId_TextfieldDefaultBackground) |
| 177 : parent_background_color_; | 221 : parent_background_color_; |
| 178 } | 222 } |
| 179 | 223 |
| 180 gfx::Size IconLabelBubbleView::GetSizeForLabelWidth(int width) const { | 224 gfx::Size IconLabelBubbleView::GetSizeForLabelWidth(int label_width) const { |
| 181 gfx::Size size(image_->GetPreferredSize()); | 225 gfx::Size size(image_->GetPreferredSize()); |
| 182 if (ShouldShowBackground()) { | 226 bool shrinking = IsShrinking(); |
| 183 const int non_label_width = GetBubbleOuterPadding(true) + | 227 // Animation continues for the last few pixels even after the label is not |
| 184 GetImageAndPaddingWidth() + | 228 // visible in order to slide the icon into its final position. Therefore it |
| 185 GetBubbleOuterPadding(false); | 229 // is necessary to animate |total_width| even when the background is hidden |
| 186 size = gfx::Size(WidthMultiplier() * (width + non_label_width), 0); | 230 // as long as the animation is still shrinking. |
| 187 if (!ui::MaterialDesignController::IsModeMaterial()) | 231 if (ShouldShowBackground() || shrinking) { |
| 188 size.SetToMax(background_painter_->GetMinimumSize()); | 232 const int image_width = size.width(); |
| 233 const int padding = GetLayoutConstant(ICON_LABEL_VIEW_INTERNAL_PADDING) + | |
| 234 GetBubbleOuterPadding(true) + | |
| 235 GetBubbleOuterPadding(false); | |
| 236 // |multiplier| grows from zero to one, stays equal to one and then shrinks | |
| 237 // to zero again. The view width should correspondingly grow from zero to | |
| 238 // fully showing both label and icon, stay there, then shrink to just large | |
| 239 // enough to show the icon. We don't want to shrink all the way back to | |
| 240 // zero, since this would mean the view would completely disappear and then | |
| 241 // pop back to an icon after the animation finishes. | |
| 242 int total_width = WidthMultiplier() * (label_width + image_width + padding); | |
| 243 if (shrinking) | |
| 244 total_width = std::max(total_width, image_width); | |
| 245 size.set_width(total_width); | |
| 189 } | 246 } |
| 247 return size; | |
| 248 } | |
| 190 | 249 |
| 191 return size; | 250 int IconLabelBubbleView::GetBubbleOuterPadding(bool leading) const { |
| 251 if (ui::MaterialDesignController::IsModeMaterial()) | |
| 252 return GetBubbleOuterPaddingMd(leading); | |
| 253 | |
| 254 return GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING) - | |
| 255 GetLayoutConstant(LOCATION_BAR_BUBBLE_HORIZONTAL_PADDING) + | |
| 256 (leading ? 0 : GetLayoutConstant(ICON_LABEL_VIEW_TRAILING_PADDING)); | |
| 192 } | 257 } |
| 193 | 258 |
| 194 void IconLabelBubbleView::SetLabelBackgroundColor( | 259 void IconLabelBubbleView::SetLabelBackgroundColor( |
| 195 SkColor chip_background_color) { | 260 SkColor chip_background_color) { |
| 196 // The background images are painted atop |parent_background_color_|. | 261 // The background images are painted atop |parent_background_color_|. |
| 197 // Alpha-blend |chip_background_color| with |parent_background_color_| to | 262 // Alpha-blend |chip_background_color| with |parent_background_color_| to |
| 198 // determine the actual color the label text will sit atop. | 263 // determine the actual color the label text will sit atop. |
| 199 // Tricky bit: We alpha blend an opaque version of |chip_background_color| | 264 // Tricky bit: We alpha blend an opaque version of |chip_background_color| |
| 200 // against |parent_background_color_| using the original image grid color's | 265 // against |parent_background_color_| using the original image grid color's |
| 201 // alpha. This is because AlphaBlend(a, b, 255) always returns |a| unchanged | 266 // alpha. This is because AlphaBlend(a, b, 255) always returns |a| unchanged |
| 202 // even if |a| is a color with non-255 alpha. | 267 // even if |a| is a color with non-255 alpha. |
| 203 label_->SetBackgroundColor(color_utils::AlphaBlend( | 268 label_->SetBackgroundColor(color_utils::AlphaBlend( |
| 204 SkColorSetA(chip_background_color, 255), GetParentBackgroundColor(), | 269 SkColorSetA(chip_background_color, 255), GetParentBackgroundColor(), |
| 205 SkColorGetA(chip_background_color))); | 270 SkColorGetA(chip_background_color))); |
| 206 } | 271 } |
| 207 | 272 |
| 208 int IconLabelBubbleView::GetBubbleOuterPadding(bool leading) const { | |
| 209 if (ui::MaterialDesignController::IsModeMaterial()) | |
| 210 return GetBubbleOuterPaddingMd(leading); | |
| 211 | |
| 212 return GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING) - | |
| 213 GetLayoutConstant(LOCATION_BAR_BUBBLE_HORIZONTAL_PADDING) + | |
| 214 (leading ? 0 : GetLayoutConstant(ICON_LABEL_VIEW_TRAILING_PADDING)); | |
| 215 } | |
| 216 | |
| 217 int IconLabelBubbleView::GetBubbleOuterPaddingMd(bool leading) const { | 273 int IconLabelBubbleView::GetBubbleOuterPaddingMd(bool leading) const { |
| 218 // When the image is empty, leading and trailing padding are equal. | 274 // When the image is empty, leading and trailing padding are equal. |
| 219 if (image_->GetPreferredSize().IsEmpty() || !leading) | 275 if (image_->GetPreferredSize().IsEmpty() || !leading) |
| 220 return GetLayoutConstant(ICON_LABEL_VIEW_TRAILING_PADDING); | 276 return GetLayoutConstant(ICON_LABEL_VIEW_TRAILING_PADDING); |
| 221 | 277 |
| 222 // Leading padding is 2dp. | 278 // Leading padding is 2dp. |
| 223 return 2; | 279 return 2; |
| 224 } | 280 } |
| 225 | 281 |
| 226 const char* IconLabelBubbleView::GetClassName() const { | 282 const char* IconLabelBubbleView::GetClassName() const { |
| 227 return "IconLabelBubbleView"; | 283 return "IconLabelBubbleView"; |
| 228 } | 284 } |
| 229 | 285 |
| 230 void IconLabelBubbleView::OnPaint(gfx::Canvas* canvas) { | 286 void IconLabelBubbleView::OnPaint(gfx::Canvas* canvas) { |
| 231 if (!ShouldShowBackground()) | 287 if (!ShouldShowBackground()) |
| 232 return; | 288 return; |
| 233 if (background_painter_) { | 289 if (background_painter_) { |
| 234 views::Painter::PaintPainterAt(canvas, background_painter_.get(), | 290 views::Painter::PaintPainterAt(canvas, background_painter_.get(), |
| 235 GetContentsBounds()); | 291 GetContentsBounds()); |
| 236 } | 292 } |
| 237 if (background()) | 293 if (background()) |
| 238 background()->Paint(canvas, this); | 294 background()->Paint(canvas, this); |
| 239 } | 295 } |
| OLD | NEW |