1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ash/shelf/overflow_button.h"
6
7#include "ash/ash_switches.h"
8#include "ash/shelf/shelf_layout_manager.h"
9#include "ash/shelf/shelf_widget.h"
10#include "grit/ash_resources.h"
11#include "grit/ash_strings.h"
12#include "third_party/skia/include/core/SkPaint.h"
13#include "third_party/skia/include/core/SkPath.h"
14#include "ui/base/l10n/l10n_util.h"
15#include "ui/base/resource/resource_bundle.h"
16#include "ui/gfx/animation/throb_animation.h"
17#include "ui/gfx/canvas.h"
18#include "ui/gfx/image/image_skia_operations.h"
19#include "ui/gfx/skbitmap_operations.h"
20#include "ui/gfx/skia_util.h"
21#include "ui/gfx/transform.h"
22#include "ui/views/widget/widget.h"
23
24namespace ash {
25namespace {
26
27const int kButtonHoverAlpha = 150;
28
29const int kButtonCornerRadius = 2;
30
31const int kButtonHoverSize = 28;
32
33const int kBackgroundOffset = (48 - kButtonHoverSize) / 2;
34
35}  // namesapce
36
37OverflowButton::OverflowButton(views::ButtonListener* listener)
38    : CustomButton(listener),
39      bottom_image_(NULL) {
40  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
41  bottom_image_ = rb.GetImageNamed(IDR_ASH_SHELF_OVERFLOW).ToImageSkia();
42
43
44  SetAccessibilityFocusable(true);
45  SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_OVERFLOW_NAME));
46}
47
48OverflowButton::~OverflowButton() {}
49
50void OverflowButton::OnShelfAlignmentChanged() {
51  SchedulePaint();
52}
53
54void OverflowButton::PaintBackground(gfx::Canvas* canvas, int alpha) {
55  gfx::Rect bounds(GetContentsBounds());
56  gfx::Rect rect(0, 0, kButtonHoverSize, kButtonHoverSize);
57  ShelfLayoutManager* shelf =
58      ShelfLayoutManager::ForShelf(GetWidget()->GetNativeView());
59
60  // Nudge the background a little to line up right.
61  if (shelf->IsHorizontalAlignment()) {
62    rect.set_origin(gfx::Point(
63        bounds.x() + ((bounds.width() - kButtonHoverSize) / 2) - 1,
64        bounds.y() + kBackgroundOffset - 1));
65
66  } else {
67    rect.set_origin(gfx::Point(
68        bounds.x() + kBackgroundOffset - 1,
69        bounds.y() + ((bounds.height() - kButtonHoverSize) / 2) - 1));
70  }
71
72  SkPaint paint;
73  paint.setAntiAlias(true);
74  paint.setStyle(SkPaint::kFill_Style);
75  paint.setColor(SkColorSetARGB(
76      kButtonHoverAlpha * hover_animation_->GetCurrentValue(),
77      0, 0, 0));
78
79  const SkScalar radius = SkIntToScalar(kButtonCornerRadius);
80  SkPath path;
81  path.addRoundRect(gfx::RectToSkRect(rect), radius, radius);
82  canvas->DrawPath(path, paint);
83}
84
85void OverflowButton::OnPaint(gfx::Canvas* canvas) {
86  ShelfLayoutManager* layout_manager =
87      ShelfLayoutManager::ForShelf(GetWidget()->GetNativeView());
88  ShelfAlignment alignment = layout_manager->GetAlignment();
89
90  gfx::Rect bounds(GetContentsBounds());
91  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
92  int background_image_id = 0;
93  if (layout_manager->shelf_widget()->shelf()->IsShowingOverflowBubble())
94    background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED;
95  else if(layout_manager->shelf_widget()->GetDimsShelf())
96    background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_ON_BLACK;
97  else
98    background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL;
99
100  const gfx::ImageSkia* background =
101      rb.GetImageNamed(background_image_id).ToImageSkia();
102  if (alignment == SHELF_ALIGNMENT_LEFT) {
103    bounds = gfx::Rect(
104        bounds.right() - background->width() -
105            ShelfLayoutManager::kShelfItemInset,
106        bounds.y() + (bounds.height() - background->height()) / 2,
107        background->width(), background->height());
108  } else if (alignment == SHELF_ALIGNMENT_RIGHT) {
109    bounds = gfx::Rect(
110        bounds.x() + ShelfLayoutManager::kShelfItemInset,
111        bounds.y() + (bounds.height() - background->height()) / 2,
112        background->width(), background->height());
113  } else {
114    bounds = gfx::Rect(
115        bounds.x() + (bounds.width() - background->width()) / 2,
116        bounds.y() + ShelfLayoutManager::kShelfItemInset,
117        background->width(), background->height());
118  }
119  canvas->DrawImageInt(*background, bounds.x(), bounds.y());
120
121  if (height() < kButtonHoverSize)
122    return;
123
124  const gfx::ImageSkia* image = NULL;
125
126  switch(alignment) {
127    case SHELF_ALIGNMENT_LEFT:
128      if (left_image_.isNull()) {
129        left_image_ = gfx::ImageSkiaOperations::CreateRotatedImage(
130            *bottom_image_, SkBitmapOperations::ROTATION_90_CW);
131      }
132      image = &left_image_;
133      break;
134    case SHELF_ALIGNMENT_RIGHT:
135      if (right_image_.isNull()) {
136        right_image_ = gfx::ImageSkiaOperations::CreateRotatedImage(
137            *bottom_image_, SkBitmapOperations::ROTATION_270_CW);
138      }
139      image = &right_image_;
140      break;
141    default:
142      image = bottom_image_;
143      break;
144  }
145
146  canvas->DrawImageInt(*image,
147                       bounds.x() + ((bounds.width() - image->width()) / 2),
148                       bounds.y() + ((bounds.height() - image->height()) / 2));
149}
150
151}  // namespace ash
152