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" |
| 11 #include "ui/base/resource/resource_bundle.h" | 11 #include "ui/base/resource/resource_bundle.h" |
| 12 #include "ui/gfx/canvas.h" | 12 #include "ui/gfx/canvas.h" |
| 13 #include "ui/gfx/color_utils.h" | 13 #include "ui/gfx/color_utils.h" |
| 14 #include "ui/gfx/image/image_util.h" | 14 #include "ui/gfx/image/image_util.h" |
| 15 #include "ui/gfx/scoped_canvas.h" | 15 #include "ui/gfx/scoped_canvas.h" |
| 16 #include "ui/native_theme/native_theme.h" | 16 #include "ui/native_theme/native_theme.h" |
| 17 #include "ui/views/animation/ink_drop_highlight.h" | 17 #include "ui/views/animation/ink_drop_highlight.h" |
| 18 #include "ui/views/border.h" | 18 #include "ui/views/border.h" |
| 19 #include "ui/views/controls/image_view.h" | 19 #include "ui/views/controls/image_view.h" |
| 20 #include "ui/views/controls/textfield/textfield.h" | 20 #include "ui/views/controls/textfield/textfield.h" |
| 21 #include "ui/views/painter.h" | 21 #include "ui/views/painter.h" |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 // Extra padding to place at the end of the chip when the label is showing. | 25 // Amount of space on either side of the separator that appears after the label. |
| 26 const int kExtraTrailingPadding = 7; | 26 constexpr int kSpaceBesideSeparator = 8; |
| 27 | |
| 28 // We really only want 1 px for the separator, but there's no way to use that to | |
| 29 // lay out, so the best we can do is to reserve a whole DIP. | |
|
Evan Stade
2016/06/15 23:12:58
wouldn't the more correct thing to do be reserve 0
Peter Kasting
2016/06/16 05:12:39
Yeah, that would be better. Changed, though this
| |
| 30 constexpr int kSeparatorWidth = 1; | |
| 27 | 31 |
| 28 SkColor CalculateImageColor(gfx::ImageSkia* image) { | 32 SkColor CalculateImageColor(gfx::ImageSkia* image) { |
| 29 // We grab the color of the middle pixel of the image, which we treat as | 33 // We grab the color of the middle pixel of the image, which we treat as |
| 30 // the representative color of the entire image (reasonable, given the current | 34 // the representative color of the entire image (reasonable, given the current |
| 31 // appearance of these assets). | 35 // appearance of these assets). |
| 32 const SkBitmap& bitmap(image->GetRepresentation(1.0f).sk_bitmap()); | 36 const SkBitmap& bitmap(image->GetRepresentation(1.0f).sk_bitmap()); |
| 33 SkAutoLockPixels pixel_lock(bitmap); | 37 SkAutoLockPixels pixel_lock(bitmap); |
| 34 return bitmap.getColor(bitmap.width() / 2, bitmap.height() / 2); | 38 return bitmap.getColor(bitmap.width() / 2, bitmap.height() / 2); |
| 35 } | 39 } |
| 36 | 40 |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 } | 226 } |
| 223 | 227 |
| 224 gfx::Size IconLabelBubbleView::GetSizeForLabelWidth(int label_width) const { | 228 gfx::Size IconLabelBubbleView::GetSizeForLabelWidth(int label_width) const { |
| 225 gfx::Size size(image_->GetPreferredSize()); | 229 gfx::Size size(image_->GetPreferredSize()); |
| 226 const bool shrinking = IsShrinking(); | 230 const bool shrinking = IsShrinking(); |
| 227 // Animation continues for the last few pixels even after the label is not | 231 // Animation continues for the last few pixels even after the label is not |
| 228 // visible in order to slide the icon into its final position. Therefore it | 232 // visible in order to slide the icon into its final position. Therefore it |
| 229 // is necessary to animate |total_width| even when the background is hidden | 233 // is necessary to animate |total_width| even when the background is hidden |
| 230 // as long as the animation is still shrinking. | 234 // as long as the animation is still shrinking. |
| 231 if (ShouldShowBackground() || shrinking) { | 235 if (ShouldShowBackground() || shrinking) { |
| 232 const int extra_trailing_padding = | |
| 233 ui::MaterialDesignController::IsModeMaterial() ? kExtraTrailingPadding | |
| 234 : 0; | |
| 235 // |multiplier| grows from zero to one, stays equal to one and then shrinks | 236 // |multiplier| grows from zero to one, stays equal to one and then shrinks |
| 236 // to zero again. The view width should correspondingly grow from zero to | 237 // to zero again. The view width should correspondingly grow from zero to |
| 237 // fully showing both label and icon, stay there, then shrink to just large | 238 // fully showing both label and icon, stay there, then shrink to just large |
| 238 // enough to show the icon. We don't want to shrink all the way back to | 239 // enough to show the icon. We don't want to shrink all the way back to |
| 239 // zero, since this would mean the view would completely disappear and then | 240 // zero, since this would mean the view would completely disappear and then |
| 240 // pop back to an icon after the animation finishes. | 241 // pop back to an icon after the animation finishes. |
| 241 const int max_width = MinimumWidthForImageWithBackgroundShown() + | 242 const int max_width = GetImageTrailingEdge() + GetInternalSpacing() + |
| 242 GetInternalSpacing() + label_width + | 243 label_width + GetPostLabelWidth(); |
| 243 extra_trailing_padding; | |
| 244 const int current_width = WidthMultiplier() * max_width; | 244 const int current_width = WidthMultiplier() * max_width; |
| 245 size.set_width(shrinking ? std::max(current_width, size.width()) | 245 size.set_width(shrinking ? std::max(current_width, size.width()) |
| 246 : current_width); | 246 : current_width); |
| 247 } | 247 } |
| 248 return size; | 248 return size; |
| 249 } | 249 } |
| 250 | 250 |
| 251 int IconLabelBubbleView::MinimumWidthForImageWithBackgroundShown() const { | 251 int IconLabelBubbleView::MinimumWidthForImageWithBackgroundShown() const { |
| 252 return GetOuterPadding(true) + image_->GetPreferredSize().width() + | 252 return GetImageTrailingEdge() + GetOuterPadding(false); |
| 253 GetOuterPadding(false); | |
| 254 } | 253 } |
| 255 | 254 |
| 256 void IconLabelBubbleView::SetLabelBackgroundColor( | 255 void IconLabelBubbleView::SetLabelBackgroundColor( |
| 257 SkColor chip_background_color) { | 256 SkColor chip_background_color) { |
| 258 // The background images are painted atop |parent_background_color_|. | 257 // The background images are painted atop |parent_background_color_|. |
| 259 // Alpha-blend |chip_background_color| with |parent_background_color_| to | 258 // Alpha-blend |chip_background_color| with |parent_background_color_| to |
| 260 // determine the actual color the label text will sit atop. | 259 // determine the actual color the label text will sit atop. |
| 261 // Tricky bit: We alpha blend an opaque version of |chip_background_color| | 260 // Tricky bit: We alpha blend an opaque version of |chip_background_color| |
| 262 // against |parent_background_color_| using the original image grid color's | 261 // against |parent_background_color_| using the original image grid color's |
| 263 // alpha. This is because AlphaBlend(a, b, 255) always returns |a| unchanged | 262 // alpha. This is because AlphaBlend(a, b, 255) always returns |a| unchanged |
| 264 // even if |a| is a color with non-255 alpha. | 263 // even if |a| is a color with non-255 alpha. |
| 265 label_->SetBackgroundColor(color_utils::AlphaBlend( | 264 label_->SetBackgroundColor(color_utils::AlphaBlend( |
| 266 SkColorSetA(chip_background_color, 255), GetParentBackgroundColor(), | 265 SkColorSetA(chip_background_color, 255), GetParentBackgroundColor(), |
| 267 SkColorGetA(chip_background_color))); | 266 SkColorGetA(chip_background_color))); |
| 268 } | 267 } |
| 269 | 268 |
| 270 int IconLabelBubbleView::GetOuterPadding(bool leading) const { | 269 int IconLabelBubbleView::GetOuterPadding(bool leading) const { |
| 271 if (ui::MaterialDesignController::IsModeMaterial()) | 270 if (ui::MaterialDesignController::IsModeMaterial()) |
| 272 return GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING); | 271 return GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING); |
| 273 | 272 |
| 274 return GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING) - | 273 return GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING) - |
| 275 GetLayoutConstant(LOCATION_BAR_BUBBLE_HORIZONTAL_PADDING) + | 274 GetLayoutConstant(LOCATION_BAR_BUBBLE_HORIZONTAL_PADDING) + |
| 276 (leading ? 0 : kTrailingPaddingPreMD); | 275 (leading ? 0 : kTrailingPaddingPreMD); |
| 277 } | 276 } |
| 278 | 277 |
| 278 int IconLabelBubbleView::GetImageTrailingEdge() const { | |
| 279 return GetOuterPadding(true) + image_->GetPreferredSize().width(); | |
| 280 } | |
| 281 | |
| 279 int IconLabelBubbleView::GetInternalSpacing() const { | 282 int IconLabelBubbleView::GetInternalSpacing() const { |
| 280 return image_->GetPreferredSize().IsEmpty() | 283 return image_->GetPreferredSize().IsEmpty() |
| 281 ? 0 | 284 ? 0 |
| 282 : GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING); | 285 : GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING); |
| 283 } | 286 } |
| 284 | 287 |
| 288 int IconLabelBubbleView::GetPostLabelWidth() const { | |
| 289 if (!ui::MaterialDesignController::IsModeMaterial()) | |
| 290 return GetOuterPadding(false); | |
| 291 | |
| 292 // The location bar will add LOCATION_BAR_HORIZONTAL_PADDING after us. | |
| 293 return (kSpaceBesideSeparator * 2) + kSeparatorWidth - | |
| 294 GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING); | |
| 295 } | |
| 296 | |
| 285 const char* IconLabelBubbleView::GetClassName() const { | 297 const char* IconLabelBubbleView::GetClassName() const { |
| 286 return "IconLabelBubbleView"; | 298 return "IconLabelBubbleView"; |
| 287 } | 299 } |
| 288 | 300 |
| 289 void IconLabelBubbleView::OnPaint(gfx::Canvas* canvas) { | 301 void IconLabelBubbleView::OnPaint(gfx::Canvas* canvas) { |
| 290 if (!ShouldShowBackground()) | 302 if (!ShouldShowBackground()) |
| 291 return; | 303 return; |
| 292 if (background_painter_) { | 304 if (background_painter_) { |
| 293 views::Painter::PaintPainterAt(canvas, background_painter_.get(), | 305 views::Painter::PaintPainterAt(canvas, background_painter_.get(), |
| 294 GetContentsBounds()); | 306 GetContentsBounds()); |
| 295 } | 307 } |
| 296 | 308 |
| 297 // In MD, draw a separator and not a background. | 309 // In MD, draw a separator and not a background. |
| 298 if (ui::MaterialDesignController::IsModeMaterial()) { | 310 if (ui::MaterialDesignController::IsModeMaterial()) { |
| 299 const SkColor plain_text_color = GetNativeTheme()->GetSystemColor( | 311 const SkColor plain_text_color = GetNativeTheme()->GetSystemColor( |
| 300 ui::NativeTheme::kColorId_TextfieldDefaultColor); | 312 ui::NativeTheme::kColorId_TextfieldDefaultColor); |
| 301 const SkColor separator_color = SkColorSetA( | 313 const SkColor separator_color = SkColorSetA( |
| 302 plain_text_color, color_utils::IsDark(plain_text_color) ? 0x59 : 0xCC); | 314 plain_text_color, color_utils::IsDark(plain_text_color) ? 0x59 : 0xCC); |
| 303 | 315 |
| 304 // Amount of padding that is built into the whatever view comes after this | |
| 305 // one in the location bar (e.g. omnibox textfield). | |
| 306 int post_chip_spacing = | |
| 307 GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING); | |
| 308 // Amount of space to leave after the separator (dp). | |
| 309 const int kPostSeparatorSpacing = | |
| 310 (GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING) + | 316 (GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING) + |
| 311 kExtraTrailingPadding + post_chip_spacing) / | 317 gfx::Rect bounds(GetLocalBounds()); |
| 312 2 - | |
| 313 post_chip_spacing; | |
| 314 // Height of the separator (dp). | |
| 315 const int kSeparatorHeight = 16; | 318 const int kSeparatorHeight = 16; |
| 316 gfx::Rect bounds(GetLocalBounds()); | 319 bounds.Inset(GetPostLabelWidth() - kSpaceBesideSeparator - kSeparatorWidth, |
| 317 bounds.Inset(kPostSeparatorSpacing, | |
| 318 (bounds.height() - kSeparatorHeight) / 2); | 320 (bounds.height() - kSeparatorHeight) / 2); |
| 319 | 321 |
| 320 // 1px at all scale factors. | 322 // Draw the 1 px separator. |
| 321 gfx::ScopedCanvas scoped_canvas(canvas); | 323 gfx::ScopedCanvas scoped_canvas(canvas); |
| 322 const float scale = canvas->UndoDeviceScaleFactor(); | 324 const float scale = canvas->UndoDeviceScaleFactor(); |
| 325 // Keep the separator aligned on a pixel center, but center it within the | |
| 326 // DIP if the scale factor is large enough. | |
| 323 const gfx::RectF pixel_aligned_bounds = | 327 const gfx::RectF pixel_aligned_bounds = |
| 324 gfx::ScaleRect(gfx::RectF(bounds), scale) - gfx::Vector2dF(0.5f, 0); | 328 gfx::ScaleRect(gfx::RectF(bounds), scale) - |
| 329 gfx::Vector2dF(std::floor((scale - 1) / 2) + 0.5f, 0); | |
| 325 canvas->DrawLine(pixel_aligned_bounds.top_right(), | 330 canvas->DrawLine(pixel_aligned_bounds.top_right(), |
| 326 pixel_aligned_bounds.bottom_right(), separator_color); | 331 pixel_aligned_bounds.bottom_right(), separator_color); |
| 327 } | 332 } |
| 328 } | 333 } |
| OLD | NEW |