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/views/corewm/image_grid.h" 15 16 namespace { 17 18 // Final opacity for resize effect. 19 const float kShadowTargetOpacity = 0.25f; 20 // Animation time for resize effect in milliseconds. 21 const int kShadowAnimationDurationMs = 100; 22 23 // Sets up a layer as invisible and fully transparent, without animating. 24 void 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|. 30 void 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 42 namespace ash { 43 namespace internal { 44 45 ResizeShadow::ResizeShadow() : last_hit_test_(HTNOWHERE) {} 46 47 ResizeShadow::~ResizeShadow() {} 48 49 void ResizeShadow::Init(aura::Window* window) { 50 // Set up our image grid and images. 51 ResourceBundle& res = ResourceBundle::GetSharedInstance(); 52 image_grid_.reset(new views::corewm::ImageGrid); 53 image_grid_->SetImages( 54 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP_LEFT), 55 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP), 56 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP_RIGHT), 57 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_LEFT), 58 NULL, 59 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_RIGHT), 60 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM_LEFT), 61 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM), 62 &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM_RIGHT)); 63 // Initialize all layers to invisible/transparent. 64 InitLayer(image_grid_->top_left_layer()); 65 InitLayer(image_grid_->top_layer()); 66 InitLayer(image_grid_->top_right_layer()); 67 InitLayer(image_grid_->left_layer()); 68 InitLayer(image_grid_->right_layer()); 69 InitLayer(image_grid_->bottom_left_layer()); 70 InitLayer(image_grid_->bottom_layer()); 71 InitLayer(image_grid_->bottom_right_layer()); 72 // Add image grid as a child of the window's layer so it follows the window 73 // as it moves. 74 window->layer()->Add(image_grid_->layer()); 75 } 76 77 void ResizeShadow::ShowForHitTest(int hit) { 78 // Don't start animations unless something changed. 79 if (hit == last_hit_test_) 80 return; 81 last_hit_test_ = hit; 82 83 // Show affected corners. 84 ShowLayer(image_grid_->top_left_layer(), hit == HTTOPLEFT); 85 ShowLayer(image_grid_->top_right_layer(), hit == HTTOPRIGHT); 86 ShowLayer(image_grid_->bottom_left_layer(), hit == HTBOTTOMLEFT); 87 ShowLayer(image_grid_->bottom_right_layer(), hit == HTBOTTOMRIGHT); 88 89 // Show affected edges. 90 ShowLayer(image_grid_->top_layer(), 91 hit == HTTOPLEFT || hit == HTTOP || hit == HTTOPRIGHT); 92 ShowLayer(image_grid_->left_layer(), 93 hit == HTTOPLEFT || hit == HTLEFT || hit == HTBOTTOMLEFT); 94 ShowLayer(image_grid_->right_layer(), 95 hit == HTTOPRIGHT || hit == HTRIGHT || hit == HTBOTTOMRIGHT); 96 ShowLayer(image_grid_->bottom_layer(), 97 hit == HTBOTTOMLEFT || hit == HTBOTTOM || hit == HTBOTTOMRIGHT); 98 } 99 100 void ResizeShadow::Hide() { 101 ShowForHitTest(HTNOWHERE); 102 } 103 104 void ResizeShadow::Layout(const gfx::Rect& content_bounds) { 105 gfx::Rect local_bounds(content_bounds.size()); 106 image_grid_->SetContentBounds(local_bounds); 107 } 108 109 } // namespace internal 110 } // namespace ash 111