15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/slide_out_view.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/transform.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SlideOutView::SlideOutView() 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : gesture_scroll_amount_(0.f) { 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If accelerated compositing is not available, this widget tracks the 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // OnSlideOut event but does not render any visible changes. 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SetPaintToLayer(true); 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SetFillsBoundsOpaquely(false); 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SlideOutView::~SlideOutView() { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SlideOutView::OnGestureEvent(ui::GestureEvent* event) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event->type() == ui::ET_SCROLL_FLING_START) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The threshold for the fling velocity is computed empirically. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The unit is in pixels/second. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const float kFlingThresholdForClose = 800.f; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fabsf(event->details().velocity_x()) > kFlingThresholdForClose) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SlideOutAndClose(event->details().velocity_x() < 0 ? SLIDE_LEFT : 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SLIDE_RIGHT); 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->StopPropagation(); 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RestoreVisualState(); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!event->IsScrollGestureEvent()) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gesture_scroll_amount_ = 0.f; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The scroll-update events include the incremental scroll amount. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gesture_scroll_amount_ += event->details().scroll_x(); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Transform transform; 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) transform.Translate(gesture_scroll_amount_, 0.0); 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) layer()->SetTransform(transform); 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) layer()->SetOpacity( 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1.f - std::min(fabsf(gesture_scroll_amount_) / width(), 1.f)); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (event->type() == ui::ET_GESTURE_SCROLL_END) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const float kScrollRatioForClosingNotification = 0.5f; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float scrolled_ratio = fabsf(gesture_scroll_amount_) / width(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (scrolled_ratio >= kScrollRatioForClosingNotification) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SlideOutAndClose(gesture_scroll_amount_ < 0 ? SLIDE_LEFT : SLIDE_RIGHT); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->StopPropagation(); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RestoreVisualState(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->SetHandled(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SlideOutView::RestoreVisualState() { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Restore the layer state. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kSwipeRestoreDurationMS = 150; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator()); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings.SetTransitionDuration( 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kSwipeRestoreDurationMS)); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layer()->SetTransform(gfx::Transform()); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layer()->SetOpacity(1.f); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SlideOutView::SlideOutAndClose(SlideDirection direction) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kSwipeOutTotalDurationMS = 150; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int swipe_out_duration = kSwipeOutTotalDurationMS * layer()->opacity(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator()); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings.SetTransitionDuration( 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(swipe_out_duration)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings.AddObserver(this); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Transform transform; 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) transform.Translate(direction == SLIDE_LEFT ? -width() : width(), 0.0); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layer()->SetTransform(transform); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layer()->SetOpacity(0.f); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SlideOutView::OnImplicitAnimationsCompleted() { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnSlideOut(); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace views 97