diff options
-rw-r--r-- | ash/wm/image_grid.cc | 12 | ||||
-rw-r--r-- | ash/wm/image_grid.h | 28 | ||||
-rw-r--r-- | ash/wm/image_grid_unittest.cc | 149 | ||||
-rw-r--r-- | ash/wm/resize_shadow.cc | 207 | ||||
-rw-r--r-- | ash/wm/resize_shadow.h | 38 | ||||
-rw-r--r-- | ash/wm/shadow.cc | 16 | ||||
-rw-r--r-- | ui/resources/ui_resources.grd | 8 |
7 files changed, 211 insertions, 247 deletions
diff --git a/ash/wm/image_grid.cc b/ash/wm/image_grid.cc index f8b87e9..c9c341f 100644 --- a/ash/wm/image_grid.cc +++ b/ash/wm/image_grid.cc @@ -203,6 +203,18 @@ void ImageGrid::SetSize(const gfx::Size& size) { } } +void ImageGrid::SetContentBounds(const gfx::Rect& content_bounds) { + SetSize( + gfx::Size( + content_bounds.width() + left_image_width_ + right_image_width_, + content_bounds.height() + top_image_height_ + bottom_image_height_)); + layer_->SetBounds( + gfx::Rect(content_bounds.x() - left_image_width_, + content_bounds.y() - top_image_height_, + layer_->bounds().width(), + layer_->bounds().height())); +} + void ImageGrid::ImagePainter::SetClipRect(const gfx::Rect& clip_rect, ui::Layer* layer) { if (clip_rect != clip_rect_) { diff --git a/ash/wm/image_grid.h b/ash/wm/image_grid.h index aedf002..5794a74 100644 --- a/ash/wm/image_grid.h +++ b/ash/wm/image_grid.h @@ -64,19 +64,6 @@ class ASH_EXPORT ImageGrid { class ASH_EXPORT TestAPI { public: TestAPI(ImageGrid* grid) : grid_(grid) {} - ui::Layer* top_left_layer() const { return grid_->top_left_layer_.get(); } - ui::Layer* top_layer() const { return grid_->top_layer_.get(); } - ui::Layer* top_right_layer() const { return grid_->top_right_layer_.get(); } - ui::Layer* left_layer() const { return grid_->left_layer_.get(); } - ui::Layer* center_layer() const { return grid_->center_layer_.get(); } - ui::Layer* right_layer() const { return grid_->right_layer_.get(); } - ui::Layer* bottom_left_layer() const { - return grid_->bottom_left_layer_.get(); - } - ui::Layer* bottom_layer() const { return grid_->bottom_layer_.get(); } - ui::Layer* bottom_right_layer() const { - return grid_->bottom_right_layer_.get(); - } gfx::Rect top_left_clip_rect() const { return grid_->top_left_painter_->clip_rect_; @@ -109,6 +96,17 @@ class ASH_EXPORT ImageGrid { int left_image_width() const { return left_image_width_; } int right_image_width() const { return right_image_width_; } + // Visible to allow independent layer animations and for testing. + ui::Layer* top_left_layer() const { return top_left_layer_.get(); } + ui::Layer* top_layer() const { return top_layer_.get(); } + ui::Layer* top_right_layer() const { return top_right_layer_.get(); } + ui::Layer* left_layer() const { return left_layer_.get(); } + ui::Layer* center_layer() const { return center_layer_.get(); } + ui::Layer* right_layer() const { return right_layer_.get(); } + ui::Layer* bottom_left_layer() const { return bottom_left_layer_.get(); } + ui::Layer* bottom_layer() const { return bottom_layer_.get(); } + ui::Layer* bottom_right_layer() const { return bottom_right_layer_.get(); } + // Sets the grid to display the passed-in images (any of which can be NULL). // Ownership of the images remains with the caller. May be called more than // once to switch images. @@ -124,6 +122,10 @@ class ASH_EXPORT ImageGrid { void SetSize(const gfx::Size& size); + // Sets the grid to a position and size such that the inner edges of the top, + // bottom, left and right images will be flush with |content_bounds|. + void SetContentBounds(const gfx::Rect& content_bounds); + private: // Delegate responsible for painting a specific image on a layer. class ImagePainter : public ui::LayerDelegate { diff --git a/ash/wm/image_grid_unittest.cc b/ash/wm/image_grid_unittest.cc index e578467..715ddb9 100644 --- a/ash/wm/image_grid_unittest.cc +++ b/ash/wm/image_grid_unittest.cc @@ -43,15 +43,15 @@ TEST_F(ImageGridTest, Basic) { image_BxB.get(), image_1xB.get(), image_BxB.get()); ImageGrid::TestAPI test_api(&grid); - ASSERT_TRUE(test_api.top_left_layer() != NULL); - ASSERT_TRUE(test_api.top_layer() != NULL); - ASSERT_TRUE(test_api.top_right_layer() != NULL); - ASSERT_TRUE(test_api.left_layer() != NULL); - ASSERT_TRUE(test_api.center_layer() != NULL); - ASSERT_TRUE(test_api.right_layer() != NULL); - ASSERT_TRUE(test_api.bottom_left_layer() != NULL); - ASSERT_TRUE(test_api.bottom_layer() != NULL); - ASSERT_TRUE(test_api.bottom_right_layer() != NULL); + ASSERT_TRUE(grid.top_left_layer() != NULL); + ASSERT_TRUE(grid.top_layer() != NULL); + ASSERT_TRUE(grid.top_right_layer() != NULL); + ASSERT_TRUE(grid.left_layer() != NULL); + ASSERT_TRUE(grid.center_layer() != NULL); + ASSERT_TRUE(grid.right_layer() != NULL); + ASSERT_TRUE(grid.bottom_left_layer() != NULL); + ASSERT_TRUE(grid.bottom_layer() != NULL); + ASSERT_TRUE(grid.bottom_right_layer() != NULL); const gfx::Size size(20, 30); grid.SetSize(size); @@ -59,33 +59,33 @@ TEST_F(ImageGridTest, Basic) { // The top-left layer should be flush with the top-left corner and unscaled. EXPECT_EQ(gfx::Rect(0, 0, kBorder, kBorder).ToString(), test_api.GetTransformedLayerBounds( - *test_api.top_left_layer()).ToString()); + *grid.top_left_layer()).ToString()); // The top layer should be flush with the top edge and stretched horizontally // between the two top corners. EXPECT_EQ(gfx::Rect( kBorder, 0, size.width() - 2 * kBorder, kBorder).ToString(), test_api.GetTransformedLayerBounds( - *test_api.top_layer()).ToString()); + *grid.top_layer()).ToString()); // The top-right layer should be flush with the top-right corner and unscaled. EXPECT_EQ(gfx::Rect(size.width() - kBorder, 0, kBorder, kBorder).ToString(), test_api.GetTransformedLayerBounds( - *test_api.top_right_layer()).ToString()); + *grid.top_right_layer()).ToString()); // The left layer should be flush with the left edge and stretched vertically // between the two left corners. EXPECT_EQ(gfx::Rect( 0, kBorder, kBorder, size.height() - 2 * kBorder).ToString(), test_api.GetTransformedLayerBounds( - *test_api.left_layer()).ToString()); + *grid.left_layer()).ToString()); // The center layer should fill the space in the middle of the grid. EXPECT_EQ(gfx::Rect( kBorder, kBorder, size.width() - 2 * kBorder, size.height() - 2 * kBorder).ToString(), test_api.GetTransformedLayerBounds( - *test_api.center_layer()).ToString()); + *grid.center_layer()).ToString()); // The right layer should be flush with the right edge and stretched // vertically between the two right corners. @@ -93,13 +93,13 @@ TEST_F(ImageGridTest, Basic) { size.width() - kBorder, kBorder, kBorder, size.height() - 2 * kBorder).ToString(), test_api.GetTransformedLayerBounds( - *test_api.right_layer()).ToString()); + *grid.right_layer()).ToString()); // The bottom-left layer should be flush with the bottom-left corner and // unscaled. EXPECT_EQ(gfx::Rect(0, size.height() - kBorder, kBorder, kBorder).ToString(), test_api.GetTransformedLayerBounds( - *test_api.bottom_left_layer()).ToString()); + *grid.bottom_left_layer()).ToString()); // The bottom layer should be flush with the bottom edge and stretched // horizontally between the two bottom corners. @@ -107,7 +107,7 @@ TEST_F(ImageGridTest, Basic) { kBorder, size.height() - kBorder, size.width() - 2 * kBorder, kBorder).ToString(), test_api.GetTransformedLayerBounds( - *test_api.bottom_layer()).ToString()); + *grid.bottom_layer()).ToString()); // The bottom-right layer should be flush with the bottom-right corner and // unscaled. @@ -115,7 +115,38 @@ TEST_F(ImageGridTest, Basic) { size.width() - kBorder, size.height() - kBorder, kBorder, kBorder).ToString(), test_api.GetTransformedLayerBounds( - *test_api.bottom_right_layer()).ToString()); + *grid.bottom_right_layer()).ToString()); +} + +// Test that an ImageGrid's layers are transformed correctly when +// SetContentBounds() is called. +TEST_F(ImageGridTest, SetContentBounds) { + // Size of the images around the grid's border. + const int kBorder = 2; + + scoped_ptr<gfx::Image> image_1x1(CreateImage(gfx::Size(1, 1))); + scoped_ptr<gfx::Image> image_1xB(CreateImage(gfx::Size(1, kBorder))); + scoped_ptr<gfx::Image> image_Bx1(CreateImage(gfx::Size(kBorder, 1))); + scoped_ptr<gfx::Image> image_BxB(CreateImage(gfx::Size(kBorder, kBorder))); + + ImageGrid grid; + grid.SetImages(image_BxB.get(), image_1xB.get(), image_BxB.get(), + image_Bx1.get(), image_1x1.get(), image_Bx1.get(), + image_BxB.get(), image_1xB.get(), image_BxB.get()); + + ImageGrid::TestAPI test_api(&grid); + + const gfx::Point origin(5, 10); + const gfx::Size size(20, 30); + grid.SetContentBounds(gfx::Rect(origin, size)); + + // The master layer is positioned above the top-left corner of the content + // bounds and has height/width that contain the grid and bounds. + EXPECT_EQ(gfx::Rect(origin.x() - kBorder, + origin.y() - kBorder, + size.width() + 2 * kBorder, + size.height() + 2 * kBorder).ToString(), + test_api.GetTransformedLayerBounds(*grid.layer()).ToString()); } // Check that we don't crash if only a single image is supplied. @@ -129,15 +160,15 @@ TEST_F(ImageGridTest, SingleImage) { NULL, NULL, NULL); ImageGrid::TestAPI test_api(&grid); - EXPECT_TRUE(test_api.top_left_layer() == NULL); - ASSERT_TRUE(test_api.top_layer() != NULL); - EXPECT_TRUE(test_api.top_right_layer() == NULL); - EXPECT_TRUE(test_api.left_layer() == NULL); - EXPECT_TRUE(test_api.center_layer() == NULL); - EXPECT_TRUE(test_api.right_layer() == NULL); - EXPECT_TRUE(test_api.bottom_left_layer() == NULL); - EXPECT_TRUE(test_api.bottom_layer() == NULL); - EXPECT_TRUE(test_api.bottom_right_layer() == NULL); + EXPECT_TRUE(grid.top_left_layer() == NULL); + ASSERT_TRUE(grid.top_layer() != NULL); + EXPECT_TRUE(grid.top_right_layer() == NULL); + EXPECT_TRUE(grid.left_layer() == NULL); + EXPECT_TRUE(grid.center_layer() == NULL); + EXPECT_TRUE(grid.right_layer() == NULL); + EXPECT_TRUE(grid.bottom_left_layer() == NULL); + EXPECT_TRUE(grid.bottom_layer() == NULL); + EXPECT_TRUE(grid.bottom_right_layer() == NULL); const gfx::Size kSize(10, 10); grid.SetSize(kSize); @@ -146,7 +177,7 @@ TEST_F(ImageGridTest, SingleImage) { // shouldn't be scaled vertically. EXPECT_EQ(gfx::Rect(0, 0, kSize.width(), kBorder).ToString(), test_api.GetTransformedLayerBounds( - *test_api.top_layer()).ToString()); + *grid.top_layer()).ToString()); } // Check that we don't crash when we reset existing images to NULL and @@ -162,30 +193,30 @@ TEST_F(ImageGridTest, ResetImages) { // Only the top edge has a layer. ImageGrid::TestAPI test_api(&grid); - ASSERT_TRUE(test_api.top_left_layer() == NULL); - ASSERT_FALSE(test_api.top_layer() == NULL); - ASSERT_TRUE(test_api.top_right_layer() == NULL); - ASSERT_TRUE(test_api.left_layer() == NULL); - ASSERT_TRUE(test_api.center_layer() == NULL); - ASSERT_TRUE(test_api.right_layer() == NULL); - ASSERT_TRUE(test_api.bottom_left_layer() == NULL); - ASSERT_TRUE(test_api.bottom_layer() == NULL); - ASSERT_TRUE(test_api.bottom_right_layer() == NULL); + ASSERT_TRUE(grid.top_left_layer() == NULL); + ASSERT_FALSE(grid.top_layer() == NULL); + ASSERT_TRUE(grid.top_right_layer() == NULL); + ASSERT_TRUE(grid.left_layer() == NULL); + ASSERT_TRUE(grid.center_layer() == NULL); + ASSERT_TRUE(grid.right_layer() == NULL); + ASSERT_TRUE(grid.bottom_left_layer() == NULL); + ASSERT_TRUE(grid.bottom_layer() == NULL); + ASSERT_TRUE(grid.bottom_right_layer() == NULL); grid.SetImages(NULL, NULL, NULL, NULL, NULL, NULL, NULL, image.get(), NULL); // Now only the bottom edge has a layer. - ASSERT_TRUE(test_api.top_left_layer() == NULL); - ASSERT_TRUE(test_api.top_layer() == NULL); - ASSERT_TRUE(test_api.top_right_layer() == NULL); - ASSERT_TRUE(test_api.left_layer() == NULL); - ASSERT_TRUE(test_api.center_layer() == NULL); - ASSERT_TRUE(test_api.right_layer() == NULL); - ASSERT_TRUE(test_api.bottom_left_layer() == NULL); - ASSERT_FALSE(test_api.bottom_layer() == NULL); - ASSERT_TRUE(test_api.bottom_right_layer() == NULL); + ASSERT_TRUE(grid.top_left_layer() == NULL); + ASSERT_TRUE(grid.top_layer() == NULL); + ASSERT_TRUE(grid.top_right_layer() == NULL); + ASSERT_TRUE(grid.left_layer() == NULL); + ASSERT_TRUE(grid.center_layer() == NULL); + ASSERT_TRUE(grid.right_layer() == NULL); + ASSERT_TRUE(grid.bottom_left_layer() == NULL); + ASSERT_FALSE(grid.bottom_layer() == NULL); + ASSERT_TRUE(grid.bottom_right_layer() == NULL); } // Test that side (top, left, right, bottom) layers that are narrower than their @@ -217,14 +248,14 @@ TEST_F(ImageGridTest, SmallerSides) { EXPECT_EQ(gfx::Rect( kCorner, 0, kSize.width() - 2 * kCorner, kEdge).ToString(), test_api.GetTransformedLayerBounds( - *test_api.top_layer()).ToString()); + *grid.top_layer()).ToString()); // The left layer should be flush with the left edge and stretched vertically // between the top left corner and the bottom. EXPECT_EQ(gfx::Rect( 0, kCorner, kEdge, kSize.height() - kCorner).ToString(), test_api.GetTransformedLayerBounds( - *test_api.left_layer()).ToString()); + *grid.left_layer()).ToString()); // The right layer should be flush with the right edge and stretched // vertically between the top right corner and the bottom. @@ -232,7 +263,7 @@ TEST_F(ImageGridTest, SmallerSides) { kSize.width() - kEdge, kCorner, kEdge, kSize.height() - kCorner).ToString(), test_api.GetTransformedLayerBounds( - *test_api.right_layer()).ToString()); + *grid.right_layer()).ToString()); } // Test that we hide or clip layers as needed when the grid is assigned a small @@ -268,11 +299,11 @@ TEST_F(ImageGridTest, TooSmall) { grid.SetSize(kSmallSize); // The scalable images around the sides and in the center should be hidden. - EXPECT_FALSE(test_api.top_layer()->visible()); - EXPECT_FALSE(test_api.bottom_layer()->visible()); - EXPECT_FALSE(test_api.left_layer()->visible()); - EXPECT_FALSE(test_api.right_layer()->visible()); - EXPECT_FALSE(test_api.center_layer()->visible()); + EXPECT_FALSE(grid.top_layer()->visible()); + EXPECT_FALSE(grid.bottom_layer()->visible()); + EXPECT_FALSE(grid.left_layer()->visible()); + EXPECT_FALSE(grid.right_layer()->visible()); + EXPECT_FALSE(grid.center_layer()->visible()); // The corner images' clip rects should sum to the expected size. EXPECT_EQ(kSmallSize.width(), @@ -294,11 +325,11 @@ TEST_F(ImageGridTest, TooSmall) { grid.SetSize(kLargeSize); // The scalable images should be visible now. - EXPECT_TRUE(test_api.top_layer()->visible()); - EXPECT_TRUE(test_api.bottom_layer()->visible()); - EXPECT_TRUE(test_api.left_layer()->visible()); - EXPECT_TRUE(test_api.right_layer()->visible()); - EXPECT_TRUE(test_api.center_layer()->visible()); + EXPECT_TRUE(grid.top_layer()->visible()); + EXPECT_TRUE(grid.bottom_layer()->visible()); + EXPECT_TRUE(grid.left_layer()->visible()); + EXPECT_TRUE(grid.right_layer()->visible()); + EXPECT_TRUE(grid.center_layer()->visible()); // We shouldn't be clipping the corner images anymore. EXPECT_TRUE(test_api.top_left_clip_rect().IsEmpty()); diff --git a/ash/wm/resize_shadow.cc b/ash/wm/resize_shadow.cc index 983fdfb..5807700 100644 --- a/ash/wm/resize_shadow.cc +++ b/ash/wm/resize_shadow.cc @@ -4,167 +4,106 @@ #include "ash/wm/resize_shadow.h" +#include "ash/wm/image_grid.h" +#include "base/time.h" #include "grit/ui_resources.h" -#include "third_party/skia/include/core/SkColor.h" #include "ui/aura/window.h" -#include "ui/base/animation/slide_animation.h" #include "ui/base/hit_test.h" +#include "ui/base/resource/resource_bundle.h" #include "ui/gfx/compositor/layer.h" #include "ui/gfx/compositor/scoped_layer_animation_settings.h" namespace { -// Height or width for the resize border shadow. -const int kShadowSize = 6; -// Amount to inset the resize effect from the window corners. -const int kShadowInset = 4; -// Color for resize effect. -const SkColor kShadowLayerColor = SkColorSetRGB(0, 0, 0); // Final opacity for resize effect. -const int kShadowTargetOpacity = 64; +const float kShadowTargetOpacity = 0.25f; // Animation time for resize effect in milliseconds. -const int kShadowSlideDurationMs = 200; +const int kShadowAnimationDurationMs = 200; + +// 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() {} +ResizeShadow::ResizeShadow() : last_hit_test_(HTNOWHERE) {} ResizeShadow::~ResizeShadow() {} void ResizeShadow::Init(aura::Window* window) { - ui::Layer* parent = window->layer(); - InitLayer(parent, &top_layer_); - InitLayer(parent, &left_layer_); - InitLayer(parent, &right_layer_); - InitLayer(parent, &bottom_layer_); - InitAnimation(&top_animation_); - InitAnimation(&left_animation_); - InitAnimation(&right_animation_); - InitAnimation(&bottom_animation_); + // Set up our image grid and images. + ResourceBundle& res = ResourceBundle::GetSharedInstance(); + image_grid_.reset(new 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_test) { - // TODO(jamescook): Add support for top_left, top_right, bottom_left, and - // bottom_right corners. This approach matches the mocks but looks a little - // funny. - bool top = false; - bool left = false; - bool right = false; - bool bottom = false; - switch (hit_test) { - case HTTOPLEFT: - top = true; - left = true; - break; - case HTTOP: - top = true; - break; - case HTTOPRIGHT: - top = true; - right = true; - break; - case HTLEFT: - left = true; - break; - case HTRIGHT: - right = true; - break; - case HTBOTTOMLEFT: - left = true; - bottom = true; - break; - case HTBOTTOM: - bottom = true; - break; - case HTBOTTOMRIGHT: - bottom = true; - right = true; - break; - default: - break; - } - if (top) - top_animation_->Show(); - else - top_animation_->Hide(); - if (left) - left_animation_->Show(); - else - left_animation_->Hide(); - if (right) - right_animation_->Show(); - else - right_animation_->Hide(); - if (bottom) - bottom_animation_->Show(); - else - bottom_animation_->Hide(); +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() { - // Small optimization since we frequently invoke Hide(). - if (top_animation_->IsShowing() || - left_animation_->IsShowing() || - right_animation_->IsShowing() || - bottom_animation_->IsShowing()) - ShowForHitTest(HTNOWHERE); -} - -void ResizeShadow::Layout(const gfx::Rect& bounds) { - // Position the resize border effects near the window edges. - top_layer_->SetBounds(gfx::Rect(kShadowInset, - -kShadowSize, - bounds.width() - 2 * kShadowInset, - kShadowSize)); - bottom_layer_->SetBounds(gfx::Rect(kShadowInset, - bounds.height(), - bounds.width() - 2 * kShadowInset, - kShadowSize)); - left_layer_->SetBounds(gfx::Rect(-kShadowSize, - kShadowInset, - kShadowSize, - bounds.height() - 2 * kShadowInset)); - right_layer_->SetBounds(gfx::Rect(bounds.width(), - kShadowInset, - kShadowSize, - bounds.height() - 2 * kShadowInset)); -} - -void ResizeShadow::AnimationProgressed(const ui::Animation* animation) { - int opacity = animation->CurrentValueBetween(0, kShadowTargetOpacity); - if (animation == top_animation_.get()) - UpdateLayerOpacity(top_layer_.get(), opacity); - else if (animation == left_animation_.get()) - UpdateLayerOpacity(left_layer_.get(), opacity); - else if (animation == right_animation_.get()) - UpdateLayerOpacity(right_layer_.get(), opacity); - else if (animation == bottom_animation_.get()) - UpdateLayerOpacity(bottom_layer_.get(), opacity); -} - -void ResizeShadow::InitLayer(ui::Layer* parent, - scoped_ptr<ui::Layer>* new_layer) { - // Use solid colors because they don't require video memory. - new_layer->reset(new ui::Layer(ui::Layer::LAYER_SOLID_COLOR)); - // Transparency must be part of the color for solid color layers. - // Start fully transparent so we can smoothly animate in. - new_layer->get()->SetColor(SkColorSetARGB(0, 0, 0, 0)); - new_layer->get()->SetVisible(false); - parent->Add(new_layer->get()); -} - -void ResizeShadow::InitAnimation(scoped_ptr<ui::SlideAnimation>* animation) { - animation->reset(new ui::SlideAnimation(this)); - animation->get()->SetSlideDuration(kShadowSlideDurationMs); + ShowForHitTest(HTNOWHERE); } -void ResizeShadow::UpdateLayerOpacity(ui::Layer* layer, int opacity) { - SkColor color = SkColorSetA(kShadowLayerColor, opacity); - layer->SetColor(color); - layer->SetVisible(opacity != 0); +void ResizeShadow::Layout(const gfx::Rect& content_bounds) { + gfx::Rect local_bounds(content_bounds.size()); + image_grid_->SetContentBounds(local_bounds); } } // namespace internal diff --git a/ash/wm/resize_shadow.h b/ash/wm/resize_shadow.h index b0307fa..0961607 100644 --- a/ash/wm/resize_shadow.h +++ b/ash/wm/resize_shadow.h @@ -8,7 +8,6 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" -#include "ui/base/animation/animation_delegate.h" namespace aura { class Window; @@ -18,19 +17,20 @@ class Rect; } namespace ui { class Layer; -class SlideAnimation; } namespace ash { namespace internal { +class ImageGrid; + // A class to render the resize edge effect when the user moves their mouse // over a sizing edge. This is just a visual effect; the actual resize is // handled by the EventFilter. -class ResizeShadow : public ui::AnimationDelegate { +class ResizeShadow { public: ResizeShadow(); - virtual ~ResizeShadow(); + ~ResizeShadow(); // Initializes the resize effect layers for a given |window|. void Init(aura::Window* window); @@ -42,34 +42,16 @@ class ResizeShadow : public ui::AnimationDelegate { // Hides all resize effects. void Hide(); - // Updates the effect positions based on the |bounds| of its parent. + // Updates the effect positions based on the |bounds| of the window. void Layout(const gfx::Rect& bounds); - // ui::AnimationDelegate overrides: - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; - private: - void InitLayer(ui::Layer* parent, scoped_ptr<ui::Layer>* new_layer); - - void InitAnimation(scoped_ptr<ui::SlideAnimation>* animation); - - // Update the |opacity| for |layer| and sets the layer invisible if it is - // completely transparent. - void UpdateLayerOpacity(ui::Layer* layer, int opacity); - - // Layers of type LAYER_SOLID_COLOR for efficiency. - scoped_ptr<ui::Layer> top_layer_; - scoped_ptr<ui::Layer> left_layer_; - scoped_ptr<ui::Layer> right_layer_; - scoped_ptr<ui::Layer> bottom_layer_; + // Images for the shadow effect. + scoped_ptr<ImageGrid> image_grid_; - // Slide animations for layer opacity. - // TODO(jamescook): Switch to using ui::ScopedLayerAnimationSettings once - // solid color layers support that for opacity. - scoped_ptr<ui::SlideAnimation> top_animation_; - scoped_ptr<ui::SlideAnimation> left_animation_; - scoped_ptr<ui::SlideAnimation> right_animation_; - scoped_ptr<ui::SlideAnimation> bottom_animation_; + // Hit test value from last call to ShowForHitTest(). Used to prevent + // repeatedly triggering the same animations for the same hit. + int last_hit_test_; DISALLOW_COPY_AND_ASSIGN(ResizeShadow); }; diff --git a/ash/wm/shadow.cc b/ash/wm/shadow.cc index c6fbd44a..d763bc7 100644 --- a/ash/wm/shadow.cc +++ b/ash/wm/shadow.cc @@ -38,7 +38,7 @@ float GetOpacityForStyle(ash::internal::Shadow::Style style) { namespace ash { namespace internal { -Shadow::Shadow() { +Shadow::Shadow() : style_(STYLE_ACTIVE) { } Shadow::~Shadow() { @@ -167,18 +167,8 @@ void Shadow::UpdateImagesForStyle() { } void Shadow::UpdateImageGridBounds() { - image_grid_->SetSize( - gfx::Size(content_bounds_.width() + - image_grid_->left_image_width() + - image_grid_->right_image_width(), - content_bounds_.height() + - image_grid_->top_image_height() + - image_grid_->bottom_image_height())); - image_grid_->layer()->SetBounds( - gfx::Rect(content_bounds_.x() - image_grid_->left_image_width(), - content_bounds_.y() - image_grid_->top_image_height(), - image_grid_->layer()->bounds().width(), - image_grid_->layer()->bounds().height())); + // Update bounds based on content bounds and image sizes. + image_grid_->SetContentBounds(content_bounds_); } } // namespace internal diff --git a/ui/resources/ui_resources.grd b/ui/resources/ui_resources.grd index 6f89ae5..a0a8fd2 100644 --- a/ui/resources/ui_resources.grd +++ b/ui/resources/ui_resources.grd @@ -150,6 +150,14 @@ <include name="IDR_AURA_LAUNCHER_OVERFLOW_PUSHED" file="aura/launcher_overflow_p.png" type="BINDATA" /> <include name="IDR_AURA_MULTI_WINDOW_RESIZE_H" file="aura/multi_window_resize_h.png" type="BINDATA" /> <include name="IDR_AURA_MULTI_WINDOW_RESIZE_V" file="aura/multi_window_resize_v.png" type="BINDATA" /> + <include name="IDR_AURA_RESIZE_SHADOW_TOP_LEFT" file="aura/resize_shadow_top_left.png" type="BINDATA" /> + <include name="IDR_AURA_RESIZE_SHADOW_TOP" file="aura/resize_shadow_top.png" type="BINDATA" /> + <include name="IDR_AURA_RESIZE_SHADOW_TOP_RIGHT" file="aura/resize_shadow_top_right.png" type="BINDATA" /> + <include name="IDR_AURA_RESIZE_SHADOW_LEFT" file="aura/resize_shadow_left.png" type="BINDATA" /> + <include name="IDR_AURA_RESIZE_SHADOW_RIGHT" file="aura/resize_shadow_right.png" type="BINDATA" /> + <include name="IDR_AURA_RESIZE_SHADOW_BOTTOM_LEFT" file="aura/resize_shadow_bottom_left.png" type="BINDATA" /> + <include name="IDR_AURA_RESIZE_SHADOW_BOTTOM" file="aura/resize_shadow_bottom.png" type="BINDATA" /> + <include name="IDR_AURA_RESIZE_SHADOW_BOTTOM_RIGHT" file="aura/resize_shadow_bottom_right.png" type="BINDATA" /> <include name="IDR_AURA_SHADOW_ACTIVE_TOP_LEFT" file="aura/window_shadow_active_top_left.png" type="BINDATA" /> <include name="IDR_AURA_SHADOW_ACTIVE_TOP" file="aura/window_shadow_active_top.png" type="BINDATA" /> <include name="IDR_AURA_SHADOW_ACTIVE_TOP_RIGHT" file="aura/window_shadow_active_top_right.png" type="BINDATA" /> |