Chromium Code Reviews| Index: ash/system/tray/tray_background_view.cc |
| diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc |
| index fc24c14932af7c4673e9a46c1d195ce8701d965a..8d88d79a774dea2b71a103ce197624d6018c8219 100644 |
| --- a/ash/system/tray/tray_background_view.cc |
| +++ b/ash/system/tray/tray_background_view.cc |
| @@ -22,12 +22,17 @@ |
| #include "ui/aura/window.h" |
| #include "ui/aura/window_event_dispatcher.h" |
| #include "ui/base/resource/resource_bundle.h" |
| +#include "ui/compositor/layer.h" |
| +#include "ui/compositor/layer_animation_element.h" |
| +#include "ui/compositor/scoped_layer_animation_settings.h" |
| +#include "ui/gfx/animation/tween.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/image/image_skia_operations.h" |
| #include "ui/gfx/rect.h" |
| #include "ui/gfx/screen.h" |
| #include "ui/gfx/skia_util.h" |
| +#include "ui/gfx/transform.h" |
| #include "ui/views/background.h" |
| #include "ui/views/layout/box_layout.h" |
| @@ -37,7 +42,15 @@ const int kTrayBackgroundAlpha = 100; |
| const int kTrayBackgroundHoverAlpha = 150; |
| const SkColor kTrayBackgroundPressedColor = SkColorSetRGB(66, 129, 244); |
| -const int kAnimationDurationForPopupMS = 200; |
| +const int kAnimationDurationForPopupMs = 200; |
| + |
| +// Duration of opacity animation for visibility changes. |
| +const int kAnimationDurationForVisibilityMs = 250; |
| + |
| +// When becoming visible delay the animation so that StatusAreaWidgetDelegate |
| +// can animate sibling views out of the position to be occuped by the |
| +// TrayBackgroundView. |
| +const int kShowAnimationDelayMs = 100; |
| } // namespace |
| @@ -307,6 +320,9 @@ TrayBackgroundView::TrayBackgroundView(StatusAreaWidget* status_area_widget) |
| tray_container_ = new TrayContainer(shelf_alignment_); |
| SetContents(tray_container_); |
| tray_event_filter_.reset(new TrayEventFilter); |
| + |
| + SetPaintToLayer(true); |
| + SetFillsBoundsOpaquely(false); |
| } |
| TrayBackgroundView::~TrayBackgroundView() { |
| @@ -319,6 +335,56 @@ void TrayBackgroundView::Initialize() { |
| SetTrayBorder(); |
| } |
| +void TrayBackgroundView::SetVisible(bool visible) { |
| + if (visible == layer()->GetTargetVisibility()) |
| + return; |
| + |
| + if (visible) { |
| + // The alignment of the shelf can change while the TrayBackgroundView is |
| + // hidden. Reset the offscreen transform so that the animation to becoming |
| + // visible reflects the current layout. |
| + HideTransformation(); |
| + // SetVisible(false) is defered until the animation for hiding is done. |
| + // Otherwise the view is immediately hidden and the animation does not |
| + // render. |
| + views::View::SetVisible(visible); |
| + } |
| + |
| + ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); |
| + animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds( |
| + kAnimationDurationForVisibilityMs)); |
| + animation.SetPreemptionStrategy( |
| + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| + |
| + if (visible) { |
| + animation.SetTweenType(gfx::Tween::EASE_OUT); |
| + // Show is delayed so as to allow time for other children of |
| + // StatusAreaWidget to begin animating to their new positions. |
| + layer()->GetAnimator()->SchedulePauseForProperties( |
| + base::TimeDelta::FromMilliseconds(kShowAnimationDelayMs), |
| + ui::LayerAnimationElement::OPACITY | |
| + ui::LayerAnimationElement::TRANSFORM); |
| + layer()->SetOpacity(1.0f); |
| + gfx::Transform transform; |
| + transform.Translate(0.0f, 0.0f); |
| + layer()->SetTransform(transform); |
| + // If SetVisible(true) is called during an animation to not visible, then |
| + // replacing that animation with the one to become visible ends the original |
| + // animation. This could result to calls to views::View::SetVisible(false) |
| + // after setting it to true. This will set the layer to not visibible, so it |
| + // must be turned on again here. |
|
flackr
2014/05/15 21:39:43
This doesn't seem like it should be the case. If a
|
| + layer()->SetVisible(true); |
| + } else { |
| + // Listen only to the hide animation. As we cannot turn off visibility |
| + // until the animation is over. |
| + animation.AddObserver(this); |
| + animation.SetTweenType(gfx::Tween::EASE_IN); |
| + layer()->SetOpacity(0.0f); |
| + layer()->SetVisible(false); |
| + HideTransformation(); |
| + } |
| +} |
| + |
| const char* TrayBackgroundView::GetClassName() const { |
| return kViewClassName; |
| } |
| @@ -420,6 +486,26 @@ void TrayBackgroundView::SetTrayBorder() { |
| top_edge, left_edge, bottom_edge, right_edge)); |
| } |
| +void TrayBackgroundView::OnImplicitAnimationsCompleted() { |
| + // If there is another animation in the queue, the reverse animation was |
| + // triggered before the completion of animating to invisible. Do not turn off |
| + // the visibility so that the next animation may render. |
|
flackr
2014/05/15 21:39:43
How about just checking GetTargetVisibility? If th
jonross
2014/05/16 15:56:20
Unfortunately no. When a new animation is being ad
|
| + if(layer()->GetAnimator()->is_animating() || |
| + layer()->GetTargetVisibility()) |
| + return; |
| + views::View::SetVisible(false); |
| +} |
| + |
| +void TrayBackgroundView::HideTransformation() { |
| + gfx::Transform transform; |
| + if (shelf_alignment_ == SHELF_ALIGNMENT_BOTTOM || |
| + shelf_alignment_ == SHELF_ALIGNMENT_TOP) |
| + transform.Translate(width(), 0.0f); |
| + else |
| + transform.Translate(0.0f, height()); |
| + layer()->SetTransform(transform); |
| +} |
| + |
| void TrayBackgroundView::InitializeBubbleAnimations( |
| views::Widget* bubble_widget) { |
| wm::SetWindowVisibilityAnimationType( |
| @@ -430,7 +516,7 @@ void TrayBackgroundView::InitializeBubbleAnimations( |
| wm::ANIMATE_HIDE); |
| wm::SetWindowVisibilityAnimationDuration( |
| bubble_widget->GetNativeWindow(), |
| - base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS)); |
| + base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMs)); |
| } |
| aura::Window* TrayBackgroundView::GetBubbleWindowContainer() const { |