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.
5 #include "athena/wm/overview_toolbar.h"
7 #include "athena/resources/grit/athena_resources.h"
8 #include "athena/strings/grit/athena_strings.h"
10 #include "base/time/time.h"
11 #include "ui/aura/window.h"
12 #include "ui/base/l10n/l10n_util.h"
13 #include "ui/base/resource/resource_bundle.h"
14 #include "ui/compositor/closure_animation_observer.h"
15 #include "ui/compositor/layer.h"
16 #include "ui/compositor/layer_delegate.h"
17 #include "ui/compositor/scoped_layer_animation_settings.h"
18 #include "ui/events/event.h"
19 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/transform.h"
24 const int kActionButtonImageSize
= 54;
25 const int kActionButtonTextSize
= 20;
26 const int kActionButtonPaddingFromRight
= 32;
31 class ActionButton
: public ui::LayerDelegate
{
33 ActionButton(int resource_id
, const base::string16
& label
)
34 : resource_id_(resource_id
), label_(label
) {
35 layer_
.reset(new ui::Layer(ui::LAYER_TEXTURED
));
36 layer_
->set_delegate(this);
37 layer_
->SetFillsBoundsOpaquely(false);
38 layer_
->SetVisible(true);
39 layer_
->SetOpacity(0);
42 ~ActionButton() override
{}
44 static void DestroyAfterFadeout(scoped_ptr
<ActionButton
> button
) {
45 ui::Layer
* layer
= button
->layer();
46 ui::ScopedLayerAnimationSettings
settings(layer
->GetAnimator());
47 settings
.AddObserver(new ui::ClosureAnimationObserver(
48 base::Bind(&ActionButton::DestroyImmediately
, base::Passed(&button
))));
52 void SetPosition(const gfx::Point
& position
) {
55 gfx::Size(kActionButtonImageSize
,
56 kActionButtonImageSize
+ kActionButtonTextSize
)));
59 ui::Layer
* layer() { return layer_
.get(); }
62 static void DestroyImmediately(scoped_ptr
<ActionButton
> button
) {
67 void OnPaintLayer(gfx::Canvas
* canvas
) override
{
68 ui::ResourceBundle
& bundle
= ui::ResourceBundle::GetSharedInstance();
69 canvas
->DrawImageInt(*bundle
.GetImageSkiaNamed(resource_id_
), 0, 0);
70 gfx::ShadowValues shadow
;
71 shadow
.push_back(gfx::ShadowValue(gfx::Point(0, 1), 2, SK_ColorBLACK
));
72 shadow
.push_back(gfx::ShadowValue(gfx::Point(0, -1), 2, SK_ColorBLACK
));
73 canvas
->DrawStringRectWithShadows(label_
,
77 kActionButtonImageSize
,
78 kActionButtonImageSize
,
79 kActionButtonTextSize
),
81 gfx::Canvas::TEXT_ALIGN_CENTER
,
85 void OnDelegatedFrameDamage(const gfx::Rect
& damage_rect_in_dip
) override
{}
87 void OnDeviceScaleFactorChanged(float device_scale_factor
) override
{}
88 base::Closure
PrepareForLayerBoundsChange() override
{
89 return base::Closure();
93 base::string16 label_
;
94 scoped_ptr
<ui::Layer
> layer_
;
96 DISALLOW_COPY_AND_ASSIGN(ActionButton
);
99 OverviewToolbar::OverviewToolbar(aura::Window
* container
)
101 disabled_action_bitfields_(0),
102 close_(new ActionButton(
103 IDR_ATHENA_OVERVIEW_TRASH
,
104 l10n_util::GetStringUTF16(IDS_ATHENA_OVERVIEW_CLOSE
))),
105 split_(new ActionButton(
106 IDR_ATHENA_OVERVIEW_SPLIT
,
107 l10n_util::GetStringUTF16(IDS_ATHENA_OVERVIEW_SPLIT
))),
108 current_action_(ACTION_TYPE_NONE
),
109 container_bounds_(container
->bounds()) {
110 const int kPaddingFromBottom
= 200;
111 const int kPaddingBetweenButtons
= 200;
113 int x
= container_bounds_
.right() -
114 (kActionButtonPaddingFromRight
+ kActionButtonImageSize
);
115 int y
= container_bounds_
.bottom() -
116 (kPaddingFromBottom
+ kActionButtonImageSize
);
117 split_
->SetPosition(gfx::Point(x
, y
));
118 y
-= kPaddingBetweenButtons
;
119 close_
->SetPosition(gfx::Point(x
, y
));
121 container
->layer()->Add(split_
->layer());
122 container
->layer()->Add(close_
->layer());
125 OverviewToolbar::~OverviewToolbar() {
126 // If the buttons are visible, then fade them out, instead of destroying them
129 ActionButton::DestroyAfterFadeout(split_
.Pass());
130 ActionButton::DestroyAfterFadeout(close_
.Pass());
134 OverviewToolbar::ActionType
OverviewToolbar::GetHighlightAction(
135 const ui::GestureEvent
& event
) const {
136 if (IsActionEnabled(ACTION_TYPE_SPLIT
) &&
137 IsEventOverButton(split_
.get(), event
))
138 return ACTION_TYPE_SPLIT
;
139 if (IsActionEnabled(ACTION_TYPE_CLOSE
) &&
140 IsEventOverButton(close_
.get(), event
))
141 return ACTION_TYPE_CLOSE
;
142 return ACTION_TYPE_NONE
;
145 void OverviewToolbar::SetHighlightAction(ActionType action
) {
146 CHECK(IsActionEnabled(action
));
147 if (current_action_
== action
)
149 current_action_
= action
;
153 TransformButton(close_
.get());
154 TransformButton(split_
.get());
158 void OverviewToolbar::ShowActionButtons() {
160 ToggleActionButtonsVisibility();
163 void OverviewToolbar::HideActionButtons() {
165 ToggleActionButtonsVisibility();
168 void OverviewToolbar::DisableAction(ActionType action
) {
169 CHECK_NE(current_action_
, action
);
170 disabled_action_bitfields_
|= (1u << action
);
173 void OverviewToolbar::ToggleActionButtonsVisibility() {
175 TransformButton(close_
.get());
176 TransformButton(split_
.get());
179 bool OverviewToolbar::IsActionEnabled(ActionType action
) const {
180 return !(disabled_action_bitfields_
& (1u << action
));
183 bool OverviewToolbar::IsEventOverButton(ActionButton
* button
,
184 const ui::GestureEvent
& event
) const {
185 const int kBoundsInsetForTarget
= 30;
186 gfx::RectF bounds
= button
->layer()->bounds();
187 bounds
.Inset(-kBoundsInsetForTarget
, -kBoundsInsetForTarget
);
188 return bounds
.Contains(event
.location());
191 gfx::Transform
OverviewToolbar::ComputeTransformFor(
192 ActionButton
* button
) const {
194 return gfx::Transform();
196 const float kHighlightScale
= 1.5;
197 bool button_is_highlighted
=
198 (current_action_
== ACTION_TYPE_CLOSE
&& button
== close_
.get()) ||
199 (current_action_
== ACTION_TYPE_SPLIT
&& button
== split_
.get());
200 gfx::Transform transform
;
201 if (button_is_highlighted
) {
202 transform
.Translate(-kActionButtonImageSize
* (kHighlightScale
- 1) / 2, 0);
203 transform
.Scale(kHighlightScale
, kHighlightScale
);
208 void OverviewToolbar::TransformButton(ActionButton
* button
) {
209 ui::ScopedLayerAnimationSettings
split_settings(
210 button
->layer()->GetAnimator());
211 split_settings
.SetTweenType(gfx::Tween::SMOOTH_IN_OUT
);
212 button
->layer()->SetTransform(ComputeTransformFor(button
));
213 bool button_is_enabled
=
214 (button
== close_
.get() && IsActionEnabled(ACTION_TYPE_CLOSE
)) ||
215 (button
== split_
.get() && IsActionEnabled(ACTION_TYPE_SPLIT
));
216 button
->layer()->SetOpacity((button_is_enabled
&& shown_
) ? 1 : 0);
219 } // namespace athena