Home | History | Annotate | Download | only in wm
      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