// Copyright 2013 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/overflow_button.h"
#include "ash/ash_switches.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_widget.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/skbitmap_operations.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"
#include "ui/views/widget/widget.h"
namespace ash {
namespace internal {
namespace {
const int kButtonHoverAlpha = 150;
const int kButtonCornerRadius = 2;
const int kButtonHoverSize = 28;
const int kBackgroundOffset = (48 - kButtonHoverSize) / 2;
} // namesapce
OverflowButton::OverflowButton(views::ButtonListener* listener)
: CustomButton(listener),
bottom_image_(NULL) {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
bottom_image_ = rb.GetImageNamed(IDR_AURA_LAUNCHER_OVERFLOW).ToImageSkia();
SetAccessibilityFocusable(true);
SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_OVERFLOW_NAME));
}
OverflowButton::~OverflowButton() {}
void OverflowButton::OnShelfAlignmentChanged() {
SchedulePaint();
}
void OverflowButton::PaintBackground(gfx::Canvas* canvas, int alpha) {
gfx::Rect bounds(GetContentsBounds());
gfx::Rect rect(0, 0, kButtonHoverSize, kButtonHoverSize);
ShelfLayoutManager* shelf =
ShelfLayoutManager::ForLauncher(GetWidget()->GetNativeView());
// Nudge the background a little to line up right.
if (shelf->IsHorizontalAlignment()) {
rect.set_origin(gfx::Point(
bounds.x() + ((bounds.width() - kButtonHoverSize) / 2) - 1,
bounds.y() + kBackgroundOffset - 1));
} else {
rect.set_origin(gfx::Point(
bounds.x() + kBackgroundOffset - 1,
bounds.y() + ((bounds.height() - kButtonHoverSize) / 2) - 1));
}
SkPaint paint;
paint.setAntiAlias(true);
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(SkColorSetARGB(
kButtonHoverAlpha * hover_animation_->GetCurrentValue(),
0, 0, 0));
const SkScalar radius = SkIntToScalar(kButtonCornerRadius);
SkPath path;
path.addRoundRect(gfx::RectToSkRect(rect), radius, radius);
canvas->DrawPath(path, paint);
}
void OverflowButton::OnPaint(gfx::Canvas* canvas) {
ShelfLayoutManager* layout_manager = ShelfLayoutManager::ForLauncher(
GetWidget()->GetNativeView());
ShelfAlignment alignment = layout_manager->GetAlignment();
gfx::Rect bounds(GetContentsBounds());
if (ash::switches::UseAlternateShelfLayout()) {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
int background_image_id = 0;
if (layout_manager->shelf_widget()->launcher()->IsShowingOverflowBubble())
background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED;
else if(layout_manager->shelf_widget()->GetDimsShelf())
background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_ON_BLACK;
else
background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL;
const gfx::ImageSkia* background =
rb.GetImageNamed(background_image_id).ToImageSkia();
if (alignment == SHELF_ALIGNMENT_LEFT) {
bounds = gfx::Rect(
bounds.right() - background->width() -
ShelfLayoutManager::kShelfItemInset,
bounds.y() + (bounds.height() - background->height()) / 2,
background->width(), background->height());
} else if (alignment == SHELF_ALIGNMENT_RIGHT) {
bounds = gfx::Rect(
bounds.x() + ShelfLayoutManager::kShelfItemInset,
bounds.y() + (bounds.height() - background->height()) / 2,
background->width(), background->height());
} else {
bounds = gfx::Rect(
bounds.x() + (bounds.width() - background->width()) / 2,
bounds.y() + ShelfLayoutManager::kShelfItemInset,
background->width(), background->height());
}
canvas->DrawImageInt(*background, bounds.x(), bounds.y());
} else {
if (alignment == SHELF_ALIGNMENT_BOTTOM) {
bounds = gfx::Rect(
bounds.x() + ((bounds.width() - kButtonHoverSize) / 2) - 1,
bounds.y() + kBackgroundOffset - 1,
kButtonHoverSize, kButtonHoverSize);
} else {
bounds = gfx::Rect(
bounds.x() + kBackgroundOffset -1,
bounds.y() + ((bounds.height() - kButtonHoverSize) / 2) -1,
kButtonHoverSize, kButtonHoverSize);
}
if (hover_animation_->is_animating()) {
PaintBackground(
canvas,
kButtonHoverAlpha * hover_animation_->GetCurrentValue());
} else if (state() == STATE_HOVERED || state() == STATE_PRESSED) {
PaintBackground(canvas, kButtonHoverAlpha);
}
}
if (height() < kButtonHoverSize)
return;
const gfx::ImageSkia* image = NULL;
switch(alignment) {
case SHELF_ALIGNMENT_LEFT:
if (left_image_.isNull()) {
left_image_ = gfx::ImageSkiaOperations::CreateRotatedImage(
*bottom_image_, SkBitmapOperations::ROTATION_90_CW);
}
image = &left_image_;
break;
case SHELF_ALIGNMENT_RIGHT:
if (right_image_.isNull()) {
right_image_ = gfx::ImageSkiaOperations::CreateRotatedImage(
*bottom_image_, SkBitmapOperations::ROTATION_270_CW);
}
image = &right_image_;
break;
default:
image = bottom_image_;
break;
}
canvas->DrawImageInt(*image,
bounds.x() + ((bounds.width() - image->width()) / 2),
bounds.y() + ((bounds.height() - image->height()) / 2));
}
} // namespace internal
} // namespace ash