diff options
author | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-06 23:45:52 +0000 |
---|---|---|
committer | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-06 23:45:52 +0000 |
commit | b43a8979ea49b29dad4617c1a718493dd3973bf0 (patch) | |
tree | 1b7093683c5250480b36ee67802f9bdb1717427a /ui | |
parent | 33ade1dbecd20b268cd725be938f8caccc71fcda (diff) | |
download | chromium_src-b43a8979ea49b29dad4617c1a718493dd3973bf0.zip chromium_src-b43a8979ea49b29dad4617c1a718493dd3973bf0.tar.gz chromium_src-b43a8979ea49b29dad4617c1a718493dd3973bf0.tar.bz2 |
aura: Draw shadows around tooltip windows.
Also, add padding around the tooltip text and disable the
border when shadows are enabled.
I'm also updating the existing shadow code in aura_shell to
clip corner images as needed when they're too large to fit
within the requested size.
BUG=106507
TEST=added
Review URL: http://codereview.chromium.org/8821028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113294 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/aura_shell/image_grid.cc | 110 | ||||
-rw-r--r-- | ui/aura_shell/image_grid.h | 24 | ||||
-rw-r--r-- | ui/aura_shell/image_grid_unittest.cc | 73 | ||||
-rw-r--r-- | ui/aura_shell/shell_tooltip_manager.cc | 43 | ||||
-rw-r--r-- | ui/views/widget/native_widget_aura.cc | 3 |
5 files changed, 215 insertions, 38 deletions
diff --git a/ui/aura_shell/image_grid.cc b/ui/aura_shell/image_grid.cc index 14d69ce..99f8d90 100644 --- a/ui/aura_shell/image_grid.cc +++ b/ui/aura_shell/image_grid.cc @@ -13,6 +13,7 @@ #include "third_party/skia/include/core/SkXfermode.h" using std::max; +using std::min; namespace aura_shell { namespace internal { @@ -92,45 +93,81 @@ void ImageGrid::SetSize(const gfx::Size& size) { float center_height = size.height() - top_row_height_ - bottom_row_height_; if (top_layer_.get()) { - ui::Transform transform; - transform.SetScaleX(center_width / top_layer_->bounds().width()); - transform.ConcatTranslate(left_column_width_, 0); - top_layer_->SetTransform(transform); + if (center_width > 0) { + ui::Transform transform; + transform.SetScaleX(center_width / top_layer_->bounds().width()); + transform.ConcatTranslate(left_column_width_, 0); + top_layer_->SetTransform(transform); + } + top_layer_->SetVisible(center_width > 0); } if (bottom_layer_.get()) { - ui::Transform transform; - transform.SetScaleX(center_width / bottom_layer_->bounds().width()); - transform.ConcatTranslate( - left_column_width_, size.height() - bottom_layer_->bounds().height()); - bottom_layer_->SetTransform(transform); + if (center_width > 0) { + ui::Transform transform; + transform.SetScaleX(center_width / bottom_layer_->bounds().width()); + transform.ConcatTranslate( + left_column_width_, size.height() - bottom_layer_->bounds().height()); + bottom_layer_->SetTransform(transform); + } + bottom_layer_->SetVisible(center_width > 0); } if (left_layer_.get()) { - ui::Transform transform; - transform.SetScaleY(center_height / left_layer_->bounds().height()); - transform.ConcatTranslate(0, top_row_height_); - left_layer_->SetTransform(transform); + if (center_height > 0) { + ui::Transform transform; + transform.SetScaleY(center_height / left_layer_->bounds().height()); + transform.ConcatTranslate(0, top_row_height_); + left_layer_->SetTransform(transform); + } + left_layer_->SetVisible(center_height > 0); } if (right_layer_.get()) { - ui::Transform transform; - transform.SetScaleY(center_height / right_layer_->bounds().height()); - transform.ConcatTranslate( - size.width() - right_layer_->bounds().width(), top_row_height_); - right_layer_->SetTransform(transform); + if (center_height > 0) { + ui::Transform transform; + transform.SetScaleY(center_height / right_layer_->bounds().height()); + transform.ConcatTranslate( + size.width() - right_layer_->bounds().width(), top_row_height_); + right_layer_->SetTransform(transform); + } + right_layer_->SetVisible(center_height > 0); } + // Calculate the available amount of space for corner images on all sides of + // the grid. If the images don't fit, we need to clip them. + const int left = min(left_column_width_, size_.width() / 2); + const int right = min(right_column_width_, size_.width() - left); + const int top = min(top_row_height_, size_.height() / 2); + const int bottom = min(bottom_row_height_, size_.height() - top); + if (top_left_layer_.get()) { // No transformation needed; it should be at (0, 0) and unscaled. + top_left_painter_->SetClipRect( + LayerExceedsSize(top_left_layer_.get(), gfx::Size(left, top)) ? + gfx::Rect(gfx::Rect(0, 0, left, top)) : + gfx::Rect(), + top_left_layer_.get()); } if (top_right_layer_.get()) { ui::Transform transform; transform.SetTranslateX(size.width() - top_right_layer_->bounds().width()); top_right_layer_->SetTransform(transform); + top_right_painter_->SetClipRect( + LayerExceedsSize(top_right_layer_.get(), gfx::Size(right, top)) ? + gfx::Rect(top_right_layer_->bounds().width() - right, 0, + right, top) : + gfx::Rect(), + top_right_layer_.get()); } if (bottom_left_layer_.get()) { ui::Transform transform; transform.SetTranslateY( size.height() - bottom_left_layer_->bounds().height()); bottom_left_layer_->SetTransform(transform); + bottom_left_painter_->SetClipRect( + LayerExceedsSize(bottom_left_layer_.get(), gfx::Size(left, bottom)) ? + gfx::Rect(0, bottom_left_layer_->bounds().height() - bottom, + left, bottom) : + gfx::Rect(), + bottom_left_layer_.get()); } if (bottom_right_layer_.get()) { ui::Transform transform; @@ -138,18 +175,38 @@ void ImageGrid::SetSize(const gfx::Size& size) { size.width() - bottom_right_layer_->bounds().width(), size.height() - bottom_right_layer_->bounds().height()); bottom_right_layer_->SetTransform(transform); + bottom_right_painter_->SetClipRect( + LayerExceedsSize(bottom_right_layer_.get(), gfx::Size(right, bottom)) ? + gfx::Rect(bottom_right_layer_->bounds().width() - right, + bottom_right_layer_->bounds().height() - bottom, + right, bottom) : + gfx::Rect(), + bottom_right_layer_.get()); } if (center_layer_.get()) { - ui::Transform transform; - transform.SetScale(center_width / center_layer_->bounds().width(), - center_height / center_layer_->bounds().height()); - transform.ConcatTranslate(left_column_width_, top_row_height_); - center_layer_->SetTransform(transform); + if (center_width > 0 && center_height > 0) { + ui::Transform transform; + transform.SetScale(center_width / center_layer_->bounds().width(), + center_height / center_layer_->bounds().height()); + transform.ConcatTranslate(left_column_width_, top_row_height_); + center_layer_->SetTransform(transform); + } + center_layer_->SetVisible(center_width > 0 && center_height > 0); + } +} + +void ImageGrid::ImagePainter::SetClipRect(const gfx::Rect& clip_rect, + ui::Layer* layer) { + if (clip_rect != clip_rect_) { + clip_rect_ = clip_rect; + layer->ScheduleDraw(); } } void ImageGrid::ImagePainter::OnPaintLayer(gfx::Canvas* canvas) { + if (!clip_rect_.IsEmpty()) + canvas->ClipRect(clip_rect_); canvas->DrawBitmapInt(*(image_->ToSkBitmap()), 0, 0); } @@ -160,6 +217,13 @@ gfx::Size ImageGrid::GetImageSize(const gfx::Image* image) { gfx::Size(); } +// static +bool ImageGrid::LayerExceedsSize(const ui::Layer* layer, + const gfx::Size& size) { + return layer->bounds().width() > size.width() || + layer->bounds().height() > size.height(); +} + void ImageGrid::InitImage(const gfx::Image* image, scoped_ptr<ui::Layer>* layer_ptr, scoped_ptr<ImagePainter>* painter_ptr) { diff --git a/ui/aura_shell/image_grid.h b/ui/aura_shell/image_grid.h index a5ff264..892ab7f0 100644 --- a/ui/aura_shell/image_grid.h +++ b/ui/aura_shell/image_grid.h @@ -78,6 +78,19 @@ class AURA_SHELL_EXPORT ImageGrid { return grid_->bottom_right_layer_.get(); } + gfx::Rect top_left_clip_rect() const { + return grid_->top_left_painter_->clip_rect_; + } + gfx::Rect top_right_clip_rect() const { + return grid_->top_right_painter_->clip_rect_; + } + gfx::Rect bottom_left_clip_rect() const { + return grid_->bottom_left_painter_->clip_rect_; + } + gfx::Rect bottom_right_clip_rect() const { + return grid_->bottom_right_painter_->clip_rect_; + } + // Returns |layer|'s bounds after applying the layer's current transform. gfx::Rect GetTransformedLayerBounds(const ui::Layer& layer); @@ -117,18 +130,29 @@ class AURA_SHELL_EXPORT ImageGrid { ImagePainter(const gfx::Image* image) : image_(image) {} virtual ~ImagePainter() {} + // Clips |layer| to |clip_rect|. Triggers a repaint if the clipping + // rectangle has changed. An empty rectangle disables clipping. + void SetClipRect(const gfx::Rect& clip_rect, ui::Layer* layer); + // ui::LayerDelegate implementation: virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE; private: + friend class TestAPI; + const gfx::Image* image_; // not owned + gfx::Rect clip_rect_; + DISALLOW_COPY_AND_ASSIGN(ImagePainter); }; // Returns the dimensions of |image| if non-NULL or gfx::Size(0, 0) otherwise. static gfx::Size GetImageSize(const gfx::Image* image); + // Returns true if |layer|'s bounds don't fit within |size|. + static bool LayerExceedsSize(const ui::Layer* layer, const gfx::Size& size); + // Initializes |layer_ptr| and |painter_ptr| to display |image|. // Also adds the passed-in layer to |layer_|. void InitImage(const gfx::Image* image, diff --git a/ui/aura_shell/image_grid_unittest.cc b/ui/aura_shell/image_grid_unittest.cc index e75bd403..185a0fa 100644 --- a/ui/aura_shell/image_grid_unittest.cc +++ b/ui/aura_shell/image_grid_unittest.cc @@ -180,7 +180,6 @@ TEST_F(ImageGridTest, SmallerSides) { test_api.GetTransformedLayerBounds( *test_api.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( @@ -197,5 +196,77 @@ TEST_F(ImageGridTest, SmallerSides) { *test_api.right_layer()).ToString()); } +// Test that we hide or clip layers as needed when the grid is assigned a small +// size. +TEST_F(ImageGridTest, TooSmall) { + const int kCorner = 5; + const int kCenter = 3; + const int kEdge = 3; + + scoped_ptr<gfx::Image> top_left_image( + CreateImage(gfx::Size(kCorner, kCorner))); + scoped_ptr<gfx::Image> top_image(CreateImage(gfx::Size(kEdge, kEdge))); + scoped_ptr<gfx::Image> top_right_image( + CreateImage(gfx::Size(kCorner, kCorner))); + scoped_ptr<gfx::Image> left_image(CreateImage(gfx::Size(kEdge, kEdge))); + scoped_ptr<gfx::Image> center_image(CreateImage(gfx::Size(kCenter, kCenter))); + scoped_ptr<gfx::Image> right_image(CreateImage(gfx::Size(kEdge, kEdge))); + scoped_ptr<gfx::Image> bottom_left_image( + CreateImage(gfx::Size(kCorner, kCorner))); + scoped_ptr<gfx::Image> bottom_image(CreateImage(gfx::Size(kEdge, kEdge))); + scoped_ptr<gfx::Image> bottom_right_image( + CreateImage(gfx::Size(kCorner, kCorner))); + + ImageGrid grid; + grid.Init( + top_left_image.get(), top_image.get(), top_right_image.get(), + left_image.get(), center_image.get(), right_image.get(), + bottom_left_image.get(), bottom_image.get(), bottom_right_image.get()); + ImageGrid::TestAPI test_api(&grid); + + // Set a size that's smaller than the combined (unscaled) corner images. + const gfx::Size kSmallSize(kCorner + kCorner - 3, kCorner + kCorner - 5); + 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()); + + // The corner images' clip rects should sum to the expected size. + EXPECT_EQ(kSmallSize.width(), + test_api.top_left_clip_rect().width() + + test_api.top_right_clip_rect().width()); + EXPECT_EQ(kSmallSize.width(), + test_api.bottom_left_clip_rect().width() + + test_api.bottom_right_clip_rect().width()); + EXPECT_EQ(kSmallSize.height(), + test_api.top_left_clip_rect().height() + + test_api.bottom_left_clip_rect().height()); + EXPECT_EQ(kSmallSize.height(), + test_api.top_right_clip_rect().height() + + test_api.bottom_right_clip_rect().height()); + + // Resize the grid to be large enough to show all images. + const gfx::Size kLargeSize(kCorner + kCorner + kCenter, + kCorner + kCorner + kCenter); + 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()); + + // We shouldn't be clipping the corner images anymore. + EXPECT_TRUE(test_api.top_left_clip_rect().IsEmpty()); + EXPECT_TRUE(test_api.top_right_clip_rect().IsEmpty()); + EXPECT_TRUE(test_api.bottom_left_clip_rect().IsEmpty()); + EXPECT_TRUE(test_api.bottom_right_clip_rect().IsEmpty()); +} + } // namespace test } // namespace aura_shell diff --git a/ui/aura_shell/shell_tooltip_manager.cc b/ui/aura_shell/shell_tooltip_manager.cc index 0544ca8..ac8fa54 100644 --- a/ui/aura_shell/shell_tooltip_manager.cc +++ b/ui/aura_shell/shell_tooltip_manager.cc @@ -6,9 +6,11 @@ #include <vector> +#include "base/command_line.h" #include "base/location.h" #include "base/string_split.h" #include "base/time.h" +#include "ui/aura/aura_switches.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/event.h" #include "ui/aura/window.h" @@ -26,14 +28,19 @@ namespace { -SkColor kTooltipBackground = 0xFFFFFFCC; -SkColor kTooltipBorder = 0xFF000000; -int kTooltipBorderWidth = 1; -int kTooltipTimeoutMs = 500; +const SkColor kTooltipBackground = 0xFFFFFFCC; +const SkColor kTooltipBorder = 0xFF646450; +const int kTooltipBorderWidth = 1; +const int kTooltipHorizontalPadding = 3; +// TODO(derat): This padding is needed on Chrome OS devices but seems excessive +// when running the same binary on a Linux workstation; presumably there's a +// difference in font metrics. Rationalize this. +const int kTooltipVerticalPadding = 2; +const int kTooltipTimeoutMs = 500; // FIXME: get cursor offset from actual cursor size. -int kCursorOffsetX = 10; -int kCursorOffsetY = 15; +const int kCursorOffsetX = 10; +const int kCursorOffsetY = 15; // Maximum number of characters we allow in a tooltip. const size_t kMaxTooltipLength = 1024; @@ -107,8 +114,11 @@ class ShellTooltipManager::Tooltip { Tooltip() { label_.set_background( views::Background::CreateSolidBackground(kTooltipBackground)); - label_.set_border( - views::Border::CreateSolidBorder(kTooltipBorderWidth, kTooltipBorder)); + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAuraNoShadows)) { + label_.set_border( + views::Border::CreateSolidBorder(kTooltipBorderWidth, + kTooltipBorder)); + } label_.set_parent_owned(false); widget_.reset(CreateTooltip()); widget_->SetContentsView(&label_); @@ -126,8 +136,14 @@ class ShellTooltipManager::Tooltip { location.x(), location.y()); label_.SetText(tooltip_text); - SetTooltipBounds(location, max_width + 2 * kTooltipBorderWidth, - label_.GetPreferredSize().height()); + int width = max_width + 2 * kTooltipHorizontalPadding; + int height = label_.GetPreferredSize().height() + + 2 * kTooltipVerticalPadding; + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAuraNoShadows)) { + width += 2 * kTooltipBorderWidth; + height += 2 * kTooltipBorderWidth; + } + SetTooltipBounds(location, width, height); } // Shows the tooltip. @@ -167,9 +183,10 @@ class ShellTooltipManager::Tooltip { //////////////////////////////////////////////////////////////////////////////// // ShellTooltipManager public: -ShellTooltipManager::ShellTooltipManager() : aura::EventFilter(NULL), - tooltip_window_(NULL), - tooltip_(new Tooltip) { +ShellTooltipManager::ShellTooltipManager() + : aura::EventFilter(NULL), + tooltip_window_(NULL), + tooltip_(new Tooltip) { tooltip_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kTooltipTimeoutMs), this, &ShellTooltipManager::TooltipTimerFired); diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index 2bdba97..aca71bd 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc @@ -168,7 +168,8 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) { static_cast<aura::WindowDragDropDelegate*>(this)); } - if (window_type == Widget::InitParams::TYPE_MENU) + if (window_type == Widget::InitParams::TYPE_MENU || + window_type == Widget::InitParams::TYPE_TOOLTIP) window_->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_RECTANGULAR); } |