Commit 2ffcdcfb authored by Matthew Mourgos's avatar Matthew Mourgos Committed by Commit Bot

CrOS Shelf: Calculate color for shelf notification badges

The color for the shelf notification badges is calculated by getting a
light vibrant color from the shelf app icon image. If no color can be
calculated then white is used as the default notification color.

Bug: 1080827
Change-Id: I2b858b7c15f1a54191afe063716c64a9fa58b925
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2241291
Commit-Queue: Matthew Mourgos <mmourgos@chromium.org>
Reviewed-by: default avatarToni Baržić <tbarzic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796037}
parent a2aee2f4
......@@ -1910,6 +1910,7 @@ test("ash_unittests") {
"shelf/login_shelf_gesture_controller_unittest.cc",
"shelf/login_shelf_view_unittest.cc",
"shelf/scrollable_shelf_view_unittest.cc",
"shelf/shelf_app_button_unittest.cc",
"shelf/shelf_application_menu_model_unittest.cc",
"shelf/shelf_background_animator_unittest.cc",
"shelf/shelf_button_pressed_metric_tracker_unittest.cc",
......
......@@ -28,6 +28,7 @@
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_analysis.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/scoped_canvas.h"
......@@ -48,10 +49,10 @@ constexpr int kStatusIndicatorActiveSize = 8;
constexpr int kStatusIndicatorRunningSize = 4;
constexpr int kStatusIndicatorThickness = 2;
constexpr int kNotificationIndicatorRadiusDip = 7;
constexpr SkColor kIndicatorColor = SK_ColorWHITE;
constexpr SkColor kDefaultIndicatorColor = SK_ColorWHITE;
// Slightly different colors and alpha in the new UI.
constexpr SkColor kIndicatorColorActive = kIndicatorColor;
constexpr SkColor kIndicatorColorActive = kDefaultIndicatorColor;
constexpr SkColor kIndicatorColorRunning = SkColorSetA(SK_ColorWHITE, 0x7F);
// The time threshold before an item can be dragged.
......@@ -66,6 +67,30 @@ constexpr float kAppIconScale = 1.2f;
// The drag and drop app icon scaling up or down animation transition duration.
constexpr int kDragDropAppIconScaleTransitionMs = 200;
// Uses the icon image to calculate the light vibrant color to be used for
// the notification indicator.
base::Optional<SkColor> CalculateNotificationColor(gfx::ImageSkia image) {
const SkBitmap* source = image.bitmap();
if (!source || source->empty() || source->isNull())
return base::nullopt;
std::vector<color_utils::ColorProfile> color_profiles;
color_profiles.push_back(color_utils::ColorProfile(
color_utils::LumaRange::LIGHT, color_utils::SaturationRange::VIBRANT));
std::vector<color_utils::Swatch> best_swatches =
color_utils::CalculateProminentColorsOfBitmap(
*source, color_profiles, nullptr /* bitmap region */,
color_utils::ColorSwatchFilter());
// If the best swatch color is transparent, then
// CalculateProminentColorsOfBitmap() failed to find a suitable color.
if (best_swatches.empty() || best_swatches[0].color == SK_ColorTRANSPARENT)
return base::nullopt;
return best_swatches[0].color;
}
// Simple AnimationDelegate that owns a single ThrobAnimation instance to
// keep all Draw Attention animations in sync.
class ShelfAppButtonAnimation : public gfx::AnimationDelegate {
......@@ -177,8 +202,15 @@ class ShelfAppButton::AppNotificationIndicatorView : public views::View {
flags);
}
void SetColor(SkColor new_color) {
indicator_color_ = new_color;
SchedulePaint();
}
SkColor GetColorForTest() { return indicator_color_; }
private:
const SkColor indicator_color_;
SkColor indicator_color_;
DISALLOW_COPY_AND_ASSIGN(AppNotificationIndicatorView);
};
......@@ -343,7 +375,8 @@ ShelfAppButton::ShelfAppButton(ShelfView* shelf_view,
AddChildView(indicator_);
AddChildView(icon_view_);
if (is_notification_indicator_enabled_) {
notification_indicator_ = new AppNotificationIndicatorView(kIndicatorColor);
notification_indicator_ =
new AppNotificationIndicatorView(kDefaultIndicatorColor);
notification_indicator_->SetPaintToLayer();
notification_indicator_->layer()->SetFillsBoundsOpaquely(false);
notification_indicator_->SetVisible(false);
......@@ -383,6 +416,13 @@ void ShelfAppButton::SetImage(const gfx::ImageSkia& image) {
}
icon_image_ = image;
if (is_notification_indicator_enabled_) {
base::Optional<SkColor> notification_color =
CalculateNotificationColor(icon_image_);
notification_indicator_->SetColor(
notification_color.value_or(kDefaultIndicatorColor));
}
const int icon_size = shelf_view_->GetButtonIconSize() * icon_scale_;
// Resize the image maintaining our aspect ratio.
......@@ -918,4 +958,8 @@ void ShelfAppButton::SetInkDropAnimationStarted(bool started) {
}
}
SkColor ShelfAppButton::GetNotificationIndicatorColorForTest() {
return notification_indicator_->GetColorForTest();
}
} // namespace ash
......@@ -118,6 +118,9 @@ class ASH_EXPORT ShelfAppButton : public ShelfButton,
// Return the bounds in the local coordinates enclosing the small ripple area.
gfx::Rect CalculateSmallRippleArea() const;
// Gets the color of the |notification_indicator_| for test usage.
SkColor GetNotificationIndicatorColorForTest();
protected:
// ui::EventHandler:
void OnGestureEvent(ui::GestureEvent* event) override;
......
// Copyright 2020 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 "ash/shelf/shelf_app_button.h"
#include "ash/shelf/shelf_test_util.h"
#include "ash/shelf/shelf_view.h"
#include "ash/shelf/shelf_view_test_api.h"
#include "ash/test/ash_test_base.h"
#include "base/test/scoped_feature_list.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/color_palette.h"
namespace ash {
class ShelfAppButtonTest : public AshTestBase {
public:
ShelfAppButtonTest() {
scoped_feature_list_.InitWithFeatures({features::kNotificationIndicator},
{});
}
~ShelfAppButtonTest() override = default;
// AshTestBase:
void SetUp() override {
AshTestBase::SetUp();
test_api_.reset(
new ShelfViewTestAPI(GetPrimaryShelf()->GetShelfViewForTesting()));
}
void TearDown() override {
test_api_.reset();
AshTestBase::TearDown();
}
ShelfViewTestAPI* test_api() { return test_api_.get(); }
void SetImageForButton(int button_num, gfx::ImageSkia image) {
test_api()->GetButton(button_num)->SetImage(image);
}
SkColor GetNotificationColorForButton(int button_num) {
return test_api()
->GetButton(button_num)
->GetNotificationIndicatorColorForTest();
}
private:
std::unique_ptr<ShelfViewTestAPI> test_api_;
base::test::ScopedFeatureList scoped_feature_list_;
};
// Test that the notification indicator has a color which is calculated
// correctly when an image is set for the ShelfAppButton.
TEST_F(ShelfAppButtonTest, NotificatonBadgeColor) {
ShelfTestUtil::AddAppShortcut("app_id", TYPE_PINNED_APP);
const int width = 64;
const int height = 64;
SkBitmap all_black_icon;
all_black_icon.allocN32Pixels(width, height);
all_black_icon.eraseColor(SK_ColorBLACK);
SetImageForButton(0, gfx::ImageSkia::CreateFrom1xBitmap(all_black_icon));
// For an all black icon, a white notification badge is expected, since there
// is no other light vibrant color to get from the icon.
EXPECT_EQ(SK_ColorWHITE, GetNotificationColorForButton(0));
// Create an icon that is half kGoogleRed300 and half kGoogleRed600.
SkBitmap red_icon;
red_icon.allocN32Pixels(width, height);
red_icon.eraseColor(gfx::kGoogleRed300);
red_icon.erase(gfx::kGoogleRed600, {0, 0, width, height / 2});
SetImageForButton(0, gfx::ImageSkia::CreateFrom1xBitmap(red_icon));
// For the red icon, the notification badge should calculate and use the
// kGoogleRed300 color as the light vibrant color taken from the icon.
EXPECT_EQ(gfx::kGoogleRed300, GetNotificationColorForButton(0));
}
} // namespace ash
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment