Home | History | Annotate | Download | only in caption_buttons
      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/wm/caption_buttons/frame_caption_button.h"
      6 
      7 #include "grit/ash_resources.h"
      8 #include "ui/base/resource/resource_bundle.h"
      9 #include "ui/gfx/animation/slide_animation.h"
     10 #include "ui/gfx/canvas.h"
     11 
     12 namespace ash {
     13 
     14 namespace {
     15 
     16 // The duration of the crossfade animation when swapping the button's icon.
     17 const int kCrossfadeDurationMs = 200;
     18 
     19 }  // namespace
     20 
     21 // static
     22 const char FrameCaptionButton::kViewClassName[] = "FrameCaptionButton";
     23 
     24 FrameCaptionButton::FrameCaptionButton(views::ButtonListener* listener,
     25                                        CaptionButtonIcon icon)
     26     : ImageButton(listener),
     27       icon_(icon),
     28       style_(STYLE_SHORT_RESTORED),
     29       last_paint_scale_(1.0f),
     30       animation_(new gfx::SlideAnimation(this)) {
     31   animation_->Reset(1);
     32   UpdateImages();
     33 }
     34 
     35 FrameCaptionButton::~FrameCaptionButton() {
     36 }
     37 
     38 void FrameCaptionButton::SetIcon(CaptionButtonIcon icon, Animate animate) {
     39   if (icon_ == icon)
     40     return;
     41 
     42   if (animate == ANIMATE_YES) {
     43     gfx::Canvas canvas(size(), last_paint_scale_, false);
     44     OnPaint(&canvas);
     45     crossfade_image_ = gfx::ImageSkia(canvas.ExtractImageRep());
     46 
     47     icon_ = icon;
     48     UpdateImages();
     49 
     50     animation_->Reset(0);
     51     animation_->SetSlideDuration(kCrossfadeDurationMs);
     52     animation_->Show();
     53   } else {
     54     animation_->Reset(1);
     55     icon_ = icon;
     56     UpdateImages();
     57   }
     58 }
     59 
     60 void FrameCaptionButton::SetStyle(Style style) {
     61   if (style_ == style)
     62     return;
     63   animation_->Reset(1);
     64   style_ = style;
     65   UpdateImages();
     66 }
     67 
     68 const char* FrameCaptionButton::GetClassName() const {
     69   return kViewClassName;
     70 }
     71 
     72 void FrameCaptionButton::OnPaint(gfx::Canvas* canvas) {
     73   last_paint_scale_ = canvas->image_scale();
     74   int alpha = static_cast<int>(animation_->GetCurrentValue() * 255);
     75   int crossfade_alpha = 255 - alpha;
     76   if (crossfade_alpha > 0 && !crossfade_image_.isNull()) {
     77     gfx::Canvas composed_canvas(size(), last_paint_scale_, false);
     78     SkPaint paint;
     79     paint.setAlpha(crossfade_alpha);
     80     paint.setXfermodeMode(SkXfermode::kPlus_Mode);
     81     composed_canvas.DrawImageInt(crossfade_image_, 0, 0, paint);
     82     paint.setAlpha(alpha);
     83     ImageButton::OnPaint(&composed_canvas);
     84 
     85     canvas->DrawImageInt(
     86         gfx::ImageSkia(composed_canvas.ExtractImageRep()), 0, 0);
     87   } else {
     88     ImageButton::OnPaint(canvas);
     89   }
     90 }
     91 
     92 void FrameCaptionButton::OnGestureEvent(ui::GestureEvent* event) {
     93   // ImageButton does not become pressed when the user drags off and then back
     94   // onto the button. Make FrameCaptionButton pressed in this case because this
     95   // behavior is more consistent with AlternateFrameSizeButton.
     96   if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
     97       event->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
     98     if (HitTestPoint(event->location())) {
     99       SetState(STATE_PRESSED);
    100       RequestFocus();
    101       event->StopPropagation();
    102     } else {
    103       SetState(STATE_NORMAL);
    104     }
    105   } else if (event->type() == ui::ET_GESTURE_SCROLL_END) {
    106     if (HitTestPoint(event->location())) {
    107       SetState(STATE_HOVERED);
    108       NotifyClick(*event);
    109       event->StopPropagation();
    110     }
    111   }
    112   ImageButton::OnGestureEvent(event);
    113 }
    114 
    115 void FrameCaptionButton::StateChanged() {
    116   if (state_ == STATE_HOVERED || state_ == STATE_PRESSED)
    117     animation_->Reset(1);
    118 }
    119 
    120 void FrameCaptionButton::UpdateImages() {
    121   switch (icon_) {
    122     case CAPTION_BUTTON_ICON_MINIMIZE:
    123       SetImages(IDR_AURA_WINDOW_MINIMIZE_SHORT,
    124                 IDR_AURA_WINDOW_MINIMIZE_SHORT_H,
    125                 IDR_AURA_WINDOW_MINIMIZE_SHORT_P);
    126       break;
    127    case CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE:
    128    case CAPTION_BUTTON_ICON_LEFT_SNAPPED:
    129    case CAPTION_BUTTON_ICON_RIGHT_SNAPPED:
    130      if (style_ == STYLE_SHORT_MAXIMIZED_OR_FULLSCREEN) {
    131        SetImages(IDR_AURA_WINDOW_MAXIMIZED_RESTORE2,
    132                  IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_H,
    133                  IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_P);
    134      } else if (style_ == STYLE_SHORT_RESTORED) {
    135        SetImages(IDR_AURA_WINDOW_MAXIMIZED_RESTORE,
    136                  IDR_AURA_WINDOW_MAXIMIZED_RESTORE_H,
    137                  IDR_AURA_WINDOW_MAXIMIZED_RESTORE_P);
    138      } else {
    139        SetImages(IDR_AURA_WINDOW_MAXIMIZE,
    140                  IDR_AURA_WINDOW_MAXIMIZE_H,
    141                  IDR_AURA_WINDOW_MAXIMIZE_P);
    142      }
    143      break;
    144    case CAPTION_BUTTON_ICON_CLOSE:
    145      if (style_ == STYLE_SHORT_MAXIMIZED_OR_FULLSCREEN) {
    146        SetImages(IDR_AURA_WINDOW_MAXIMIZED_CLOSE2,
    147                  IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_H,
    148                  IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_P);
    149      } else if (style_ == STYLE_SHORT_RESTORED) {
    150        SetImages(IDR_AURA_WINDOW_MAXIMIZED_CLOSE,
    151                  IDR_AURA_WINDOW_MAXIMIZED_CLOSE_H,
    152                  IDR_AURA_WINDOW_MAXIMIZED_CLOSE_P);
    153      } else {
    154        SetImages(IDR_AURA_WINDOW_CLOSE,
    155                  IDR_AURA_WINDOW_CLOSE_H,
    156                  IDR_AURA_WINDOW_CLOSE_P);
    157      }
    158      break;
    159   }
    160 
    161   SchedulePaint();
    162 }
    163 
    164 void FrameCaptionButton::SetImages(int normal_image_id,
    165                                    int hot_image_id,
    166                                    int pushed_image_id) {
    167   ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
    168   SetImage(STATE_NORMAL, resource_bundle.GetImageSkiaNamed(normal_image_id));
    169   SetImage(STATE_HOVERED, resource_bundle.GetImageSkiaNamed(hot_image_id));
    170   SetImage(STATE_PRESSED, resource_bundle.GetImageSkiaNamed(pushed_image_id));
    171 }
    172 
    173 void FrameCaptionButton::AnimationProgressed(const gfx::Animation* animation) {
    174   SchedulePaint();
    175 }
    176 
    177 }  // namespace ash
    178