OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/wm/core/shadow.h" | 5 #include "ui/wm/core/shadow.h" |
6 | 6 |
7 #include "grit/ui_resources.h" | 7 #include "grit/ui_resources.h" |
| 8 #include "third_party/skia/include/core/SkBitmap.h" |
8 #include "ui/base/resource/resource_bundle.h" | 9 #include "ui/base/resource/resource_bundle.h" |
| 10 #include "ui/compositor/layer.h" |
9 #include "ui/compositor/scoped_layer_animation_settings.h" | 11 #include "ui/compositor/scoped_layer_animation_settings.h" |
10 #include "ui/wm/core/image_grid.h" | |
11 | 12 |
12 namespace { | 13 namespace { |
13 | 14 |
14 // Shadow opacity for different styles. | 15 // Shadow opacity for different styles. |
15 const float kActiveShadowOpacity = 1.0f; | 16 const float kActiveShadowOpacity = 1.0f; |
16 const float kInactiveShadowOpacity = 0.2f; | 17 const float kInactiveShadowOpacity = 0.2f; |
17 const float kSmallShadowOpacity = 1.0f; | 18 const float kSmallShadowOpacity = 1.0f; |
18 | 19 |
19 // Interior inset for different styles. | 20 // Interior inset for different styles. |
20 const int kActiveInteriorInset = 0; | 21 const int kActiveInteriorInset = 64; |
21 const int kInactiveInteriorInset = 0; | 22 const int kInactiveInteriorInset = 64; |
22 const int kSmallInteriorInset = 5; | 23 const int kSmallInteriorInset = 4; |
23 | 24 |
24 // Duration for opacity animation in milliseconds. | 25 // Duration for opacity animation in milliseconds. |
25 const int kShadowAnimationDurationMs = 100; | 26 const int kShadowAnimationDurationMs = 100; |
26 | 27 |
27 float GetOpacityForStyle(wm::Shadow::Style style) { | 28 float GetOpacityForStyle(wm::Shadow::Style style) { |
28 switch (style) { | 29 switch (style) { |
29 case wm::Shadow::STYLE_ACTIVE: | 30 case wm::Shadow::STYLE_ACTIVE: |
30 return kActiveShadowOpacity; | 31 return kActiveShadowOpacity; |
31 case wm::Shadow::STYLE_INACTIVE: | 32 case wm::Shadow::STYLE_INACTIVE: |
32 return kInactiveShadowOpacity; | 33 return kInactiveShadowOpacity; |
(...skipping 20 matching lines...) Expand all Loading... |
53 namespace wm { | 54 namespace wm { |
54 | 55 |
55 Shadow::Shadow() : style_(STYLE_ACTIVE), interior_inset_(0) { | 56 Shadow::Shadow() : style_(STYLE_ACTIVE), interior_inset_(0) { |
56 } | 57 } |
57 | 58 |
58 Shadow::~Shadow() { | 59 Shadow::~Shadow() { |
59 } | 60 } |
60 | 61 |
61 void Shadow::Init(Style style) { | 62 void Shadow::Init(Style style) { |
62 style_ = style; | 63 style_ = style; |
63 image_grid_.reset(new ImageGrid); | 64 |
| 65 layer_.reset(new ui::Layer()); |
| 66 layer()->SetShowNinePatch(); |
64 UpdateImagesForStyle(); | 67 UpdateImagesForStyle(); |
65 image_grid_->layer()->set_name("Shadow"); | 68 layer()->set_name("Shadow"); |
66 image_grid_->layer()->SetOpacity(GetOpacityForStyle(style_)); | 69 layer()->SetVisible(true); |
| 70 layer()->SetOpacity(GetOpacityForStyle(style_)); |
67 } | 71 } |
68 | 72 |
69 void Shadow::SetContentBounds(const gfx::Rect& content_bounds) { | 73 void Shadow::SetContentBounds(const gfx::Rect& content_bounds) { |
70 content_bounds_ = content_bounds; | 74 content_bounds_ = content_bounds; |
71 UpdateImageGridBounds(); | 75 UpdateImageBounds(); |
72 } | |
73 | |
74 ui::Layer* Shadow::layer() const { | |
75 return image_grid_->layer(); | |
76 } | 76 } |
77 | 77 |
78 void Shadow::SetStyle(Style style) { | 78 void Shadow::SetStyle(Style style) { |
79 if (style_ == style) | 79 if (style_ == style) |
80 return; | 80 return; |
81 | 81 |
82 Style old_style = style_; | 82 Style old_style = style_; |
83 style_ = style; | 83 style_ = style; |
84 | 84 |
85 // Stop waiting for any as yet unfinished implicit animations. | 85 // Stop waiting for any as yet unfinished implicit animations. |
86 StopObservingImplicitAnimations(); | 86 StopObservingImplicitAnimations(); |
87 | 87 |
88 // If we're switching to or from the small style, don't bother with | 88 // If we're switching to or from the small style, don't bother with |
89 // animations. | 89 // animations. |
90 if (style == STYLE_SMALL || old_style == STYLE_SMALL) { | 90 if (style == STYLE_SMALL || old_style == STYLE_SMALL) { |
91 UpdateImagesForStyle(); | 91 UpdateImagesForStyle(); |
92 image_grid_->layer()->SetOpacity(GetOpacityForStyle(style)); | 92 layer()->SetOpacity(GetOpacityForStyle(style)); |
93 return; | 93 return; |
94 } | 94 } |
95 | 95 |
96 // If we're becoming active, switch images now. Because the inactive image | 96 // If we're becoming active, switch images now. Because the inactive image |
97 // has a very low opacity the switch isn't noticeable and this approach | 97 // has a very low opacity the switch isn't noticeable and this approach |
98 // allows us to use only a single set of shadow images at a time. | 98 // allows us to use only a single set of shadow images at a time. |
99 if (style == STYLE_ACTIVE) { | 99 if (style == STYLE_ACTIVE) { |
100 UpdateImagesForStyle(); | 100 UpdateImagesForStyle(); |
101 // Opacity was baked into inactive image, start opacity low to match. | 101 // Opacity was baked into inactive image, start opacity low to match. |
102 image_grid_->layer()->SetOpacity(kInactiveShadowOpacity); | 102 layer()->SetOpacity(kInactiveShadowOpacity); |
103 } | 103 } |
104 | 104 |
105 { | 105 { |
106 // Property sets within this scope will be implicitly animated. | 106 // Property sets within this scope will be implicitly animated. |
107 ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator()); | 107 ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator()); |
108 settings.AddObserver(this); | 108 settings.AddObserver(this); |
109 settings.SetTransitionDuration( | 109 settings.SetTransitionDuration( |
110 base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs)); | 110 base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs)); |
111 switch (style_) { | 111 switch (style_) { |
112 case STYLE_ACTIVE: | 112 case STYLE_ACTIVE: |
113 image_grid_->layer()->SetOpacity(kActiveShadowOpacity); | 113 layer()->SetOpacity(kActiveShadowOpacity); |
114 break; | 114 break; |
115 case STYLE_INACTIVE: | 115 case STYLE_INACTIVE: |
116 image_grid_->layer()->SetOpacity(kInactiveShadowOpacity); | 116 layer()->SetOpacity(kInactiveShadowOpacity); |
117 break; | 117 break; |
118 default: | 118 default: |
119 NOTREACHED() << "Unhandled style " << style_; | 119 NOTREACHED() << "Unhandled style " << style_; |
120 break; | 120 break; |
121 } | 121 } |
122 } | 122 } |
123 } | 123 } |
124 | 124 |
125 void Shadow::OnImplicitAnimationsCompleted() { | 125 void Shadow::OnImplicitAnimationsCompleted() { |
126 // If we just finished going inactive, switch images. This doesn't cause | 126 // If we just finished going inactive, switch images. This doesn't cause |
127 // a visual pop because the inactive image opacity is so low. | 127 // a visual pop because the inactive image opacity is so low. |
128 if (style_ == STYLE_INACTIVE) { | 128 if (style_ == STYLE_INACTIVE) { |
129 UpdateImagesForStyle(); | 129 UpdateImagesForStyle(); |
130 // Opacity is baked into inactive image, so set fully opaque. | 130 // Opacity is baked into inactive image, so set fully opaque. |
131 image_grid_->layer()->SetOpacity(1.0f); | 131 layer()->SetOpacity(1.0f); |
132 } | 132 } |
133 } | 133 } |
134 | 134 |
135 void Shadow::UpdateImagesForStyle() { | 135 void Shadow::UpdateImagesForStyle() { |
136 ResourceBundle& res = ResourceBundle::GetSharedInstance(); | 136 ResourceBundle& res = ResourceBundle::GetSharedInstance(); |
| 137 gfx::Image image; |
137 switch (style_) { | 138 switch (style_) { |
138 case STYLE_ACTIVE: | 139 case STYLE_ACTIVE: |
139 image_grid_->SetImages( | 140 image = res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE); |
140 &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP_LEFT), | |
141 &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP), | |
142 &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP_RIGHT), | |
143 &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_LEFT), | |
144 NULL, | |
145 &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_RIGHT), | |
146 &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM_LEFT), | |
147 &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM), | |
148 &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM_RIGHT)); | |
149 break; | 141 break; |
150 case STYLE_INACTIVE: | 142 case STYLE_INACTIVE: |
151 image_grid_->SetImages( | 143 image = res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE); |
152 &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP_LEFT), | |
153 &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP), | |
154 &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP_RIGHT), | |
155 &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_LEFT), | |
156 NULL, | |
157 &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_RIGHT), | |
158 &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM_LEFT), | |
159 &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM), | |
160 &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM_RIGHT)); | |
161 break; | 144 break; |
162 case STYLE_SMALL: | 145 case STYLE_SMALL: |
163 image_grid_->SetImages( | 146 image = res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL); |
164 &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_LEFT), | |
165 &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP), | |
166 &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_RIGHT), | |
167 &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_LEFT), | |
168 NULL, | |
169 &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_RIGHT), | |
170 &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_LEFT), | |
171 &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM), | |
172 &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_RIGHT)); | |
173 break; | 147 break; |
174 default: | 148 default: |
175 NOTREACHED() << "Unhandled style " << style_; | 149 NOTREACHED() << "Unhandled style " << style_; |
176 break; | 150 break; |
177 } | 151 } |
178 | 152 |
179 // Update interior inset for style. | 153 // Update interior inset for style. |
180 interior_inset_ = GetInteriorInsetForStyle(style_); | 154 interior_inset_ = GetInteriorInsetForStyle(style_); |
181 | 155 |
| 156 // Update nine-patch layer image with aperture and border. |
| 157 gfx::Rect aperture(interior_inset_, |
| 158 interior_inset_, |
| 159 image.Width() - interior_inset_ * 2, |
| 160 image.Height() - interior_inset_ * 2); |
| 161 gfx::Rect border(interior_inset_, |
| 162 interior_inset_, |
| 163 interior_inset_ * 2, |
| 164 interior_inset_ * 2); |
| 165 layer()->UpdateNinePatchBitmap(image.AsBitmap(), aperture, border); |
| 166 |
182 // Image sizes may have changed. | 167 // Image sizes may have changed. |
183 UpdateImageGridBounds(); | 168 UpdateImageBounds(); |
184 } | 169 } |
185 | 170 |
186 void Shadow::UpdateImageGridBounds() { | 171 void Shadow::UpdateImageBounds() { |
187 // Update bounds based on content bounds and image sizes. | 172 // Update bounds based on content bounds and image sizes. |
188 gfx::Rect image_grid_bounds = content_bounds_; | 173 gfx::Rect image_bounds = content_bounds_; |
189 image_grid_bounds.Inset(interior_inset_, interior_inset_); | 174 image_bounds.Inset(-interior_inset_, -interior_inset_); |
190 image_grid_->SetContentBounds(image_grid_bounds); | 175 layer()->SetBounds(image_bounds); |
191 } | 176 } |
192 | 177 |
193 } // namespace wm | 178 } // namespace wm |
OLD | NEW |