Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / tabs / media_indicator_button.cc
1 // Copyright 2014 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 "chrome/browser/ui/views/tabs/media_indicator_button.h"
6
7 #include "chrome/browser/ui/views/tabs/tab.h"
8 #include "chrome/browser/ui/views/tabs/tab_controller.h"
9 #include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
10 #include "content/public/browser/user_metrics.h"
11 #include "ui/gfx/animation/animation_delegate.h"
12 #include "ui/gfx/canvas.h"
13 #include "ui/gfx/image/image.h"
14
15 using base::UserMetricsAction;
16
17 const char MediaIndicatorButton::kViewClassName[] = "MediaIndicatorButton";
18
19 class MediaIndicatorButton::FadeAnimationDelegate
20     : public gfx::AnimationDelegate {
21  public:
22   explicit FadeAnimationDelegate(MediaIndicatorButton* button)
23       : button_(button) {}
24   ~FadeAnimationDelegate() override {}
25
26  private:
27   // gfx::AnimationDelegate
28   void AnimationProgressed(const gfx::Animation* animation) override {
29     button_->SchedulePaint();
30   }
31
32   void AnimationCanceled(const gfx::Animation* animation) override {
33     button_->showing_media_state_ = button_->media_state_;
34     button_->SchedulePaint();
35   }
36
37   void AnimationEnded(const gfx::Animation* animation) override {
38     button_->showing_media_state_ = button_->media_state_;
39     button_->SchedulePaint();
40   }
41
42   MediaIndicatorButton* const button_;
43
44   DISALLOW_COPY_AND_ASSIGN(FadeAnimationDelegate);
45 };
46
47 MediaIndicatorButton::MediaIndicatorButton()
48     : views::ImageButton(NULL),
49       media_state_(TAB_MEDIA_STATE_NONE),
50       showing_media_state_(TAB_MEDIA_STATE_NONE) {
51   SetEventTargeter(
52       scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
53 }
54
55 MediaIndicatorButton::~MediaIndicatorButton() {}
56
57 void MediaIndicatorButton::TransitionToMediaState(TabMediaState next_state) {
58   if (next_state == media_state_)
59     return;
60
61   if (next_state != TAB_MEDIA_STATE_NONE) {
62     const gfx::ImageSkia* const indicator_image =
63         chrome::GetTabMediaIndicatorImage(next_state).ToImageSkia();
64     SetImage(views::CustomButton::STATE_NORMAL, indicator_image);
65     SetImage(views::CustomButton::STATE_DISABLED, indicator_image);
66     const gfx::ImageSkia* const affordance_image =
67         chrome::GetTabMediaIndicatorAffordanceImage(next_state).ToImageSkia();
68     SetImage(views::CustomButton::STATE_HOVERED, affordance_image);
69     SetImage(views::CustomButton::STATE_PRESSED, affordance_image);
70   }
71
72   if ((media_state_ == TAB_MEDIA_STATE_AUDIO_PLAYING &&
73        next_state == TAB_MEDIA_STATE_AUDIO_MUTING) ||
74       (media_state_ == TAB_MEDIA_STATE_AUDIO_MUTING &&
75        next_state == TAB_MEDIA_STATE_AUDIO_PLAYING) ||
76       (media_state_ == TAB_MEDIA_STATE_AUDIO_MUTING &&
77        next_state == TAB_MEDIA_STATE_NONE)) {
78     // Instant user feedback: No fade animation.
79     showing_media_state_ = next_state;
80     fade_animation_.reset();
81   } else {
82     if (next_state == TAB_MEDIA_STATE_NONE)
83       showing_media_state_ = media_state_;  // Fading-out indicator.
84     else
85       showing_media_state_ = next_state;  // Fading-in to next indicator.
86     fade_animation_ = chrome::CreateTabMediaIndicatorFadeAnimation(next_state);
87     if (!fade_animation_delegate_)
88       fade_animation_delegate_.reset(new FadeAnimationDelegate(this));
89     fade_animation_->set_delegate(fade_animation_delegate_.get());
90     fade_animation_->Start();
91   }
92
93   SetEnabled(chrome::IsTabAudioMutingFeatureEnabled() &&
94              (next_state == TAB_MEDIA_STATE_AUDIO_PLAYING ||
95               next_state == TAB_MEDIA_STATE_AUDIO_MUTING));
96
97   // An indicator state change should be made visible immediately, instead of
98   // the user being surprised when their mouse leaves the button.
99   if (state() == views::CustomButton::STATE_HOVERED) {
100     SetState(enabled() ? views::CustomButton::STATE_NORMAL :
101              views::CustomButton::STATE_DISABLED);
102   }
103
104   media_state_ = next_state;
105
106   // Note: The calls to SetImage(), SetEnabled(), and SetState() above will call
107   // SchedulePaint() if necessary.
108 }
109
110 const char* MediaIndicatorButton::GetClassName() const {
111   return kViewClassName;
112 }
113
114 views::View* MediaIndicatorButton::GetTooltipHandlerForPoint(
115     const gfx::Point& point) {
116   return NULL;  // Tab (the parent View) provides the tooltip.
117 }
118
119 bool MediaIndicatorButton::OnMouseDragged(const ui::MouseEvent& event) {
120   const ButtonState previous_state = state();
121   const bool ret = ImageButton::OnMouseDragged(event);
122   if (previous_state != views::CustomButton::STATE_NORMAL &&
123       state() == views::CustomButton::STATE_NORMAL)
124     content::RecordAction(UserMetricsAction("MediaIndicatorButton_Dragged"));
125   return ret;
126 }
127
128 void MediaIndicatorButton::OnPaint(gfx::Canvas* canvas) {
129   double opaqueness =
130       fade_animation_ ? fade_animation_->GetCurrentValue() : 1.0;
131   if (media_state_ == TAB_MEDIA_STATE_NONE)
132     opaqueness = 1.0 - opaqueness;  // Fading out, not in.
133   if (opaqueness < 1.0)
134     canvas->SaveLayerAlpha(opaqueness * SK_AlphaOPAQUE);
135   ImageButton::OnPaint(canvas);
136   if (opaqueness < 1.0)
137     canvas->Restore();
138 }
139
140 bool MediaIndicatorButton::DoesIntersectRect(const views::View* target,
141                                              const gfx::Rect& rect) const {
142   // If this button is not enabled, Tab (the parent View) handles all mouse
143   // events.
144   return enabled() &&
145       views::ViewTargeterDelegate::DoesIntersectRect(target, rect);
146 }
147
148 void MediaIndicatorButton::NotifyClick(const ui::Event& event) {
149   if (media_state_ == TAB_MEDIA_STATE_AUDIO_PLAYING)
150     content::RecordAction(UserMetricsAction("MediaIndicatorButton_Mute"));
151   else if (media_state_ == TAB_MEDIA_STATE_AUDIO_MUTING)
152     content::RecordAction(UserMetricsAction("MediaIndicatorButton_Unmute"));
153   else
154     NOTREACHED();
155
156   DCHECK(parent() && !strcmp(parent()->GetClassName(), Tab::kViewClassName));
157   Tab* const tab = static_cast<Tab*>(parent());
158   tab->controller()->ToggleTabAudioMute(tab);
159 }