1// Copyright (c) 2012 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 "ash/wm/resize_shadow.h" 6 7#include "base/time/time.h" 8#include "grit/ash_resources.h" 9#include "ui/aura/window.h" 10#include "ui/base/hit_test.h" 11#include "ui/base/resource/resource_bundle.h" 12#include "ui/compositor/layer.h" 13#include "ui/compositor/scoped_layer_animation_settings.h" 14#include "ui/wm/core/image_grid.h" 15 16namespace { 17 18// Final opacity for resize effect. 19const float kShadowTargetOpacity = 0.25f; 20// Animation time for resize effect in milliseconds. 21const int kShadowAnimationDurationMs = 100; 22 23// Sets up a layer as invisible and fully transparent, without animating. 24void InitLayer(ui::Layer* layer) { 25 layer->SetVisible(false); 26 layer->SetOpacity(0.f); 27} 28 29// Triggers an opacity animation that will make |layer| become |visible|. 30void ShowLayer(ui::Layer* layer, bool visible) { 31 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); 32 settings.SetTransitionDuration( 33 base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs)); 34 layer->SetOpacity(visible ? kShadowTargetOpacity : 0.f); 35 // Sets the layer visibility after a delay, which will be identical to the 36 // opacity animation duration. 37 layer->SetVisible(visible); 38} 39 40} // namespace 41 42namespace ash { 43 44ResizeShadow::ResizeShadow() : last_hit_test_(HTNOWHERE) {} 45 46ResizeShadow::~ResizeShadow() {} 47 48void ResizeShadow::Init(aura::Window* window) { 49 // Set up our image grid and images. 50 ResourceBundle& res = ResourceBundle::GetSharedInstance(); 51 image_grid_.reset(new ::wm::ImageGrid); 52 image_grid_->SetImages( 53 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP_LEFT), 54 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP), 55 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP_RIGHT), 56 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_LEFT), 57 NULL, 58 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_RIGHT), 59 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM_LEFT), 60 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM), 61 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM_RIGHT)); 62 // Initialize all layers to invisible/transparent. 63 InitLayer(image_grid_->top_left_layer()); 64 InitLayer(image_grid_->top_layer()); 65 InitLayer(image_grid_->top_right_layer()); 66 InitLayer(image_grid_->left_layer()); 67 InitLayer(image_grid_->right_layer()); 68 InitLayer(image_grid_->bottom_left_layer()); 69 InitLayer(image_grid_->bottom_layer()); 70 InitLayer(image_grid_->bottom_right_layer()); 71 // Add image grid as a child of the window's layer so it follows the window 72 // as it moves. 73 window->layer()->Add(image_grid_->layer()); 74} 75 76void ResizeShadow::ShowForHitTest(int hit) { 77 // Don't start animations unless something changed. 78 if (hit == last_hit_test_) 79 return; 80 last_hit_test_ = hit; 81 82 // Show affected corners. 83 ShowLayer(image_grid_->top_left_layer(), hit == HTTOPLEFT); 84 ShowLayer(image_grid_->top_right_layer(), hit == HTTOPRIGHT); 85 ShowLayer(image_grid_->bottom_left_layer(), hit == HTBOTTOMLEFT); 86 ShowLayer(image_grid_->bottom_right_layer(), hit == HTBOTTOMRIGHT); 87 88 // Show affected edges. 89 ShowLayer(image_grid_->top_layer(), 90 hit == HTTOPLEFT || hit == HTTOP || hit == HTTOPRIGHT); 91 ShowLayer(image_grid_->left_layer(), 92 hit == HTTOPLEFT || hit == HTLEFT || hit == HTBOTTOMLEFT); 93 ShowLayer(image_grid_->right_layer(), 94 hit == HTTOPRIGHT || hit == HTRIGHT || hit == HTBOTTOMRIGHT); 95 ShowLayer(image_grid_->bottom_layer(), 96 hit == HTBOTTOMLEFT || hit == HTBOTTOM || hit == HTBOTTOMRIGHT); 97} 98 99void ResizeShadow::Hide() { 100 ShowForHitTest(HTNOWHERE); 101} 102 103void ResizeShadow::Layout(const gfx::Rect& content_bounds) { 104 gfx::Rect local_bounds(content_bounds.size()); 105 image_grid_->SetContentBounds(local_bounds); 106} 107 108} // namespace ash 109