summaryrefslogtreecommitdiffstats
path: root/chromium/ash/wm/resize_shadow.cc
blob: cdf573d93b67a4bf1e85515debd173c551d82140 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/wm/resize_shadow.h"

#include "base/time/time.h"
#include "grit/ash_resources.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/views/corewm/image_grid.h"

namespace {

// Final opacity for resize effect.
const float kShadowTargetOpacity = 0.25f;
// Animation time for resize effect in milliseconds.
const int kShadowAnimationDurationMs = 100;

// Sets up a layer as invisible and fully transparent, without animating.
void InitLayer(ui::Layer* layer) {
  layer->SetVisible(false);
  layer->SetOpacity(0.f);
}

// Triggers an opacity animation that will make |layer| become |visible|.
void ShowLayer(ui::Layer* layer, bool visible) {
  ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
  settings.SetTransitionDuration(
      base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs));
  layer->SetOpacity(visible ? kShadowTargetOpacity : 0.f);
  // Sets the layer visibility after a delay, which will be identical to the
  // opacity animation duration.
  layer->SetVisible(visible);
}

}  // namespace

namespace ash {
namespace internal {

ResizeShadow::ResizeShadow() : last_hit_test_(HTNOWHERE) {}

ResizeShadow::~ResizeShadow() {}

void ResizeShadow::Init(aura::Window* window) {
  // Set up our image grid and images.
  ResourceBundle& res = ResourceBundle::GetSharedInstance();
  image_grid_.reset(new views::corewm::ImageGrid);
  image_grid_->SetImages(
      &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP_LEFT),
      &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP),
      &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP_RIGHT),
      &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_LEFT),
      NULL,
      &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_RIGHT),
      &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM_LEFT),
      &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM),
      &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM_RIGHT));
  // Initialize all layers to invisible/transparent.
  InitLayer(image_grid_->top_left_layer());
  InitLayer(image_grid_->top_layer());
  InitLayer(image_grid_->top_right_layer());
  InitLayer(image_grid_->left_layer());
  InitLayer(image_grid_->right_layer());
  InitLayer(image_grid_->bottom_left_layer());
  InitLayer(image_grid_->bottom_layer());
  InitLayer(image_grid_->bottom_right_layer());
  // Add image grid as a child of the window's layer so it follows the window
  // as it moves.
  window->layer()->Add(image_grid_->layer());
}

void ResizeShadow::ShowForHitTest(int hit) {
  // Don't start animations unless something changed.
  if (hit == last_hit_test_)
    return;
  last_hit_test_ = hit;

  // Show affected corners.
  ShowLayer(image_grid_->top_left_layer(), hit == HTTOPLEFT);
  ShowLayer(image_grid_->top_right_layer(), hit == HTTOPRIGHT);
  ShowLayer(image_grid_->bottom_left_layer(), hit == HTBOTTOMLEFT);
  ShowLayer(image_grid_->bottom_right_layer(), hit == HTBOTTOMRIGHT);

  // Show affected edges.
  ShowLayer(image_grid_->top_layer(),
            hit == HTTOPLEFT || hit == HTTOP || hit == HTTOPRIGHT);
  ShowLayer(image_grid_->left_layer(),
            hit == HTTOPLEFT || hit == HTLEFT || hit == HTBOTTOMLEFT);
  ShowLayer(image_grid_->right_layer(),
            hit == HTTOPRIGHT || hit == HTRIGHT || hit == HTBOTTOMRIGHT);
  ShowLayer(image_grid_->bottom_layer(),
            hit == HTBOTTOMLEFT || hit == HTBOTTOM || hit == HTBOTTOMRIGHT);
}

void ResizeShadow::Hide() {
  ShowForHitTest(HTNOWHERE);
}

void ResizeShadow::Layout(const gfx::Rect& content_bounds) {
  gfx::Rect local_bounds(content_bounds.size());
  image_grid_->SetContentBounds(local_bounds);
}

}  // namespace internal
}  // namespace ash