blob: 29978742c9d6c06987d537c163e80e6fa41a01a3 [file] [log] [blame]
// Copyright 2014 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/app_list_button.h"
#include <math.h> // std::ceil
#include "ash/public/cpp/shelf_types.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_constants.h"
#include "base/logging.h"
#include "chromeos/strings/grit/chromeos_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
#include "ui/views/animation/ink_drop_impl.h"
namespace ash {
namespace {
constexpr uint8_t kVoiceInteractionRunningAlpha = 255; // 100% alpha
constexpr uint8_t kVoiceInteractionNotRunningAlpha = 138; // 54% alpha
} // namespace
// static
const char AppListButton::kViewClassName[] = "ash/AppListButton";
AppListButton::AppListButton(ShelfView* shelf_view, Shelf* shelf)
: ShelfControlButton(shelf_view), controller_(this, shelf) {
DCHECK(shelf_view);
DCHECK(shelf);
SetAccessibleName(
l10n_util::GetStringUTF16(IDS_ASH_SHELF_APP_LIST_LAUNCHER_TITLE));
set_notify_action(Button::NOTIFY_ON_PRESS);
set_has_ink_drop_action_on_click(false);
}
AppListButton::~AppListButton() = default;
void AppListButton::OnGestureEvent(ui::GestureEvent* event) {
if (!controller_.MaybeHandleGestureEvent(event, shelf_view()))
Button::OnGestureEvent(event);
}
const char* AppListButton::GetClassName() const {
return kViewClassName;
}
void AppListButton::OnVoiceInteractionAvailabilityChanged() {
SchedulePaint();
}
bool AppListButton::IsShowingAppList() const {
return controller_.is_showing_app_list();
}
void AppListButton::PaintButtonContents(gfx::Canvas* canvas) {
gfx::PointF circle_center(GetCenterPoint());
// Paint a white ring as the foreground for the app list circle. The ceil/dsf
// math assures that the ring draws sharply and is centered at all scale
// factors.
float ring_outer_radius_dp = 7.f;
float ring_thickness_dp = 1.5f;
if (controller_.IsVoiceInteractionAvailable()) {
ring_outer_radius_dp = 8.f;
ring_thickness_dp = 1.f;
}
{
gfx::ScopedCanvas scoped_canvas(canvas);
const float dsf = canvas->UndoDeviceScaleFactor();
circle_center.Scale(dsf);
cc::PaintFlags fg_flags;
fg_flags.setAntiAlias(true);
fg_flags.setStyle(cc::PaintFlags::kStroke_Style);
fg_flags.setColor(kShelfIconColor);
if (controller_.IsVoiceInteractionAvailable()) {
// active: 100% alpha, inactive: 54% alpha
fg_flags.setAlpha(controller_.IsVoiceInteractionRunning()
? kVoiceInteractionRunningAlpha
: kVoiceInteractionNotRunningAlpha);
}
const float thickness = std::ceil(ring_thickness_dp * dsf);
const float radius = std::ceil(ring_outer_radius_dp * dsf) - thickness / 2;
fg_flags.setStrokeWidth(thickness);
// Make sure the center of the circle lands on pixel centers.
canvas->DrawCircle(circle_center, radius, fg_flags);
if (controller_.IsVoiceInteractionAvailable()) {
fg_flags.setAlpha(255);
const float kCircleRadiusDp = 5.f;
fg_flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->DrawCircle(circle_center, std::ceil(kCircleRadiusDp * dsf),
fg_flags);
}
}
}
} // namespace ash