Home | History | Annotate | Download | only in launcher
      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
      3 // found in the LICENSE file.
      4 
      5 #include "ash/launcher/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/animation/throb_animation.h"
     15 #include "ui/base/l10n/l10n_util.h"
     16 #include "ui/base/resource/resource_bundle.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 
     24 namespace ash {
     25 namespace internal {
     26 
     27 namespace {
     28 
     29 const int kButtonHoverAlpha = 150;
     30 
     31 const int kButtonCornerRadius = 2;
     32 
     33 const int kButtonHoverSize = 28;
     34 
     35 const int kBackgroundOffset = (48 - kButtonHoverSize) / 2;
     36 
     37 // Padding from the inner edge of the shelf (towards center of display) to
     38 // the edge of the background image of the overflow button.
     39 const int kImagePaddingFromShelf = 5;
     40 
     41 }  // namesapce
     42 
     43 OverflowButton::OverflowButton(views::ButtonListener* listener)
     44     : CustomButton(listener),
     45       bottom_image_(NULL) {
     46   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
     47   bottom_image_ = rb.GetImageNamed(IDR_AURA_LAUNCHER_OVERFLOW).ToImageSkia();
     48 
     49 
     50   set_accessibility_focusable(true);
     51   SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_OVERFLOW_NAME));
     52 }
     53 
     54 OverflowButton::~OverflowButton() {}
     55 
     56 void OverflowButton::OnShelfAlignmentChanged() {
     57   SchedulePaint();
     58 }
     59 
     60 void OverflowButton::PaintBackground(gfx::Canvas* canvas, int alpha) {
     61   gfx::Rect bounds(GetContentsBounds());
     62   gfx::Rect rect(0, 0, kButtonHoverSize, kButtonHoverSize);
     63   ShelfLayoutManager* shelf =
     64       ShelfLayoutManager::ForLauncher(GetWidget()->GetNativeView());
     65 
     66   // Nudge the background a little to line up right.
     67   if (shelf->IsHorizontalAlignment()) {
     68     rect.set_origin(gfx::Point(
     69         bounds.x() + ((bounds.width() - kButtonHoverSize) / 2) - 1,
     70         bounds.y() + kBackgroundOffset - 1));
     71 
     72   } else {
     73     rect.set_origin(gfx::Point(
     74         bounds.x() + kBackgroundOffset - 1,
     75         bounds.y() + ((bounds.height() - kButtonHoverSize) / 2) - 1));
     76   }
     77 
     78   SkPaint paint;
     79   paint.setAntiAlias(true);
     80   paint.setStyle(SkPaint::kFill_Style);
     81   paint.setColor(SkColorSetARGB(
     82       kButtonHoverAlpha * hover_animation_->GetCurrentValue(),
     83       0, 0, 0));
     84 
     85   const SkScalar radius = SkIntToScalar(kButtonCornerRadius);
     86   SkPath path;
     87   path.addRoundRect(gfx::RectToSkRect(rect), radius, radius);
     88   canvas->DrawPath(path, paint);
     89 }
     90 
     91 void OverflowButton::OnPaint(gfx::Canvas* canvas) {
     92   ShelfLayoutManager* layout_manager = ShelfLayoutManager::ForLauncher(
     93       GetWidget()->GetNativeView());
     94   ShelfAlignment alignment = layout_manager->GetAlignment();
     95 
     96   gfx::Rect bounds(GetContentsBounds());
     97   if (ash::switches::UseAlternateShelfLayout()) {
     98     ResourceBundle& rb = ResourceBundle::GetSharedInstance();
     99     int background_image_id = 0;
    100     if (layout_manager->shelf_widget()->launcher()->IsShowingOverflowBubble())
    101       background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED;
    102     else if(layout_manager->shelf_widget()->GetDimsShelf())
    103       background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_ON_BLACK;
    104     else
    105       background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL;
    106 
    107     const gfx::ImageSkia* background =
    108         rb.GetImageNamed(background_image_id).ToImageSkia();
    109     if (alignment == SHELF_ALIGNMENT_LEFT) {
    110       bounds = gfx::Rect(
    111           bounds.right() - background->width() - kImagePaddingFromShelf,
    112           bounds.y() + (bounds.height() - background->height()) / 2,
    113           background->width(), background->height());
    114     } else if (alignment == SHELF_ALIGNMENT_RIGHT) {
    115       bounds = gfx::Rect(
    116           bounds.x() + kImagePaddingFromShelf,
    117           bounds.y() + (bounds.height() - background->height()) / 2,
    118           background->width(), background->height());
    119     } else {
    120       bounds = gfx::Rect(
    121           bounds.x() + (bounds.width() - background->width()) / 2,
    122           bounds.y() + kImagePaddingFromShelf,
    123           background->width(), background->height());
    124     }
    125     canvas->DrawImageInt(*background, bounds.x(), bounds.y());
    126   } else {
    127     if (alignment == SHELF_ALIGNMENT_BOTTOM) {
    128       bounds = gfx::Rect(
    129           bounds.x() + ((bounds.width() - kButtonHoverSize) / 2) - 1,
    130           bounds.y() + kBackgroundOffset - 1,
    131           kButtonHoverSize, kButtonHoverSize);
    132     } else {
    133       bounds = gfx::Rect(
    134           bounds.x() + kBackgroundOffset -1,
    135           bounds.y() + ((bounds.height() - kButtonHoverSize) / 2) -1,
    136           kButtonHoverSize, kButtonHoverSize);
    137     }
    138     if (hover_animation_->is_animating()) {
    139       PaintBackground(
    140           canvas,
    141           kButtonHoverAlpha * hover_animation_->GetCurrentValue());
    142     } else if (state() == STATE_HOVERED || state() == STATE_PRESSED) {
    143       PaintBackground(canvas, kButtonHoverAlpha);
    144     }
    145   }
    146 
    147   if (height() < kButtonHoverSize)
    148     return;
    149 
    150   const gfx::ImageSkia* image = NULL;
    151 
    152   switch(alignment) {
    153     case SHELF_ALIGNMENT_LEFT:
    154       if (left_image_.isNull()) {
    155         left_image_ = gfx::ImageSkiaOperations::CreateRotatedImage(
    156             *bottom_image_, SkBitmapOperations::ROTATION_90_CW);
    157       }
    158       image = &left_image_;
    159       break;
    160     case SHELF_ALIGNMENT_RIGHT:
    161       if (right_image_.isNull()) {
    162         right_image_ = gfx::ImageSkiaOperations::CreateRotatedImage(
    163             *bottom_image_, SkBitmapOperations::ROTATION_270_CW);
    164       }
    165       image = &right_image_;
    166       break;
    167     default:
    168       image = bottom_image_;
    169       break;
    170   }
    171 
    172   canvas->DrawImageInt(*image,
    173                        bounds.x() + ((bounds.width() - image->width()) / 2),
    174                        bounds.y() + ((bounds.height() - image->height()) / 2));
    175 }
    176 
    177 }  // namespace internal
    178 }  // namespace ash
    179