Index: ash/frame/caption_buttons/frame_caption_button_container_view.cc |
diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view.cc b/ash/frame/caption_buttons/frame_caption_button_container_view.cc |
index f533f14a8119b6f39ed57c5bdb777ce7c71ad084..2280dbdb19f476fb9e961fa40d8d3d2b662551e4 100644 |
--- a/ash/frame/caption_buttons/frame_caption_button_container_view.cc |
+++ b/ash/frame/caption_buttons/frame_caption_button_container_view.cc |
@@ -5,6 +5,7 @@ |
#include "ash/frame/caption_buttons/frame_caption_button_container_view.h" |
#include <cmath> |
+#include <map> |
flackr
2014/05/08 19:02:21
unused?
jonross
2014/05/08 21:15:40
Cpplint, used outside my changed.
|
#include "ash/ash_switches.h" |
#include "ash/frame/caption_buttons/alternate_frame_size_button.h" |
@@ -15,7 +16,10 @@ |
#include "grit/ui_strings.h" // Accessibility names |
#include "ui/base/hit_test.h" |
#include "ui/base/l10n/l10n_util.h" |
+#include "ui/compositor/layer.h" |
#include "ui/compositor/scoped_animation_duration_scale_mode.h" |
+#include "ui/compositor/scoped_layer_animation_settings.h" |
+#include "ui/gfx/animation/tween.h" |
#include "ui/gfx/canvas.h" |
#include "ui/gfx/insets.h" |
#include "ui/gfx/point.h" |
@@ -26,6 +30,14 @@ namespace ash { |
namespace { |
+// Visual design parameters for animating the transition to maximize mode. |
+// When the size button hides we delay sliding the minimize button into its |
+// location. Also used to delay showing the size button so that the minimize |
+// button slides out of that position. |
+const int kAnimationDelay = 100; |
flackr
2014/05/08 19:02:21
Units?
jonross
2014/05/08 21:15:40
Done.
|
+const int kMinimizeSlideDuration = 500; |
+const int kSizeFadeDuration = 250; |
+ |
// Converts |point| from |src| to |dst| and hittests against |dst|. |
bool ConvertPointToViewAndHitTest(const views::View* src, |
const views::View* dst, |
@@ -50,6 +62,9 @@ FrameCaptionButtonContainerView::FrameCaptionButtonContainerView( |
close_button_(NULL) { |
bool alternate_style = switches::UseAlternateFrameCaptionButtonStyle(); |
+ SetPaintToLayer(true); |
+ SetFillsBoundsOpaquely(false); |
+ |
// Insert the buttons left to right. |
minimize_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_MINIMIZE); |
minimize_button_->SetAccessibleName( |
@@ -59,6 +74,8 @@ FrameCaptionButtonContainerView::FrameCaptionButtonContainerView( |
minimize_button_->SetVisible( |
minimize_allowed == MINIMIZE_ALLOWED && |
(alternate_style || !frame_->widget_delegate()->CanMaximize())); |
+ minimize_button_->SetPaintToLayer(true); |
+ minimize_button_->SetFillsBoundsOpaquely(false); |
AddChildView(minimize_button_); |
if (alternate_style) |
@@ -67,12 +84,16 @@ FrameCaptionButtonContainerView::FrameCaptionButtonContainerView( |
size_button_ = new FrameMaximizeButton(this, frame); |
size_button_->SetAccessibleName( |
l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE)); |
+ size_button_->SetPaintToLayer(true); |
+ size_button_->SetFillsBoundsOpaquely(false); |
UpdateSizeButtonVisibility(false); |
AddChildView(size_button_); |
close_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_CLOSE); |
close_button_->SetAccessibleName( |
l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); |
+ close_button_->SetPaintToLayer(true); |
+ close_button_->SetFillsBoundsOpaquely(false); |
AddChildView(close_button_); |
} |
@@ -143,8 +164,34 @@ void FrameCaptionButtonContainerView::UpdateSizeButtonVisibility( |
// time when ShellObserver::OnMaximizeModeStarted is called. This prevents |
// this method from performing that check, and instead relies on the calling |
// code to tell it to force being hidden. |
- size_button_->SetVisible( |
- !force_hidden && frame_->widget_delegate()->CanMaximize()); |
+ |
+ bool visible = !force_hidden && frame_->widget_delegate()->CanMaximize(); |
+ |
+ // Turning visibility off prevents animations from rendering. Setting the |
+ // size button visibility to false will occur after the animation. |
+ if (visible) |
+ size_button_->SetVisible(visible); |
+ |
+ ui::ScopedLayerAnimationSettings settings( |
+ size_button_->layer()->GetAnimator()); |
+ settings.SetTransitionDuration( |
+ base::TimeDelta::FromMilliseconds(kSizeFadeDuration)); |
+ settings.SetPreemptionStrategy( |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
+ |
+ if (visible) { |
+ settings.SetTweenType(gfx::Tween::EASE_OUT); |
+ // Delay fade in so that the minimize button has begun its sliding |
+ // animation. For visual design. |
+ size_button_->layer()->GetAnimator()->SchedulePauseForProperties( |
+ base::TimeDelta::FromMilliseconds(kAnimationDelay), |
+ ui::LayerAnimationElement::OPACITY); |
+ size_button_->layer()->SetOpacity(1.0f); |
+ } else { |
+ settings.SetTweenType(gfx::Tween::EASE_IN); |
+ settings.AddObserver(this); |
flackr
2014/05/08 19:02:21
nit: comment this will SetVisible(false) when anim
jonross
2014/05/08 21:15:40
Done.
|
+ size_button_->layer()->SetOpacity(0.0f); |
flackr
2014/05/08 19:02:21
Also ->SetVisible(false);
jonross
2014/05/08 21:15:40
Done.
|
+ } |
} |
gfx::Size FrameCaptionButtonContainerView::GetPreferredSize() { |
@@ -158,15 +205,40 @@ gfx::Size FrameCaptionButtonContainerView::GetPreferredSize() { |
} |
void FrameCaptionButtonContainerView::Layout() { |
- int x = 0; |
- for (int i = 0; i < child_count(); ++i) { |
+ scoped_ptr<ui::ScopedLayerAnimationSettings> animation; |
+ int x = width(); |
+ for (int i = child_count() - 1; i >= 0; --i) { |
views::View* child = child_at(i); |
- if (!child->visible()) |
+ if (!child->visible() || |
+ (child == size_button_ && child->layer()->GetTargetOpacity() == 0.0f)) |
flackr
2014/05/08 19:02:21
GetTargetVisibility. Try to avoid making this spec
jonross
2014/05/08 21:15:40
Done.
|
continue; |
gfx::Size size = child->GetPreferredSize(); |
+ // Animate the minimize button if the size button is currently animating |
+ // its visibility. |
+ if (child == minimize_button_ && |
+ size_button_->layer()->GetAnimator()->is_animating()) { |
flackr
2014/05/08 19:02:21
This is awfully specific to the button that's goin
jonross
2014/05/08 21:15:40
Done.
|
+ if (size_button_->layer()->GetTargetOpacity() == 1.0f) { |
+ child->SetBounds(x, 0, size.width(), size.height()); |
+ } else { |
+ // Delay sliding to where the size button was located. For visual |
+ // design. |
+ child->layer()->GetAnimator()->SchedulePauseForProperties( |
+ base::TimeDelta::FromMilliseconds(kAnimationDelay), |
+ ui::LayerAnimationElement::BOUNDS); |
+ } |
+ |
+ ui::ScopedLayerAnimationSettings* settings = |
+ new ui::ScopedLayerAnimationSettings(child->layer()->GetAnimator()); |
+ settings->SetTransitionDuration( |
+ base::TimeDelta::FromMilliseconds(kMinimizeSlideDuration)); |
+ settings->SetPreemptionStrategy( |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
+ settings->SetTweenType(gfx::Tween::EASE_OUT); |
+ animation.reset(settings); |
+ } |
+ x -= size.width(); |
child->SetBounds(x, 0, size.width(), size.height()); |
- x += size.width(); |
} |
} |
@@ -218,7 +290,7 @@ void FrameCaptionButtonContainerView::ButtonPressed(views::Button* sender, |
if (sender == minimize_button_) { |
frame_->Minimize(); |
} else if (sender == size_button_) { |
- if (frame_->IsFullscreen()) { // Can be clicked in immersive fullscreen. |
+ if (frame_->IsFullscreen()) { // Can be clicked in immersive fullscreen. |
flackr
2014/05/08 19:02:21
Why two spaces before comment?
jonross
2014/05/08 21:15:40
cpplint marked this.
|
frame_->SetFullscreen(false); |
action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_EXIT_FULLSCREEN; |
} else if (frame_->IsMaximized()) { |
@@ -228,7 +300,7 @@ void FrameCaptionButtonContainerView::ButtonPressed(views::Button* sender, |
frame_->Maximize(); |
action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE; |
} |
- } else if(sender == close_button_) { |
+ } else if (sender == close_button_) { |
frame_->Close(); |
action = ash::UMA_WINDOW_CLOSE_BUTTON_CLICK; |
} else { |
@@ -305,6 +377,18 @@ void FrameCaptionButtonContainerView::SetHoveredAndPressedButtons( |
} |
} |
+void FrameCaptionButtonContainerView::OnImplicitAnimationsCompleted() { |
+ size_button_->SetVisible(false); |
+ // TODO(jonross): currently we need to delay telling the parent about the |
+ // size change from visibility. When the size changes this forces a relayout |
+ // and we want to animate both the bounds of FrameCaptionButtonContainerView |
+ // along with that of its children. However when the parent is currently |
+ // having its bounds changed this leads to strange animations where this view |
+ // renders outside of its parents. Create a more specific animation where |
flackr
2014/05/08 19:02:21
Can we avoid this by animating Translate transform
|
+ // height and y are immediately fixed, and where we only animate width and x. |
+ PreferredSizeChanged(); |
+} |
+ |
FrameCaptionButtonContainerView::ButtonIconIds::ButtonIconIds() |
: icon_image_id(-1), |
inactive_icon_image_id(-1), |