diff options
author | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-18 21:58:23 +0000 |
---|---|---|
committer | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-18 21:58:23 +0000 |
commit | b1ed27851db7f86d7f71dfe4c897c796a953fc25 (patch) | |
tree | b9d972e7a6770b4c9055507fe2e9d329b0974106 /views | |
parent | cee34b707ac41e83ff9d9045c0ffda49ec3f556f (diff) | |
download | chromium_src-b1ed27851db7f86d7f71dfe4c897c796a953fc25.zip chromium_src-b1ed27851db7f86d7f71dfe4c897c796a953fc25.tar.gz chromium_src-b1ed27851db7f86d7f71dfe4c897c796a953fc25.tar.bz2 |
views: Move bubble, events, focus and layout to ui/views/.
Left stub files that will be removed in a follow up patch after updating
the files to point to the new location.
BUG=104039
R=ben@chromium.org
Review URL: http://codereview.chromium.org/8588064
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110761 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
50 files changed, 101 insertions, 9247 deletions
diff --git a/views/bubble/border_contents_view.cc b/views/bubble/border_contents_view.cc deleted file mode 100644 index 67c893a..0000000 --- a/views/bubble/border_contents_view.cc +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) 2011 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 "views/bubble/border_contents_view.h" - -#include <algorithm> - -#include "ui/gfx/screen.h" - -static const int kTopMargin = 6; -static const int kLeftMargin = 6; -static const int kBottomMargin = 6; -static const int kRightMargin = 6; - -namespace { - -// Computes how much |window_bounds| is off-screen of the monitor bounds -// |monitor_bounds| and puts the values in |offscreen_insets|. -// Returns false if |window_bounds| is actually contained in |monitor_bounds|, -// in which case |offscreen_insets| is not modified. -bool ComputeOffScreenInsets(const gfx::Rect& monitor_bounds, - const gfx::Rect& window_bounds, - gfx::Insets* offscreen_insets) { - if (monitor_bounds.Contains(window_bounds)) - return false; - - if (!offscreen_insets) - return true; - - // window_bounds - // +-------------------------------+ - // | top | - // | +----------------+ | - // | left | monitor_bounds | right | - // | +----------------+ | - // | bottom | - // +-------------------------------+ - int top = std::max(0, monitor_bounds.y() - window_bounds.y()); - int left = std::max(0, monitor_bounds.x() - window_bounds.x()); - int bottom = std::max(0, window_bounds.bottom() - monitor_bounds.bottom()); - int right = std::max(0, window_bounds.right() - monitor_bounds.right()); - - offscreen_insets->Set(top, left, bottom, right); - return true; -} - -// Convenience method that returns the height of |insets| if |vertical| is -// true, its width otherwise. -int GetInsetsLength(const gfx::Insets& insets, bool vertical) { - return vertical ? insets.height() : insets.width(); -} - -} // namespace - -namespace views { - -BorderContentsView::BorderContentsView() - : bubble_border_(NULL), - content_margins_(kTopMargin, kLeftMargin, kBottomMargin, kRightMargin) { -} - -BorderContentsView::BorderContentsView(int top_margin, - int left_margin, - int bottom_margin, - int right_margin) - : bubble_border_(NULL), - content_margins_(top_margin, left_margin, bottom_margin, right_margin) { -} - -BorderContentsView::~BorderContentsView() {} - -void BorderContentsView::Init() { - // Default arrow location. - BubbleBorder::ArrowLocation arrow_location = - BubbleBorder::TOP_LEFT; - if (base::i18n::IsRTL()) - arrow_location = BubbleBorder::horizontal_mirror(arrow_location); - DCHECK(!bubble_border_); - - // TODO(alicet): Expose the shadow option in BorderContentsView when we make - // the fullscreen exit bubble use the new bubble code. - bubble_border_ = new BubbleBorder(arrow_location, - views::BubbleBorder::NO_SHADOW); - set_border(bubble_border_); - set_background(new BubbleBackground(bubble_border_)); -} - -void BorderContentsView::SetBackgroundColor(SkColor color) { - bubble_border_->set_background_color(color); -} - -void BorderContentsView::SetAlignment( - views::BubbleBorder::BubbleAlignment alignment) { - bubble_border_->set_alignment(alignment); -} - -void BorderContentsView::SizeAndGetBounds( - const gfx::Rect& position_relative_to, - BubbleBorder::ArrowLocation arrow_location, - bool allow_bubble_offscreen, - const gfx::Size& contents_size, - gfx::Rect* contents_bounds, - gfx::Rect* window_bounds) { - if (base::i18n::IsRTL()) - arrow_location = BubbleBorder::horizontal_mirror(arrow_location); - bubble_border_->set_arrow_location(arrow_location); - // Set the border. - set_border(bubble_border_); - - // Give the contents a margin. - gfx::Size local_contents_size(contents_size); - local_contents_size.Enlarge(content_margins_.width(), - content_margins_.height()); - - // Try putting the arrow in its initial location, and calculating the bounds. - *window_bounds = - bubble_border_->GetBounds(position_relative_to, local_contents_size); - if (!allow_bubble_offscreen) { - gfx::Rect monitor_bounds = GetMonitorBounds(position_relative_to); - if (!monitor_bounds.IsEmpty()) { - // Try to resize vertically if this does not fit on the screen. - MirrorArrowIfOffScreen(true, // |vertical|. - position_relative_to, monitor_bounds, - local_contents_size, &arrow_location, - window_bounds); - // Then try to resize horizontally if it still does not fit on the screen. - MirrorArrowIfOffScreen(false, // |vertical|. - position_relative_to, monitor_bounds, - local_contents_size, &arrow_location, - window_bounds); - } - } - - // Calculate the bounds of the contained contents (in window coordinates) by - // subtracting the border dimensions and margin amounts. - *contents_bounds = gfx::Rect(gfx::Point(), window_bounds->size()); - gfx::Insets insets; - bubble_border_->GetInsets(&insets); - insets += content_margins_; - contents_bounds->Inset(insets); -} - -gfx::Rect BorderContentsView::GetMonitorBounds(const gfx::Rect& rect) { - return gfx::Screen::GetMonitorWorkAreaNearestPoint(rect.CenterPoint()); -} - -void BorderContentsView::MirrorArrowIfOffScreen( - bool vertical, - const gfx::Rect& position_relative_to, - const gfx::Rect& monitor_bounds, - const gfx::Size& local_contents_size, - BubbleBorder::ArrowLocation* arrow_location, - gfx::Rect* window_bounds) { - // If the bounds don't fit, move the arrow to its mirrored position to see if - // it improves things. - gfx::Insets offscreen_insets; - if (ComputeOffScreenInsets(monitor_bounds, *window_bounds, - &offscreen_insets) && - GetInsetsLength(offscreen_insets, vertical) > 0) { - BubbleBorder::ArrowLocation original_arrow_location = - *arrow_location; - *arrow_location = - vertical ? BubbleBorder::vertical_mirror(*arrow_location) : - BubbleBorder::horizontal_mirror(*arrow_location); - - // Change the arrow and get the new bounds. - bubble_border_->set_arrow_location(*arrow_location); - *window_bounds = bubble_border_->GetBounds(position_relative_to, - local_contents_size); - gfx::Insets new_offscreen_insets; - // If there is more of the window offscreen, we'll keep the old arrow. - if (ComputeOffScreenInsets(monitor_bounds, *window_bounds, - &new_offscreen_insets) && - GetInsetsLength(new_offscreen_insets, vertical) >= - GetInsetsLength(offscreen_insets, vertical)) { - *arrow_location = original_arrow_location; - bubble_border_->set_arrow_location(*arrow_location); - *window_bounds = bubble_border_->GetBounds(position_relative_to, - local_contents_size); - } - } -} - -} // namespace views diff --git a/views/bubble/border_contents_view.h b/views/bubble/border_contents_view.h index 49ddb6a..a6c1bf2 100644 --- a/views/bubble/border_contents_view.h +++ b/views/bubble/border_contents_view.h @@ -6,83 +6,7 @@ #define VIEWS_BUBBLE_BORDER_CONTENTS_VIEW_H_ #pragma once -#include "views/bubble/bubble_border.h" -#include "third_party/skia/include/core/SkColor.h" -#include "views/view.h" - -namespace views { - -// This is used to paint the border and background of the Bubble. -class VIEWS_EXPORT BorderContentsView : public View { - public: - BorderContentsView(); - BorderContentsView(int top_margin, - int left_margin, - int bottom_margin, - int right_margin); - - // Must be called before this object can be used. - void Init(); - - // Sets the background color. - void SetBackgroundColor(SkColor color); - - // Sets the bubble alignment. - void SetAlignment(views::BubbleBorder::BubbleAlignment alignment); - - // Given the size of the contents and the rect to point at, returns the bounds - // of both the border and the contents inside the bubble. - // |arrow_location| specifies the preferred location for the arrow - // anchor. If the bubble does not fit on the monitor and - // |allow_bubble_offscreen| is false, the arrow location may change so the - // bubble shows entirely. - virtual void SizeAndGetBounds( - const gfx::Rect& position_relative_to, // In screen coordinates - BubbleBorder::ArrowLocation arrow_location, - bool allow_bubble_offscreen, - const gfx::Size& contents_size, - gfx::Rect* contents_bounds, // Returned in window coordinates - gfx::Rect* window_bounds); // Returned in screen coordinates - - // Sets content margins. - void set_content_margins(const gfx::Insets& margins) { - content_margins_ = margins; - } - - // Accessor for |content_margins_|. - const gfx::Insets& content_margins() const { - return content_margins_; - } - - protected: - virtual ~BorderContentsView(); - - // Returns the bounds for the monitor showing the specified |rect|. - virtual gfx::Rect GetMonitorBounds(const gfx::Rect& rect); - - BubbleBorder* bubble_border() const { return bubble_border_; } - - private: - // Changes |arrow_location| to its mirrored version, vertically if |vertical| - // is true, horizontally otherwise, if |window_bounds| don't fit in - // |monitor_bounds|. - void MirrorArrowIfOffScreen( - bool vertical, - const gfx::Rect& position_relative_to, - const gfx::Rect& monitor_bounds, - const gfx::Size& local_contents_size, - BubbleBorder::ArrowLocation* arrow_location, - gfx::Rect* window_bounds); - - // The bubble border. - BubbleBorder* bubble_border_; - - // Margins between the content and the inside of the border, in pixels. - gfx::Insets content_margins_; - - DISALLOW_COPY_AND_ASSIGN(BorderContentsView); -}; - -} // namespace views +#include "ui/views/bubble/border_contents_view.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_BUBBLE_BORDER_CONTENTS_VIEW_H_ diff --git a/views/bubble/bubble_border.cc b/views/bubble/bubble_border.cc deleted file mode 100644 index 368b0be..0000000 --- a/views/bubble/bubble_border.cc +++ /dev/null @@ -1,511 +0,0 @@ -// Copyright (c) 2011 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 "views/bubble/bubble_border.h" - -#include <algorithm> // for std::max - -#include "base/logging.h" -#include "grit/ui_resources.h" -#include "grit/ui_resources_standard.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas_skia.h" -#include "ui/gfx/path.h" - -namespace views { - -struct BubbleBorder::BorderImages { - BorderImages() - : left(NULL), - top_left(NULL), - top(NULL), - top_right(NULL), - right(NULL), - bottom_right(NULL), - bottom(NULL), - bottom_left(NULL), - left_arrow(NULL), - top_arrow(NULL), - right_arrow(NULL), - bottom_arrow(NULL) { - } - - SkBitmap* left; - SkBitmap* top_left; - SkBitmap* top; - SkBitmap* top_right; - SkBitmap* right; - SkBitmap* bottom_right; - SkBitmap* bottom; - SkBitmap* bottom_left; - SkBitmap* left_arrow; - SkBitmap* top_arrow; - SkBitmap* right_arrow; - SkBitmap* bottom_arrow; -}; - -// static -struct BubbleBorder::BorderImages* BubbleBorder::normal_images_ = NULL; -struct BubbleBorder::BorderImages* BubbleBorder::shadow_images_ = NULL; - - -// The height inside the arrow image, in pixels. -static const int kArrowInteriorHeight = 7; - -BubbleBorder::BubbleBorder(ArrowLocation arrow_location, Shadow shadow) - : override_arrow_offset_(0), - arrow_location_(arrow_location), - alignment_(ALIGN_ARROW_TO_MID_ANCHOR), - background_color_(SK_ColorWHITE) { - images_ = GetBorderImages(shadow); - - // Calculate horizontal and vertical insets for arrow by ensuring that - // the widest arrow and corner images will have enough room to avoid overlap - int offset_x = - (std::max(images_->top_arrow->width(), - images_->bottom_arrow->width()) / 2) + - std::max(std::max(images_->top_left->width(), - images_->top_right->width()), - std::max(images_->bottom_left->width(), - images_->bottom_right->width())); - int offset_y = - (std::max(images_->left_arrow->height(), - images_->right_arrow->height()) / 2) + - std::max(std::max(images_->top_left->height(), - images_->top_right->height()), - std::max(images_->bottom_left->height(), - images_->bottom_right->height())); - arrow_offset_ = std::max(offset_x, offset_y); -} - -gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to, - const gfx::Size& contents_size) const { - // Desired size is size of contents enlarged by the size of the border images. - gfx::Size border_size(contents_size); - gfx::Insets insets; - GetInsets(&insets); - border_size.Enlarge(insets.left() + insets.right(), - insets.top() + insets.bottom()); - - // Screen position depends on the arrow location. - // The arrow should overlap the target by some amount since there is space - // for shadow between arrow tip and bitmap bounds. - const int kArrowOverlap = 3; - int x = position_relative_to.x(); - int y = position_relative_to.y(); - int w = position_relative_to.width(); - int h = position_relative_to.height(); - int arrow_offset = override_arrow_offset_ ? override_arrow_offset_ : - arrow_offset_; - - // Calculate bubble x coordinate. - switch (arrow_location_) { - case TOP_LEFT: - case BOTTOM_LEFT: - x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? w / 2 - arrow_offset : - -kArrowOverlap; - break; - - case TOP_RIGHT: - case BOTTOM_RIGHT: - x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? - w / 2 + arrow_offset - border_size.width() + 1 : - w - border_size.width() + kArrowOverlap; - break; - - case LEFT_TOP: - case LEFT_BOTTOM: - x += w - kArrowOverlap; - break; - - case RIGHT_TOP: - case RIGHT_BOTTOM: - x += kArrowOverlap - border_size.width(); - break; - - case NONE: - case FLOAT: - x += w / 2 - border_size.width() / 2; - break; - } - - // Calculate bubble y coordinate. - switch (arrow_location_) { - case TOP_LEFT: - case TOP_RIGHT: - y += h - kArrowOverlap; - break; - - case BOTTOM_LEFT: - case BOTTOM_RIGHT: - y += kArrowOverlap - border_size.height(); - break; - - case LEFT_TOP: - case RIGHT_TOP: - y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? h / 2 - arrow_offset : - -kArrowOverlap; - break; - - case LEFT_BOTTOM: - case RIGHT_BOTTOM: - y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? - h / 2 + arrow_offset - border_size.height() + 1 : - h - border_size.height() + kArrowOverlap; - break; - - case NONE: - y += h; - break; - - case FLOAT: - y += h / 2 - border_size.height() / 2; - break; - } - - return gfx::Rect(x, y, border_size.width(), border_size.height()); -} - -void BubbleBorder::GetInsets(gfx::Insets* insets) const { - int top = images_->top->height(); - int bottom = images_->bottom->height(); - int left = images_->left->width(); - int right = images_->right->width(); - switch (arrow_location_) { - case TOP_LEFT: - case TOP_RIGHT: - top = std::max(top, images_->top_arrow->height()); - break; - - case BOTTOM_LEFT: - case BOTTOM_RIGHT: - bottom = std::max(bottom, images_->bottom_arrow->height()); - break; - - case LEFT_TOP: - case LEFT_BOTTOM: - left = std::max(left, images_->left_arrow->width()); - break; - - case RIGHT_TOP: - case RIGHT_BOTTOM: - right = std::max(right, images_->right_arrow->width()); - break; - - case NONE: - case FLOAT: - // Nothing to do. - break; - } - insets->Set(top, left, bottom, right); -} - -int BubbleBorder::SetArrowOffset(int offset, const gfx::Size& contents_size) { - gfx::Size border_size(contents_size); - gfx::Insets insets; - GetInsets(&insets); - border_size.Enlarge(insets.left() + insets.right(), - insets.top() + insets.bottom()); - offset = std::max(arrow_offset_, - std::min(offset, (is_arrow_on_horizontal(arrow_location_) ? - border_size.width() : border_size.height()) - arrow_offset_)); - override_arrow_offset_ = offset; - return override_arrow_offset_; -} - -// static -BubbleBorder::BorderImages* BubbleBorder::GetBorderImages(Shadow shadow) { - if (shadow == SHADOW && shadow_images_ == NULL) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - shadow_images_ = new BorderImages(); - shadow_images_->left = rb.GetBitmapNamed(IDR_BUBBLE_SHADOW_L); - shadow_images_->top_left = rb.GetBitmapNamed(IDR_BUBBLE_SHADOW_TL); - shadow_images_->top = rb.GetBitmapNamed(IDR_BUBBLE_SHADOW_T); - shadow_images_->top_right = rb.GetBitmapNamed(IDR_BUBBLE_SHADOW_TR); - shadow_images_->right = rb.GetBitmapNamed(IDR_BUBBLE_SHADOW_R); - shadow_images_->bottom_right = rb.GetBitmapNamed(IDR_BUBBLE_SHADOW_BR); - shadow_images_->bottom = rb.GetBitmapNamed(IDR_BUBBLE_SHADOW_B); - shadow_images_->bottom_left = rb.GetBitmapNamed(IDR_BUBBLE_SHADOW_BL); - shadow_images_->left_arrow = new SkBitmap(); - shadow_images_->top_arrow = new SkBitmap(); - shadow_images_->right_arrow = new SkBitmap(); - shadow_images_->bottom_arrow = new SkBitmap(); - } else if (shadow == NO_SHADOW && normal_images_ == NULL) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - normal_images_ = new BorderImages(); - normal_images_->left = rb.GetBitmapNamed(IDR_BUBBLE_L); - normal_images_->top_left = rb.GetBitmapNamed(IDR_BUBBLE_TL); - normal_images_->top = rb.GetBitmapNamed(IDR_BUBBLE_T); - normal_images_->top_right = rb.GetBitmapNamed(IDR_BUBBLE_TR); - normal_images_->right = rb.GetBitmapNamed(IDR_BUBBLE_R); - normal_images_->bottom_right = rb.GetBitmapNamed(IDR_BUBBLE_BR); - normal_images_->bottom = rb.GetBitmapNamed(IDR_BUBBLE_B); - normal_images_->bottom_left = rb.GetBitmapNamed(IDR_BUBBLE_BL); - normal_images_->left_arrow = rb.GetBitmapNamed(IDR_BUBBLE_L_ARROW); - normal_images_->top_arrow = rb.GetBitmapNamed(IDR_BUBBLE_T_ARROW); - normal_images_->right_arrow = rb.GetBitmapNamed(IDR_BUBBLE_R_ARROW); - normal_images_->bottom_arrow = rb.GetBitmapNamed(IDR_BUBBLE_B_ARROW); - } - return shadow == SHADOW ? shadow_images_ : normal_images_; -} - -BubbleBorder::~BubbleBorder() {} - -void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { - // Convenience shorthand variables. - const int tl_width = images_->top_left->width(); - const int tl_height = images_->top_left->height(); - const int t_height = images_->top->height(); - const int tr_width = images_->top_right->width(); - const int tr_height = images_->top_right->height(); - const int l_width = images_->left->width(); - const int r_width = images_->right->width(); - const int br_width = images_->bottom_right->width(); - const int br_height = images_->bottom_right->height(); - const int b_height = images_->bottom->height(); - const int bl_width = images_->bottom_left->width(); - const int bl_height = images_->bottom_left->height(); - - gfx::Insets insets; - GetInsets(&insets); - const int top = insets.top() - t_height; - const int bottom = view.height() - insets.bottom() + b_height; - const int left = insets.left() - l_width; - const int right = view.width() - insets.right() + r_width; - const int height = bottom - top; - const int width = right - left; - - // |arrow_offset| is offset of arrow from the begining of the edge. - int arrow_offset = arrow_offset_; - if (override_arrow_offset_) - arrow_offset = override_arrow_offset_; - else if (is_arrow_on_horizontal(arrow_location_) && - !is_arrow_on_left(arrow_location_)) { - arrow_offset = view.width() - arrow_offset - 1; - } else if (!is_arrow_on_horizontal(arrow_location_) && - !is_arrow_on_top(arrow_location_)) { - arrow_offset = view.height() - arrow_offset - 1; - } - - // Left edge. - if (arrow_location_ == LEFT_TOP || arrow_location_ == LEFT_BOTTOM) { - int start_y = top + tl_height; - int before_arrow = - arrow_offset - start_y - images_->left_arrow->height() / 2; - int after_arrow = height - tl_height - bl_height - - images_->left_arrow->height() - before_arrow; - int tip_y = start_y + before_arrow + images_->left_arrow->height() / 2; - DrawArrowInterior(canvas, - false, - images_->left_arrow->width() - kArrowInteriorHeight, - tip_y, - kArrowInteriorHeight, - images_->left_arrow->height() / 2 - 1); - DrawEdgeWithArrow(canvas, - false, - images_->left, - images_->left_arrow, - left, - start_y, - before_arrow, - after_arrow, - images_->left->width() - images_->left_arrow->width()); - } else { - canvas->TileImageInt(*images_->left, left, top + tl_height, l_width, - height - tl_height - bl_height); - } - - // Top left corner. - canvas->DrawBitmapInt(*images_->top_left, left, top); - - // Top edge. - if (arrow_location_ == TOP_LEFT || arrow_location_ == TOP_RIGHT) { - int start_x = left + tl_width; - int before_arrow = arrow_offset - start_x - images_->top_arrow->width() / 2; - int after_arrow = width - tl_width - tr_width - - images_->top_arrow->width() - before_arrow; - DrawArrowInterior(canvas, - true, - start_x + before_arrow + images_->top_arrow->width() / 2, - images_->top_arrow->height() - kArrowInteriorHeight, - 1 - images_->top_arrow->width() / 2, - kArrowInteriorHeight); - DrawEdgeWithArrow(canvas, - true, - images_->top, - images_->top_arrow, - start_x, - top, - before_arrow, - after_arrow, - images_->top->height() - images_->top_arrow->height()); - } else { - canvas->TileImageInt(*images_->top, left + tl_width, top, - width - tl_width - tr_width, t_height); - } - - // Top right corner. - canvas->DrawBitmapInt(*images_->top_right, right - tr_width, top); - - // Right edge. - if (arrow_location_ == RIGHT_TOP || arrow_location_ == RIGHT_BOTTOM) { - int start_y = top + tr_height; - int before_arrow = - arrow_offset - start_y - images_->right_arrow->height() / 2; - int after_arrow = height - tl_height - bl_height - - images_->right_arrow->height() - before_arrow; - int tip_y = start_y + before_arrow + images_->right_arrow->height() / 2; - DrawArrowInterior(canvas, - false, - right - r_width + kArrowInteriorHeight, - tip_y, - -kArrowInteriorHeight, - images_->right_arrow->height() / 2 - 1); - DrawEdgeWithArrow(canvas, - false, - images_->right, - images_->right_arrow, - right - r_width, - start_y, - before_arrow, - after_arrow, - 0); - } else { - canvas->TileImageInt(*images_->right, right - r_width, top + tr_height, - r_width, height - tr_height - br_height); - } - - // Bottom right corner. - canvas->DrawBitmapInt(*images_->bottom_right, - right - br_width, - bottom - br_height); - - // Bottom edge. - if (arrow_location_ == BOTTOM_LEFT || arrow_location_ == BOTTOM_RIGHT) { - int start_x = left + bl_width; - int before_arrow = - arrow_offset - start_x - images_->bottom_arrow->width() / 2; - int after_arrow = width - bl_width - br_width - - images_->bottom_arrow->width() - before_arrow; - int tip_x = start_x + before_arrow + images_->bottom_arrow->width() / 2; - DrawArrowInterior(canvas, - true, - tip_x, - bottom - b_height + kArrowInteriorHeight, - 1 - images_->bottom_arrow->width() / 2, - -kArrowInteriorHeight); - DrawEdgeWithArrow(canvas, - true, - images_->bottom, - images_->bottom_arrow, - start_x, - bottom - b_height, - before_arrow, - after_arrow, - 0); - } else { - canvas->TileImageInt(*images_->bottom, left + bl_width, bottom - b_height, - width - bl_width - br_width, b_height); - } - - // Bottom left corner. - canvas->DrawBitmapInt(*images_->bottom_left, left, bottom - bl_height); -} - -void BubbleBorder::DrawEdgeWithArrow(gfx::Canvas* canvas, - bool is_horizontal, - SkBitmap* edge, - SkBitmap* arrow, - int start_x, - int start_y, - int before_arrow, - int after_arrow, - int offset) const { - /* Here's what the parameters mean: - * start_x - * . - * . ┌───┐ ┬ offset - * start_y..........┌────┬────────┤ ▲ ├────────┬────┐ - * │ / │--------│∙ ∙│--------│ \ │ - * │ / ├────────┴───┴────────┤ \ │ - * ├───┬┘ └┬───┤ - * └───┬────┘ └───┬────┘ - * before_arrow ─┘ └─ after_arrow - */ - if (before_arrow) { - canvas->TileImageInt(*edge, start_x, start_y, - is_horizontal ? before_arrow : edge->width(), - is_horizontal ? edge->height() : before_arrow); - } - - canvas->DrawBitmapInt(*arrow, - start_x + (is_horizontal ? before_arrow : offset), - start_y + (is_horizontal ? offset : before_arrow)); - - if (after_arrow) { - start_x += (is_horizontal ? before_arrow + arrow->width() : 0); - start_y += (is_horizontal ? 0 : before_arrow + arrow->height()); - canvas->TileImageInt(*edge, start_x, start_y, - is_horizontal ? after_arrow : edge->width(), - is_horizontal ? edge->height() : after_arrow); - } -} - -void BubbleBorder::DrawArrowInterior(gfx::Canvas* canvas, - bool is_horizontal, - int tip_x, - int tip_y, - int shift_x, - int shift_y) const { - /* This function fills the interior of the arrow with background color. - * It draws isosceles triangle under semitransparent arrow tip. - * - * Here's what the parameters mean: - * - * ┌──────── |tip_x| - * ┌─────┐ - * │ ▲ │ ──── |tip y| - * │∙∙∙∙∙│ ┐ - * └─────┘ └─── |shift_x| (offset from tip to vertexes of isosceles triangle) - * └────────── |shift_y| - */ - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(background_color_); - gfx::Path path; - path.incReserve(4); - path.moveTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); - path.lineTo(SkIntToScalar(tip_x + shift_x), - SkIntToScalar(tip_y + shift_y)); - if (is_horizontal) - path.lineTo(SkIntToScalar(tip_x - shift_x), SkIntToScalar(tip_y + shift_y)); - else - path.lineTo(SkIntToScalar(tip_x + shift_x), SkIntToScalar(tip_y - shift_y)); - path.close(); - canvas->GetSkCanvas()->drawPath(path, paint); -} - -///////////////////////// - -void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { - // The border of this view creates an anti-aliased round-rect region for the - // contents, which we need to fill with the background color. - // NOTE: This doesn't handle an arrow location of "NONE", which has square top - // corners. - SkPaint paint; - paint.setAntiAlias(true); - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(border_->background_color()); - gfx::Path path; - gfx::Rect bounds(view->GetContentsBounds()); - SkRect rect; - rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()), - SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom())); - SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); - path.addRoundRect(rect, radius, radius); - canvas->GetSkCanvas()->drawPath(path, paint); -} - -} // namespace views diff --git a/views/bubble/bubble_border.h b/views/bubble/bubble_border.h index 7f00072..5612eb70 100644 --- a/views/bubble/bubble_border.h +++ b/views/bubble/bubble_border.h @@ -6,178 +6,7 @@ #define VIEWS_BUBBLE_BUBBLE_BORDER_H_ #pragma once -#include "views/background.h" -#include "views/border.h" - -class SkBitmap; - -namespace views { - -// Renders a border, with optional arrow, and a custom dropshadow. -// This can be used to produce floating "bubble" objects with rounded corners. -class VIEWS_EXPORT BubbleBorder : public views::Border { - public: - // Possible locations for the (optional) arrow. - // 0 bit specifies left or right. - // 1 bit specifies top or bottom. - // 2 bit specifies horizontal or vertical. - enum ArrowLocation { - TOP_LEFT = 0, - TOP_RIGHT = 1, - BOTTOM_LEFT = 2, - BOTTOM_RIGHT = 3, - LEFT_TOP = 4, - RIGHT_TOP = 5, - LEFT_BOTTOM = 6, - RIGHT_BOTTOM = 7, - NONE = 8, // No arrow. Positioned under the supplied rect. - FLOAT = 9 // No arrow. Centered over the supplied rect. - }; - - enum Shadow { - SHADOW = 0, - NO_SHADOW = 1 - }; - - // The position of the bubble in relation to the anchor. - enum BubbleAlignment { - // The tip of the arrow points to the middle of the anchor. - ALIGN_ARROW_TO_MID_ANCHOR, - // The edge nearest to the arrow is lined up with the edge of the anchor. - ALIGN_EDGE_TO_ANCHOR_EDGE - }; - - BubbleBorder(ArrowLocation arrow_location, Shadow shadow); - - // Returns the radius of the corner of the border. - static int GetCornerRadius() { - // We can't safely calculate a border radius by comparing the sizes of the - // side and corner images, because either may have been extended in various - // directions in order to do more subtle dropshadow fading or other effects. - // So we hardcode the most accurate value. - return 4; - } - - // Sets the location for the arrow. - void set_arrow_location(ArrowLocation arrow_location) { - arrow_location_ = arrow_location; - } - ArrowLocation arrow_location() const { return arrow_location_; } - - // Sets the alignment. - void set_alignment(BubbleAlignment alignment) { alignment_ = alignment; } - BubbleAlignment alignment() const { return alignment_; } - - static ArrowLocation horizontal_mirror(ArrowLocation loc) { - return loc >= NONE ? loc : static_cast<ArrowLocation>(loc ^ 1); - } - - static ArrowLocation vertical_mirror(ArrowLocation loc) { - return loc >= NONE ? loc : static_cast<ArrowLocation>(loc ^ 2); - } - - static bool has_arrow(ArrowLocation loc) { - return loc >= NONE ? false : true; - } - - static bool is_arrow_on_left(ArrowLocation loc) { - return loc >= NONE ? false : !(loc & 1); - } - - static bool is_arrow_on_top(ArrowLocation loc) { - return loc >= NONE ? false : !(loc & 2); - } - - static bool is_arrow_on_horizontal(ArrowLocation loc) { - return loc >= NONE ? false : !(loc & 4); - } - - // Sets the background color for the arrow body. This is irrelevant if you do - // not also set the arrow location to something other than NONE. - void set_background_color(SkColor background_color) { - background_color_ = background_color; - } - SkColor background_color() const { return background_color_; } - - // For borders with an arrow, gives the desired bounds (in screen coordinates) - // given the rect to point to and the size of the contained contents. This - // depends on the arrow location, so if you change that, you should call this - // again to find out the new coordinates. - gfx::Rect GetBounds(const gfx::Rect& position_relative_to, - const gfx::Size& contents_size) const; - - // Sets a fixed offset for the arrow from the beginning of corresponding edge. - // The arrow will still point to the same location but the bubble will shift - // location to make that happen. Returns actuall arrow offset, in case of - // overflow it differ from desired. - int SetArrowOffset(int offset, const gfx::Size& contents_size); - - // Overridden from views::Border: - virtual void GetInsets(gfx::Insets* insets) const; - - private: - struct BorderImages; - - // Loads images if necessary. - static BorderImages* GetBorderImages(Shadow shadow); - - virtual ~BubbleBorder(); - - // Overridden from views::Border: - virtual void Paint(const views::View& view, gfx::Canvas* canvas) const; - - void DrawEdgeWithArrow(gfx::Canvas* canvas, - bool is_horizontal, - SkBitmap* edge, - SkBitmap* arrow, - int start_x, - int start_y, - int before_arrow, - int after_arrow, - int offset) const; - - void DrawArrowInterior(gfx::Canvas* canvas, - bool is_horizontal, - int tip_x, - int tip_y, - int shift_x, - int shift_y) const; - - // Border graphics. - struct BorderImages* images_; - - // Image bundles. - static struct BorderImages* normal_images_; - static struct BorderImages* shadow_images_; - - // Minimal offset of the arrow from the closet edge of bounding rect. - int arrow_offset_; - - // If specified, overrides the pre-calculated |arrow_offset_| of the arrow. - int override_arrow_offset_; - - ArrowLocation arrow_location_; - BubbleAlignment alignment_; - SkColor background_color_; - - DISALLOW_COPY_AND_ASSIGN(BubbleBorder); -}; - -// A Background that clips itself to the specified BubbleBorder and uses -// the background color of the BubbleBorder. -class VIEWS_EXPORT BubbleBackground : public views::Background { - public: - explicit BubbleBackground(BubbleBorder* border) : border_(border) {} - - // Background overrides. - virtual void Paint(gfx::Canvas* canvas, views::View* view) const; - - private: - BubbleBorder* border_; - - DISALLOW_COPY_AND_ASSIGN(BubbleBackground); -}; - -} // namespace views +#include "ui/views/bubble/bubble_border.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_BUBBLE_BUBBLE_BORDER_H_ diff --git a/views/bubble/bubble_delegate.cc b/views/bubble/bubble_delegate.cc deleted file mode 100644 index b3baea4..0000000 --- a/views/bubble/bubble_delegate.cc +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) 2011 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 "views/bubble/bubble_delegate.h" - -#include "ui/base/animation/slide_animation.h" -#include "views/bubble/bubble_frame_view.h" -#include "views/widget/widget.h" - -// The duration of the fade animation in milliseconds. -static const int kHideFadeDurationMS = 200; - -namespace views { - -namespace { - -// Create a widget to host the bubble. -Widget* CreateBubbleWidget(BubbleDelegateView* bubble, Widget* parent) { - Widget* bubble_widget = new Widget(); - Widget::InitParams bubble_params(Widget::InitParams::TYPE_BUBBLE); - bubble_params.delegate = bubble; - bubble_params.transparent = true; - bubble_params.parent_widget = parent; -#if defined(OS_WIN) && !defined(USE_AURA) - bubble_params.type = Widget::InitParams::TYPE_WINDOW_FRAMELESS; - bubble_params.transparent = false; -#endif - bubble_widget->Init(bubble_params); - return bubble_widget; -} - -#if defined(OS_WIN) && !defined(USE_AURA) -// The border widget's delegate, needed for transparent Windows native controls. -// TODO(msw): Remove this when Windows native controls are no longer needed. -class VIEWS_EXPORT BubbleBorderDelegateView : public WidgetDelegateView { - public: - explicit BubbleBorderDelegateView(BubbleDelegateView* bubble) - : bubble_(bubble) {} - virtual ~BubbleBorderDelegateView() {} - - // WidgetDelegateView overrides: - virtual bool CanActivate() const OVERRIDE; - virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE; - - private: - BubbleDelegateView* bubble_; - - DISALLOW_COPY_AND_ASSIGN(BubbleBorderDelegateView); -}; - -bool BubbleBorderDelegateView::CanActivate() const { return false; } - -NonClientFrameView* BubbleBorderDelegateView::CreateNonClientFrameView() { - return bubble_->CreateNonClientFrameView(); -} - -// Create a widget to host the bubble's border. -Widget* CreateBorderWidget(BubbleDelegateView* bubble, Widget* parent) { - Widget* border_widget = new Widget(); - Widget::InitParams border_params(Widget::InitParams::TYPE_BUBBLE); - border_params.delegate = new BubbleBorderDelegateView(bubble); - border_params.transparent = true; - border_params.parent_widget = parent; - if (!border_params.parent_widget) - border_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - border_widget->Init(border_params); - return border_widget; -} -#endif - -} // namespace - -BubbleDelegateView::BubbleDelegateView() - : close_on_esc_(true), - close_on_deactivate_(true), - allow_bubble_offscreen_(false), - anchor_view_(NULL), - arrow_location_(BubbleBorder::TOP_LEFT), - color_(SK_ColorWHITE), - border_widget_(NULL), - use_focusless_(false) { - set_background(views::Background::CreateSolidBackground(color_)); - AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, 0)); -} - -BubbleDelegateView::BubbleDelegateView( - View* anchor_view, - BubbleBorder::ArrowLocation arrow_location, - const SkColor& color) - : close_on_esc_(true), - close_on_deactivate_(true), - allow_bubble_offscreen_(false), - anchor_view_(anchor_view), - arrow_location_(arrow_location), - color_(color), - original_opacity_(255), - border_widget_(NULL), - use_focusless_(false) { - set_background(views::Background::CreateSolidBackground(color_)); - AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, 0)); -} - -BubbleDelegateView::~BubbleDelegateView() { - if (border_widget_) - border_widget_->Close(); -} - -// static -Widget* BubbleDelegateView::CreateBubble(BubbleDelegateView* bubble_delegate) { - bubble_delegate->Init(); - Widget* parent = bubble_delegate->anchor_view() ? - bubble_delegate->anchor_view()->GetWidget() : NULL; - Widget* bubble_widget = CreateBubbleWidget(bubble_delegate, parent); - -#if defined(OS_WIN) && !defined(USE_AURA) - // First set the contents view to initialize view bounds for widget sizing. - bubble_widget->SetContentsView(bubble_delegate->GetContentsView()); - bubble_delegate->border_widget_ = CreateBorderWidget(bubble_delegate, parent); -#endif - - bubble_delegate->SizeToContents(); - bubble_widget->AddObserver(bubble_delegate); - if (parent && parent->GetTopLevelWidget()) - parent->GetTopLevelWidget()->DisableInactiveRendering(); - return bubble_widget; -} - -View* BubbleDelegateView::GetInitiallyFocusedView() { - return this; -} - -BubbleDelegateView* BubbleDelegateView::AsBubbleDelegate() { - return this; -} - -View* BubbleDelegateView::GetContentsView() { - return this; -} - -NonClientFrameView* BubbleDelegateView::CreateNonClientFrameView() { - return new BubbleFrameView(GetArrowLocation(), - GetPreferredSize(), - GetColor(), - allow_bubble_offscreen_); -} - -void BubbleDelegateView::OnWidgetActivationChanged(Widget* widget, - bool active) { - if (close_on_deactivate() && widget == GetWidget() && !active) { - GetWidget()->RemoveObserver(this); - GetWidget()->Close(); - } -} - -gfx::Point BubbleDelegateView::GetAnchorPoint() { - if (!anchor_view()) - return gfx::Point(); - - BubbleBorder::ArrowLocation location = GetArrowLocation(); - gfx::Point anchor(anchor_view()->bounds().CenterPoint()); - // By default, pick the middle of |anchor_view_|'s edge opposite the arrow. - if (BubbleBorder::is_arrow_on_horizontal(location)) { - anchor.SetPoint(anchor_view()->width() / 2, - BubbleBorder::is_arrow_on_top(location) ? anchor_view()->height() : 0); - } else if (BubbleBorder::has_arrow(location)) { - anchor.SetPoint( - BubbleBorder::is_arrow_on_left(location) ? anchor_view()->width() : 0, - anchor_view_->height() / 2); - } - View::ConvertPointToScreen(anchor_view(), &anchor); - return anchor; -} - -BubbleBorder::ArrowLocation BubbleDelegateView::GetArrowLocation() const { - return arrow_location_; -} - -SkColor BubbleDelegateView::GetColor() const { - return color_; -} - -void BubbleDelegateView::Show() { - if (border_widget_) - border_widget_->Show(); - GetWidget()->Show(); - GetFocusManager()->SetFocusedView(GetInitiallyFocusedView()); -} - -void BubbleDelegateView::StartFade(bool fade_in) { - fade_animation_.reset(new ui::SlideAnimation(this)); - fade_animation_->SetSlideDuration(kHideFadeDurationMS); - fade_animation_->Reset(fade_in ? 0.0 : 1.0); - if (fade_in) { - original_opacity_ = 0; - if (border_widget_) - border_widget_->SetOpacity(original_opacity_); - GetWidget()->SetOpacity(original_opacity_); - Show(); - fade_animation_->Show(); - } else { - original_opacity_ = 255; - fade_animation_->Hide(); - } -} - -void BubbleDelegateView::ResetFade() { - fade_animation_.reset(); - if (border_widget_) - border_widget_->SetOpacity(original_opacity_); - GetWidget()->SetOpacity(original_opacity_); -} - -bool BubbleDelegateView::AcceleratorPressed( - const ui::Accelerator& accelerator) { - if (!close_on_esc() || accelerator.key_code() != ui::VKEY_ESCAPE) - return false; - if (fade_animation_.get()) - fade_animation_->Reset(); - GetWidget()->Close(); - return true; -} - -void BubbleDelegateView::AnimationEnded(const ui::Animation* animation) { - if (animation != fade_animation_.get()) - return; - bool closed = fade_animation_->GetCurrentValue() == 0; - fade_animation_->Reset(); - if (closed) - GetWidget()->Close(); -} - -void BubbleDelegateView::AnimationProgressed(const ui::Animation* animation) { - if (animation != fade_animation_.get()) - return; - DCHECK(fade_animation_->is_animating()); - unsigned char opacity = fade_animation_->GetCurrentValue() * 255; -#if defined(OS_WIN) && !defined(USE_AURA) - // Explicitly set the content Widget's layered style and set transparency via - // SetLayeredWindowAttributes. This is done because initializing the Widget as - // transparent and setting opacity via UpdateLayeredWindow doesn't support - // hosting child native Windows controls. - const HWND hwnd = GetWidget()->GetNativeView(); - const DWORD style = GetWindowLong(hwnd, GWL_EXSTYLE); - if ((opacity == 255) == !!(style & WS_EX_LAYERED)) - SetWindowLong(hwnd, GWL_EXSTYLE, style ^ WS_EX_LAYERED); - SetLayeredWindowAttributes(hwnd, 0, opacity, LWA_ALPHA); - // Update the border widget's opacity. - border_widget_->SetOpacity(opacity); - border_widget_->non_client_view()->SchedulePaint(); -#endif - GetWidget()->SetOpacity(opacity); - SchedulePaint(); -} - -void BubbleDelegateView::Init() {} - -void BubbleDelegateView::SizeToContents() { -#if defined(OS_WIN) && !defined(USE_AURA) - border_widget_->SetBounds(GetBubbleBounds()); - GetWidget()->SetBounds(GetBubbleClientBounds()); -#else - GetWidget()->SetBounds(GetBubbleBounds()); -#endif -} - -BubbleFrameView* BubbleDelegateView::GetBubbleFrameView() const { - const Widget* widget = border_widget_ ? border_widget_ : GetWidget(); - return static_cast<BubbleFrameView*>(widget->non_client_view()->frame_view()); -} - -gfx::Rect BubbleDelegateView::GetBubbleBounds() { - // The argument rect has its origin at the bubble's arrow anchor point; - // its size is the preferred size of the bubble's client view (this view). - return GetBubbleFrameView()->GetWindowBoundsForClientBounds( - gfx::Rect(GetAnchorPoint(), GetPreferredSize())); -} - -#if defined(OS_WIN) && !defined(USE_AURA) -gfx::Rect BubbleDelegateView::GetBubbleClientBounds() const { - gfx::Rect client_bounds(GetBubbleFrameView()->GetBoundsForClientView()); - client_bounds.Offset(border_widget_->GetWindowScreenBounds().origin()); - return client_bounds; -} -#endif - -} // namespace views diff --git a/views/bubble/bubble_delegate.h b/views/bubble/bubble_delegate.h index e782b82..c533220 100644 --- a/views/bubble/bubble_delegate.h +++ b/views/bubble/bubble_delegate.h @@ -6,148 +6,7 @@ #define VIEWS_BUBBLE_BUBBLE_DELEGATE_H_ #pragma once -#include "base/gtest_prod_util.h" -#include "ui/base/animation/animation_delegate.h" -#include "views/bubble/bubble_border.h" -#include "views/widget/widget.h" -#include "views/widget/widget_delegate.h" - -namespace ui { -class SlideAnimation; -} // namespace ui - -namespace views { - -class BubbleFrameView; - -// BubbleDelegateView creates frame and client views for bubble Widgets. -// BubbleDelegateView itself is the client's contents view. -// -/////////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, - public ui::AnimationDelegate, - public Widget::Observer { - public: - BubbleDelegateView(); - BubbleDelegateView(View* anchor_view, - BubbleBorder::ArrowLocation arrow_location, - const SkColor& color); - virtual ~BubbleDelegateView(); - - // Create and initialize the bubble Widget(s) with proper bounds. - static Widget* CreateBubble(BubbleDelegateView* bubble_delegate); - - // WidgetDelegate overrides: - virtual View* GetInitiallyFocusedView() OVERRIDE; - virtual BubbleDelegateView* AsBubbleDelegate() OVERRIDE; - virtual View* GetContentsView() OVERRIDE; - virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE; - - // Widget::Observer overrides: - virtual void OnWidgetActivationChanged(Widget* widget, bool active) OVERRIDE; - - bool close_on_esc() const { return close_on_esc_; } - void set_close_on_esc(bool close_on_esc) { close_on_esc_ = close_on_esc; } - - bool close_on_deactivate() const { return close_on_deactivate_; } - void set_close_on_deactivate(bool close_on_deactivate) { - close_on_deactivate_ = close_on_deactivate; - } - - bool allow_bubble_offscreen() const { return allow_bubble_offscreen_; } - void set_allow_bubble_offscreen(bool allow_bubble_offscreen) { - allow_bubble_offscreen_ = allow_bubble_offscreen; - } - - View* anchor_view() const { return anchor_view_; } - - bool use_focusless() const { return use_focusless_; } - void set_use_focusless(bool use_focusless) { - use_focusless_ = use_focusless; - } - - // Get the arrow's anchor point in screen space. - virtual gfx::Point GetAnchorPoint(); - - // Get the arrow's location on the bubble. - virtual BubbleBorder::ArrowLocation GetArrowLocation() const; - - // Get the color used for the background and border. - virtual SkColor GetColor() const; - - // Show the bubble's widget (and |border_widget_| on Windows). - void Show(); - - // Fade the bubble in or out via Widget transparency. - // Fade in calls Widget::Show; fade out calls Widget::Close upon completion. - void StartFade(bool fade_in); - - // Reset fade and opacity of bubble. Restore the opacity of the - // bubble to the setting before StartFade() was called. - void ResetFade(); - - protected: - // View overrides: - virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; - - // ui::AnimationDelegate overrides: - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; - - // Perform view initialization on the contents for bubble sizing. - virtual void Init(); - - // Resizes and potentially moves the Bubble to best accommodate the - // contents preferred size. - void SizeToContents(); - - private: - FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewBasicTest, NonClientHitTest); - FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CreateDelegate); - - BubbleFrameView* GetBubbleFrameView() const; - - // Get bubble bounds from the anchor point and client view's preferred size. - gfx::Rect GetBubbleBounds(); - -#if defined(OS_WIN) && !defined(USE_AURA) - // Get bounds for the Windows-only widget that hosts the bubble's contents. - gfx::Rect GetBubbleClientBounds() const; -#endif - - // Fade animation for bubble. - scoped_ptr<ui::SlideAnimation> fade_animation_; - - // Flags controlling bubble closure on the escape key and deactivation. - bool close_on_esc_; - bool close_on_deactivate_; - - // Whether the bubble is allowed to be displayed offscreen, or if auto - // re-positioning should be performed. - bool allow_bubble_offscreen_; - - // The view hosting this bubble; the arrow is anchored to this view. - View* anchor_view_; - - // The arrow's location on the bubble. - BubbleBorder::ArrowLocation arrow_location_; - - // The background color of the bubble. - SkColor color_; - - // Original opacity of the bubble. - int original_opacity_; - - // The widget hosting the border for this bubble (non-Aura Windows only). - Widget* border_widget_; - - // Create a popup window for focusless bubbles on Linux/ChromeOS. - // These bubbles are not interactive and should not gain focus. - bool use_focusless_; - - DISALLOW_COPY_AND_ASSIGN(BubbleDelegateView); -}; - -} // namespace views +#include "ui/views/bubble/bubble_delegate.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_BUBBLE_BUBBLE_DELEGATE_H_ diff --git a/views/bubble/bubble_delegate_unittest.cc b/views/bubble/bubble_delegate_unittest.cc deleted file mode 100644 index f6d256a..0000000 --- a/views/bubble/bubble_delegate_unittest.cc +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2011 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 "ui/views/test/views_test_base.h" -#include "views/bubble/bubble_delegate.h" -#include "views/bubble/bubble_frame_view.h" -#include "views/widget/widget.h" - -namespace views { - -typedef ViewsTestBase BubbleDelegateTest; - -TEST_F(BubbleDelegateTest, CreateDelegate) { - BubbleDelegateView* bubble_delegate = new BubbleDelegateView( - NULL, BubbleBorder::NONE, SK_ColorGREEN); - Widget* bubble_widget( - BubbleDelegateView::CreateBubble(bubble_delegate)); - EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate()); - EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget()); - - BubbleBorder* border = - bubble_delegate->GetBubbleFrameView()->bubble_border(); - EXPECT_EQ(bubble_delegate->GetArrowLocation(), border->arrow_location()); - EXPECT_EQ(bubble_delegate->GetColor(), border->background_color()); - - bubble_widget->CloseNow(); - RunPendingMessages(); -} - -} // namespace views diff --git a/views/bubble/bubble_frame_view.cc b/views/bubble/bubble_frame_view.cc deleted file mode 100644 index 85e1f6e..0000000 --- a/views/bubble/bubble_frame_view.cc +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2011 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 "views/bubble/bubble_frame_view.h" - -#include <algorithm> - -#include "ui/views/window/client_view.h" -#include "views/bubble/border_contents_view.h" -#include "views/bubble/bubble_border.h" -#include "views/layout/fill_layout.h" -#include "views/widget/widget.h" - -namespace views { - -BubbleFrameView::BubbleFrameView(BubbleBorder::ArrowLocation location, - const gfx::Size& client_size, - SkColor color, - bool allow_bubble_offscreen) - : border_contents_(new BorderContentsView()), - location_(location), - allow_bubble_offscreen_(allow_bubble_offscreen) { - border_contents_->Init(); - bubble_border()->set_arrow_location(location_); - bubble_border()->set_background_color(color); - SetLayoutManager(new views::FillLayout()); - AddChildView(border_contents_); - gfx::Rect bounds(gfx::Point(), client_size); - gfx::Rect windows_bounds = GetWindowBoundsForClientBounds(bounds); - border_contents_->SetBoundsRect( - gfx::Rect(gfx::Point(), windows_bounds.size())); - SetBoundsRect(windows_bounds); -} - -BubbleFrameView::~BubbleFrameView() {} - -gfx::Rect BubbleFrameView::GetBoundsForClientView() const { - gfx::Insets margin; - bubble_border()->GetInsets(&margin); - margin += border_contents_->content_margins(); - return gfx::Rect(margin.left(), - margin.top(), - std::max(width() - margin.width(), 0), - std::max(height() - margin.height(), 0)); -} - -gfx::Rect BubbleFrameView::GetWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const { - // The |client_bounds| origin is the bubble arrow anchor point. - gfx::Rect position_relative_to(client_bounds.origin(), gfx::Size()); - // The |client_bounds| size is the bubble client view size. - gfx::Rect content_bounds; - gfx::Rect window_bounds; - border_contents_->SizeAndGetBounds(position_relative_to, - location_, - allow_bubble_offscreen_, - client_bounds.size(), - &content_bounds, - &window_bounds); - return window_bounds; -} - -int BubbleFrameView::NonClientHitTest(const gfx::Point& point) { - return GetWidget()->client_view()->NonClientHitTest(point); -} - -gfx::Size BubbleFrameView::GetPreferredSize() { - Widget* widget = GetWidget(); - gfx::Rect rect(gfx::Point(), widget->client_view()->GetPreferredSize()); - return widget->non_client_view()->GetWindowBoundsForClientBounds(rect).size(); -} - -BubbleBorder* BubbleFrameView::bubble_border() const { - return static_cast<BubbleBorder*>(border_contents_->border()); -} - -} // namespace views diff --git a/views/bubble/bubble_frame_view.h b/views/bubble/bubble_frame_view.h index 1e3cbda..268e1a2 100644 --- a/views/bubble/bubble_frame_view.h +++ b/views/bubble/bubble_frame_view.h @@ -6,52 +6,7 @@ #define VIEWS_BUBBLE_BUBBLE_FRAME_VIEW_H_ #pragma once -#include "base/gtest_prod_util.h" -#include "ui/views/window/non_client_view.h" -#include "views/bubble/bubble_border.h" - -namespace views { - -class BorderContentsView; - -// BubbleFrameView to render BubbleBorder. -// -//////////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView { - public: - BubbleFrameView(BubbleBorder::ArrowLocation location, - const gfx::Size& client_size, - SkColor color, - bool allow_bubble_offscreen); - virtual ~BubbleFrameView(); - - // NonClientFrameView overrides: - virtual gfx::Rect GetBoundsForClientView() const OVERRIDE; - virtual gfx::Rect GetWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const OVERRIDE; - virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE; - virtual void GetWindowMask(const gfx::Size& size, - gfx::Path* window_mask) OVERRIDE {} - virtual void EnableClose(bool enable) OVERRIDE {} - virtual void ResetWindowControls() OVERRIDE {} - virtual void UpdateWindowIcon() OVERRIDE {} - - // View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE; - - // Accessor for bubble border inside border contents. - BubbleBorder* bubble_border() const; - - private: - FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewBasicTest, GetBoundsForClientView); - - BorderContentsView* border_contents_; - BubbleBorder::ArrowLocation location_; - bool allow_bubble_offscreen_; - - DISALLOW_COPY_AND_ASSIGN(BubbleFrameView); -}; - -} // namespace views +#include "ui/views/bubble/bubble_frame_view.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_BUBBLE_BUBBLE_FRAME_VIEW_H_ diff --git a/views/bubble/bubble_frame_view_unittest.cc b/views/bubble/bubble_frame_view_unittest.cc deleted file mode 100644 index 6699bfd..0000000 --- a/views/bubble/bubble_frame_view_unittest.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2011 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 "ui/base/hit_test.h" -#include "ui/views/test/views_test_base.h" -#include "views/bubble/border_contents_view.h" -#include "views/bubble/bubble_border.h" -#include "views/bubble/bubble_delegate.h" -#include "views/bubble/bubble_frame_view.h" -#include "views/widget/widget.h" - -namespace views { - -typedef ViewsTestBase BubbleFrameViewBasicTest; - -const BubbleBorder::ArrowLocation kArrow = BubbleBorder::TOP_LEFT; -const gfx::Rect kRect(10, 10, 200, 200); -const SkColor kBackgroundColor = SK_ColorRED; -const bool kAllowBubbleOffscreen = true; - -TEST_F(BubbleFrameViewBasicTest, GetBoundsForClientView) { - BubbleFrameView frame(kArrow, kRect.size(), kBackgroundColor, - kAllowBubbleOffscreen); - EXPECT_EQ(frame.GetWindowBoundsForClientBounds(kRect).size(), frame.size()); - EXPECT_EQ(kArrow, frame.bubble_border()->arrow_location()); - EXPECT_EQ(kBackgroundColor, frame.bubble_border()->background_color()); - - int margin_x = frame.border_contents_->content_margins().left(); - int margin_y = frame.border_contents_->content_margins().top(); - gfx::Insets insets; - frame.bubble_border()->GetInsets(&insets); - EXPECT_EQ(insets.left() + margin_x, frame.GetBoundsForClientView().x()); - EXPECT_EQ(insets.top() + margin_y, frame.GetBoundsForClientView().y()); -} - -namespace { - -class SizedBubbleDelegateView : public BubbleDelegateView { - public: - SizedBubbleDelegateView() {} - virtual ~SizedBubbleDelegateView() {} - - // View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(SizedBubbleDelegateView); -}; - -gfx::Size SizedBubbleDelegateView::GetPreferredSize() { return kRect.size(); } - -} // namespace - -TEST_F(BubbleFrameViewBasicTest, NonClientHitTest) { - BubbleDelegateView* delegate = new SizedBubbleDelegateView(); - Widget* widget(BubbleDelegateView::CreateBubble(delegate)); - delegate->Show(); - gfx::Point kPtInBound(100, 100); - gfx::Point kPtOutsideBound(1000, 1000); - BubbleFrameView* bubble_frame_view = delegate->GetBubbleFrameView(); - EXPECT_EQ(HTCLIENT, bubble_frame_view->NonClientHitTest(kPtInBound)); - EXPECT_EQ(HTNOWHERE, bubble_frame_view->NonClientHitTest(kPtOutsideBound)); - widget->CloseNow(); - RunPendingMessages(); -} - -} // namespace views diff --git a/views/events/event.cc b/views/events/event.cc deleted file mode 100644 index 67d165e..0000000 --- a/views/events/event.cc +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2011 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 "views/events/event.h" - -#include "base/logging.h" -#include "ui/base/keycodes/keyboard_code_conversion.h" -#include "views/view.h" -#include "views/widget/root_view.h" - -namespace views { - -//////////////////////////////////////////////////////////////////////////////// -// Event, protected: - -Event::Event(ui::EventType type, int flags) - : type_(type), - time_stamp_(base::Time::NowFromSystemTime()), - flags_(flags) { - // Safely initialize the pointer/struct to null/empty. - memset(&native_event_, 0, sizeof(native_event_)); -#if defined(TOOLKIT_USES_GTK) - gdk_event_ = NULL; -#endif -} - -Event::Event(const NativeEvent& native_event, ui::EventType type, int flags) - : native_event_(native_event), - type_(type), - time_stamp_(base::Time::NowFromSystemTime()), - flags_(flags) { -#if defined(TOOLKIT_USES_GTK) - gdk_event_ = NULL; -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -// LocatedEvent, protected: - -#if !defined(USE_AURA) -LocatedEvent::LocatedEvent(const NativeEvent& native_event) - : Event(native_event, - ui::EventTypeFromNative(native_event), - ui::EventFlagsFromNative(native_event)), - location_(ui::EventLocationFromNative(native_event)) { -} -#endif - -// TODO(msw): Kill this legacy constructor when we update uses. -LocatedEvent::LocatedEvent(ui::EventType type, - const gfx::Point& location, - int flags) - : Event(type, flags), - location_(location) { -} - -LocatedEvent::LocatedEvent(const LocatedEvent& model, - View* source, - View* target) - : Event(model), - location_(model.location_) { - if (target && target != source) - View::ConvertPointToView(source, target, &location_); -} - -LocatedEvent::LocatedEvent(const LocatedEvent& model, View* root) - : Event(model), - location_(model.location_) { - View::ConvertPointFromWidget(root, &location_); -} - -//////////////////////////////////////////////////////////////////////////////// -// KeyEvent, public: - -#if !defined(USE_AURA) -KeyEvent::KeyEvent(const NativeEvent& native_event) - : Event(native_event, - ui::EventTypeFromNative(native_event), - ui::EventFlagsFromNative(native_event)), - key_code_(ui::KeyboardCodeFromNative(native_event)), - character_(0), - unmodified_character_(0) { -} -#endif - -KeyEvent::KeyEvent(ui::EventType type, - ui::KeyboardCode key_code, - int event_flags) - : Event(type, event_flags), - key_code_(key_code), - character_(ui::GetCharacterFromKeyCode(key_code, event_flags)), - unmodified_character_(0) { -} - -//////////////////////////////////////////////////////////////////////////////// -// MouseEvent, public: - -MouseEvent::MouseEvent(const NativeEvent& native_event) - : LocatedEvent(native_event) { -} - -MouseEvent::MouseEvent(const MouseEvent& model, View* source, View* target) - : LocatedEvent(model, source, target) { -} - -MouseEvent::MouseEvent(const TouchEvent& touch) - : LocatedEvent(touch.native_event()) { - // The location of the event is correctly extracted from the native event. But - // it is necessary to update the event type. - ui::EventType mtype = ui::ET_UNKNOWN; - switch (touch.type()) { - case ui::ET_TOUCH_RELEASED: - mtype = ui::ET_MOUSE_RELEASED; - break; - case ui::ET_TOUCH_PRESSED: - mtype = ui::ET_MOUSE_PRESSED; - break; - case ui::ET_TOUCH_MOVED: - mtype = ui::ET_MOUSE_MOVED; - break; - default: - NOTREACHED() << "Invalid mouse event."; - } - set_type(mtype); - - // It may not be possible to extract the button-information necessary for a - // MouseEvent from the native event for a TouchEvent, so the flags are - // explicitly updated as well. The button is approximated from the touchpoint - // identity. - int new_flags = flags() & ~(ui::EF_LEFT_BUTTON_DOWN | - ui::EF_RIGHT_BUTTON_DOWN | - ui::EF_MIDDLE_BUTTON_DOWN); - int button = ui::EF_LEFT_BUTTON_DOWN; - if (touch.identity() == 1) - button = ui::EF_RIGHT_BUTTON_DOWN; - else if (touch.identity() == 2) - button = ui::EF_MIDDLE_BUTTON_DOWN; - set_flags(new_flags | button); -} - -//////////////////////////////////////////////////////////////////////////////// -// MouseWheelEvent, public: - -#if !defined(USE_AURA) -MouseWheelEvent::MouseWheelEvent(const NativeEvent& native_event) - : MouseEvent(native_event), - offset_(ui::GetMouseWheelOffset(native_event)) { -} -#endif - -//////////////////////////////////////////////////////////////////////////////// -// TouchEvent, public: - -TouchEvent::TouchEvent(ui::EventType type, - int x, - int y, - int flags, - int touch_id, - float radius_x, - float radius_y, - float angle, - float force) - : LocatedEvent(type, gfx::Point(x, y), flags), - touch_id_(touch_id), - radius_x_(radius_x), - radius_y_(radius_y), - rotation_angle_(angle), - force_(force) { -} - -TouchEvent::TouchEvent(const TouchEvent& model, View* source, View* target) - : LocatedEvent(model, source, target), - touch_id_(model.touch_id_), - radius_x_(model.radius_x_), - radius_y_(model.radius_y_), - rotation_angle_(model.rotation_angle_), - force_(model.force_) { -} - -//////////////////////////////////////////////////////////////////////////////// -// TouchEvent, private: - -TouchEvent::TouchEvent(const TouchEvent& model, View* root) - : LocatedEvent(model, root), - touch_id_(model.touch_id_), - radius_x_(model.radius_x_), - radius_y_(model.radius_y_), - rotation_angle_(model.rotation_angle_), - force_(model.force_) { -} - -//////////////////////////////////////////////////////////////////////////////// -// MouseWheelEvent, public: - -// This value matches windows WHEEL_DELTA. -// static -const int MouseWheelEvent::kWheelDelta = 120; - -} // namespace views diff --git a/views/events/event.h b/views/events/event.h index d1b9b88..015eb08 100644 --- a/views/events/event.h +++ b/views/events/event.h @@ -6,410 +6,7 @@ #define VIEWS_EVENTS_EVENT_H_ #pragma once -#include "base/basictypes.h" -#include "base/time.h" -#include "ui/base/events.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/gfx/point.h" -#include "views/views_export.h" - -namespace ui { -class OSExchangeData; -} - -#if defined(USE_AURA) -namespace aura { -class Event; -} -#endif - -// TODO(msw): Remove GTK support from views event code when possible. -#if defined(TOOLKIT_USES_GTK) -typedef union _GdkEvent GdkEvent; -#endif - -namespace views { - -#if defined(USE_AURA) -typedef aura::Event* NativeEvent; -#else -typedef base::NativeEvent NativeEvent; -#endif - -class View; - -namespace internal { -class NativeWidgetView; -class RootView; -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Event class -// -// An event encapsulates an input event that can be propagated into view -// hierarchies. An event has a type, some flags and a time stamp. -// -// Each major event type has a corresponding Event subclass. -// -// Events are immutable but support copy -// -//////////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT Event { - public: - const NativeEvent& native_event() const { return native_event_; } -#if defined(TOOLKIT_USES_GTK) - GdkEvent* gdk_event() const { return gdk_event_; } -#endif - ui::EventType type() const { return type_; } - const base::Time& time_stamp() const { return time_stamp_; } - int flags() const { return flags_; } - void set_flags(int flags) { flags_ = flags; } - - // The following methods return true if the respective keys were pressed at - // the time the event was created. - bool IsShiftDown() const { return (flags_ & ui::EF_SHIFT_DOWN) != 0; } - bool IsControlDown() const { return (flags_ & ui::EF_CONTROL_DOWN) != 0; } - bool IsCapsLockDown() const { return (flags_ & ui::EF_CAPS_LOCK_DOWN) != 0; } - bool IsAltDown() const { return (flags_ & ui::EF_ALT_DOWN) != 0; } - - bool IsMouseEvent() const { - return type_ == ui::ET_MOUSE_PRESSED || - type_ == ui::ET_MOUSE_DRAGGED || - type_ == ui::ET_MOUSE_RELEASED || - type_ == ui::ET_MOUSE_MOVED || - type_ == ui::ET_MOUSE_ENTERED || - type_ == ui::ET_MOUSE_EXITED || - type_ == ui::ET_MOUSEWHEEL; - } - - bool IsTouchEvent() const { - return type_ == ui::ET_TOUCH_RELEASED || - type_ == ui::ET_TOUCH_PRESSED || - type_ == ui::ET_TOUCH_MOVED || - type_ == ui::ET_TOUCH_STATIONARY || - type_ == ui::ET_TOUCH_CANCELLED; - } - - protected: - Event(ui::EventType type, int flags); - Event(const NativeEvent& native_event, ui::EventType type, int flags); -#if defined(TOOLKIT_USES_GTK) - Event(GdkEvent* gdk_event, ui::EventType type, int flags); -#endif - - Event(const Event& model) - : native_event_(model.native_event()), -#if defined(TOOLKIT_USES_GTK) - gdk_event_(model.gdk_event_), -#endif - type_(model.type()), - time_stamp_(model.time_stamp()), - flags_(model.flags()) { - } - - void set_type(ui::EventType type) { type_ = type; } - - private: - void operator=(const Event&); - - NativeEvent native_event_; -#if defined(TOOLKIT_USES_GTK) - GdkEvent* gdk_event_; -#endif - ui::EventType type_; - base::Time time_stamp_; - int flags_; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// LocatedEvent class -// -// A generic event that is used for any events that is located at a specific -// position in the screen. -// -//////////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT LocatedEvent : public Event { - public: - int x() const { return location_.x(); } - int y() const { return location_.y(); } - const gfx::Point& location() const { return location_; } - - protected: - explicit LocatedEvent(const NativeEvent& native_event); -#if defined(TOOLKIT_USES_GTK) - explicit LocatedEvent(GdkEvent* gdk_event); -#endif - - // TODO(msw): Kill this legacy constructor when we update uses. - // Simple initialization from cracked metadata. - LocatedEvent(ui::EventType type, const gfx::Point& location, int flags); - - // Create a new LocatedEvent which is identical to the provided model. - // If source / target views are provided, the model location will be converted - // from |source| coordinate system to |target| coordinate system. - LocatedEvent(const LocatedEvent& model, View* source, View* target); - - // This constructor is to allow converting the location of an event from the - // widget's coordinate system to the RootView's coordinate system. - LocatedEvent(const LocatedEvent& model, View* root); - - gfx::Point location_; -}; - -class TouchEvent; - -//////////////////////////////////////////////////////////////////////////////// -// -// MouseEvent class -// -// A mouse event is used for any input event related to the mouse. -// -//////////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT MouseEvent : public LocatedEvent { - public: - explicit MouseEvent(const NativeEvent& native_event); -#if defined(TOOLKIT_USES_GTK) - explicit MouseEvent(GdkEvent* gdk_event); -#endif - - // Create a new MouseEvent which is identical to the provided model. - // If source / target views are provided, the model location will be converted - // from |source| coordinate system to |target| coordinate system. - MouseEvent(const MouseEvent& model, View* source, View* target); - - // Creates a new MouseEvent from a TouchEvent. The location of the TouchEvent - // is the same as the MouseEvent. Other attributes (e.g. type, flags) are - // mapped from the TouchEvent to appropriate MouseEvent attributes. - // GestureManager uses this to convert TouchEvents that are not handled by any - // view. - explicit MouseEvent(const TouchEvent& touch); - - // TODO(msw): Kill this legacy constructor when we update uses. - // Create a new mouse event - MouseEvent(ui::EventType type, int x, int y, int flags) - : LocatedEvent(type, gfx::Point(x, y), flags) { - } - - // Conveniences to quickly test what button is down - bool IsOnlyLeftMouseButton() const { - return (flags() & ui::EF_LEFT_BUTTON_DOWN) && - !(flags() & (ui::EF_MIDDLE_BUTTON_DOWN | ui::EF_RIGHT_BUTTON_DOWN)); - } - - bool IsLeftMouseButton() const { - return (flags() & ui::EF_LEFT_BUTTON_DOWN) != 0; - } - - bool IsOnlyMiddleMouseButton() const { - return (flags() & ui::EF_MIDDLE_BUTTON_DOWN) && - !(flags() & (ui::EF_LEFT_BUTTON_DOWN | ui::EF_RIGHT_BUTTON_DOWN)); - } - - bool IsMiddleMouseButton() const { - return (flags() & ui::EF_MIDDLE_BUTTON_DOWN) != 0; - } - - bool IsOnlyRightMouseButton() const { - return (flags() & ui::EF_RIGHT_BUTTON_DOWN) && - !(flags() & (ui::EF_LEFT_BUTTON_DOWN | ui::EF_MIDDLE_BUTTON_DOWN)); - } - - bool IsRightMouseButton() const { - return (flags() & ui::EF_RIGHT_BUTTON_DOWN) != 0; - } - - protected: - MouseEvent(const MouseEvent& model, View* root) - : LocatedEvent(model, root) { - } - - private: - friend class internal::NativeWidgetView; - friend class internal::RootView; - - DISALLOW_COPY_AND_ASSIGN(MouseEvent); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// TouchEvent class -// -// A touch event is generated by touch screen and advanced track -// pad devices. There is a deliberate direct correspondence between -// TouchEvent and PlatformTouchPoint. -// -//////////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT TouchEvent : public LocatedEvent { - public: - explicit TouchEvent(const NativeEvent& native_event); - - // Create a new touch event. - TouchEvent(ui::EventType type, - int x, - int y, - int flags, - int touch_id, - float radius_x, - float radius_y, - float angle, - float force); - - // Create a new TouchEvent which is identical to the provided model. - // If source / target views are provided, the model location will be converted - // from |source| coordinate system to |target| coordinate system. - TouchEvent(const TouchEvent& model, View* source, View* target); - - int identity() const { return touch_id_; } - - float radius_x() const { return radius_x_; } - float radius_y() const { return radius_y_; } - float rotation_angle() const { return rotation_angle_; } - float force() const { return force_; } - - private: - friend class internal::NativeWidgetView; - friend class internal::RootView; - - TouchEvent(const TouchEvent& model, View* root); - - // The identity (typically finger) of the touch starting at 0 and incrementing - // for each separable additional touch that the hardware can detect. - const int touch_id_; - - // Radius of the X (major) axis of the touch ellipse. 1.0 if unknown. - const float radius_x_; - - // Radius of the Y (minor) axis of the touch ellipse. 1.0 if unknown. - const float radius_y_; - - // Angle of the major axis away from the X axis. Default 0.0. - const float rotation_angle_; - - // Force (pressure) of the touch. Normalized to be [0, 1]. Default to be 0.0. - const float force_; - - DISALLOW_COPY_AND_ASSIGN(TouchEvent); -}; - -//////////////////////////////////////////////////////////////////////////////// -// KeyEvent class -// -// KeyEvent encapsulates keyboard input events - key press and release. -// -//////////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT KeyEvent : public Event { - public: - explicit KeyEvent(const NativeEvent& native_event); -#if defined(TOOLKIT_USES_GTK) - explicit KeyEvent(GdkEvent* gdk_event); -#endif - - // Creates a new KeyEvent synthetically (i.e. not in response to an input - // event from the host environment). This is typically only used in testing as - // some metadata obtainable from the underlying native event is not present. - // It's also used by input methods to fabricate keyboard events. - KeyEvent(ui::EventType type, - ui::KeyboardCode key_code, - int event_flags); - - ui::KeyboardCode key_code() const { return key_code_; } - - // These setters allow an I18N virtual keyboard to fabricate a keyboard event - // which does not have a corresponding ui::KeyboardCode (example: U+00E1 Latin - // small letter A with acute, U+0410 Cyrillic capital letter A.) - // GetCharacter() and GetUnmodifiedCharacter() return the character. - void set_character(uint16 character) { character_ = character; } - void set_unmodified_character(uint16 unmodified_character) { - unmodified_character_ = unmodified_character; - } - - // Gets the character generated by this key event. It only supports Unicode - // BMP characters. - uint16 GetCharacter() const; - - // Gets the character generated by this key event ignoring concurrently-held - // modifiers (except shift). - uint16 GetUnmodifiedCharacter() const; - - private: - ui::KeyboardCode key_code_; - - uint16 character_; - uint16 unmodified_character_; - - DISALLOW_COPY_AND_ASSIGN(KeyEvent); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// MouseWheelEvent class -// -// A MouseWheelEvent is used to propagate mouse wheel user events. -// Note: e.GetOffset() > 0 means scroll up / left. -// -//////////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT MouseWheelEvent : public MouseEvent { - public: - // See |offset| for details. - static const int kWheelDelta; - - explicit MouseWheelEvent(const NativeEvent& native_event); -#if defined(TOOLKIT_USES_GTK) - explicit MouseWheelEvent(GdkEvent* gdk_event); -#endif - - // The amount to scroll. This is in multiples of kWheelDelta. - int offset() const { return offset_; } - - private: - friend class internal::RootView; - friend class internal::NativeWidgetView; - - MouseWheelEvent(const MouseWheelEvent& model, View* root) - : MouseEvent(model, root), - offset_(model.offset_) { - } - - int offset_; - - DISALLOW_COPY_AND_ASSIGN(MouseWheelEvent); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// DropTargetEvent class -// -// A DropTargetEvent is sent to the view the mouse is over during a drag and -// drop operation. -// -//////////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT DropTargetEvent : public LocatedEvent { - public: - DropTargetEvent(const ui::OSExchangeData& data, - int x, - int y, - int source_operations) - : LocatedEvent(ui::ET_DROP_TARGET_EVENT, gfx::Point(x, y), 0), - data_(data), - source_operations_(source_operations) { - // TODO(msw): Hook up key state flags for CTRL + drag and drop, etc. - } - - const ui::OSExchangeData& data() const { return data_; } - int source_operations() const { return source_operations_; } - - private: - // Data associated with the drag/drop session. - const ui::OSExchangeData& data_; - - // Bitmask of supported ui::DragDropTypes::DragOperation by the source. - int source_operations_; - - DISALLOW_COPY_AND_ASSIGN(DropTargetEvent); -}; - -} // namespace views +#include "ui/views/events/event.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_EVENTS_EVENT_H_ diff --git a/views/events/event_aura.cc b/views/events/event_aura.cc deleted file mode 100644 index a4d3169..0000000 --- a/views/events/event_aura.cc +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2011 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 "views/events/event.h" - -#include "base/logging.h" -#include "ui/aura/event.h" -#include "ui/base/keycodes/keyboard_code_conversion.h" - -namespace views { - -//////////////////////////////////////////////////////////////////////////////// -// LocatedEvent, protected: - -LocatedEvent::LocatedEvent(const NativeEvent& native_event) - : Event(native_event, native_event->type(), native_event->flags()), - location_(static_cast<aura::LocatedEvent*>(native_event)->location()) { -} - -//////////////////////////////////////////////////////////////////////////////// -// TouchEvent, public: - -TouchEvent::TouchEvent(const NativeEvent& event) - : LocatedEvent(event), - touch_id_(static_cast<aura::TouchEvent*>(event)->touch_id()), - radius_x_(static_cast<aura::TouchEvent*>(event)->radius_x()), - radius_y_(static_cast<aura::TouchEvent*>(event)->radius_y()), - rotation_angle_(static_cast<aura::TouchEvent*>(event)->rotation_angle()), - force_(static_cast<aura::TouchEvent*>(event)->force()) { -} - -//////////////////////////////////////////////////////////////////////////////// -// KeyEvent, public: - -KeyEvent::KeyEvent(const NativeEvent& native_event) - : Event(native_event, native_event->type(), native_event->flags()), - key_code_(static_cast<aura::KeyEvent*>(native_event)->key_code()), - character_(ui::GetCharacterFromKeyCode(key_code_, flags())), - unmodified_character_(0) { -} - -uint16 KeyEvent::GetCharacter() const { - return character_; -} - -uint16 KeyEvent::GetUnmodifiedCharacter() const { - if (unmodified_character_) - return unmodified_character_; - - return ui::GetCharacterFromKeyCode(key_code_, flags() & ui::EF_SHIFT_DOWN); -} - -//////////////////////////////////////////////////////////////////////////////// -// MouseWheelEvent, public: - -MouseWheelEvent::MouseWheelEvent(const NativeEvent& native_event) - : MouseEvent(native_event), - offset_(ui::GetMouseWheelOffset(native_event->native_event())) { -} - -} // namespace views diff --git a/views/events/event_gtk.cc b/views/events/event_gtk.cc deleted file mode 100644 index fb0c88a..0000000 --- a/views/events/event_gtk.cc +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) 2011 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 "views/events/event.h" - -#include <gdk/gdk.h> - -#include "base/logging.h" -#include "ui/base/keycodes/keyboard_code_conversion_gtk.h" -#include "ui/gfx/point.h" - -namespace { - -unsigned int GetGdkStateFromNative(GdkEvent* gdk_event) { - switch (gdk_event->type) { - case GDK_KEY_PRESS: - case GDK_KEY_RELEASE: - return gdk_event->key.state; - case GDK_BUTTON_PRESS: - case GDK_2BUTTON_PRESS: - case GDK_3BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - return gdk_event->button.state; - case GDK_SCROLL: - return gdk_event->scroll.state; - case GDK_MOTION_NOTIFY: - return gdk_event->motion.state; - case GDK_ENTER_NOTIFY: - case GDK_LEAVE_NOTIFY: - return gdk_event->crossing.state; - default: - NOTREACHED(); - break; - } - return 0; -} - -int GetFlagsFromGdkState(unsigned int state) { - int flags = 0; - flags |= (state & GDK_LOCK_MASK) ? ui::EF_CAPS_LOCK_DOWN : 0; - flags |= (state & GDK_CONTROL_MASK) ? ui::EF_CONTROL_DOWN : 0; - flags |= (state & GDK_SHIFT_MASK) ? ui::EF_SHIFT_DOWN : 0; - flags |= (state & GDK_MOD1_MASK) ? ui::EF_ALT_DOWN : 0; - flags |= (state & GDK_BUTTON1_MASK) ? ui::EF_LEFT_BUTTON_DOWN : 0; - flags |= (state & GDK_BUTTON2_MASK) ? ui::EF_MIDDLE_BUTTON_DOWN : 0; - flags |= (state & GDK_BUTTON3_MASK) ? ui::EF_RIGHT_BUTTON_DOWN : 0; - return flags; -} - -//////////////////////////////////////////////////////////////////////////////// -// These functions mirror ui/base/events.h, but GTK is in the midst of removal. - -ui::EventType EventTypeFromNative(GdkEvent* gdk_event) { - // Add new event types as necessary. - switch (gdk_event->type) { - case GDK_2BUTTON_PRESS: - case GDK_3BUTTON_PRESS: - case GDK_BUTTON_PRESS: - return ui::ET_MOUSE_PRESSED; - case GDK_BUTTON_RELEASE: - return ui::ET_MOUSE_RELEASED; - case GDK_DRAG_MOTION: - return ui::ET_MOUSE_DRAGGED; - case GDK_ENTER_NOTIFY: - return ui::ET_MOUSE_ENTERED; - case GDK_KEY_PRESS: - return ui::ET_KEY_PRESSED; - case GDK_KEY_RELEASE: - return ui::ET_KEY_RELEASED; - case GDK_LEAVE_NOTIFY: - return ui::ET_MOUSE_EXITED; - case GDK_MOTION_NOTIFY: - if (gdk_event->motion.state & GDK_BUTTON1_MASK || - gdk_event->motion.state & GDK_BUTTON2_MASK || - gdk_event->motion.state & GDK_BUTTON3_MASK || - gdk_event->motion.state & GDK_BUTTON4_MASK || - gdk_event->motion.state & GDK_BUTTON5_MASK) { - return ui::ET_MOUSE_DRAGGED; - } - return ui::ET_MOUSE_MOVED; - case GDK_SCROLL: - return ui::ET_MOUSEWHEEL; - default: - NOTREACHED(); - break; - } - return ui::ET_UNKNOWN; -} - -int EventFlagsFromNative(GdkEvent* gdk_event) { - int flags = GetFlagsFromGdkState(GetGdkStateFromNative(gdk_event)); - if (gdk_event->type == GDK_2BUTTON_PRESS) - flags |= ui::EF_IS_DOUBLE_CLICK; - if (gdk_event->type == GDK_BUTTON_PRESS || - gdk_event->type == GDK_2BUTTON_PRESS || - gdk_event->type == GDK_3BUTTON_PRESS || - gdk_event->type == GDK_BUTTON_RELEASE) { - switch (gdk_event->button.button) { - case 1: - return flags | ui::EF_LEFT_BUTTON_DOWN; - case 2: - return flags | ui::EF_MIDDLE_BUTTON_DOWN; - case 3: - return flags | ui::EF_RIGHT_BUTTON_DOWN; - } - } - return flags; -} - -gfx::Point EventLocationFromNative(GdkEvent* gdk_event) { - double x = 0, y = 0; - if (gdk_event_get_coords(gdk_event, &x, &y)) - return gfx::Point(static_cast<int>(x), static_cast<int>(y)); - return gfx::Point(); -} - -ui::KeyboardCode KeyboardCodeFromNative(GdkEvent* gdk_event) { - DCHECK(gdk_event->type == GDK_KEY_PRESS || - gdk_event->type == GDK_KEY_RELEASE); - return ui::KeyboardCodeFromGdkEventKey(&gdk_event->key); -} - -int GetMouseWheelOffset(GdkEvent* gdk_event) { - DCHECK(gdk_event->type == GDK_SCROLL); - int offset = (gdk_event->scroll.direction == GDK_SCROLL_UP || - gdk_event->scroll.direction == GDK_SCROLL_LEFT) ? 1 : -1; - return offset; -} - -} // namespace - -namespace views { - -//////////////////////////////////////////////////////////////////////////////// -// Event, protected: - -Event::Event(GdkEvent* gdk_event, ui::EventType type, int flags) - : native_event_(NULL), - gdk_event_(gdk_event), - type_(type), - time_stamp_(base::Time::NowFromSystemTime()), - flags_(flags) { -} - -//////////////////////////////////////////////////////////////////////////////// -// LocatedEvent, protected: - -LocatedEvent::LocatedEvent(GdkEvent* gdk_event) - : Event(gdk_event, - EventTypeFromNative(gdk_event), - EventFlagsFromNative(gdk_event)), - location_(EventLocationFromNative(gdk_event)) { -} - -//////////////////////////////////////////////////////////////////////////////// -// KeyEvent, public: - -KeyEvent::KeyEvent(GdkEvent* gdk_event) - : Event(gdk_event, - EventTypeFromNative(gdk_event), - EventFlagsFromNative(gdk_event)), - key_code_(KeyboardCodeFromNative(gdk_event)), - character_(0), - unmodified_character_(0) { -} - -//////////////////////////////////////////////////////////////////////////////// -// MouseEvent, public: - -MouseEvent::MouseEvent(GdkEvent* gdk_event) - : LocatedEvent(gdk_event) { -} - -//////////////////////////////////////////////////////////////////////////////// -// MouseWheelEvent, public: - -MouseWheelEvent::MouseWheelEvent(GdkEvent* gdk_event) - : MouseEvent(gdk_event), - offset_(kWheelDelta * GetMouseWheelOffset(gdk_event)) { -} - -} // namespace views diff --git a/views/events/event_unittest.cc b/views/events/event_unittest.cc deleted file mode 100644 index 211877d..0000000 --- a/views/events/event_unittest.cc +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h" - -#include "base/basictypes.h" -#include "views/events/event.h" - -// Bug 99129. -#if defined(USE_AURA) -#define MAYBE_KeyEvent FAILS_KeyEvent -#define MAYBE_KeyEventDirectUnicode FAILS_KeyEventDirectUnicode -#else -#define MAYBE_KeyEvent KeyEvent -#define MAYBE_KeyEventDirectUnicode KeyEventDirectUnicode -#endif - -namespace views { - -class EventTest : public testing::Test { - public: - EventTest() { - } - - private: - DISALLOW_COPY_AND_ASSIGN(EventTest); -}; - -TEST_F(EventTest, MAYBE_KeyEvent) { - static const struct { - ui::KeyboardCode key_code; - int flags; - uint16 character; - uint16 unmodified_character; - } kTestData[] = { - { ui::VKEY_A, 0, 'a', 'a' }, - { ui::VKEY_A, ui::EF_SHIFT_DOWN, 'A', 'A' }, - { ui::VKEY_A, ui::EF_CAPS_LOCK_DOWN, 'A', 'a' }, - { ui::VKEY_A, ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN, 'a', 'A' }, - { ui::VKEY_A, ui::EF_CONTROL_DOWN, 0x01, 'a' }, - { ui::VKEY_A, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, '\x01', 'A' }, - { ui::VKEY_Z, 0, 'z', 'z' }, - { ui::VKEY_Z, ui::EF_SHIFT_DOWN, 'Z', 'Z' }, - { ui::VKEY_Z, ui::EF_CAPS_LOCK_DOWN, 'Z', 'z' }, - { ui::VKEY_Z, ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN, 'z', 'Z' }, - { ui::VKEY_Z, ui::EF_CONTROL_DOWN, '\x1A', 'z' }, - { ui::VKEY_Z, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, '\x1A', 'Z' }, - - { ui::VKEY_2, ui::EF_CONTROL_DOWN, '\0', '2' }, - { ui::VKEY_2, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, '\0', '@' }, - { ui::VKEY_6, ui::EF_CONTROL_DOWN, '\0', '6' }, - { ui::VKEY_6, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, '\x1E', '^' }, - { ui::VKEY_OEM_MINUS, ui::EF_CONTROL_DOWN, '\0', '-' }, - { ui::VKEY_OEM_MINUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, '\x1F', '_'}, - { ui::VKEY_OEM_4, ui::EF_CONTROL_DOWN, '\x1B', '[' }, - { ui::VKEY_OEM_4, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, '\0', '{' }, - { ui::VKEY_OEM_5, ui::EF_CONTROL_DOWN, '\x1C', '\\' }, - { ui::VKEY_OEM_5, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, '\0', '|' }, - { ui::VKEY_OEM_6, ui::EF_CONTROL_DOWN, '\x1D', ']' }, - { ui::VKEY_OEM_6, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, '\0', '}' }, - { ui::VKEY_RETURN, ui::EF_CONTROL_DOWN, '\x0A', '\r' }, - - { ui::VKEY_0, 0, '0', '0' }, - { ui::VKEY_0, ui::EF_SHIFT_DOWN, ')', ')' }, - { ui::VKEY_0, ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN, ')', ')' }, - { ui::VKEY_0, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, '\0', ')' }, - - { ui::VKEY_9, 0, '9', '9' }, - { ui::VKEY_9, ui::EF_SHIFT_DOWN, '(', '(' }, - { ui::VKEY_9, ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN, '(', '(' }, - { ui::VKEY_9, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, '\0', '(' }, - - { ui::VKEY_NUMPAD0, ui::EF_CONTROL_DOWN, '\0', '0' }, - { ui::VKEY_NUMPAD0, ui::EF_SHIFT_DOWN, '0', '0' }, - - { ui::VKEY_NUMPAD9, ui::EF_CONTROL_DOWN, '\0', '9' }, - { ui::VKEY_NUMPAD9, ui::EF_SHIFT_DOWN, '9', '9' }, - - { ui::VKEY_TAB, ui::EF_CONTROL_DOWN, '\0', '\t' }, - { ui::VKEY_TAB, ui::EF_SHIFT_DOWN, '\t', '\t' }, - - { ui::VKEY_MULTIPLY, ui::EF_CONTROL_DOWN, '\0', '*' }, - { ui::VKEY_MULTIPLY, ui::EF_SHIFT_DOWN, '*', '*' }, - { ui::VKEY_ADD, ui::EF_CONTROL_DOWN, '\0', '+' }, - { ui::VKEY_ADD, ui::EF_SHIFT_DOWN, '+', '+' }, - { ui::VKEY_SUBTRACT, ui::EF_CONTROL_DOWN, '\0', '-' }, - { ui::VKEY_SUBTRACT, ui::EF_SHIFT_DOWN, '-', '-' }, - { ui::VKEY_DECIMAL, ui::EF_CONTROL_DOWN, '\0', '.' }, - { ui::VKEY_DECIMAL, ui::EF_SHIFT_DOWN, '.', '.' }, - { ui::VKEY_DIVIDE, ui::EF_CONTROL_DOWN, '\0', '/' }, - { ui::VKEY_DIVIDE, ui::EF_SHIFT_DOWN, '/', '/' }, - - { ui::VKEY_OEM_1, ui::EF_CONTROL_DOWN, '\0', ';' }, - { ui::VKEY_OEM_1, ui::EF_SHIFT_DOWN, ':', ':' }, - { ui::VKEY_OEM_PLUS, ui::EF_CONTROL_DOWN, '\0', '=' }, - { ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN, '+', '+' }, - { ui::VKEY_OEM_COMMA, ui::EF_CONTROL_DOWN, '\0', ',' }, - { ui::VKEY_OEM_COMMA, ui::EF_SHIFT_DOWN, '<', '<' }, - { ui::VKEY_OEM_PERIOD, ui::EF_CONTROL_DOWN, '\0', '.' }, - { ui::VKEY_OEM_PERIOD, ui::EF_SHIFT_DOWN, '>', '>' }, - { ui::VKEY_OEM_3, ui::EF_CONTROL_DOWN, '\0', '`' }, - { ui::VKEY_OEM_3, ui::EF_SHIFT_DOWN, '~', '~' }, - }; - - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestData); ++i) { - KeyEvent key(ui::ET_KEY_PRESSED, kTestData[i].key_code, kTestData[i].flags); - EXPECT_EQ(kTestData[i].character, key.GetCharacter()) - << " Index:" << i << " key_code:" << kTestData[i].key_code; - EXPECT_EQ(kTestData[i].unmodified_character, key.GetUnmodifiedCharacter()) - << " Index:" << i << " key_code:" << kTestData[i].key_code; - } -} - -TEST_F(EventTest, MAYBE_KeyEventDirectUnicode) { - KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, ui::EF_SHIFT_DOWN); - key.set_character(0x1234U); - key.set_unmodified_character(0x4321U); - EXPECT_EQ(0x1234U, key.GetCharacter()); - EXPECT_EQ(0x4321U, key.GetUnmodifiedCharacter()); - KeyEvent key2(ui::ET_KEY_RELEASED, ui::VKEY_UNKNOWN, ui::EF_CONTROL_DOWN); - key2.set_character(0x4321U); - key2.set_unmodified_character(0x1234U); - EXPECT_EQ(0x4321U, key2.GetCharacter()); - EXPECT_EQ(0x1234U, key2.GetUnmodifiedCharacter()); -} - -} // namespace views diff --git a/views/events/event_wayland.cc b/views/events/event_wayland.cc deleted file mode 100644 index 44998e6..0000000 --- a/views/events/event_wayland.cc +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2011 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 "views/events/event.h" - -#include "base/logging.h" -#include "ui/base/keycodes/keyboard_code_conversion.h" - -namespace views { - -////////////////////////////////////////////////////////////////////////////// -// KeyEvent, public: - -uint16 KeyEvent::GetCharacter() const { - return ui::GetCharacterFromKeyCode(key_code_, flags()); -} - -uint16 KeyEvent::GetUnmodifiedCharacter() const { - return ui::GetCharacterFromKeyCode(key_code_, flags() & ui::EF_SHIFT_DOWN); -} - -} // namespace views diff --git a/views/events/event_win.cc b/views/events/event_win.cc deleted file mode 100644 index 03b855e..0000000 --- a/views/events/event_win.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2011 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 "views/events/event.h" - -#include "base/logging.h" -#include "ui/base/keycodes/keyboard_code_conversion.h" - -namespace views { - -//////////////////////////////////////////////////////////////////////////////// -// KeyEvent, public: - -uint16 KeyEvent::GetCharacter() const { - if (character_) - return character_; - return (native_event().message == WM_CHAR) ? key_code_ : - ui::GetCharacterFromKeyCode(key_code_, flags()); -} - -uint16 KeyEvent::GetUnmodifiedCharacter() const { - if (unmodified_character_) - return unmodified_character_; - // Looks like there is no way to get unmodified character on Windows. - return (native_event().message == WM_CHAR) ? key_code_ : - ui::GetCharacterFromKeyCode(key_code_, flags() & ui::EF_SHIFT_DOWN); -} - -} // namespace views diff --git a/views/events/event_x.cc b/views/events/event_x.cc deleted file mode 100644 index 1c9e330..0000000 --- a/views/events/event_x.cc +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2011 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 "views/events/event.h" - -#include <gdk/gdk.h> -#include <gdk/gdkx.h> -#include <X11/extensions/XInput2.h> -#include <X11/Xlib.h> - -#include "base/logging.h" -#include "base/utf_string_conversions.h" -#include "ui/base/events.h" -#include "ui/base/keycodes/keyboard_code_conversion.h" -#include "ui/base/keycodes/keyboard_code_conversion_x.h" -#include "ui/base/touch/touch_factory.h" -#include "views/widget/root_view.h" - -namespace views { - -namespace { - -// The following two functions are copied from event_gtk.cc. These will be -// removed when GTK dependency is removed. -#if defined(TOOLKIT_USES_GTK) -uint16 GetCharacterFromGdkKeyval(guint keyval) { - guint32 ch = gdk_keyval_to_unicode(keyval); - - // We only support BMP characters. - return ch < 0xFFFE ? static_cast<uint16>(ch) : 0; -} - -GdkEventKey* GetGdkEventKeyFromNative(GdkEvent* gdk_event) { - DCHECK(gdk_event->type == GDK_KEY_PRESS || - gdk_event->type == GDK_KEY_RELEASE); - return &gdk_event->key; -} -#endif - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// KeyEvent, public: - -uint16 KeyEvent::GetCharacter() const { - if (character_) - return character_; - - if (!native_event()) { -#if defined(TOOLKIT_USES_GTK) - // This event may have been created from a Gdk event. - if (!IsControlDown() && gdk_event()) { - uint16 ch = GetCharacterFromGdkKeyval( - GetGdkEventKeyFromNative(gdk_event())->keyval); - if (ch) - return ch; - } -#endif - return ui::GetCharacterFromKeyCode(key_code_, flags()); - } - - DCHECK(native_event()->type == KeyPress || - native_event()->type == KeyRelease); - - uint16 ch = ui::DefaultSymbolFromXEvent(native_event()); - return ch ? ch : ui::GetCharacterFromKeyCode(key_code_, flags()); -} - -uint16 KeyEvent::GetUnmodifiedCharacter() const { - if (unmodified_character_) - return unmodified_character_; - - if (!native_event()) { -#if defined(TOOLKIT_USES_GTK) - // This event may have been created from a Gdk event. - if (gdk_event()) { - GdkEventKey* key = GetGdkEventKeyFromNative(gdk_event()); - - static const guint kIgnoredModifiers = - GDK_CONTROL_MASK | GDK_LOCK_MASK | GDK_MOD1_MASK | GDK_MOD2_MASK | - GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK | GDK_SUPER_MASK | - GDK_HYPER_MASK | GDK_META_MASK; - - // We can't use things like (key->state & GDK_SHIFT_MASK), as it may mask - // out bits used by X11 or Gtk internally. - GdkModifierType modifiers = - static_cast<GdkModifierType>(key->state & ~kIgnoredModifiers); - guint keyval = 0; - if (gdk_keymap_translate_keyboard_state(NULL, key->hardware_keycode, - modifiers, key->group, &keyval, NULL, NULL, NULL)) { - uint16 ch = GetCharacterFromGdkKeyval(keyval); - if (ch) - return ch; - } - } -#endif - return ui::GetCharacterFromKeyCode(key_code_, flags() & ui::EF_SHIFT_DOWN); - } - - DCHECK(native_event()->type == KeyPress || - native_event()->type == KeyRelease); - - XKeyEvent *key = &native_event()->xkey; - - static const unsigned int kIgnoredModifiers = ControlMask | LockMask | - Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask; - - // We can't use things like (key.state & ShiftMask), as it may mask out bits - // used by X11 internally. - key->state &= ~kIgnoredModifiers; - uint16 ch = ui::DefaultSymbolFromXEvent(native_event()); - return ch ? ch : - ui::GetCharacterFromKeyCode(key_code_, flags() & ui::EF_SHIFT_DOWN); -} - -//////////////////////////////////////////////////////////////////////////////// -// TouchEvent, public: - -TouchEvent::TouchEvent(const base::NativeEvent& native_event) - : LocatedEvent(native_event), - touch_id_(ui::GetTouchId(native_event)), - radius_x_(ui::GetTouchRadiusX(native_event)), - radius_y_(ui::GetTouchRadiusY(native_event)), - rotation_angle_(ui::GetTouchAngle(native_event)), - force_(ui::GetTouchForce(native_event)) { -#if defined(USE_XI2_MT) - if (type() == ui::ET_TOUCH_RELEASED) { - // NOTE: The slot is allocated by TouchFactory for each XI_TouchBegin - // event, which carries a new tracking ID to identify a new touch - // sequence. - ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); - float tracking_id; - if (factory->ExtractTouchParam(*native_event, - ui::TouchFactory::TP_TRACKING_ID, - &tracking_id)) { - factory->ReleaseSlotForTrackingID(tracking_id); - } - } -#else - if (type() == ui::ET_TOUCH_PRESSED || type() == ui::ET_TOUCH_RELEASED) { - ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); - float slot; - if (factory->ExtractTouchParam(*native_event, - ui::TouchFactory::TP_SLOT_ID, &slot)) { - factory->SetSlotUsed(slot, type() == ui::ET_TOUCH_PRESSED); - } - } -#endif -} - -} // namespace views diff --git a/views/focus/accelerator_handler.h b/views/focus/accelerator_handler.h index e0036e0..5eef62a 100644 --- a/views/focus/accelerator_handler.h +++ b/views/focus/accelerator_handler.h @@ -6,56 +6,7 @@ #define VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ #pragma once -#include "build/build_config.h" - -#if defined(TOOLKIT_USES_GTK) -#include <gdk/gdk.h> -#endif - -#include <set> -#include <vector> - -#include "base/message_loop.h" -#include "views/views_export.h" - -namespace views { - -#if defined(TOUCH_UI) || defined(USE_AURA) -#if defined(USE_X11) && !defined(USE_WAYLAND) -// Dispatch an XEvent to the RootView. Return true if the event was dispatched -// and handled, false otherwise. -bool VIEWS_EXPORT DispatchXEvent(XEvent* xevent); -#endif // USE_X11 && !USE_WAYLAND -#endif // TOUCH_UI || USE_AURA - -// This class delegates the key messages to the associated FocusManager class -// for the window that is receiving these messages for accelerator processing. -class VIEWS_EXPORT AcceleratorHandler : public MessageLoop::Dispatcher { - public: - AcceleratorHandler(); - - // Dispatcher method. This returns true if an accelerator was processed by the - // focus manager -#if defined(OS_WIN) - virtual bool Dispatch(const MSG& msg); -#elif defined(USE_WAYLAND) - virtual base::MessagePumpDispatcher::DispatchStatus Dispatch( - base::wayland::WaylandEvent* ev); -#elif defined(TOUCH_UI) || defined(USE_AURA) - virtual base::MessagePumpDispatcher::DispatchStatus Dispatch(XEvent* xev); -#else - virtual bool Dispatch(GdkEvent* event); -#endif - - private: -#if defined(OS_WIN) - // The keys currently pressed and consumed by the FocusManager. - std::set<WPARAM> pressed_keys_; -#endif - - DISALLOW_COPY_AND_ASSIGN(AcceleratorHandler); -}; - -} // namespace views +#include "ui/views/focus/accelerator_handler.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ diff --git a/views/focus/accelerator_handler_aura.cc b/views/focus/accelerator_handler_aura.cc deleted file mode 100644 index ab552899..0000000 --- a/views/focus/accelerator_handler_aura.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2011 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 "views/focus/accelerator_handler.h" - -namespace views { - -AcceleratorHandler::AcceleratorHandler() { -} - -#if defined(OS_WIN) -bool AcceleratorHandler::Dispatch(const MSG& msg) { - TranslateMessage(&msg); - DispatchMessage(&msg); - return true; -} -#else -base::MessagePumpDispatcher::DispatchStatus AcceleratorHandler::Dispatch( - XEvent*) { - return base::MessagePumpDispatcher::EVENT_IGNORED; -} - -bool DispatchXEvent(XEvent* xev) { - return false; -} -#endif // defined(OS_WIN) - -} // namespace views diff --git a/views/focus/accelerator_handler_gtk.cc b/views/focus/accelerator_handler_gtk.cc deleted file mode 100644 index fab3b86..0000000 --- a/views/focus/accelerator_handler_gtk.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2011 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 "views/focus/accelerator_handler.h" - -#include <gtk/gtk.h> - -#include "views/focus/focus_manager.h" - -namespace views { - -AcceleratorHandler::AcceleratorHandler() {} - -bool AcceleratorHandler::Dispatch(GdkEvent* event) { - // The logic for handling keyboard accelerators has been moved into - // NativeWidgetGtk::OnEventKey handler (views/widget/widget_gtk.cc). - gtk_main_do_event(event); - return true; -} - -} // namespace views diff --git a/views/focus/accelerator_handler_gtk_unittest.cc b/views/focus/accelerator_handler_gtk_unittest.cc deleted file mode 100644 index 098325d..0000000 --- a/views/focus/accelerator_handler_gtk_unittest.cc +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2011 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 <gdk/gdkkeysyms.h> - -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/rect.h" -#include "ui/base/models/accelerator.h" -#include "views/focus/accelerator_handler.h" -#include "views/focus/focus_manager.h" -#include "views/view.h" -#include "views/widget/widget.h" -#include "views/widget/widget_delegate.h" - -namespace views { - -class AcceleratorHandlerGtkTest - : public testing::Test, - public WidgetDelegate, - public ui::AcceleratorTarget { - public: - AcceleratorHandlerGtkTest() - : kMenuAccelerator(ui::VKEY_MENU, false, false, false), - kHomepageAccelerator(ui::VKEY_HOME, false, false, true), - content_view_(NULL) { - } - - virtual void SetUp() { - window_ = Widget::CreateWindowWithBounds(this, gfx::Rect(0, 0, 500, 500)); - window_->Show(); - FocusManager* focus_manager = window_->GetFocusManager(); - focus_manager->RegisterAccelerator(kMenuAccelerator, this); - focus_manager->RegisterAccelerator(kHomepageAccelerator, this); - menu_pressed_ = false; - home_pressed_ = false; - } - - virtual void TearDown() { - window_->Close(); - - // Flush the message loop to make application verifiers happy. - message_loop_.RunAllPending(); - } - - GdkEventKey CreateKeyEvent(GdkEventType type, guint keyval, guint state) { - GdkEventKey evt; - memset(&evt, 0, sizeof(evt)); - evt.type = type; - evt.keyval = keyval; - // The keyval won't be a "correct" hardware keycode for any real hardware, - // but the code should never depend on exact hardware keycodes, just the - // fact that the code for presses and releases of the same key match. - evt.hardware_keycode = keyval; - evt.state = state; - GtkWidget* widget = GTK_WIDGET(window_->GetNativeWindow()); - evt.window = widget->window; - return evt; - } - - // AcceleratorTarget implementation. - virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) { - if (accelerator == kMenuAccelerator) - menu_pressed_ = true; - else if (accelerator == kHomepageAccelerator) - home_pressed_ = true; - return true; - } - - // WidgetDelegate Implementation. - virtual View* GetContentsView() { - if (!content_view_) - content_view_ = new View(); - return content_view_; - } - virtual const views::Widget* GetWidget() const { - return content_view_->GetWidget(); - } - virtual views::Widget* GetWidget() { - return content_view_->GetWidget(); - } - - virtual void InitContentView() { - } - - protected: - bool menu_pressed_; - bool home_pressed_; - - private: - ui::Accelerator kMenuAccelerator; - ui::Accelerator kHomepageAccelerator; - Widget* window_; - View* content_view_; - MessageLoopForUI message_loop_; - DISALLOW_COPY_AND_ASSIGN(AcceleratorHandlerGtkTest); -}; - -// Test that the homepage accelerator (Alt+Home) is activated on key down -// and that the menu accelerator (Alt) is never activated. -TEST_F(AcceleratorHandlerGtkTest, TestHomepageAccelerator) { - AcceleratorHandler handler; - GdkEventKey evt; - - ASSERT_FALSE(menu_pressed_); - ASSERT_FALSE(home_pressed_); - - evt = CreateKeyEvent(GDK_KEY_PRESS, GDK_Alt_L, 0); - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - - ASSERT_FALSE(menu_pressed_); - ASSERT_FALSE(home_pressed_); - - evt = CreateKeyEvent(GDK_KEY_PRESS, GDK_Home, GDK_MOD1_MASK); - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - - ASSERT_FALSE(menu_pressed_); - ASSERT_TRUE(home_pressed_); - - evt = CreateKeyEvent(GDK_KEY_RELEASE, GDK_Home, GDK_MOD1_MASK); - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - evt = CreateKeyEvent(GDK_KEY_RELEASE, GDK_Alt_L, 0); - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - - ASSERT_FALSE(menu_pressed_); - ASSERT_TRUE(home_pressed_); -} - -// Test that the menu accelerator is activated on key up and not key down. -TEST_F(AcceleratorHandlerGtkTest, TestMenuAccelerator) { - AcceleratorHandler handler; - GdkEventKey evt; - - ASSERT_FALSE(menu_pressed_); - - evt = CreateKeyEvent(GDK_KEY_PRESS, GDK_Alt_L, 0); - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - - ASSERT_FALSE(menu_pressed_); - - evt = CreateKeyEvent(GDK_KEY_RELEASE, GDK_Alt_L, 0); - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - - ASSERT_TRUE(menu_pressed_); -} - -// Test that the menu accelerator isn't confused by the interaction of the -// Alt and Shift keys. Try the following sequence on Linux: -// Press Alt -// Press Shift -// Release Alt -// Release Shift -// The key codes for pressing Alt and releasing Alt are different! This -// caused a bug in a previous version of the code, which is now fixed by -// keeping track of hardware keycodes, which are consistent. -TEST_F(AcceleratorHandlerGtkTest, TestAltShiftInteraction) { - AcceleratorHandler handler; - GdkEventKey evt; - - ASSERT_FALSE(menu_pressed_); - - // Press Shift. - evt = CreateKeyEvent(GDK_KEY_PRESS, GDK_Shift_L, 0); - evt.hardware_keycode = 0x32; - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - // Press Alt - but GDK calls this Meta when Shift is also down. - evt = CreateKeyEvent(GDK_KEY_PRESS, GDK_Meta_L, 0); - evt.hardware_keycode = 0x40; - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - - // Release Shift. - evt = CreateKeyEvent(GDK_KEY_RELEASE, GDK_Shift_L, 0); - evt.hardware_keycode = 0x32; - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - // Release Alt - with Shift not down, the keyval is now Alt, but - // the hardware keycode is unchanged. - evt = CreateKeyEvent(GDK_KEY_RELEASE, GDK_Alt_L, 0); - evt.hardware_keycode = 0x40; - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - - ASSERT_FALSE(menu_pressed_); - - // Press Alt by itself. - evt = CreateKeyEvent(GDK_KEY_PRESS, GDK_Alt_L, 0); - evt.hardware_keycode = 0x40; - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - - // This line fails if we don't keep track of hardware keycodes. - ASSERT_FALSE(menu_pressed_); - - // Release Alt - now this should trigger the menu shortcut. - evt = CreateKeyEvent(GDK_KEY_RELEASE, GDK_Alt_L, 0); - evt.hardware_keycode = 0x40; - EXPECT_TRUE(handler.Dispatch(reinterpret_cast<GdkEvent*>(&evt))); - - ASSERT_TRUE(menu_pressed_); -} - -} // namespace views diff --git a/views/focus/accelerator_handler_touch.cc b/views/focus/accelerator_handler_touch.cc deleted file mode 100644 index 1c4c9b3..0000000 --- a/views/focus/accelerator_handler_touch.cc +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2011 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 "views/focus/accelerator_handler.h" - -#include <bitset> -#include <gtk/gtk.h> -#include <X11/extensions/XInput2.h> - -#include "ui/base/touch/touch_factory.h" -#include "ui/views/ime/input_method.h" -#include "views/events/event.h" -#include "views/focus/focus_manager.h" -#include "views/view.h" -#include "views/widget/native_widget.h" - -namespace views { - -namespace { - -Widget* FindWidgetForGdkWindow(GdkWindow* gdk_window) { - gpointer data = NULL; - gdk_window_get_user_data(gdk_window, &data); - GtkWidget* gtk_widget = reinterpret_cast<GtkWidget*>(data); - if (!gtk_widget || !GTK_IS_WIDGET(gtk_widget)) { - DLOG(WARNING) << "no GtkWidget found for that GdkWindow"; - return NULL; - } - Widget* widget = Widget::GetWidgetForNativeView(gtk_widget); - - if (!widget) { - DLOG(WARNING) << "no NativeWidgetGtk found for that GtkWidget"; - return NULL; - } - return widget; -} - -} // namespace - -bool DispatchX2Event(Widget* widget, XEvent* xev) { - XGenericEventCookie* cookie = &xev->xcookie; - switch (cookie->evtype) { - case XI_KeyPress: - case XI_KeyRelease: { - // TODO(sad): We don't capture XInput2 events from keyboard yet. - break; - } -#if defined(USE_XI2_MT) - case XI_TouchBegin: - case XI_TouchEnd: - case XI_TouchUpdate: { - // Hide the cursor when a touch event comes in. - ui::TouchFactory::GetInstance()->SetCursorVisible(false, false); - - // If the TouchEvent is processed by |widget|, then return. - TouchEvent touch(xev); - if (widget->OnTouchEvent(touch) != ui::TOUCH_STATUS_UNKNOWN) - return true; - - // We do not want to generate a mouse event for an unprocessed touch - // event here. That is already done by the gesture manager in - // RootView::OnTouchEvent. - return false; - } -#endif - case XI_ButtonPress: - case XI_ButtonRelease: - case XI_Motion: { - XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(cookie->data); - - // Scrolling the wheel generates press/release events with button id's 4 - // and 5. In case of a wheelscroll, we do not want to show the cursor. - if (xievent->detail == 4 || xievent->detail == 5) { - MouseWheelEvent wheelev(xev); - return widget->OnMouseEvent(wheelev); - } - - ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); - // Is the event coming from a touch device? - if (factory->IsTouchDevice(xievent->sourceid)) { - // Hide the cursor when a touch event comes in. - factory->SetCursorVisible(false, false); - - // With XInput 2.0, XI_ButtonPress and XI_ButtonRelease events are - // ignored, as XI_Motion events contain enough data to detect finger - // press and release. See more notes in TouchFactory::TouchParam. - if ((cookie->evtype == XI_ButtonPress || - cookie->evtype == XI_ButtonRelease) && - factory->IsRealTouchDevice(xievent->sourceid)) - return false; - - // If the TouchEvent is processed by |widget|, then return. Otherwise - // let it fall through so it can be used as a MouseEvent, if desired. - TouchEvent touch(xev); - if (widget->OnTouchEvent(touch) != ui::TOUCH_STATUS_UNKNOWN) - return true; - - // We do not want to generate a mouse event for an unprocessed touch - // event here. That is already done by the gesture manager in - // RootView::OnTouchEvent. - return false; - } else { - MouseEvent mouseev(xev); - - // Show the cursor. Start a timer to hide the cursor after a delay on - // move (not drag) events, or if the only button pressed is released. - bool start_timer = mouseev.type() == ui::ET_MOUSE_MOVED; - start_timer |= mouseev.type() == ui::ET_MOUSE_RELEASED && - (mouseev.IsOnlyLeftMouseButton() || - mouseev.IsOnlyMiddleMouseButton() || - mouseev.IsOnlyRightMouseButton()); - factory->SetCursorVisible(true, start_timer); - - return widget->OnMouseEvent(mouseev); - } - } - } - return false; -} - -bool DispatchXEvent(XEvent* xev) { - GdkDisplay* gdisp = gdk_display_get_default(); - XID xwindow = xev->xany.window; - - if (xev->type == GenericEvent) { - if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(xev)) - return true; // Consume the event. - - XGenericEventCookie* cookie = &xev->xcookie; - if (cookie->evtype == XI_HierarchyChanged) { - ui::TouchFactory::GetInstance()->UpdateDeviceList(cookie->display); - return true; - } - - XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data); - xwindow = xiev->event; - } - - GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow); - Widget* widget = FindWidgetForGdkWindow(gwind); - if (widget) { - switch (xev->type) { - case KeyPress: - case KeyRelease: { - KeyEvent keyev(xev); - InputMethod* ime = widget->GetInputMethod(); - // Always dispatch key events to the input method first, to make sure - // that the input method's hotkeys work all time. - if (ime) { - ime->DispatchKeyEvent(keyev); - return true; - } - return widget->OnKeyEvent(keyev); - } - case ButtonPress: - case ButtonRelease: - if (xev->xbutton.button == 4 || xev->xbutton.button == 5) { - // Scrolling the wheel triggers button press/release events. - MouseWheelEvent wheelev(xev); - return widget->OnMouseEvent(wheelev); - } - // fallthrough - case MotionNotify: { - MouseEvent mouseev(xev); - return widget->OnMouseEvent(mouseev); - } - - case GenericEvent: { - return DispatchX2Event(widget, xev); - } - } - } - - return false; -} - -AcceleratorHandler::AcceleratorHandler() {} - -base::MessagePumpDispatcher::DispatchStatus - AcceleratorHandler::Dispatch(XEvent* xev) { - return DispatchXEvent(xev) ? - base::MessagePumpDispatcher::EVENT_PROCESSED : - base::MessagePumpDispatcher::EVENT_IGNORED; -} - -} // namespace views diff --git a/views/focus/accelerator_handler_wayland.cc b/views/focus/accelerator_handler_wayland.cc deleted file mode 100644 index a8963ee..0000000 --- a/views/focus/accelerator_handler_wayland.cc +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2011 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 "views/focus/accelerator_handler.h" - -#include "views/focus/focus_manager.h" - -namespace views { - -AcceleratorHandler::AcceleratorHandler() {} - -base::MessagePumpDispatcher::DispatchStatus - AcceleratorHandler::Dispatch(base::wayland::WaylandEvent* ev) { - return base::MessagePumpDispatcher::EVENT_IGNORED; -} - -} // namespace views diff --git a/views/focus/accelerator_handler_win.cc b/views/focus/accelerator_handler_win.cc deleted file mode 100644 index 8f2c8e8..0000000 --- a/views/focus/accelerator_handler_win.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2011 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 "views/focus/accelerator_handler.h" - -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/keycodes/keyboard_code_conversion_win.h" -#include "views/events/event.h" -#include "views/focus/focus_manager.h" -#include "views/widget/widget.h" - -namespace views { - -AcceleratorHandler::AcceleratorHandler() { -} - -bool AcceleratorHandler::Dispatch(const MSG& msg) { - bool process_message = true; - - if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) { - Widget* widget = Widget::GetTopLevelWidgetForNativeView(msg.hwnd); - FocusManager* focus_manager = widget ? widget->GetFocusManager() : NULL; - if (focus_manager) { - switch (msg.message) { - case WM_KEYDOWN: - case WM_SYSKEYDOWN: { - KeyEvent event(msg); - process_message = focus_manager->OnKeyEvent(event); - if (!process_message) { - // Record that this key is pressed so we can remember not to - // translate and dispatch the associated WM_KEYUP. - pressed_keys_.insert(msg.wParam); - } - break; - } - case WM_KEYUP: - case WM_SYSKEYUP: { - std::set<WPARAM>::iterator iter = pressed_keys_.find(msg.wParam); - if (iter != pressed_keys_.end()) { - // Don't translate/dispatch the KEYUP since we have eaten the - // associated KEYDOWN. - pressed_keys_.erase(iter); - return true; - } - break; - } - } - } - } - - if (process_message) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - return true; -} - -} // namespace views diff --git a/views/focus/external_focus_tracker.cc b/views/focus/external_focus_tracker.cc deleted file mode 100644 index 193b57e..0000000 --- a/views/focus/external_focus_tracker.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2011 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 "views/focus/external_focus_tracker.h" - -#include "base/logging.h" -#include "views/view.h" -#include "views/focus/view_storage.h" - -namespace views { - -ExternalFocusTracker::ExternalFocusTracker(View* parent_view, - FocusManager* focus_manager) - : focus_manager_(focus_manager), - parent_view_(parent_view) { - DCHECK(focus_manager); - DCHECK(parent_view); - view_storage_ = ViewStorage::GetInstance(); - last_focused_view_storage_id_ = view_storage_->CreateStorageID(); - // Store the view which is focused when we're created. - StartTracking(); -} - -ExternalFocusTracker::~ExternalFocusTracker() { - view_storage_->RemoveView(last_focused_view_storage_id_); - if (focus_manager_) - focus_manager_->RemoveFocusChangeListener(this); -} - -void ExternalFocusTracker::OnWillChangeFocus(View* focused_before, - View* focused_now) { - if (focused_now && !parent_view_->Contains(focused_now) && - parent_view_ != focused_now) { - // Store the newly focused view. - StoreLastFocusedView(focused_now); - } -} - -void ExternalFocusTracker::OnDidChangeFocus(View* focused_before, - View* focused_now) { -} - -void ExternalFocusTracker::FocusLastFocusedExternalView() { - View* last_focused_view = - view_storage_->RetrieveView(last_focused_view_storage_id_); - if (last_focused_view) - last_focused_view->RequestFocus(); -} - -void ExternalFocusTracker::SetFocusManager(FocusManager* focus_manager) { - if (focus_manager_) - focus_manager_->RemoveFocusChangeListener(this); - focus_manager_ = focus_manager; - if (focus_manager_) - StartTracking(); -} - -void ExternalFocusTracker::StoreLastFocusedView(View* view) { - view_storage_->RemoveView(last_focused_view_storage_id_); - // If the view is NULL, remove the last focused view from storage, but don't - // try to store NULL. - if (view != NULL) - view_storage_->StoreView(last_focused_view_storage_id_, view); -} - -void ExternalFocusTracker::StartTracking() { - StoreLastFocusedView(focus_manager_->GetFocusedView()); - focus_manager_->AddFocusChangeListener(this); -} - -} // namespace views diff --git a/views/focus/external_focus_tracker.h b/views/focus/external_focus_tracker.h index 62f553b..b350c9c 100644 --- a/views/focus/external_focus_tracker.h +++ b/views/focus/external_focus_tracker.h @@ -6,73 +6,7 @@ #define VIEWS_FOCUS_EXTERNAL_FOCUS_TRACKER_H_ #pragma once -#include "views/focus/focus_manager.h" - -namespace views { - -class View; -class ViewStorage; - -// ExternalFocusTracker tracks the last focused view which belongs to the -// provided focus manager and is not either the provided parent view or one of -// its descendants. This is generally used if the parent view want to return -// focus to some other view once it is dismissed. The parent view and the focus -// manager must exist for the duration of the tracking. If the focus manager -// must be deleted before this object is deleted, make sure to call -// SetFocusManager(NULL) first. -// -// Typical use: When a view is added to the view hierarchy, it instantiates an -// ExternalFocusTracker and passes in itself and its focus manager. Then, -// when that view wants to return focus to the last focused view which is not -// itself and not a descandant of itself, (usually when it is being closed) -// it calls FocusLastFocusedExternalView. -class VIEWS_EXPORT ExternalFocusTracker : public FocusChangeListener { - public: - ExternalFocusTracker(View* parent_view, FocusManager* focus_manager); - - virtual ~ExternalFocusTracker(); - // FocusChangeListener implementation. - virtual void OnWillChangeFocus(View* focused_before, View* focused_now); - virtual void OnDidChangeFocus(View* focused_before, View* focused_now); - - // Focuses last focused view which is not a child of parent view and is not - // parent view itself. Returns true if focus for a view was requested, false - // otherwise. - void FocusLastFocusedExternalView(); - - // Sets the focus manager whose focus we are tracking. |focus_manager| can - // be NULL, but no focus changes will be tracked. This is useful if the focus - // manager went away, but you might later want to start tracking with a new - // manager later, or call FocusLastFocusedExternalView to focus the previous - // view. - void SetFocusManager(FocusManager* focus_manager); - - private: - // Store the provided view. This view will be focused when - // FocusLastFocusedExternalView is called. - void StoreLastFocusedView(View* view); - - // Store the currently focused view for our view manager and register as a - // listener for future focus changes. - void StartTracking(); - - // Focus manager which we are a listener for. - FocusManager* focus_manager_; - - // ID of the last focused view, which we store in view_storage_. - int last_focused_view_storage_id_; - - // Used to store the last focused view which is not a child of - // ExternalFocusTracker. - ViewStorage* view_storage_; - - // The parent view of views which we should not track focus changes to. We - // also do not track changes to parent_view_ itself. - View* parent_view_; - - DISALLOW_COPY_AND_ASSIGN(ExternalFocusTracker); -}; - -} // namespace views +#include "ui/views/focus/external_focus_tracker.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_FOCUS_EXTERNAL_FOCUS_TRACKER_H_ diff --git a/views/focus/focus_manager.cc b/views/focus/focus_manager.cc deleted file mode 100644 index 3ee0755..0000000 --- a/views/focus/focus_manager.cc +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (c) 2011 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 "views/focus/focus_manager.h" - -#include <algorithm> - -#include "base/auto_reset.h" -#include "base/logging.h" -#include "build/build_config.h" -#include "ui/base/accelerator_manager.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/models/accelerator.h" -#include "views/focus/focus_search.h" -#include "views/focus/view_storage.h" -#include "views/focus/widget_focus_manager.h" -#include "views/view.h" -#include "views/widget/root_view.h" -#include "views/widget/widget.h" - -namespace views { - -FocusManager::FocusManager(Widget* widget) - : widget_(widget), - focused_view_(NULL), - accelerator_manager_(new ui::AcceleratorManager), - focus_change_reason_(kReasonDirectFocusChange), - is_changing_focus_(false) { - DCHECK(widget_); - stored_focused_view_storage_id_ = - ViewStorage::GetInstance()->CreateStorageID(); -} - -FocusManager::~FocusManager() { -} - -bool FocusManager::OnKeyEvent(const KeyEvent& event) { -#if defined(OS_WIN) - // If the focused view wants to process the key event as is, let it be. - // On Linux we always dispatch key events to the focused view first, so - // we should not do this check here. See also NativeWidgetGtk::OnKeyEvent(). - if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event)) - return true; -#endif - - // Intercept Tab related messages for focus traversal. - // Note that we don't do focus traversal if the root window is not part of the - // active window hierarchy as this would mean we have no focused view and - // would focus the first focusable view. -#if defined(OS_WIN) && !defined(USE_AURA) - HWND top_window = widget_->GetNativeView(); - HWND active_window = ::GetActiveWindow(); - if ((active_window == top_window || ::IsChild(active_window, top_window)) && - IsTabTraversalKeyEvent(event)) { - AdvanceFocus(event.IsShiftDown()); - return false; - } -#else - if (IsTabTraversalKeyEvent(event)) { - AdvanceFocus(event.IsShiftDown()); - return false; - } -#endif - - // Intercept arrow key messages to switch between grouped views. - ui::KeyboardCode key_code = event.key_code(); - if (focused_view_ && focused_view_->GetGroup() != -1 && - (key_code == ui::VKEY_UP || key_code == ui::VKEY_DOWN || - key_code == ui::VKEY_LEFT || key_code == ui::VKEY_RIGHT)) { - bool next = (key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_DOWN); - View::Views views; - focused_view_->parent()->GetViewsInGroup(focused_view_->GetGroup(), &views); - View::Views::const_iterator i( - std::find(views.begin(), views.end(), focused_view_)); - DCHECK(i != views.end()); - int index = static_cast<int>(i - views.begin()); - index += next ? 1 : -1; - if (index < 0) { - index = static_cast<int>(views.size()) - 1; - } else if (index >= static_cast<int>(views.size())) { - index = 0; - } - SetFocusedViewWithReason(views[index], kReasonFocusTraversal); - return false; - } - - // Process keyboard accelerators. - // If the key combination matches an accelerator, the accelerator is - // triggered, otherwise the key event is processed as usual. - ui::Accelerator accelerator(event.key_code(), - event.IsShiftDown(), - event.IsControlDown(), - event.IsAltDown()); - if (ProcessAccelerator(accelerator)) { - // If a shortcut was activated for this keydown message, do not propagate - // the event further. - return false; - } - return true; -} - -void FocusManager::ValidateFocusedView() { - if (focused_view_) { - if (!ContainsView(focused_view_)) - ClearFocus(); - } -} - -// Tests whether a view is valid, whether it still belongs to the window -// hierarchy of the FocusManager. -bool FocusManager::ContainsView(View* view) { - Widget* widget = view->GetWidget(); - return widget ? widget->GetFocusManager() == this : false; -} - -void FocusManager::AdvanceFocus(bool reverse) { - View* v = GetNextFocusableView(focused_view_, reverse, false); - // Note: Do not skip this next block when v == focused_view_. If the user - // tabs past the last focusable element in a webpage, we'll get here, and if - // the TabContentsContainerView is the only focusable view (possible in - // fullscreen mode), we need to run this block in order to cycle around to the - // first element on the page. - if (v) { - v->AboutToRequestFocusFromTabTraversal(reverse); - SetFocusedViewWithReason(v, kReasonFocusTraversal); - } -} - -void FocusManager::ClearNativeFocus() { - // Keep the top root window focused so we get keyboard events. - widget_->ClearNativeFocus(); -} - -View* FocusManager::GetNextFocusableView(View* original_starting_view, - bool reverse, - bool dont_loop) { - FocusTraversable* focus_traversable = NULL; - - // Let's revalidate the focused view. - ValidateFocusedView(); - - View* starting_view = NULL; - if (original_starting_view) { - // Search up the containment hierarchy to see if a view is acting as - // a pane, and wants to implement its own focus traversable to keep - // the focus trapped within that pane. - View* pane_search = original_starting_view; - while (pane_search) { - focus_traversable = pane_search->GetPaneFocusTraversable(); - if (focus_traversable) { - starting_view = original_starting_view; - break; - } - pane_search = pane_search->parent(); - } - - if (!focus_traversable) { - if (!reverse) { - // If the starting view has a focus traversable, use it. - // This is the case with NativeWidgetWins for example. - focus_traversable = original_starting_view->GetFocusTraversable(); - - // Otherwise default to the root view. - if (!focus_traversable) { - focus_traversable = - original_starting_view->GetWidget()->GetFocusTraversable(); - starting_view = original_starting_view; - } - } else { - // When you are going back, starting view's FocusTraversable - // should not be used. - focus_traversable = - original_starting_view->GetWidget()->GetFocusTraversable(); - starting_view = original_starting_view; - } - } - } else { - focus_traversable = widget_->GetFocusTraversable(); - } - - // Traverse the FocusTraversable tree down to find the focusable view. - View* v = FindFocusableView(focus_traversable, starting_view, reverse); - if (v) { - return v; - } else { - // Let's go up in the FocusTraversable tree. - FocusTraversable* parent_focus_traversable = - focus_traversable->GetFocusTraversableParent(); - starting_view = focus_traversable->GetFocusTraversableParentView(); - while (parent_focus_traversable) { - FocusTraversable* new_focus_traversable = NULL; - View* new_starting_view = NULL; - // When we are going backward, the parent view might gain the next focus. - bool check_starting_view = reverse; - v = parent_focus_traversable->GetFocusSearch()->FindNextFocusableView( - starting_view, reverse, FocusSearch::UP, - check_starting_view, &new_focus_traversable, &new_starting_view); - - if (new_focus_traversable) { - DCHECK(!v); - - // There is a FocusTraversable, traverse it down. - v = FindFocusableView(new_focus_traversable, NULL, reverse); - } - - if (v) - return v; - - starting_view = focus_traversable->GetFocusTraversableParentView(); - parent_focus_traversable = - parent_focus_traversable->GetFocusTraversableParent(); - } - - // If we get here, we have reached the end of the focus hierarchy, let's - // loop. Make sure there was at least a view to start with, to prevent - // infinitely looping in empty windows. - if (!dont_loop && original_starting_view) { - // Easy, just clear the selection and press tab again. - // By calling with NULL as the starting view, we'll start from the - // top_root_view. - return GetNextFocusableView(NULL, reverse, true); - } - } - return NULL; -} - -void FocusManager::SetFocusedViewWithReason( - View* view, FocusChangeReason reason) { - if (focused_view_ == view) - return; - - AutoReset<bool> auto_changing_focus(&is_changing_focus_, true); - // Update the reason for the focus change (since this is checked by - // some listeners), then notify all listeners. - focus_change_reason_ = reason; - FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_, - OnWillChangeFocus(focused_view_, view)); - - View* old_focused_view = focused_view_; - focused_view_ = view; - if (old_focused_view) - old_focused_view->Blur(); - if (focused_view_) - focused_view_->Focus(); - - FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_, - OnDidChangeFocus(old_focused_view, focused_view_)); -} - -void FocusManager::ClearFocus() { - SetFocusedView(NULL); - ClearNativeFocus(); -} - -void FocusManager::StoreFocusedView() { - ViewStorage* view_storage = ViewStorage::GetInstance(); - if (!view_storage) { - // This should never happen but bug 981648 seems to indicate it could. - NOTREACHED(); - return; - } - - // TODO (jcampan): when a TabContents containing a popup is closed, the focus - // is stored twice causing an assert. We should find a better alternative than - // removing the view from the storage explicitly. - view_storage->RemoveView(stored_focused_view_storage_id_); - - if (!focused_view_) - return; - - view_storage->StoreView(stored_focused_view_storage_id_, focused_view_); - - View* v = focused_view_; - - { - // Temporarily disable notification. ClearFocus() will set the focus to the - // main browser window. This extra focus bounce which happens during - // deactivation can confuse registered WidgetFocusListeners, as the focus - // is not changing due to a user-initiated event. - AutoNativeNotificationDisabler local_notification_disabler; - ClearFocus(); - } - - if (v) - v->SchedulePaint(); // Remove focus border. -} - -void FocusManager::RestoreFocusedView() { - ViewStorage* view_storage = ViewStorage::GetInstance(); - if (!view_storage) { - // This should never happen but bug 981648 seems to indicate it could. - NOTREACHED(); - return; - } - - View* view = view_storage->RetrieveView(stored_focused_view_storage_id_); - if (view) { - if (ContainsView(view)) { - if (!view->IsFocusableInRootView() && - view->IsAccessibilityFocusableInRootView()) { - // RequestFocus would fail, but we want to restore focus to controls - // that had focus in accessibility mode. - SetFocusedViewWithReason(view, kReasonFocusRestore); - } else { - // This usually just sets the focus if this view is focusable, but - // let the view override RequestFocus if necessary. - view->RequestFocus(); - - // If it succeeded, the reason would be incorrect; set it to - // focus restore. - if (focused_view_ == view) - focus_change_reason_ = kReasonFocusRestore; - } - } - } -} - -void FocusManager::ClearStoredFocusedView() { - ViewStorage* view_storage = ViewStorage::GetInstance(); - if (!view_storage) { - // This should never happen but bug 981648 seems to indicate it could. - NOTREACHED(); - return; - } - view_storage->RemoveView(stored_focused_view_storage_id_); -} - -// Find the next (previous if reverse is true) focusable view for the specified -// FocusTraversable, starting at the specified view, traversing down the -// FocusTraversable hierarchy. -View* FocusManager::FindFocusableView(FocusTraversable* focus_traversable, - View* starting_view, - bool reverse) { - FocusTraversable* new_focus_traversable = NULL; - View* new_starting_view = NULL; - View* v = focus_traversable->GetFocusSearch()->FindNextFocusableView( - starting_view, - reverse, - FocusSearch::DOWN, - false, - &new_focus_traversable, - &new_starting_view); - - // Let's go down the FocusTraversable tree as much as we can. - while (new_focus_traversable) { - DCHECK(!v); - focus_traversable = new_focus_traversable; - starting_view = new_starting_view; - new_focus_traversable = NULL; - starting_view = NULL; - v = focus_traversable->GetFocusSearch()->FindNextFocusableView( - starting_view, - reverse, - FocusSearch::DOWN, - false, - &new_focus_traversable, - &new_starting_view); - } - return v; -} - -void FocusManager::RegisterAccelerator( - const ui::Accelerator& accelerator, - ui::AcceleratorTarget* target) { - accelerator_manager_->Register(accelerator, target); -} - -void FocusManager::UnregisterAccelerator(const ui::Accelerator& accelerator, - ui::AcceleratorTarget* target) { - accelerator_manager_->Unregister(accelerator, target); -} - -void FocusManager::UnregisterAccelerators(ui::AcceleratorTarget* target) { - accelerator_manager_->UnregisterAll(target); -} - -bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) { - return accelerator_manager_->Process(accelerator); -} - -ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( - const ui::Accelerator& accelerator) const { - return accelerator_manager_->GetCurrentTarget(accelerator); -} - -void FocusManager::FocusNativeView(gfx::NativeView native_view) { - widget_->FocusNativeView(native_view); -} - -// static -bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) { - return key_event.key_code() == ui::VKEY_TAB && !key_event.IsControlDown(); -} - -void FocusManager::ViewRemoved(View* removed) { - // If the view being removed contains (or is) the focused view, - // clear the focus. However, it's not safe to call ClearFocus() - // (and in turn ClearNativeFocus()) here because ViewRemoved() can - // be called while the top level widget is being destroyed. - if (focused_view_ && removed && removed->Contains(focused_view_)) - SetFocusedView(NULL); -} - -void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) { - focus_change_listeners_.AddObserver(listener); -} - -void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) { - focus_change_listeners_.RemoveObserver(listener); -} - -} // namespace views diff --git a/views/focus/focus_manager.h b/views/focus/focus_manager.h index 5d4caa7..5432cb5 100644 --- a/views/focus/focus_manager.h +++ b/views/focus/focus_manager.h @@ -6,278 +6,7 @@ #define VIEWS_FOCUS_FOCUS_MANAGER_H_ #pragma once -#include <list> -#include <map> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "ui/base/models/accelerator.h" -#include "ui/gfx/native_widget_types.h" -#include "views/views_export.h" -#include "views/events/event.h" - -// The FocusManager class is used to handle focus traversal, store/restore -// focused views and handle keyboard accelerators. -// -// There are 2 types of focus: -// - the native focus, which is the focus that an gfx::NativeView has. -// - the view focus, which is the focus that a views::View has. -// -// Each native view must register with their Focus Manager so the focus manager -// gets notified when they are focused (and keeps track of the native focus) and -// as well so that the tab key events can be intercepted. -// They can provide when they register a View that is kept in synch in term of -// focus. This is used in NativeControl for example, where a View wraps an -// actual native window. -// This is already done for you if you subclass the NativeControl class or if -// you use the NativeViewHost class. -// -// When creating a top window (derived from views::Widget) that is not a child -// window, it creates and owns a FocusManager to manage the focus for itself and -// all its child windows. -// -// The FocusTraversable interface exposes the methods a class should implement -// in order to be able to be focus traversed when tab key is pressed. -// RootViews implement FocusTraversable. -// The FocusManager contains a top FocusTraversable instance, which is the top -// RootView. -// -// If you just use views, then the focus traversal is handled for you by the -// RootView. The default traversal order is the order in which the views have -// been added to their container. You can modify this order by using the View -// method SetNextFocusableView(). -// -// If you are embedding a native view containing a nested RootView (for example -// by adding a NativeControl that contains a NativeWidgetWin as its native -// component), then you need to: -// - override the View::GetFocusTraversable() method in your outer component. -// It should return the RootView of the inner component. This is used when -// the focus traversal traverse down the focus hierarchy to enter the nested -// RootView. In the example mentioned above, the NativeControl overrides -// GetFocusTraversable() and returns hwnd_view_container_->GetRootView(). -// - call Widget::SetFocusTraversableParent() on the nested RootView and point -// it to the outer RootView. This is used when the focus goes out of the -// nested RootView. In the example: -// hwnd_view_container_->GetWidget()->SetFocusTraversableParent( -// native_control->GetRootView()); -// - call RootView::SetFocusTraversableParentView() on the nested RootView with -// the parent view that directly contains the native window. This is needed -// when traversing up from the nested RootView to know which view to start -// with when going to the next/previous view. -// In our example: -// hwnd_view_container_->GetWidget()->SetFocusTraversableParent( -// native_control); -// -// Note that FocusTraversable do not have to be RootViews: AccessibleToolbarView -// is FocusTraversable. - -namespace ui { -class AcceleratorTarget; -class AcceleratorManager; -} - -namespace views { - -class FocusSearch; -class RootView; -class View; -class Widget; - -// The FocusTraversable interface is used by components that want to process -// focus traversal events (due to Tab/Shift-Tab key events). -class VIEWS_EXPORT FocusTraversable { - public: - // Return a FocusSearch object that implements the algorithm to find - // the next or previous focusable view. - virtual FocusSearch* GetFocusSearch() = 0; - - // Should return the parent FocusTraversable. - // The top RootView which is the top FocusTraversable returns NULL. - virtual FocusTraversable* GetFocusTraversableParent() = 0; - - // This should return the View this FocusTraversable belongs to. - // It is used when walking up the view hierarchy tree to find which view - // should be used as the starting view for finding the next/previous view. - virtual View* GetFocusTraversableParentView() = 0; - - protected: - virtual ~FocusTraversable() {} -}; - -// This interface should be implemented by classes that want to be notified when -// the focus is about to change. See the Add/RemoveFocusChangeListener methods. -class VIEWS_EXPORT FocusChangeListener { - public: - // No change to focus state has occurred yet when this function is called. - virtual void OnWillChangeFocus(View* focused_before, View* focused_now) = 0; - - // Called after focus state has changed. - virtual void OnDidChangeFocus(View* focused_before, View* focused_now) = 0; - - protected: - virtual ~FocusChangeListener() {} -}; - -class VIEWS_EXPORT FocusManager { - public: - // The reason why the focus changed. - enum FocusChangeReason { - // The focus changed because the user traversed focusable views using - // keys like Tab or Shift+Tab. - kReasonFocusTraversal, - - // The focus changed due to restoring the focus. - kReasonFocusRestore, - - // The focus changed due to a click or a shortcut to jump directly to - // a particular view. - kReasonDirectFocusChange - }; - - explicit FocusManager(Widget* widget); - virtual ~FocusManager(); - - // Processes the passed key event for accelerators and tab traversal. - // Returns false if the event has been consumed and should not be processed - // further. - bool OnKeyEvent(const KeyEvent& event); - - // Returns true is the specified is part of the hierarchy of the window - // associated with this FocusManager. - bool ContainsView(View* view); - - // Advances the focus (backward if reverse is true). - void AdvanceFocus(bool reverse); - - // The FocusManager keeps track of the focused view within a RootView. - View* GetFocusedView() { return focused_view_; } - const View* GetFocusedView() const { return focused_view_; } - - // Low-level methods to force the focus to change (and optionally provide - // a reason). If the focus change should only happen if the view is - // currenty focusable, enabled, and visible, call view->RequestFocus(). - void SetFocusedViewWithReason(View* view, FocusChangeReason reason); - void SetFocusedView(View* view) { - SetFocusedViewWithReason(view, kReasonDirectFocusChange); - } - - // Get the reason why the focus most recently changed. - FocusChangeReason focus_change_reason() const { - return focus_change_reason_; - } - - // Clears the focused view. The window associated with the top root view gets - // the native focus (so we still get keyboard events). - void ClearFocus(); - - // Validates the focused view, clearing it if the window it belongs too is not - // attached to the window hierarchy anymore. - void ValidateFocusedView(); - - // Stores and restores the focused view. Used when the window becomes - // active/inactive. - void StoreFocusedView(); - void RestoreFocusedView(); - - // Clears the stored focused view. - void ClearStoredFocusedView(); - - // Returns true if in the process of changing the focused view. - bool is_changing_focus() const { return is_changing_focus_; } - - // Register a keyboard accelerator for the specified target. If multiple - // targets are registered for an accelerator, a target registered later has - // higher priority. - // Note that we are currently limited to accelerators that are either: - // - a key combination including Ctrl or Alt - // - the escape key - // - the enter key - // - any F key (F1, F2, F3 ...) - // - any browser specific keys (as available on special keyboards) - void RegisterAccelerator(const ui::Accelerator& accelerator, - ui::AcceleratorTarget* target); - - // Unregister the specified keyboard accelerator for the specified target. - void UnregisterAccelerator(const ui::Accelerator& accelerator, - ui::AcceleratorTarget* target); - - // Unregister all keyboard accelerator for the specified target. - void UnregisterAccelerators(ui::AcceleratorTarget* target); - - // Activate the target associated with the specified accelerator. - // First, AcceleratorPressed handler of the most recently registered target - // is called, and if that handler processes the event (i.e. returns true), - // this method immediately returns. If not, we do the same thing on the next - // target, and so on. - // Returns true if an accelerator was activated. - bool ProcessAccelerator(const ui::Accelerator& accelerator); - - // Called by a RootView when a view within its hierarchy is removed - // from its parent. This will only be called by a RootView in a - // hierarchy of Widgets that this FocusManager is attached to the - // parent Widget of. - void ViewRemoved(View* removed); - - // Adds/removes a listener. The FocusChangeListener is notified every time - // the focused view is about to change. - void AddFocusChangeListener(FocusChangeListener* listener); - void RemoveFocusChangeListener(FocusChangeListener* listener); - - // Returns the AcceleratorTarget that should be activated for the specified - // keyboard accelerator, or NULL if no view is registered for that keyboard - // accelerator. - ui::AcceleratorTarget* GetCurrentTargetForAccelerator( - const ui::Accelerator& accelertor) const; - - // Sets the focus to the specified native view. - virtual void FocusNativeView(gfx::NativeView native_view); - - // Clears the native view having the focus. - virtual void ClearNativeFocus(); - - // Convenience method that returns true if the passed |key_event| should - // trigger tab traversal (if it is a TAB key press with or without SHIFT - // pressed). - static bool IsTabTraversalKeyEvent(const KeyEvent& key_event); - - private: - // Returns the next focusable view. - View* GetNextFocusableView(View* starting_view, bool reverse, bool dont_loop); - - // Returns the focusable view found in the FocusTraversable specified starting - // at the specified view. This traverses down along the FocusTraversable - // hierarchy. - // Returns NULL if no focusable view were found. - View* FindFocusableView(FocusTraversable* focus_traversable, - View* starting_view, - bool reverse); - - // The top-level Widget this FocusManager is associated with. - Widget* widget_; - - // The view that currently is focused. - View* focused_view_; - - // The AcceleratorManager this FocusManager is associated with. - scoped_ptr<ui::AcceleratorManager> accelerator_manager_; - - // The storage id used in the ViewStorage to store/restore the view that last - // had focus. - int stored_focused_view_storage_id_; - - // The reason why the focus most recently changed. - FocusChangeReason focus_change_reason_; - - // The list of registered FocusChange listeners. - ObserverList<FocusChangeListener, true> focus_change_listeners_; - - // See description above getter. - bool is_changing_focus_; - - DISALLOW_COPY_AND_ASSIGN(FocusManager); -}; - -} // namespace views +#include "ui/views/focus/focus_manager.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_FOCUS_FOCUS_MANAGER_H_ diff --git a/views/focus/focus_manager_factory.cc b/views/focus/focus_manager_factory.cc deleted file mode 100644 index 457f60b..0000000 --- a/views/focus/focus_manager_factory.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2011 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 "views/focus/focus_manager_factory.h" - -#include "base/compiler_specific.h" -#include "views/focus/focus_manager.h" - -namespace { - -using views::FocusManager; - -class DefaultFocusManagerFactory : public views::FocusManagerFactory { - public: - DefaultFocusManagerFactory() : views::FocusManagerFactory() {} - virtual ~DefaultFocusManagerFactory() {} - - protected: - virtual FocusManager* CreateFocusManager(views::Widget* widget) OVERRIDE { - return new FocusManager(widget); - } - - private: - DISALLOW_COPY_AND_ASSIGN(DefaultFocusManagerFactory); -}; - -views::FocusManagerFactory* focus_manager_factory = NULL; - -} // namespace - -namespace views { - -FocusManagerFactory::FocusManagerFactory() { -} - -FocusManagerFactory::~FocusManagerFactory() { -} - -// static -FocusManager* FocusManagerFactory::Create(Widget* widget) { - if (!focus_manager_factory) - focus_manager_factory = new DefaultFocusManagerFactory(); - return focus_manager_factory->CreateFocusManager(widget); -} - -// static -void FocusManagerFactory::Install(FocusManagerFactory* f) { - if (f == focus_manager_factory) - return; - delete focus_manager_factory; - focus_manager_factory = f ? f : new DefaultFocusManagerFactory(); -} - -} // namespace views diff --git a/views/focus/focus_manager_factory.h b/views/focus/focus_manager_factory.h index 136b254..825cc34 100644 --- a/views/focus/focus_manager_factory.h +++ b/views/focus/focus_manager_factory.h @@ -6,36 +6,7 @@ #define VIEWS_FOCUS_FOCUS_MANAGER_FACTORY_H_ #pragma once -#include "base/basictypes.h" -#include "views/views_export.h" - -namespace views { - -class FocusManager; -class Widget; - -// A factory to create FocusManager. This is used in unit tests -// to inject a custom factory. -class VIEWS_EXPORT FocusManagerFactory { - public: - // Create a FocusManager for the given |widget| using installe Factory. - static FocusManager* Create(Widget* widget); - - // Installs FocusManagerFactory. If |factory| is NULL, it resets - // to the default factory which creates plain FocusManager. - static void Install(FocusManagerFactory* factory); - - protected: - FocusManagerFactory(); - virtual ~FocusManagerFactory(); - - // Create a FocusManager for the given |widget|. - virtual FocusManager* CreateFocusManager(Widget* widget) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FocusManagerFactory); -}; - -} // namespace views +#include "ui/views/focus/focus_manager_factory.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_FOCUS_FOCUS_MANAGER_FACTORY_H_ diff --git a/views/focus/focus_manager_unittest.cc b/views/focus/focus_manager_unittest.cc deleted file mode 100644 index d4372f2..0000000 --- a/views/focus/focus_manager_unittest.cc +++ /dev/null @@ -1,1763 +0,0 @@ -// Copyright (c) 2011 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 "base/logging.h" -#include "base/string16.h" -#include "base/string_number_conversions.h" -#include "base/utf_string_conversions.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/models/accelerator.h" -#include "ui/base/models/combobox_model.h" -#include "ui/gfx/rect.h" -#include "ui/views/test/views_test_base.h" -#include "ui/views/window/non_client_view.h" -#include "views/background.h" -#include "views/border.h" -#include "views/controls/button/checkbox.h" -#include "views/controls/button/radio_button.h" -#include "views/controls/combobox/combobox.h" -#include "views/controls/combobox/native_combobox_wrapper.h" -#include "views/controls/label.h" -#include "views/controls/link.h" -#include "views/controls/native/native_view_host.h" -#include "views/controls/scroll_view.h" -#include "views/controls/tabbed_pane/native_tabbed_pane_wrapper.h" -#include "views/controls/tabbed_pane/tabbed_pane.h" -#include "views/controls/textfield/textfield.h" -#include "views/focus/accelerator_handler.h" -#include "views/focus/focus_manager_factory.h" -#include "views/widget/root_view.h" -#include "views/widget/widget.h" -#include "views/widget/widget_delegate.h" - -#if defined(OS_LINUX) -#include "ui/base/keycodes/keyboard_code_conversion_gtk.h" -#endif - -namespace { -const int kWindowWidth = 600; -const int kWindowHeight = 500; - -int count = 1; - -const int kTopCheckBoxID = count++; // 1 -const int kLeftContainerID = count++; -const int kAppleLabelID = count++; -const int kAppleTextfieldID = count++; -const int kOrangeLabelID = count++; // 5 -const int kOrangeTextfieldID = count++; -const int kBananaLabelID = count++; -const int kBananaTextfieldID = count++; -const int kKiwiLabelID = count++; -const int kKiwiTextfieldID = count++; // 10 -const int kFruitButtonID = count++; -const int kFruitCheckBoxID = count++; -const int kComboboxID = count++; - -const int kRightContainerID = count++; -const int kAsparagusButtonID = count++; // 15 -const int kBroccoliButtonID = count++; -const int kCauliflowerButtonID = count++; - -const int kInnerContainerID = count++; -const int kScrollViewID = count++; -const int kRosettaLinkID = count++; // 20 -const int kStupeurEtTremblementLinkID = count++; -const int kDinerGameLinkID = count++; -const int kRidiculeLinkID = count++; -const int kClosetLinkID = count++; -const int kVisitingLinkID = count++; // 25 -const int kAmelieLinkID = count++; -const int kJoyeuxNoelLinkID = count++; -const int kCampingLinkID = count++; -const int kBriceDeNiceLinkID = count++; -const int kTaxiLinkID = count++; // 30 -const int kAsterixLinkID = count++; - -const int kOKButtonID = count++; -const int kCancelButtonID = count++; -const int kHelpButtonID = count++; - -const int kStyleContainerID = count++; // 35 -const int kBoldCheckBoxID = count++; -const int kItalicCheckBoxID = count++; -const int kUnderlinedCheckBoxID = count++; -const int kStyleHelpLinkID = count++; -const int kStyleTextEditID = count++; // 40 - -const int kSearchContainerID = count++; -const int kSearchTextfieldID = count++; -const int kSearchButtonID = count++; -const int kHelpLinkID = count++; - -const int kThumbnailContainerID = count++; // 45 -const int kThumbnailStarID = count++; -const int kThumbnailSuperStarID = count++; - -} // namespace - -namespace views { - -class FocusManagerTest : public ViewsTestBase, public WidgetDelegate { - public: - FocusManagerTest() - : window_(NULL), - content_view_(NULL), - focus_change_listener_(NULL) { - } - - ~FocusManagerTest() { - } - - virtual void SetUp() OVERRIDE { - ViewsTestBase::SetUp(); - window_ = Widget::CreateWindowWithBounds(this, bounds()); - InitContentView(); - window_->Show(); - } - - virtual void TearDown() OVERRIDE { - if (focus_change_listener_) - GetFocusManager()->RemoveFocusChangeListener(focus_change_listener_); - window_->Close(); - - // Flush the message loop to make application verifiers happy. - RunPendingMessages(); - ViewsTestBase::TearDown(); - } - - FocusManager* GetFocusManager() { - return window_->GetFocusManager(); - } - - void FocusNativeView(gfx::NativeView native_view) { -#if defined(USE_AURA) - NOTIMPLEMENTED(); -#elif defined(OS_WIN) - ::SendMessage(native_view, WM_SETFOCUS, NULL, NULL); -#else - gint return_val; - GdkEventFocus event; - event.type = GDK_FOCUS_CHANGE; - event.window = - gtk_widget_get_root_window(GTK_WIDGET(window_->GetNativeWindow())); - event.send_event = TRUE; - event.in = TRUE; - gtk_signal_emit_by_name(GTK_OBJECT(native_view), "focus-in-event", - &event, &return_val); -#endif - } - - // WidgetDelegate Implementation. - virtual View* GetContentsView() OVERRIDE { - if (!content_view_) - content_view_ = new View(); - return content_view_; - } - virtual Widget* GetWidget() OVERRIDE { - return content_view_->GetWidget(); - } - virtual const Widget* GetWidget() const OVERRIDE { - return content_view_->GetWidget(); - } - - virtual void InitContentView() { - } - - protected: - virtual gfx::Rect bounds() { - return gfx::Rect(0, 0, 500, 500); - } - - // Mocks activating/deactivating the window. - void SimulateActivateWindow() { -#if defined(USE_AURA) - NOTIMPLEMENTED(); -#elif defined(OS_WIN) - ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL); -#else - gboolean result; - g_signal_emit_by_name(G_OBJECT(window_->GetNativeWindow()), - "focus_in_event", 0, &result); -#endif - } - void SimulateDeactivateWindow() { -#if defined(USE_AURA) - NOTIMPLEMENTED(); -#elif defined(OS_WIN) - ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_INACTIVE, NULL); -#else - gboolean result; - g_signal_emit_by_name(G_OBJECT(window_->GetNativeWindow()), - "focus_out_event", 0, & result); -#endif - } - - Widget* window_; - View* content_view_; - - void AddFocusChangeListener(FocusChangeListener* listener) { - ASSERT_FALSE(focus_change_listener_); - focus_change_listener_ = listener; - GetFocusManager()->AddFocusChangeListener(listener); - } - -#if defined(USE_AURA) - void PostKeyDown(ui::KeyboardCode key_code) { - NOTIMPLEMENTED(); - } - - void PostKeyUp(ui::KeyboardCode key_code) { - NOTIMPLEMENTED(); - } -#elif defined(OS_WIN) - void PostKeyDown(ui::KeyboardCode key_code) { - ::PostMessage(window_->GetNativeWindow(), WM_KEYDOWN, key_code, 0); - } - - void PostKeyUp(ui::KeyboardCode key_code) { - ::PostMessage(window_->GetNativeWindow(), WM_KEYUP, key_code, 0); - } -#elif defined(OS_LINUX) - void PostKeyDown(ui::KeyboardCode key_code) { - PostKeyEvent(key_code, true); - } - - void PostKeyUp(ui::KeyboardCode key_code) { - PostKeyEvent(key_code, false); - } - - void PostKeyEvent(ui::KeyboardCode key_code, bool pressed) { - int keyval = GdkKeyCodeForWindowsKeyCode(key_code, false); - GdkKeymapKey* keys; - gint n_keys; - gdk_keymap_get_entries_for_keyval( - gdk_keymap_get_default(), - keyval, - &keys, - &n_keys); - GdkEvent* event = gdk_event_new(pressed ? GDK_KEY_PRESS : GDK_KEY_RELEASE); - GdkEventKey* key_event = reinterpret_cast<GdkEventKey*>(event); - int modifier = 0; - if (pressed) - key_event->state = modifier | GDK_KEY_PRESS_MASK; - else - key_event->state = modifier | GDK_KEY_RELEASE_MASK; - - key_event->window = GTK_WIDGET(window_->GetNativeWindow())->window; - DCHECK(key_event->window != NULL); - g_object_ref(key_event->window); - key_event->send_event = true; - key_event->time = GDK_CURRENT_TIME; - key_event->keyval = keyval; - key_event->hardware_keycode = keys[0].keycode; - key_event->group = keys[0].group; - - g_free(keys); - - gdk_event_put(event); - gdk_event_free(event); - } -#endif - - private: - FocusChangeListener* focus_change_listener_; - - DISALLOW_COPY_AND_ASSIGN(FocusManagerTest); -}; - -// BorderView is a view containing a native window with its own view hierarchy. -// It is interesting to test focus traversal from a view hierarchy to an inner -// view hierarchy. -class BorderView : public NativeViewHost { - public: - explicit BorderView(View* child) : child_(child), widget_(NULL) { - DCHECK(child); - set_focusable(false); - } - - virtual ~BorderView() {} - - virtual internal::RootView* GetContentsRootView() { - return static_cast<internal::RootView*>(widget_->GetRootView()); - } - - virtual FocusTraversable* GetFocusTraversable() { - return static_cast<internal::RootView*>(widget_->GetRootView()); - } - - virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child) { - NativeViewHost::ViewHierarchyChanged(is_add, parent, child); - - if (child == this && is_add) { - if (!widget_) { - widget_ = new Widget; - Widget::InitParams params(Widget::InitParams::TYPE_CONTROL); -#if defined(OS_WIN) - params.parent = parent->GetWidget()->GetNativeView(); -#elif defined(TOOLKIT_USES_GTK) - params.parent = native_view(); -#else - NOTREACHED(); -#endif - widget_->Init(params); - widget_->SetFocusTraversableParentView(this); - widget_->SetContentsView(child_); - } - - // We have been added to a view hierarchy, attach the native view. - Attach(widget_->GetNativeView()); - // Also update the FocusTraversable parent so the focus traversal works. - static_cast<internal::RootView*>(widget_->GetRootView())-> - SetFocusTraversableParent(GetWidget()->GetFocusTraversable()); - } - } - - private: - View* child_; - Widget* widget_; - - DISALLOW_COPY_AND_ASSIGN(BorderView); -}; - -class DummyComboboxModel : public ui::ComboboxModel { - public: - virtual int GetItemCount() { return 10; } - - virtual string16 GetItemAt(int index) { - return ASCIIToUTF16("Item ") + base::IntToString16(index); - } -}; - -// A View that can act as a pane. -class PaneView : public View, public FocusTraversable { - public: - PaneView() : focus_search_(NULL) {} - - // If this method is called, this view will use GetPaneFocusTraversable to - // have this provided FocusSearch used instead of the default one, allowing - // you to trap focus within the pane. - void EnablePaneFocus(FocusSearch* focus_search) { - focus_search_ = focus_search; - } - - // Overridden from views::View: - virtual FocusTraversable* GetPaneFocusTraversable() { - if (focus_search_) - return this; - else - return NULL; - } - - // Overridden from views::FocusTraversable: - virtual views::FocusSearch* GetFocusSearch() { - return focus_search_; - } - virtual FocusTraversable* GetFocusTraversableParent() { - return NULL; - } - virtual View* GetFocusTraversableParentView() { - return NULL; - } - - private: - FocusSearch* focus_search_; -}; - -class FocusTraversalTest : public FocusManagerTest { - public: - ~FocusTraversalTest(); - - virtual void InitContentView(); - - protected: - FocusTraversalTest(); - - virtual gfx::Rect bounds() { - return gfx::Rect(0, 0, 600, 460); - } - - View* FindViewByID(int id) { - View* view = GetContentsView()->GetViewByID(id); - if (view) - return view; - if (style_tab_) - view = style_tab_->GetSelectedTab()->GetViewByID(id); - if (view) - return view; - view = search_border_view_->GetContentsRootView()->GetViewByID(id); - if (view) - return view; - return NULL; - } - - protected: - TabbedPane* style_tab_; - BorderView* search_border_view_; - DummyComboboxModel combobox_model_; - PaneView* left_container_; - PaneView* right_container_; - - DISALLOW_COPY_AND_ASSIGN(FocusTraversalTest); -}; - -//////////////////////////////////////////////////////////////////////////////// -// FocusTraversalTest -//////////////////////////////////////////////////////////////////////////////// - -FocusTraversalTest::FocusTraversalTest() - : style_tab_(NULL), - search_border_view_(NULL) { -} - -FocusTraversalTest::~FocusTraversalTest() { -} - -void FocusTraversalTest::InitContentView() { - // Create a complicated view hierarchy with lots of control types for - // use by all of the focus traversal tests. - // - // Class name, ID, and asterisk next to focusable views: - // - // View - // Checkbox * kTopCheckBoxID - // PaneView kLeftContainerID - // Label kAppleLabelID - // Textfield * kAppleTextfieldID - // Label kOrangeLabelID - // Textfield * kOrangeTextfieldID - // Label kBananaLabelID - // Textfield * kBananaTextfieldID - // Label kKiwiLabelID - // Textfield * kKiwiTextfieldID - // NativeButton * kFruitButtonID - // Checkbox * kFruitCheckBoxID - // Combobox * kComboboxID - // PaneView kRightContainerID - // RadioButton * kAsparagusButtonID - // RadioButton * kBroccoliButtonID - // RadioButton * kCauliflowerButtonID - // View kInnerContainerID - // ScrollView kScrollViewID - // View - // Link * kRosettaLinkID - // Link * kStupeurEtTremblementLinkID - // Link * kDinerGameLinkID - // Link * kRidiculeLinkID - // Link * kClosetLinkID - // Link * kVisitingLinkID - // Link * kAmelieLinkID - // Link * kJoyeuxNoelLinkID - // Link * kCampingLinkID - // Link * kBriceDeNiceLinkID - // Link * kTaxiLinkID - // Link * kAsterixLinkID - // NativeButton * kOKButtonID - // NativeButton * kCancelButtonID - // NativeButton * kHelpButtonID - // TabbedPane * kStyleContainerID - // View - // Checkbox * kBoldCheckBoxID - // Checkbox * kItalicCheckBoxID - // Checkbox * kUnderlinedCheckBoxID - // Link * kStyleHelpLinkID - // Textfield * kStyleTextEditID - // Other - // BorderView kSearchContainerID - // View - // Textfield * kSearchTextfieldID - // NativeButton * kSearchButtonID - // Link * kHelpLinkID - // View * kThumbnailContainerID - // NativeButton * kThumbnailStarID - // NativeButton * kThumbnailSuperStarID - - content_view_->set_background( - Background::CreateSolidBackground(SK_ColorWHITE)); - - Checkbox* cb = new Checkbox(ASCIIToUTF16("This is a checkbox")); - content_view_->AddChildView(cb); - // In this fast paced world, who really has time for non hard-coded layout? - cb->SetBounds(10, 10, 200, 20); - cb->set_id(kTopCheckBoxID); - - left_container_ = new PaneView(); - left_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK)); - left_container_->set_background( - Background::CreateSolidBackground(240, 240, 240)); - left_container_->set_id(kLeftContainerID); - content_view_->AddChildView(left_container_); - left_container_->SetBounds(10, 35, 250, 200); - - int label_x = 5; - int label_width = 50; - int label_height = 15; - int text_field_width = 150; - int y = 10; - int gap_between_labels = 10; - - Label* label = new Label(ASCIIToUTF16("Apple:")); - label->set_id(kAppleLabelID); - left_container_->AddChildView(label); - label->SetBounds(label_x, y, label_width, label_height); - - Textfield* text_field = new Textfield(); - text_field->set_id(kAppleTextfieldID); - left_container_->AddChildView(text_field); - text_field->SetBounds(label_x + label_width + 5, y, - text_field_width, label_height); - - y += label_height + gap_between_labels; - - label = new Label(ASCIIToUTF16("Orange:")); - label->set_id(kOrangeLabelID); - left_container_->AddChildView(label); - label->SetBounds(label_x, y, label_width, label_height); - - text_field = new Textfield(); - text_field->set_id(kOrangeTextfieldID); - left_container_->AddChildView(text_field); - text_field->SetBounds(label_x + label_width + 5, y, - text_field_width, label_height); - - y += label_height + gap_between_labels; - - label = new Label(ASCIIToUTF16("Banana:")); - label->set_id(kBananaLabelID); - left_container_->AddChildView(label); - label->SetBounds(label_x, y, label_width, label_height); - - text_field = new Textfield(); - text_field->set_id(kBananaTextfieldID); - left_container_->AddChildView(text_field); - text_field->SetBounds(label_x + label_width + 5, y, - text_field_width, label_height); - - y += label_height + gap_between_labels; - - label = new Label(ASCIIToUTF16("Kiwi:")); - label->set_id(kKiwiLabelID); - left_container_->AddChildView(label); - label->SetBounds(label_x, y, label_width, label_height); - - text_field = new Textfield(); - text_field->set_id(kKiwiTextfieldID); - left_container_->AddChildView(text_field); - text_field->SetBounds(label_x + label_width + 5, y, - text_field_width, label_height); - - y += label_height + gap_between_labels; - - NativeTextButton* button = new NativeTextButton(NULL, - ASCIIToUTF16("Click me")); - button->SetBounds(label_x, y + 10, 80, 30); - button->set_id(kFruitButtonID); - left_container_->AddChildView(button); - y += 40; - - cb = new Checkbox(ASCIIToUTF16("This is another check box")); - cb->SetBounds(label_x + label_width + 5, y, 180, 20); - cb->set_id(kFruitCheckBoxID); - left_container_->AddChildView(cb); - y += 20; - - Combobox* combobox = new Combobox(&combobox_model_); - combobox->SetBounds(label_x + label_width + 5, y, 150, 30); - combobox->set_id(kComboboxID); - left_container_->AddChildView(combobox); - - right_container_ = new PaneView(); - right_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK)); - right_container_->set_background( - Background::CreateSolidBackground(240, 240, 240)); - right_container_->set_id(kRightContainerID); - content_view_->AddChildView(right_container_); - right_container_->SetBounds(270, 35, 300, 200); - - y = 10; - int radio_button_height = 18; - int gap_between_radio_buttons = 10; - RadioButton* radio_button = new RadioButton(ASCIIToUTF16("Asparagus"), 1); - radio_button->set_id(kAsparagusButtonID); - right_container_->AddChildView(radio_button); - radio_button->SetBounds(5, y, 70, radio_button_height); - radio_button->SetGroup(1); - y += radio_button_height + gap_between_radio_buttons; - radio_button = new RadioButton(ASCIIToUTF16("Broccoli"), 1); - radio_button->set_id(kBroccoliButtonID); - right_container_->AddChildView(radio_button); - radio_button->SetBounds(5, y, 70, radio_button_height); - radio_button->SetGroup(1); - RadioButton* radio_button_to_check = radio_button; - y += radio_button_height + gap_between_radio_buttons; - radio_button = new RadioButton(ASCIIToUTF16("Cauliflower"), 1); - radio_button->set_id(kCauliflowerButtonID); - right_container_->AddChildView(radio_button); - radio_button->SetBounds(5, y, 70, radio_button_height); - radio_button->SetGroup(1); - y += radio_button_height + gap_between_radio_buttons; - - View* inner_container = new View(); - inner_container->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK)); - inner_container->set_background( - Background::CreateSolidBackground(230, 230, 230)); - inner_container->set_id(kInnerContainerID); - right_container_->AddChildView(inner_container); - inner_container->SetBounds(100, 10, 150, 180); - - ScrollView* scroll_view = new ScrollView(); - scroll_view->set_id(kScrollViewID); - inner_container->AddChildView(scroll_view); - scroll_view->SetBounds(1, 1, 148, 178); - - View* scroll_content = new View(); - scroll_content->SetBounds(0, 0, 200, 200); - scroll_content->set_background( - Background::CreateSolidBackground(200, 200, 200)); - scroll_view->SetContents(scroll_content); - - static const char* const kTitles[] = { - "Rosetta", "Stupeur et tremblement", "The diner game", - "Ridicule", "Le placard", "Les Visiteurs", "Amelie", - "Joyeux Noel", "Camping", "Brice de Nice", - "Taxi", "Asterix" - }; - - static const int kIDs[] = { - kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID, - kRidiculeLinkID, kClosetLinkID, kVisitingLinkID, kAmelieLinkID, - kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID, - kTaxiLinkID, kAsterixLinkID - }; - - DCHECK(arraysize(kTitles) == arraysize(kIDs)); - - y = 5; - for (size_t i = 0; i < arraysize(kTitles); ++i) { - Link* link = new Link(ASCIIToUTF16(kTitles[i])); - link->SetHorizontalAlignment(Label::ALIGN_LEFT); - link->set_id(kIDs[i]); - scroll_content->AddChildView(link); - link->SetBounds(5, y, 300, 15); - y += 15; - } - - y = 250; - int width = 60; - button = new NativeTextButton(NULL, ASCIIToUTF16("OK")); - button->set_id(kOKButtonID); - button->SetIsDefault(true); - - content_view_->AddChildView(button); - button->SetBounds(150, y, width, 30); - - button = new NativeTextButton(NULL, ASCIIToUTF16("Cancel")); - button->set_id(kCancelButtonID); - content_view_->AddChildView(button); - button->SetBounds(220, y, width, 30); - - button = new NativeTextButton(NULL, ASCIIToUTF16("Help")); - button->set_id(kHelpButtonID); - content_view_->AddChildView(button); - button->SetBounds(290, y, width, 30); - - y += 40; - - // Left bottom box with style checkboxes. - View* contents = new View(); - contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE)); - cb = new Checkbox(ASCIIToUTF16("Bold")); - contents->AddChildView(cb); - cb->SetBounds(10, 10, 50, 20); - cb->set_id(kBoldCheckBoxID); - - cb = new Checkbox(ASCIIToUTF16("Italic")); - contents->AddChildView(cb); - cb->SetBounds(70, 10, 50, 20); - cb->set_id(kItalicCheckBoxID); - - cb = new Checkbox(ASCIIToUTF16("Underlined")); - contents->AddChildView(cb); - cb->SetBounds(130, 10, 70, 20); - cb->set_id(kUnderlinedCheckBoxID); - - Link* link = new Link(ASCIIToUTF16("Help")); - contents->AddChildView(link); - link->SetBounds(10, 35, 70, 10); - link->set_id(kStyleHelpLinkID); - - text_field = new Textfield(); - contents->AddChildView(text_field); - text_field->SetBounds(10, 50, 100, 20); - text_field->set_id(kStyleTextEditID); - - style_tab_ = new TabbedPane(); - style_tab_->set_id(kStyleContainerID); - content_view_->AddChildView(style_tab_); - style_tab_->SetBounds(10, y, 210, 100); - style_tab_->AddTab(ASCIIToUTF16("Style"), contents); - style_tab_->AddTab(ASCIIToUTF16("Other"), new View()); - - // Right bottom box with search. - contents = new View(); - contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE)); - text_field = new Textfield(); - contents->AddChildView(text_field); - text_field->SetBounds(10, 10, 100, 20); - text_field->set_id(kSearchTextfieldID); - - button = new NativeTextButton(NULL, ASCIIToUTF16("Search")); - contents->AddChildView(button); - button->SetBounds(112, 5, 60, 30); - button->set_id(kSearchButtonID); - - link = new Link(ASCIIToUTF16("Help")); - link->SetHorizontalAlignment(Label::ALIGN_LEFT); - link->set_id(kHelpLinkID); - contents->AddChildView(link); - link->SetBounds(175, 10, 30, 20); - - search_border_view_ = new BorderView(contents); - search_border_view_->set_id(kSearchContainerID); - - content_view_->AddChildView(search_border_view_); - search_border_view_->SetBounds(300, y, 240, 50); - - y += 60; - - contents = new View(); - contents->set_focusable(true); - contents->set_background(Background::CreateSolidBackground(SK_ColorBLUE)); - contents->set_id(kThumbnailContainerID); - button = new NativeTextButton(NULL, ASCIIToUTF16("Star")); - contents->AddChildView(button); - button->SetBounds(5, 5, 50, 30); - button->set_id(kThumbnailStarID); - button = new NativeTextButton(NULL, ASCIIToUTF16("SuperStar")); - contents->AddChildView(button); - button->SetBounds(60, 5, 100, 30); - button->set_id(kThumbnailSuperStarID); - - content_view_->AddChildView(contents); - contents->SetBounds(250, y, 200, 50); - // We can only call RadioButton::SetChecked() on the radio-button is part of - // the view hierarchy. - radio_button_to_check->SetChecked(true); -} - -//////////////////////////////////////////////////////////////////////////////// -// The tests -//////////////////////////////////////////////////////////////////////////////// - -enum FocusTestEventType { - ON_FOCUS = 0, - ON_BLUR -}; - -struct FocusTestEvent { - FocusTestEvent(FocusTestEventType type, int view_id) - : type(type), - view_id(view_id) { - } - - FocusTestEventType type; - int view_id; -}; - -class SimpleTestView : public View { - public: - SimpleTestView(std::vector<FocusTestEvent>* event_list, int view_id) - : event_list_(event_list) { - set_focusable(true); - set_id(view_id); - } - - virtual void OnFocus() { - event_list_->push_back(FocusTestEvent(ON_FOCUS, id())); - } - - virtual void OnBlur() { - event_list_->push_back(FocusTestEvent(ON_BLUR, id())); - } - - private: - std::vector<FocusTestEvent>* event_list_; -}; - -// Tests that the appropriate Focus related methods are called when a View -// gets/loses focus. -TEST_F(FocusManagerTest, ViewFocusCallbacks) { - std::vector<FocusTestEvent> event_list; - const int kView1ID = 1; - const int kView2ID = 2; - - SimpleTestView* view1 = new SimpleTestView(&event_list, kView1ID); - SimpleTestView* view2 = new SimpleTestView(&event_list, kView2ID); - content_view_->AddChildView(view1); - content_view_->AddChildView(view2); - - view1->RequestFocus(); - ASSERT_EQ(1, static_cast<int>(event_list.size())); - EXPECT_EQ(ON_FOCUS, event_list[0].type); - EXPECT_EQ(kView1ID, event_list[0].view_id); - - event_list.clear(); - view2->RequestFocus(); - ASSERT_EQ(2, static_cast<int>(event_list.size())); - EXPECT_EQ(ON_BLUR, event_list[0].type); - EXPECT_EQ(kView1ID, event_list[0].view_id); - EXPECT_EQ(ON_FOCUS, event_list[1].type); - EXPECT_EQ(kView2ID, event_list[1].view_id); - - event_list.clear(); - GetFocusManager()->ClearFocus(); - ASSERT_EQ(1, static_cast<int>(event_list.size())); - EXPECT_EQ(ON_BLUR, event_list[0].type); - EXPECT_EQ(kView2ID, event_list[0].view_id); -} - -typedef std::pair<View*, View*> ViewPair; -class TestFocusChangeListener : public FocusChangeListener { - public: - virtual void OnWillChangeFocus(View* focused_before, View* focused_now) { - focus_changes_.push_back(ViewPair(focused_before, focused_now)); - } - virtual void OnDidChangeFocus(View* focused_before, View* focused_now) { - } - - const std::vector<ViewPair>& focus_changes() const { return focus_changes_; } - void ClearFocusChanges() { focus_changes_.clear(); } - - private: - // A vector of which views lost/gained focus. - std::vector<ViewPair> focus_changes_; -}; - -TEST_F(FocusManagerTest, FocusChangeListener) { - View* view1 = new View(); - view1->set_focusable(true); - View* view2 = new View(); - view2->set_focusable(true); - content_view_->AddChildView(view1); - content_view_->AddChildView(view2); - - TestFocusChangeListener listener; - AddFocusChangeListener(&listener); - - // Visual Studio 2010 has problems converting NULL to the null pointer for - // std::pair. See http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair - // It will work if we pass nullptr. -#if defined(_MSC_VER) && _MSC_VER >= 1600 - views::View* null_view = nullptr; -#else - views::View* null_view = NULL; -#endif - - view1->RequestFocus(); - ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view1)); - listener.ClearFocusChanges(); - - view2->RequestFocus(); - ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view1, view2)); - listener.ClearFocusChanges(); - - GetFocusManager()->ClearFocus(); - ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view2, null_view)); -} - -class TestNativeButton : public NativeTextButton { - public: - explicit TestNativeButton(const string16& text) - : NativeTextButton(NULL, text) { - }; - virtual gfx::NativeView TestGetNativeControlView() { - return GetWidget()->GetNativeView(); - } -}; - -class TestCheckbox : public Checkbox { - public: - explicit TestCheckbox(const string16& text) : Checkbox(text) { - }; - virtual gfx::NativeView TestGetNativeControlView() { - return GetWidget()->GetNativeView(); - } -}; - -class TestRadioButton : public RadioButton { - public: - explicit TestRadioButton(const string16& text) - : RadioButton(text, 1) { - } - virtual gfx::NativeView TestGetNativeControlView() { - return GetWidget()->GetNativeView(); - } -}; - -class TestTextfield : public Textfield { - public: - TestTextfield() { } - virtual gfx::NativeView TestGetNativeControlView() { - return native_wrapper_->GetTestingHandle(); - } -}; - -class TestCombobox : public Combobox, public ui::ComboboxModel { - public: - TestCombobox() : Combobox(this) { } - virtual gfx::NativeView TestGetNativeControlView() { - return native_wrapper_->GetTestingHandle(); - } - virtual int GetItemCount() { - return 10; - } - virtual string16 GetItemAt(int index) { - return ASCIIToUTF16("Hello combo"); - } -}; - -class TestTabbedPane : public TabbedPane { - public: - TestTabbedPane() { } - virtual gfx::NativeView TestGetNativeControlView() { - return native_tabbed_pane_->GetTestingHandle(); - } -}; - -#if !defined(TOUCH_UI) -// TODO(oshima): replace TOUCH_UI with PURE_VIEWS - -// Tests that NativeControls do set the focus View appropriately on the -// FocusManager. -TEST_F(FocusManagerTest, FAILS_FocusNativeControls) { - TestTextfield* textfield = new TestTextfield(); - TestTabbedPane* tabbed_pane = new TestTabbedPane(); - TestTextfield* textfield2 = new TestTextfield(); - - content_view_->AddChildView(textfield); - content_view_->AddChildView(tabbed_pane); - - tabbed_pane->AddTab(ASCIIToUTF16("Awesome textfield"), textfield2); - - // Simulate the native view getting the native focus (such as by user click). - FocusNativeView(textfield->TestGetNativeControlView()); - EXPECT_EQ(textfield, GetFocusManager()->GetFocusedView()); - - FocusNativeView(tabbed_pane->TestGetNativeControlView()); - EXPECT_EQ(tabbed_pane, GetFocusManager()->GetFocusedView()); - - FocusNativeView(textfield2->TestGetNativeControlView()); - EXPECT_EQ(textfield2, GetFocusManager()->GetFocusedView()); -} -#endif - -// On linux, we don't store/restore focused view because gtk handles -// this (and pure views will be the same). -#if defined(OS_WIN) - -// Test that when activating/deactivating the top window, the focus is stored/ -// restored properly. -TEST_F(FocusManagerTest, FocusStoreRestore) { - // Simulate an activate, otherwise the deactivate isn't going to do anything. - SimulateActivateWindow(); - - NativeTextButton* button = new NativeTextButton(NULL, - ASCIIToUTF16("Press me")); - View* view = new View(); - view->set_focusable(true); - - content_view_->AddChildView(button); - button->SetBounds(10, 10, 200, 30); - content_view_->AddChildView(view); - RunPendingMessages(); - - TestFocusChangeListener listener; - AddFocusChangeListener(&listener); - - view->RequestFocus(); - RunPendingMessages(); - // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler()); - - // Visual Studio 2010 has problems converting NULL to the null pointer for - // std::pair. See http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair - // It will work if we pass nullptr. -#if defined(_MSC_VER) && _MSC_VER >= 1600 - views::View* null_view = nullptr; -#else - views::View* null_view = NULL; -#endif - - // Deacivate the window, it should store its focus. - SimulateDeactivateWindow(); - EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view)); - EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(view, null_view)); - listener.ClearFocusChanges(); - - // Reactivate, focus should come-back to the previously focused view. - SimulateActivateWindow(); - EXPECT_EQ(view, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view)); - listener.ClearFocusChanges(); - - // Same test with a NativeControl. - button->RequestFocus(); - SimulateDeactivateWindow(); - EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view, button)); - EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(button, null_view)); - listener.ClearFocusChanges(); - - SimulateActivateWindow(); - EXPECT_EQ(button, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, button)); - listener.ClearFocusChanges(); - - /* - // Now test that while the window is inactive we can change the focused view - // (we do that in several places). - SimulateDeactivateWindow(); - // TODO: would have to mock the window being inactive (with a TestWidgetWin - // that would return false on IsActive()). - GetFocusManager()->SetFocusedView(view); - ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL); - - EXPECT_EQ(view, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(button, null_view)); - EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(null_view, view)); - */ -} -#endif - -#if !defined(TOUCH_UI) -// TODO(oshima): There is no tabbed pane in pure views. Replace it -// with different implementation. - -TEST_F(FocusManagerTest, ContainsView) { - View* view = new View(); - scoped_ptr<View> detached_view(new View()); - TabbedPane* tabbed_pane = new TabbedPane(); - TabbedPane* nested_tabbed_pane = new TabbedPane(); - NativeTextButton* tab_button = new NativeTextButton( - NULL, ASCIIToUTF16("tab button")); - - content_view_->AddChildView(view); - content_view_->AddChildView(tabbed_pane); - // Adding a View inside a TabbedPane to test the case of nested root view. - - tabbed_pane->AddTab(ASCIIToUTF16("Awesome tab"), nested_tabbed_pane); - nested_tabbed_pane->AddTab(ASCIIToUTF16("Awesomer tab"), tab_button); - - EXPECT_TRUE(GetFocusManager()->ContainsView(view)); - EXPECT_TRUE(GetFocusManager()->ContainsView(tabbed_pane)); - EXPECT_TRUE(GetFocusManager()->ContainsView(nested_tabbed_pane)); - EXPECT_TRUE(GetFocusManager()->ContainsView(tab_button)); - EXPECT_FALSE(GetFocusManager()->ContainsView(detached_view.get())); -} -#endif - -TEST_F(FocusTraversalTest, NormalTraversal) { - const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID, - kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID, - kFruitButtonID, kFruitCheckBoxID, kComboboxID, kBroccoliButtonID, - kRosettaLinkID, kStupeurEtTremblementLinkID, - kDinerGameLinkID, kRidiculeLinkID, kClosetLinkID, kVisitingLinkID, - kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID, - kTaxiLinkID, kAsterixLinkID, kOKButtonID, kCancelButtonID, kHelpButtonID, - kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID, - kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID, - kSearchTextfieldID, kSearchButtonID, kHelpLinkID, - kThumbnailContainerID, kThumbnailStarID, kThumbnailSuperStarID }; - - // Uncomment the following line if you want to test manually the UI of this - // test. - // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler()); - - // Let's traverse the whole focus hierarchy (several times, to make sure it - // loops OK). - GetFocusManager()->ClearFocus(); - for (int i = 0; i < 3; ++i) { - for (size_t j = 0; j < arraysize(kTraversalIDs); j++) { - GetFocusManager()->AdvanceFocus(false); - View* focused_view = GetFocusManager()->GetFocusedView(); - EXPECT_TRUE(focused_view != NULL); - if (focused_view) - EXPECT_EQ(kTraversalIDs[j], focused_view->id()); - } - } - - // Let's traverse in reverse order. - GetFocusManager()->ClearFocus(); - for (int i = 0; i < 3; ++i) { - for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) { - GetFocusManager()->AdvanceFocus(true); - View* focused_view = GetFocusManager()->GetFocusedView(); - EXPECT_TRUE(focused_view != NULL); - if (focused_view) - EXPECT_EQ(kTraversalIDs[j], focused_view->id()); - } - } -} - -TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) { - const int kDisabledIDs[] = { - kBananaTextfieldID, kFruitCheckBoxID, kComboboxID, kAsparagusButtonID, - kCauliflowerButtonID, kClosetLinkID, kVisitingLinkID, kBriceDeNiceLinkID, - kTaxiLinkID, kAsterixLinkID, kHelpButtonID, kBoldCheckBoxID, - kSearchTextfieldID, kHelpLinkID }; - - const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID, - kOrangeTextfieldID, kKiwiTextfieldID, kFruitButtonID, kBroccoliButtonID, - kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID, - kRidiculeLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, - kOKButtonID, kCancelButtonID, kStyleContainerID, kItalicCheckBoxID, - kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID, - kSearchButtonID, kThumbnailContainerID, kThumbnailStarID, - kThumbnailSuperStarID }; - - // Let's disable some views. - for (size_t i = 0; i < arraysize(kDisabledIDs); i++) { - View* v = FindViewByID(kDisabledIDs[i]); - ASSERT_TRUE(v != NULL); - v->SetEnabled(false); - } - - // Uncomment the following line if you want to test manually the UI of this - // test. - // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler()); - - View* focused_view; - // Let's do one traversal (several times, to make sure it loops ok). - GetFocusManager()->ClearFocus(); - for (int i = 0; i < 3; ++i) { - for (size_t j = 0; j < arraysize(kTraversalIDs); j++) { - GetFocusManager()->AdvanceFocus(false); - focused_view = GetFocusManager()->GetFocusedView(); - EXPECT_TRUE(focused_view != NULL); - if (focused_view) - EXPECT_EQ(kTraversalIDs[j], focused_view->id()); - } - } - - // Same thing in reverse. - GetFocusManager()->ClearFocus(); - for (int i = 0; i < 3; ++i) { - for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) { - GetFocusManager()->AdvanceFocus(true); - focused_view = GetFocusManager()->GetFocusedView(); - EXPECT_TRUE(focused_view != NULL); - if (focused_view) - EXPECT_EQ(kTraversalIDs[j], focused_view->id()); - } - } -} - -TEST_F(FocusTraversalTest, TraversalWithInvisibleViews) { - const int kInvisibleIDs[] = { kTopCheckBoxID, kOKButtonID, - kThumbnailContainerID }; - - const int kTraversalIDs[] = { kAppleTextfieldID, kOrangeTextfieldID, - kBananaTextfieldID, kKiwiTextfieldID, kFruitButtonID, kFruitCheckBoxID, - kComboboxID, kBroccoliButtonID, kRosettaLinkID, - kStupeurEtTremblementLinkID, kDinerGameLinkID, kRidiculeLinkID, - kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, - kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID, - kCancelButtonID, kHelpButtonID, kStyleContainerID, kBoldCheckBoxID, - kItalicCheckBoxID, kUnderlinedCheckBoxID, kStyleHelpLinkID, - kStyleTextEditID, kSearchTextfieldID, kSearchButtonID, kHelpLinkID }; - - - // Let's make some views invisible. - for (size_t i = 0; i < arraysize(kInvisibleIDs); i++) { - View* v = FindViewByID(kInvisibleIDs[i]); - ASSERT_TRUE(v != NULL); - v->SetVisible(false); - } - - // Uncomment the following line if you want to test manually the UI of this - // test. - // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler()); - - View* focused_view; - // Let's do one traversal (several times, to make sure it loops ok). - GetFocusManager()->ClearFocus(); - for (int i = 0; i < 3; ++i) { - for (size_t j = 0; j < arraysize(kTraversalIDs); j++) { - GetFocusManager()->AdvanceFocus(false); - focused_view = GetFocusManager()->GetFocusedView(); - EXPECT_TRUE(focused_view != NULL); - if (focused_view) - EXPECT_EQ(kTraversalIDs[j], focused_view->id()); - } - } - - // Same thing in reverse. - GetFocusManager()->ClearFocus(); - for (int i = 0; i < 3; ++i) { - for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) { - GetFocusManager()->AdvanceFocus(true); - focused_view = GetFocusManager()->GetFocusedView(); - EXPECT_TRUE(focused_view != NULL); - if (focused_view) - EXPECT_EQ(kTraversalIDs[j], focused_view->id()); - } - } -} - -TEST_F(FocusTraversalTest, PaneTraversal) { - // Tests trapping the traversal within a pane - useful for full - // keyboard accessibility for toolbars. - - // First test the left container. - const int kLeftTraversalIDs[] = { - kAppleTextfieldID, - kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID, - kFruitButtonID, kFruitCheckBoxID, kComboboxID }; - - FocusSearch focus_search_left(left_container_, true, false); - left_container_->EnablePaneFocus(&focus_search_left); - FindViewByID(kComboboxID)->RequestFocus(); - - // Traverse the focus hierarchy within the pane several times. - for (int i = 0; i < 3; ++i) { - for (size_t j = 0; j < arraysize(kLeftTraversalIDs); j++) { - GetFocusManager()->AdvanceFocus(false); - View* focused_view = GetFocusManager()->GetFocusedView(); - EXPECT_TRUE(focused_view != NULL); - if (focused_view) - EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id()); - } - } - - // Traverse in reverse order. - FindViewByID(kAppleTextfieldID)->RequestFocus(); - for (int i = 0; i < 3; ++i) { - for (int j = arraysize(kLeftTraversalIDs) - 1; j >= 0; --j) { - GetFocusManager()->AdvanceFocus(true); - View* focused_view = GetFocusManager()->GetFocusedView(); - EXPECT_TRUE(focused_view != NULL); - if (focused_view) - EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id()); - } - } - - // Now test the right container, but this time with accessibility mode. - // Make some links not focusable, but mark one of them as - // "accessibility focusable", so it should show up in the traversal. - const int kRightTraversalIDs[] = { - kBroccoliButtonID, kDinerGameLinkID, kRidiculeLinkID, - kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, - kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID }; - - FocusSearch focus_search_right(right_container_, true, true); - right_container_->EnablePaneFocus(&focus_search_right); - FindViewByID(kRosettaLinkID)->set_focusable(false); - FindViewByID(kStupeurEtTremblementLinkID)->set_focusable(false); - FindViewByID(kDinerGameLinkID)->set_accessibility_focusable(true); - FindViewByID(kDinerGameLinkID)->set_focusable(false); - FindViewByID(kAsterixLinkID)->RequestFocus(); - - // Traverse the focus hierarchy within the pane several times. - for (int i = 0; i < 3; ++i) { - for (size_t j = 0; j < arraysize(kRightTraversalIDs); j++) { - GetFocusManager()->AdvanceFocus(false); - View* focused_view = GetFocusManager()->GetFocusedView(); - EXPECT_TRUE(focused_view != NULL); - if (focused_view) - EXPECT_EQ(kRightTraversalIDs[j], focused_view->id()); - } - } - - // Traverse in reverse order. - FindViewByID(kBroccoliButtonID)->RequestFocus(); - for (int i = 0; i < 3; ++i) { - for (int j = arraysize(kRightTraversalIDs) - 1; j >= 0; --j) { - GetFocusManager()->AdvanceFocus(true); - View* focused_view = GetFocusManager()->GetFocusedView(); - EXPECT_TRUE(focused_view != NULL); - if (focused_view) - EXPECT_EQ(kRightTraversalIDs[j], focused_view->id()); - } - } -} - -// Counts accelerator calls. -class TestAcceleratorTarget : public ui::AcceleratorTarget { - public: - explicit TestAcceleratorTarget(bool process_accelerator) - : accelerator_count_(0), process_accelerator_(process_accelerator) {} - - virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) { - ++accelerator_count_; - return process_accelerator_; - } - - int accelerator_count() const { return accelerator_count_; } - - private: - int accelerator_count_; // number of times that the accelerator is activated - bool process_accelerator_; // return value of AcceleratorPressed - - DISALLOW_COPY_AND_ASSIGN(TestAcceleratorTarget); -}; - -TEST_F(FocusManagerTest, CallsNormalAcceleratorTarget) { - FocusManager* focus_manager = GetFocusManager(); - ui::Accelerator return_accelerator(ui::VKEY_RETURN, false, false, false); - ui::Accelerator escape_accelerator(ui::VKEY_ESCAPE, false, false, false); - - TestAcceleratorTarget return_target(true); - TestAcceleratorTarget escape_target(true); - EXPECT_EQ(return_target.accelerator_count(), 0); - EXPECT_EQ(escape_target.accelerator_count(), 0); - EXPECT_EQ(NULL, - focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); - EXPECT_EQ(NULL, - focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); - - // Register targets. - focus_manager->RegisterAccelerator(return_accelerator, &return_target); - focus_manager->RegisterAccelerator(escape_accelerator, &escape_target); - - // Checks if the correct target is registered. - EXPECT_EQ(&return_target, - focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); - EXPECT_EQ(&escape_target, - focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); - - // Hitting the return key. - EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); - EXPECT_EQ(return_target.accelerator_count(), 1); - EXPECT_EQ(escape_target.accelerator_count(), 0); - - // Hitting the escape key. - EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator)); - EXPECT_EQ(return_target.accelerator_count(), 1); - EXPECT_EQ(escape_target.accelerator_count(), 1); - - // Register another target for the return key. - TestAcceleratorTarget return_target2(true); - EXPECT_EQ(return_target2.accelerator_count(), 0); - focus_manager->RegisterAccelerator(return_accelerator, &return_target2); - EXPECT_EQ(&return_target2, - focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); - - // Hitting the return key; return_target2 has the priority. - EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); - EXPECT_EQ(return_target.accelerator_count(), 1); - EXPECT_EQ(return_target2.accelerator_count(), 1); - - // Register a target that does not process the accelerator event. - TestAcceleratorTarget return_target3(false); - EXPECT_EQ(return_target3.accelerator_count(), 0); - focus_manager->RegisterAccelerator(return_accelerator, &return_target3); - EXPECT_EQ(&return_target3, - focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); - - // Hitting the return key. - // Since the event handler of return_target3 returns false, return_target2 - // should be called too. - EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); - EXPECT_EQ(return_target.accelerator_count(), 1); - EXPECT_EQ(return_target2.accelerator_count(), 2); - EXPECT_EQ(return_target3.accelerator_count(), 1); - - // Unregister return_target2. - focus_manager->UnregisterAccelerator(return_accelerator, &return_target2); - EXPECT_EQ(&return_target3, - focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); - - // Hitting the return key. return_target3 and return_target should be called. - EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); - EXPECT_EQ(return_target.accelerator_count(), 2); - EXPECT_EQ(return_target2.accelerator_count(), 2); - EXPECT_EQ(return_target3.accelerator_count(), 2); - - // Unregister targets. - focus_manager->UnregisterAccelerator(return_accelerator, &return_target); - focus_manager->UnregisterAccelerator(return_accelerator, &return_target3); - focus_manager->UnregisterAccelerator(escape_accelerator, &escape_target); - - // Now there is no target registered. - EXPECT_EQ(NULL, - focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); - EXPECT_EQ(NULL, - focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); - - // Hitting the return key and the escape key. Nothing should happen. - EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); - EXPECT_EQ(return_target.accelerator_count(), 2); - EXPECT_EQ(return_target2.accelerator_count(), 2); - EXPECT_EQ(return_target3.accelerator_count(), 2); - EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator)); - EXPECT_EQ(escape_target.accelerator_count(), 1); -} - -// Unregisters itself when its accelerator is invoked. -class SelfUnregisteringAcceleratorTarget : public ui::AcceleratorTarget { - public: - SelfUnregisteringAcceleratorTarget(ui::Accelerator accelerator, - FocusManager* focus_manager) - : accelerator_(accelerator), - focus_manager_(focus_manager), - accelerator_count_(0) { - } - - virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) { - ++accelerator_count_; - focus_manager_->UnregisterAccelerator(accelerator, this); - return true; - } - - int accelerator_count() const { return accelerator_count_; } - - private: - ui::Accelerator accelerator_; - FocusManager* focus_manager_; - int accelerator_count_; - - DISALLOW_COPY_AND_ASSIGN(SelfUnregisteringAcceleratorTarget); -}; - -TEST_F(FocusManagerTest, CallsSelfDeletingAcceleratorTarget) { - FocusManager* focus_manager = GetFocusManager(); - ui::Accelerator return_accelerator(ui::VKEY_RETURN, false, false, false); - SelfUnregisteringAcceleratorTarget target(return_accelerator, focus_manager); - EXPECT_EQ(target.accelerator_count(), 0); - EXPECT_EQ(NULL, - focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); - - // Register the target. - focus_manager->RegisterAccelerator(return_accelerator, &target); - EXPECT_EQ(&target, - focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); - - // Hitting the return key. The target will be unregistered. - EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); - EXPECT_EQ(target.accelerator_count(), 1); - EXPECT_EQ(NULL, - focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); - - // Hitting the return key again; nothing should happen. - EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); - EXPECT_EQ(target.accelerator_count(), 1); -} - -class MessageTrackingView : public View { - public: - MessageTrackingView() : accelerator_pressed_(false) { - } - - virtual bool OnKeyPressed(const KeyEvent& e) { - keys_pressed_.push_back(e.key_code()); - return true; - } - - virtual bool OnKeyReleased(const KeyEvent& e) { - keys_released_.push_back(e.key_code()); - return true; - } - - virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) { - accelerator_pressed_ = true; - return true; - } - - void Reset() { - accelerator_pressed_ = false; - keys_pressed_.clear(); - keys_released_.clear(); - } - - const std::vector<ui::KeyboardCode>& keys_pressed() const { - return keys_pressed_; - } - - const std::vector<ui::KeyboardCode>& keys_released() const { - return keys_released_; - } - - bool accelerator_pressed() const { - return accelerator_pressed_; - } - - private: - bool accelerator_pressed_; - std::vector<ui::KeyboardCode> keys_pressed_; - std::vector<ui::KeyboardCode> keys_released_; - - DISALLOW_COPY_AND_ASSIGN(MessageTrackingView); -}; - -#if defined(OS_WIN) -// This test is now Windows only. Linux Views port does not handle accelerator -// keys in AcceleratorHandler anymore. The logic has been moved into -// NativeWidgetGtk::OnKeyEvent(). -// Tests that the keyup messages are eaten for accelerators. -TEST_F(FocusManagerTest, IgnoreKeyupForAccelerators) { - FocusManager* focus_manager = GetFocusManager(); - MessageTrackingView* mtv = new MessageTrackingView(); - mtv->AddAccelerator(ui::Accelerator(ui::VKEY_0, false, false, false)); - mtv->AddAccelerator(ui::Accelerator(ui::VKEY_1, false, false, false)); - content_view_->AddChildView(mtv); - focus_manager->SetFocusedView(mtv); - - // First send a non-accelerator key sequence. - PostKeyDown(ui::VKEY_9); - PostKeyUp(ui::VKEY_9); - AcceleratorHandler accelerator_handler; - MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); - MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler); - // Make sure we get a key-up and key-down. - ASSERT_EQ(1U, mtv->keys_pressed().size()); - EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]); - ASSERT_EQ(1U, mtv->keys_released().size()); - EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]); - EXPECT_FALSE(mtv->accelerator_pressed()); - mtv->Reset(); - - // Same thing with repeat and more than one key at once. - PostKeyDown(ui::VKEY_9); - PostKeyDown(ui::VKEY_9); - PostKeyDown(ui::VKEY_8); - PostKeyDown(ui::VKEY_9); - PostKeyDown(ui::VKEY_7); - PostKeyUp(ui::VKEY_9); - PostKeyUp(ui::VKEY_7); - PostKeyUp(ui::VKEY_8); - MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); - MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler); - // Make sure we get a key-up and key-down. - ASSERT_EQ(5U, mtv->keys_pressed().size()); - EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]); - EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[1]); - EXPECT_EQ(ui::VKEY_8, mtv->keys_pressed()[2]); - EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[3]); - EXPECT_EQ(ui::VKEY_7, mtv->keys_pressed()[4]); - ASSERT_EQ(3U, mtv->keys_released().size()); - EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]); - EXPECT_EQ(ui::VKEY_7, mtv->keys_released()[1]); - EXPECT_EQ(ui::VKEY_8, mtv->keys_released()[2]); - EXPECT_FALSE(mtv->accelerator_pressed()); - mtv->Reset(); - - // Now send an accelerator key sequence. - PostKeyDown(ui::VKEY_0); - PostKeyUp(ui::VKEY_0); - MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); - MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler); - EXPECT_TRUE(mtv->keys_pressed().empty()); - EXPECT_TRUE(mtv->keys_released().empty()); - EXPECT_TRUE(mtv->accelerator_pressed()); - mtv->Reset(); - - // Same thing with repeat and more than one key at once. - PostKeyDown(ui::VKEY_0); - PostKeyDown(ui::VKEY_1); - PostKeyDown(ui::VKEY_1); - PostKeyDown(ui::VKEY_0); - PostKeyDown(ui::VKEY_0); - PostKeyUp(ui::VKEY_1); - PostKeyUp(ui::VKEY_0); - MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); - MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler); - EXPECT_TRUE(mtv->keys_pressed().empty()); - EXPECT_TRUE(mtv->keys_released().empty()); - EXPECT_TRUE(mtv->accelerator_pressed()); - mtv->Reset(); -} -#endif - -#if defined(OS_WIN) && !defined(USE_AURA) -// Test that the focus manager is created successfully for the first view -// window parented to a native dialog. -TEST_F(FocusManagerTest, CreationForNativeRoot) { - // Create a window class. - WNDCLASSEX class_ex; - memset(&class_ex, 0, sizeof(class_ex)); - class_ex.cbSize = sizeof(WNDCLASSEX); - class_ex.lpfnWndProc = &DefWindowProc; - class_ex.lpszClassName = L"TestWindow"; - ATOM atom = RegisterClassEx(&class_ex); - ASSERT_TRUE(atom); - - // Create a native dialog window. - HWND hwnd = CreateWindowEx(0, class_ex.lpszClassName, NULL, - WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, - NULL, NULL, NULL, NULL); - ASSERT_TRUE(hwnd); - - // Create a view window parented to native dialog. - scoped_ptr<Widget> widget1(new Widget); - Widget::InitParams params(Widget::InitParams::TYPE_CONTROL); - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = hwnd; - params.bounds = gfx::Rect(0, 0, 100, 100); - params.top_level = true; // This is top level in views hierarchy. - widget1->Init(params); - - // Get the focus manager directly from the first window. Should exist - // because the first window is the root widget. - views::FocusManager* focus_manager1 = widget1->GetFocusManager(); - EXPECT_TRUE(focus_manager1); - - // Create another view window parented to the first view window. - scoped_ptr<Widget> widget2(new Widget); - params.parent = widget1->GetNativeView(); - params.top_level = false; // This is child widget. - widget2->Init(params); - - // Access the shared focus manager directly from the second window. - views::FocusManager* focus_manager2 = widget2->GetFocusManager(); - EXPECT_EQ(focus_manager2, focus_manager1); - - // Access the shared focus manager indirectly from the first window handle. - gfx::NativeWindow native_window = widget1->GetNativeWindow(); - views::Widget* widget = - views::Widget::GetWidgetForNativeWindow(native_window); - EXPECT_EQ(widget->GetFocusManager(), focus_manager1); - - // Access the shared focus manager indirectly from the second window handle. - native_window = widget2->GetNativeWindow(); - widget = views::Widget::GetWidgetForNativeWindow(native_window); - EXPECT_EQ(widget->GetFocusManager(), focus_manager1); - - // Access the shared focus manager indirectly from the first view handle. - gfx::NativeView native_view = widget1->GetNativeView(); - widget = views::Widget::GetTopLevelWidgetForNativeView(native_view); - EXPECT_EQ(widget->GetFocusManager(), focus_manager1); - - // Access the shared focus manager indirectly from the second view handle. - native_view = widget2->GetNativeView(); - widget = views::Widget::GetTopLevelWidgetForNativeView(native_view); - EXPECT_EQ(widget->GetFocusManager(), focus_manager1); - - DestroyWindow(hwnd); -} -#endif - -class FocusManagerDtorTest : public FocusManagerTest { - protected: - typedef std::vector<std::string> DtorTrackVector; - - class FocusManagerDtorTracked : public FocusManager { - public: - FocusManagerDtorTracked(Widget* widget, DtorTrackVector* dtor_tracker) - : FocusManager(widget), - dtor_tracker_(dtor_tracker) { - } - - virtual ~FocusManagerDtorTracked() { - dtor_tracker_->push_back("FocusManagerDtorTracked"); - } - - DtorTrackVector* dtor_tracker_; - - private: - DISALLOW_COPY_AND_ASSIGN(FocusManagerDtorTracked); - }; - - class TestFocusManagerFactory : public FocusManagerFactory { - public: - explicit TestFocusManagerFactory(DtorTrackVector* dtor_tracker) - : dtor_tracker_(dtor_tracker) { - } - - FocusManager* CreateFocusManager(Widget* widget) OVERRIDE { - return new FocusManagerDtorTracked(widget, dtor_tracker_); - } - - private: - DtorTrackVector* dtor_tracker_; - DISALLOW_COPY_AND_ASSIGN(TestFocusManagerFactory); - }; - - class NativeButtonDtorTracked : public NativeTextButton { - public: - NativeButtonDtorTracked(const string16& text, - DtorTrackVector* dtor_tracker) - : NativeTextButton(NULL, text), - dtor_tracker_(dtor_tracker) { - }; - virtual ~NativeButtonDtorTracked() { - dtor_tracker_->push_back("NativeButtonDtorTracked"); - } - - DtorTrackVector* dtor_tracker_; - }; - - class WindowDtorTracked : public Widget { - public: - explicit WindowDtorTracked(DtorTrackVector* dtor_tracker) - : dtor_tracker_(dtor_tracker) { - } - - virtual ~WindowDtorTracked() { - dtor_tracker_->push_back("WindowDtorTracked"); - } - - DtorTrackVector* dtor_tracker_; - }; - - virtual void SetUp() { - ViewsTestBase::SetUp(); - FocusManagerFactory::Install(new TestFocusManagerFactory(&dtor_tracker_)); - // Create WindowDtorTracked that uses FocusManagerDtorTracked. - window_ = new WindowDtorTracked(&dtor_tracker_); - Widget::InitParams params; - params.delegate = this; - params.bounds = gfx::Rect(0, 0, 100, 100); - window_->Init(params); - - tracked_focus_manager_ = - static_cast<FocusManagerDtorTracked*>(GetFocusManager()); - window_->Show(); - } - - virtual void TearDown() { - if (window_) { - window_->Close(); - RunPendingMessages(); - } - FocusManagerFactory::Install(NULL); - ViewsTestBase::TearDown(); - } - - FocusManager* tracked_focus_manager_; - DtorTrackVector dtor_tracker_; -}; - -TEST_F(FocusManagerDtorTest, FocusManagerDestructedLast) { - // Setup views hierarchy. - TabbedPane* tabbed_pane = new TabbedPane(); - content_view_->AddChildView(tabbed_pane); - - NativeButtonDtorTracked* button = new NativeButtonDtorTracked( - ASCIIToUTF16("button"), &dtor_tracker_); - tabbed_pane->AddTab(ASCIIToUTF16("Awesome tab"), button); - - // Close the window. - window_->Close(); - RunPendingMessages(); - - // Test window, button and focus manager should all be destructed. - ASSERT_EQ(3, static_cast<int>(dtor_tracker_.size())); - - // Focus manager should be the last one to destruct. - ASSERT_STREQ("FocusManagerDtorTracked", dtor_tracker_[2].c_str()); - - // Clear window_ so that we don't try to close it again. - window_ = NULL; -} - -} // namespace views diff --git a/views/focus/focus_search.cc b/views/focus/focus_search.cc deleted file mode 100644 index cbb95c5..0000000 --- a/views/focus/focus_search.cc +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright (c) 2010 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 "base/logging.h" -#include "views/focus/focus_manager.h" -#include "views/focus/focus_search.h" -#include "views/view.h" - -namespace views { - -FocusSearch::FocusSearch(View* root, bool cycle, bool accessibility_mode) - : root_(root), - cycle_(cycle), - accessibility_mode_(accessibility_mode) { -} - -View* FocusSearch::FindNextFocusableView(View* starting_view, - bool reverse, - Direction direction, - bool check_starting_view, - FocusTraversable** focus_traversable, - View** focus_traversable_view) { - *focus_traversable = NULL; - *focus_traversable_view = NULL; - - if (!root_->has_children()) { - NOTREACHED(); - // Nothing to focus on here. - return NULL; - } - - View* initial_starting_view = starting_view; - int starting_view_group = -1; - if (starting_view) - starting_view_group = starting_view->GetGroup(); - - if (!starting_view) { - // Default to the first/last child - starting_view = reverse ? root_->child_at(root_->child_count() - 1) : - root_->child_at(0); - // If there was no starting view, then the one we select is a potential - // focus candidate. - check_starting_view = true; - } else { - // The starting view should be a direct or indirect child of the root. - DCHECK(root_->Contains(starting_view)); - } - - View* v = NULL; - if (!reverse) { - v = FindNextFocusableViewImpl(starting_view, check_starting_view, - true, - (direction == DOWN) ? true : false, - starting_view_group, - focus_traversable, - focus_traversable_view); - } else { - // If the starting view is focusable, we don't want to go down, as we are - // traversing the view hierarchy tree bottom-up. - bool can_go_down = (direction == DOWN) && !IsFocusable(starting_view); - v = FindPreviousFocusableViewImpl(starting_view, check_starting_view, - true, - can_go_down, - starting_view_group, - focus_traversable, - focus_traversable_view); - } - - // Don't set the focus to something outside of this view hierarchy. - if (v && v != root_ && !root_->Contains(v)) - v = NULL; - - // If |cycle_| is true, prefer to keep cycling rather than returning NULL. - if (cycle_ && !v && initial_starting_view) { - v = FindNextFocusableView(NULL, reverse, direction, check_starting_view, - focus_traversable, focus_traversable_view); - DCHECK(IsFocusable(v)); - return v; - } - - // Doing some sanity checks. - if (v) { - DCHECK(IsFocusable(v)); - return v; - } - if (*focus_traversable) { - DCHECK(*focus_traversable_view); - return NULL; - } - // Nothing found. - return NULL; -} - -bool FocusSearch::IsViewFocusableCandidate(View* v, int skip_group_id) { - return IsFocusable(v) && - (v->IsGroupFocusTraversable() || skip_group_id == -1 || - v->GetGroup() != skip_group_id); -} - -bool FocusSearch::IsFocusable(View* v) { - if (accessibility_mode_) - return v && v->IsAccessibilityFocusableInRootView(); - - return v && v->IsFocusableInRootView(); -} - -View* FocusSearch::FindSelectedViewForGroup(View* view) { - if (view->IsGroupFocusTraversable() || - view->GetGroup() == -1) // No group for that view. - return view; - - View* selected_view = view->GetSelectedViewForGroup(view->GetGroup()); - if (selected_view) - return selected_view; - - // No view selected for that group, default to the specified view. - return view; -} - -View* FocusSearch::GetParent(View* v) { - return root_->Contains(v) ? v->parent() : NULL; -} - -// Strategy for finding the next focusable view: -// - keep going down the first child, stop when you find a focusable view or -// a focus traversable view (in that case return it) or when you reach a view -// with no children. -// - go to the right sibling and start the search from there (by invoking -// FindNextFocusableViewImpl on that view). -// - if the view has no right sibling, go up the parents until you find a parent -// with a right sibling and start the search from there. -View* FocusSearch::FindNextFocusableViewImpl( - View* starting_view, - bool check_starting_view, - bool can_go_up, - bool can_go_down, - int skip_group_id, - FocusTraversable** focus_traversable, - View** focus_traversable_view) { - if (check_starting_view) { - if (IsViewFocusableCandidate(starting_view, skip_group_id)) { - View* v = FindSelectedViewForGroup(starting_view); - // The selected view might not be focusable (if it is disabled for - // example). - if (IsFocusable(v)) - return v; - } - - *focus_traversable = starting_view->GetFocusTraversable(); - if (*focus_traversable) { - *focus_traversable_view = starting_view; - return NULL; - } - } - - // First let's try the left child. - if (can_go_down) { - if (starting_view->has_children()) { - View* v = FindNextFocusableViewImpl(starting_view->child_at(0), - true, false, true, skip_group_id, - focus_traversable, - focus_traversable_view); - if (v || *focus_traversable) - return v; - } - } - - // Then try the right sibling. - View* sibling = starting_view->GetNextFocusableView(); - if (sibling) { - View* v = FindNextFocusableViewImpl(sibling, - true, false, true, skip_group_id, - focus_traversable, - focus_traversable_view); - if (v || *focus_traversable) - return v; - } - - // Then go up to the parent sibling. - if (can_go_up) { - View* parent = GetParent(starting_view); - while (parent) { - sibling = parent->GetNextFocusableView(); - if (sibling) { - return FindNextFocusableViewImpl(sibling, - true, true, true, - skip_group_id, - focus_traversable, - focus_traversable_view); - } - parent = GetParent(parent); - } - } - - // We found nothing. - return NULL; -} - -// Strategy for finding the previous focusable view: -// - keep going down on the right until you reach a view with no children, if it -// it is a good candidate return it. -// - start the search on the left sibling. -// - if there are no left sibling, start the search on the parent (without going -// down). -View* FocusSearch::FindPreviousFocusableViewImpl( - View* starting_view, - bool check_starting_view, - bool can_go_up, - bool can_go_down, - int skip_group_id, - FocusTraversable** focus_traversable, - View** focus_traversable_view) { - // Let's go down and right as much as we can. - if (can_go_down) { - // Before we go into the direct children, we have to check if this view has - // a FocusTraversable. - *focus_traversable = starting_view->GetFocusTraversable(); - if (*focus_traversable) { - *focus_traversable_view = starting_view; - return NULL; - } - - if (starting_view->has_children()) { - View* view = - starting_view->child_at(starting_view->child_count() - 1); - View* v = FindPreviousFocusableViewImpl(view, true, false, true, - skip_group_id, - focus_traversable, - focus_traversable_view); - if (v || *focus_traversable) - return v; - } - } - - // Then look at this view. Here, we do not need to see if the view has - // a FocusTraversable, since we do not want to go down any more. - if (check_starting_view && - IsViewFocusableCandidate(starting_view, skip_group_id)) { - View* v = FindSelectedViewForGroup(starting_view); - // The selected view might not be focusable (if it is disabled for - // example). - if (IsFocusable(v)) - return v; - } - - // Then try the left sibling. - View* sibling = starting_view->GetPreviousFocusableView(); - if (sibling) { - return FindPreviousFocusableViewImpl(sibling, - true, true, true, - skip_group_id, - focus_traversable, - focus_traversable_view); - } - - // Then go up the parent. - if (can_go_up) { - View* parent = GetParent(starting_view); - if (parent) - return FindPreviousFocusableViewImpl(parent, - true, true, false, - skip_group_id, - focus_traversable, - focus_traversable_view); - } - - // We found nothing. - return NULL; -} - -} // namespace views diff --git a/views/focus/focus_search.h b/views/focus/focus_search.h index ae20a31..0ef2fc3 100644 --- a/views/focus/focus_search.h +++ b/views/focus/focus_search.h @@ -2,121 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef VIEWS_WIDGET_FOCUS_SEARCH_H_ -#define VIEWS_WIDGET_FOCUS_SEARCH_H_ +#ifndef VIEWS_FOCUS_FOCUS_SEARCH_H_ +#define VIEWS_FOCUS_FOCUS_SEARCH_H_ #pragma once -#include "views/view.h" +#include "ui/views/focus/focus_search.h" +// TODO(tfarina): remove this file once all includes have been updated. -namespace views { - -class FocusTraversable; - -// FocusSearch is an object that implements the algorithm to find the -// next view to focus. -class VIEWS_EXPORT FocusSearch { - public: - // The direction in which the focus traversal is going. - // TODO (jcampan): add support for lateral (left, right) focus traversal. The - // goal is to switch to focusable views on the same level when using the arrow - // keys (ala Windows: in a dialog box, arrow keys typically move between the - // dialog OK, Cancel buttons). - enum Direction { - UP = 0, - DOWN - }; - - // Constructor. - // - |root| is the root of the view hierarchy to traverse. Focus will be - // trapped inside. - // - |cycle| should be true if you want FindNextFocusableView to cycle back - // to the first view within this root when the traversal reaches - // the end. If this is true, then if you pass a valid starting - // view to FindNextFocusableView you will always get a valid view - // out, even if it's the same view. - // - |accessibility_mode| should be true if full keyboard accessibility is - // needed and you want to check IsAccessibilityFocusableInRootView(), - // rather than IsFocusableInRootView(). - FocusSearch(View* root, bool cycle, bool accessibility_mode); - virtual ~FocusSearch() {} - - // Finds the next view that should be focused and returns it. If a - // FocusTraversable is found while searching for the focusable view, - // returns NULL and sets |focus_traversable| to the FocusTraversable - // and |focus_traversable_view| to the view associated with the - // FocusTraversable. - // - // Return NULL if the end of the focus loop is reached, unless this object - // was initialized with |cycle|=true, in which case it goes back to the - // beginning when it reaches the end of the traversal. - // - |starting_view| is the view that should be used as the starting point - // when looking for the previous/next view. It may be NULL (in which case - // the first/last view should be used depending if normal/reverse). - // - |reverse| whether we should find the next (reverse is false) or the - // previous (reverse is true) view. - // - |direction| specifies whether we are traversing down (meaning we should - // look into child views) or traversing up (don't look at child views). - // - |check_starting_view| is true if starting_view may obtain the next focus. - // - |focus_traversable| is set to the focus traversable that should be - // traversed if one is found (in which case the call returns NULL). - // - |focus_traversable_view| is set to the view associated with the - // FocusTraversable set in the previous parameter (it is used as the - // starting view when looking for the next focusable view). - virtual View* FindNextFocusableView(View* starting_view, - bool reverse, - Direction direction, - bool check_starting_view, - FocusTraversable** focus_traversable, - View** focus_traversable_view); - - private: - // Convenience method that returns true if a view is focusable and does not - // belong to the specified group. - bool IsViewFocusableCandidate(View* v, int skip_group_id); - - // Convenience method; returns true if a view is not NULL and is focusable - // (checking IsAccessibilityFocusableInRootView() if accessibility_mode_ is - // true). - bool IsFocusable(View* v); - - // Returns the view selected for the group of the selected view. If the view - // does not belong to a group or if no view is selected in the group, the - // specified view is returned. - View* FindSelectedViewForGroup(View* view); - - // Get the parent, but stay within the root. Returns NULL if asked for - // the parent of root_. - View* GetParent(View* view); - - // Returns the next focusable view or view containing a FocusTraversable - // (NULL if none was found), starting at the starting_view. - // |check_starting_view|, |can_go_up| and |can_go_down| controls the - // traversal of the views hierarchy. |skip_group_id| specifies a group_id, - // -1 means no group. All views from a group are traversed in one pass. - View* FindNextFocusableViewImpl(View* starting_view, - bool check_starting_view, - bool can_go_up, - bool can_go_down, - int skip_group_id, - FocusTraversable** focus_traversable, - View** focus_traversable_view); - - // Same as FindNextFocusableViewImpl but returns the previous focusable view. - View* FindPreviousFocusableViewImpl(View* starting_view, - bool check_starting_view, - bool can_go_up, - bool can_go_down, - int skip_group_id, - FocusTraversable** focus_traversable, - View** focus_traversable_view); - - View* root_; - bool cycle_; - bool accessibility_mode_; - - DISALLOW_COPY_AND_ASSIGN(FocusSearch); -}; - -} // namespace views - -#endif // VIEWS_WIDGET_FOCUS_SEARCH_H_ +#endif // VIEWS_FOCUS_FOCUS_SEARCH_H_ diff --git a/views/focus/view_storage.cc b/views/focus/view_storage.cc deleted file mode 100644 index 17d3f8e..0000000 --- a/views/focus/view_storage.cc +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2006-2008 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 "views/focus/view_storage.h" - -#include <algorithm> - -#include "base/logging.h" -#include "base/stl_util.h" - -namespace views { - -// static -ViewStorage* ViewStorage::GetInstance() { - return Singleton<ViewStorage>::get(); -} - -ViewStorage::ViewStorage() : view_storage_next_id_(0) { -} - -ViewStorage::~ViewStorage() { - STLDeleteContainerPairSecondPointers(view_to_ids_.begin(), - view_to_ids_.end()); -} - -int ViewStorage::CreateStorageID() { - return view_storage_next_id_++; -} - -void ViewStorage::StoreView(int storage_id, View* view) { - DCHECK(view); - std::map<int, View*>::iterator iter = id_to_view_.find(storage_id); - - if (iter != id_to_view_.end()) { - NOTREACHED(); - RemoveView(storage_id); - } - - id_to_view_[storage_id] = view; - - std::vector<int>* ids = NULL; - std::map<View*, std::vector<int>*>::iterator id_iter = - view_to_ids_.find(view); - if (id_iter == view_to_ids_.end()) { - ids = new std::vector<int>(); - view_to_ids_[view] = ids; - } else { - ids = id_iter->second; - } - ids->push_back(storage_id); -} - -View* ViewStorage::RetrieveView(int storage_id) { - std::map<int, View*>::iterator iter = id_to_view_.find(storage_id); - if (iter == id_to_view_.end()) - return NULL; - return iter->second; -} - -void ViewStorage::RemoveView(int storage_id) { - EraseView(storage_id, false); -} - -void ViewStorage::ViewRemoved(View* removed) { - // Let's first retrieve the ids for that view. - std::map<View*, std::vector<int>*>::iterator ids_iter = - view_to_ids_.find(removed); - - if (ids_iter == view_to_ids_.end()) { - // That view is not in the view storage. - return; - } - - std::vector<int>* ids = ids_iter->second; - DCHECK(!ids->empty()); - EraseView((*ids)[0], true); -} - -void ViewStorage::EraseView(int storage_id, bool remove_all_ids) { - // Remove the view from id_to_view_location_. - std::map<int, View*>::iterator view_iter = id_to_view_.find(storage_id); - if (view_iter == id_to_view_.end()) - return; - - View* view = view_iter->second; - id_to_view_.erase(view_iter); - - // Also update view_to_ids_. - std::map<View*, std::vector<int>*>::iterator ids_iter = - view_to_ids_.find(view); - DCHECK(ids_iter != view_to_ids_.end()); - std::vector<int>* ids = ids_iter->second; - - if (remove_all_ids) { - for (size_t i = 0; i < ids->size(); ++i) { - view_iter = id_to_view_.find((*ids)[i]); - if (view_iter != id_to_view_.end()) - id_to_view_.erase(view_iter); - } - ids->clear(); - } else { - std::vector<int>::iterator id_iter = - std::find(ids->begin(), ids->end(), storage_id); - DCHECK(id_iter != ids->end()); - ids->erase(id_iter); - } - - if (ids->empty()) { - delete ids; - view_to_ids_.erase(ids_iter); - } -} - -} // namespace views diff --git a/views/focus/view_storage.h b/views/focus/view_storage.h index 8beb9e7..48037ed 100644 --- a/views/focus/view_storage.h +++ b/views/focus/view_storage.h @@ -6,65 +6,7 @@ #define VIEWS_FOCUS_VIEW_STORAGE_H_ #pragma once -#include "base/memory/singleton.h" -#include "views/view.h" - -// This class is a simple storage place for storing/retrieving views. It is -// used for example in the FocusManager to store/restore focused views when the -// main window becomes active/inactive. -// It automatically removes a view from the storage if the view is removed from -// the tree hierarchy. -// -// To use it, you first need to create a view storage id that can then be used -// to store/retrieve views. - -namespace views { - -class VIEWS_EXPORT ViewStorage { - public: - // Returns the global ViewStorage instance. - // It is guaranted to be non NULL. - static ViewStorage* GetInstance(); - - // Returns a unique storage id that can be used to store/retrieve views. - int CreateStorageID(); - - // Associates |view| with the specified |storage_id|. - void StoreView(int storage_id, View* view); - - // Returns the view associated with |storage_id| if any, NULL otherwise. - View* RetrieveView(int storage_id); - - // Removes the view associated with |storage_id| if any. - void RemoveView(int storage_id); - - // Notifies the ViewStorage that a view was removed from its parent somewhere. - void ViewRemoved(View* removed); - - size_t view_count() const { return view_to_ids_.size(); } - - private: - friend struct DefaultSingletonTraits<ViewStorage>; - - ViewStorage(); - ~ViewStorage(); - - // Removes the view associated with |storage_id|. If |remove_all_ids| is true, - // all other mapping pointing to the same view are removed as well. - void EraseView(int storage_id, bool remove_all_ids); - - // Next id for the view storage. - int view_storage_next_id_; - - // The association id to View used for the view storage. - std::map<int, View*> id_to_view_; - - // Association View to id, used to speed up view notification removal. - std::map<View*, std::vector<int>*> view_to_ids_; - - DISALLOW_COPY_AND_ASSIGN(ViewStorage); -}; - -} // namespace views +#include "ui/views/focus/view_storage.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_FOCUS_VIEW_STORAGE_H_ diff --git a/views/focus/widget_focus_manager.cc b/views/focus/widget_focus_manager.cc deleted file mode 100644 index 57cd2cd..0000000 --- a/views/focus/widget_focus_manager.cc +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2011 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 "views/focus/widget_focus_manager.h" - -#include "base/memory/singleton.h" - -namespace views { - -// WidgetFocusManager ---------------------------------------------------------- - -// static -WidgetFocusManager* WidgetFocusManager::GetInstance() { - return Singleton<WidgetFocusManager>::get(); -} - -void WidgetFocusManager::AddFocusChangeListener( - WidgetFocusChangeListener* listener) { - focus_change_listeners_.AddObserver(listener); -} - -void WidgetFocusManager::RemoveFocusChangeListener( - WidgetFocusChangeListener* listener) { - focus_change_listeners_.RemoveObserver(listener); -} - -void WidgetFocusManager::OnWidgetFocusEvent(gfx::NativeView focused_before, - gfx::NativeView focused_now) { - if (enabled_) { - FOR_EACH_OBSERVER(WidgetFocusChangeListener, focus_change_listeners_, - OnNativeFocusChange(focused_before, focused_now)); - } -} - -WidgetFocusManager::WidgetFocusManager() : enabled_(true) {} - -WidgetFocusManager::~WidgetFocusManager() {} - -// AutoNativeNotificationDisabler ---------------------------------------------- - -AutoNativeNotificationDisabler::AutoNativeNotificationDisabler() { - WidgetFocusManager::GetInstance()->DisableNotifications(); -} - -AutoNativeNotificationDisabler::~AutoNativeNotificationDisabler() { - WidgetFocusManager::GetInstance()->EnableNotifications(); -} - -} // namespace views diff --git a/views/focus/widget_focus_manager.h b/views/focus/widget_focus_manager.h index 503a158..b9f4e0a 100644 --- a/views/focus/widget_focus_manager.h +++ b/views/focus/widget_focus_manager.h @@ -6,77 +6,7 @@ #define VIEWS_FOCUS_WIDGET_FOCUS_MANAGER_H_ #pragma once -#include "base/basictypes.h" -#include "base/observer_list.h" -#include "ui/gfx/native_widget_types.h" -#include "views/views_export.h" - -template <typename T> struct DefaultSingletonTraits; - -namespace views { - -// This interface should be implemented by classes that want to be notified when -// the native focus is about to change. Listeners implementing this interface -// will be invoked for all native focus changes across the entire Chrome -// application. FocusChangeListeners are only called for changes within the -// children of a single top-level native-view. -class WidgetFocusChangeListener { - public: - virtual void OnNativeFocusChange(gfx::NativeView focused_before, - gfx::NativeView focused_now) = 0; - - protected: - virtual ~WidgetFocusChangeListener() {} -}; - -class VIEWS_EXPORT WidgetFocusManager { - public: - // Returns the singleton instance. - static WidgetFocusManager* GetInstance(); - - // Adds/removes a WidgetFocusChangeListener |listener| to the set of - // active listeners. - void AddFocusChangeListener(WidgetFocusChangeListener* listener); - void RemoveFocusChangeListener(WidgetFocusChangeListener* listener); - - // To be called when native-focus shifts from |focused_before| to - // |focused_now|. - // TODO(port) : Invocations to this routine are only implemented for - // the Win32 platform. Calls need to be placed appropriately for - // non-Windows environments. - void OnWidgetFocusEvent(gfx::NativeView focused_before, - gfx::NativeView focused_now); - - // Enable/Disable notification of registered listeners during calls - // to OnWidgetFocusEvent. Used to prevent unwanted focus changes from - // propagating notifications. - void EnableNotifications() { enabled_ = true; } - void DisableNotifications() { enabled_ = false; } - - private: - friend struct DefaultSingletonTraits<WidgetFocusManager>; - - WidgetFocusManager(); - ~WidgetFocusManager(); - - ObserverList<WidgetFocusChangeListener> focus_change_listeners_; - - bool enabled_; - - DISALLOW_COPY_AND_ASSIGN(WidgetFocusManager); -}; - -// A basic helper class that is used to disable native focus change -// notifications within a scope. -class VIEWS_EXPORT AutoNativeNotificationDisabler { - public: - AutoNativeNotificationDisabler(); - ~AutoNativeNotificationDisabler(); - - private: - DISALLOW_COPY_AND_ASSIGN(AutoNativeNotificationDisabler); -}; - -} // namespace views +#include "ui/views/focus/widget_focus_manager.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_FOCUS_WIDGET_FOCUS_MANAGER_H_ diff --git a/views/layout/box_layout.cc b/views/layout/box_layout.cc deleted file mode 100644 index 5441e87..0000000 --- a/views/layout/box_layout.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2011 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 "views/layout/box_layout.h" - -#include "ui/gfx/insets.h" -#include "ui/gfx/rect.h" -#include "views/view.h" - -namespace views { - -BoxLayout::BoxLayout(BoxLayout::Orientation orientation, - int inside_border_horizontal_spacing, - int inside_border_vertical_spacing, - int between_child_spacing) - : orientation_(orientation), - inside_border_horizontal_spacing_(inside_border_horizontal_spacing), - inside_border_vertical_spacing_(inside_border_vertical_spacing), - between_child_spacing_(between_child_spacing) { -} - -BoxLayout::~BoxLayout() { -} - -void BoxLayout::Layout(View* host) { - gfx::Rect child_area(host->GetLocalBounds()); - child_area.Inset(host->GetInsets()); - child_area.Inset(inside_border_horizontal_spacing_, - inside_border_vertical_spacing_); - int x = child_area.x(); - int y = child_area.y(); - for (int i = 0; i < host->child_count(); ++i) { - View* child = host->child_at(i); - if (child->IsVisible()) { - gfx::Rect bounds(x, y, child_area.width(), child_area.height()); - gfx::Size size(child->GetPreferredSize()); - if (orientation_ == kHorizontal) { - bounds.set_width(size.width()); - x += size.width() + between_child_spacing_; - } else { - bounds.set_height(size.height()); - y += size.height() + between_child_spacing_; - } - // Clamp child view bounds to |child_area|. - child->SetBoundsRect(bounds.Intersect(child_area)); - } - } -} - -gfx::Size BoxLayout::GetPreferredSize(View* host) { - gfx::Rect bounds; - int position = 0; - for (int i = 0; i < host->child_count(); ++i) { - View* child = host->child_at(i); - if (child->IsVisible()) { - gfx::Size size(child->GetPreferredSize()); - if (orientation_ == kHorizontal) { - gfx::Rect child_bounds(position, 0, size.width(), size.height()); - bounds = bounds.Union(child_bounds); - position += size.width(); - } else { - gfx::Rect child_bounds(0, position, size.width(), size.height()); - bounds = bounds.Union(child_bounds); - position += size.height(); - } - position += between_child_spacing_; - } - } - gfx::Insets insets(host->GetInsets()); - return gfx::Size( - bounds.width() + insets.width() + 2 * inside_border_horizontal_spacing_, - bounds.height() + insets.height() + 2 * inside_border_vertical_spacing_); -} - -} // namespace views diff --git a/views/layout/box_layout.h b/views/layout/box_layout.h index 2422bb6..88d7c24 100644 --- a/views/layout/box_layout.h +++ b/views/layout/box_layout.h @@ -6,57 +6,7 @@ #define VIEWS_LAYOUT_BOX_LAYOUT_H_ #pragma once -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "views/layout/layout_manager.h" +#include "ui/views/layout/box_layout.h" +// TODO(tfarina): remove this file once all includes have been updated. -namespace gfx { -class Size; -} - -namespace views { - -class View; - -// A Layout manager that arranges child views vertically or horizontally in a -// side-by-side fashion with spacing around and between the child views. The -// child views are always sized according to their preferred size. If the -// host's bounds provide insufficient space, child views will be clamped. -// Excess space will not be distributed. -class VIEWS_EXPORT BoxLayout : public LayoutManager { - public: - enum Orientation { - kHorizontal, - kVertical, - }; - - // Use |inside_border_horizontal_spacing| and - // |inside_border_vertical_spacing| to add additional space between the child - // view area and the host view border. |between_child_spacing| controls the - // space in between child views. - BoxLayout(Orientation orientation, - int inside_border_horizontal_spacing, - int inside_border_vertical_spacing, - int between_child_spacing); - virtual ~BoxLayout(); - - // Overridden from views::LayoutManager: - virtual void Layout(View* host) OVERRIDE; - virtual gfx::Size GetPreferredSize(View* host) OVERRIDE; - - private: - const Orientation orientation_; - - // Spacing between child views and host view border. - const int inside_border_horizontal_spacing_; - const int inside_border_vertical_spacing_; - - // Spacing to put in between child views. - const int between_child_spacing_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(BoxLayout); -}; - -} // namespace views - -#endif // VIEWS_LAYOUT_BOX_LAYOUT_H_ +#endif // VIEWS_LAYOUT_BOX_LAYOUT_H_ diff --git a/views/layout/box_layout_unittest.cc b/views/layout/box_layout_unittest.cc deleted file mode 100644 index 12ea2b5..0000000 --- a/views/layout/box_layout_unittest.cc +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h" -#include "views/layout/box_layout.h" -#include "views/view.h" - -class StaticSizedView : public views::View { - public: - explicit StaticSizedView(const gfx::Size& size) - : size_(size) { } - - virtual gfx::Size GetPreferredSize() { - return size_; - } - - private: - gfx::Size size_; -}; - -class BoxLayoutTest : public testing::Test { - public: - virtual void SetUp() { - host_.reset(new views::View); - } - - scoped_ptr<views::View> host_; - scoped_ptr<views::BoxLayout> layout_; -}; - -TEST_F(BoxLayoutTest, Empty) { - layout_.reset( - new views::BoxLayout(views::BoxLayout::kHorizontal, 10, 10, 20)); - EXPECT_EQ(gfx::Size(20, 20), layout_->GetPreferredSize(host_.get())); -} - -TEST_F(BoxLayoutTest, AlignmentHorizontal) { - layout_.reset(new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); - views::View* v1 = new StaticSizedView(gfx::Size(10, 20)); - host_->AddChildView(v1); - views::View* v2 = new StaticSizedView(gfx::Size(10, 10)); - host_->AddChildView(v2); - EXPECT_EQ(gfx::Size(20, 20), layout_->GetPreferredSize(host_.get())); - host_->SetBounds(0, 0, 20, 20); - layout_->Layout(host_.get()); - EXPECT_EQ(gfx::Rect(0, 0, 10, 20), v1->bounds()); - EXPECT_EQ(gfx::Rect(10, 0, 10, 20), v2->bounds()); -} - -TEST_F(BoxLayoutTest, AlignmentVertical) { - layout_.reset(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); - views::View* v1 = new StaticSizedView(gfx::Size(20, 10)); - host_->AddChildView(v1); - views::View* v2 = new StaticSizedView(gfx::Size(10, 10)); - host_->AddChildView(v2); - EXPECT_EQ(gfx::Size(20, 20), layout_->GetPreferredSize(host_.get())); - host_->SetBounds(0, 0, 20, 20); - layout_->Layout(host_.get()); - EXPECT_EQ(gfx::Rect(0, 0, 20, 10), v1->bounds()); - EXPECT_EQ(gfx::Rect(0, 10, 20, 10), v2->bounds()); -} - -TEST_F(BoxLayoutTest, Spacing) { - layout_.reset(new views::BoxLayout(views::BoxLayout::kHorizontal, 7, 7, 8)); - views::View* v1 = new StaticSizedView(gfx::Size(10, 20)); - host_->AddChildView(v1); - views::View* v2 = new StaticSizedView(gfx::Size(10, 20)); - host_->AddChildView(v2); - EXPECT_EQ(gfx::Size(42, 34), layout_->GetPreferredSize(host_.get())); - host_->SetBounds(0, 0, 100, 100); - layout_->Layout(host_.get()); - EXPECT_EQ(gfx::Rect(7, 7, 10, 86), v1->bounds()); - EXPECT_EQ(gfx::Rect(25, 7, 10, 86), v2->bounds()); -} - -TEST_F(BoxLayoutTest, Overflow) { - layout_.reset(new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); - views::View* v1 = new StaticSizedView(gfx::Size(20, 20)); - host_->AddChildView(v1); - views::View* v2 = new StaticSizedView(gfx::Size(10, 20)); - host_->AddChildView(v2); - host_->SetBounds(0, 0, 10, 10); - layout_->Layout(host_.get()); - EXPECT_EQ(gfx::Rect(0, 0, 10, 10), v1->bounds()); - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds()); -} - -TEST_F(BoxLayoutTest, NoSpace) { - layout_.reset( - new views::BoxLayout(views::BoxLayout::kHorizontal, 10, 10, 10)); - views::View* childView = new StaticSizedView(gfx::Size(20, 20)); - host_->AddChildView(childView); - host_->SetBounds(0, 0, 10, 10); - layout_->Layout(host_.get()); - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), childView->bounds()); -} - -TEST_F(BoxLayoutTest, InvisibleChild) { - layout_.reset( - new views::BoxLayout(views::BoxLayout::kHorizontal, 10, 10, 10)); - views::View* v1 = new StaticSizedView(gfx::Size(20, 20)); - v1->SetVisible(false); - host_->AddChildView(v1); - views::View* v2 = new StaticSizedView(gfx::Size(10, 10)); - host_->AddChildView(v2); - EXPECT_EQ(gfx::Size(30, 30), layout_->GetPreferredSize(host_.get())); - host_->SetBounds(0, 0, 30, 30); - layout_->Layout(host_.get()); - EXPECT_EQ(gfx::Rect(10, 10, 10, 10), v2->bounds()); -} diff --git a/views/layout/fill_layout.cc b/views/layout/fill_layout.cc deleted file mode 100644 index 13fbcce..0000000 --- a/views/layout/fill_layout.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2011 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 "views/layout/fill_layout.h" - -#include "base/logging.h" - -namespace views { - -FillLayout::FillLayout() { -} - -FillLayout::~FillLayout() { -} - -void FillLayout::Layout(View* host) { - if (!host->has_children()) - return; - - View* frame_view = host->child_at(0); - frame_view->SetBounds(0, 0, host->width(), host->height()); -} - -gfx::Size FillLayout::GetPreferredSize(View* host) { - DCHECK_EQ(1, host->child_count()); - return host->child_at(0)->GetPreferredSize(); -} - -} // namespace views diff --git a/views/layout/fill_layout.h b/views/layout/fill_layout.h index 20e989f..b3351b6 100644 --- a/views/layout/fill_layout.h +++ b/views/layout/fill_layout.h @@ -6,31 +6,7 @@ #define VIEWS_LAYOUT_FILL_LAYOUT_H_ #pragma once -#include "views/layout/layout_manager.h" -#include "views/view.h" - -namespace views { - -/////////////////////////////////////////////////////////////////////////////// -// -// FillLayout -// A simple LayoutManager that causes the associated view's one child to be -// sized to match the bounds of its parent. -// -/////////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT FillLayout : public LayoutManager { - public: - FillLayout(); - virtual ~FillLayout(); - - // Overridden from LayoutManager: - virtual void Layout(View* host); - virtual gfx::Size GetPreferredSize(View* host); - - private: - DISALLOW_COPY_AND_ASSIGN(FillLayout); -}; - -} // namespace views +#include "ui/views/layout/fill_layout.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_LAYOUT_FILL_LAYOUT_H_ diff --git a/views/layout/grid_layout.cc b/views/layout/grid_layout.cc deleted file mode 100644 index 55a50ceb..0000000 --- a/views/layout/grid_layout.cc +++ /dev/null @@ -1,1070 +0,0 @@ -// Copyright (c) 2011 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 "views/layout/grid_layout.h" - -#include <algorithm> - -#include "base/logging.h" -#include "base/stl_util.h" -#include "ui/gfx/insets.h" -#include "views/layout/layout_constants.h" -#include "views/view.h" - -namespace views { - -// LayoutElement ------------------------------------------------------ - -// A LayoutElement has a size and location along one axis. It contains -// methods that are used along both axis. -class LayoutElement { - public: - // Invokes ResetSize on all the layout elements. - template <class T> - static void ResetSizes(std::vector<T*>* elements) { - // Reset the layout width of each column. - for (typename std::vector<T*>::iterator i = elements->begin(); - i != elements->end(); ++i) { - (*i)->ResetSize(); - } - } - - // Sets the location of each element to be the sum of the sizes of the - // preceding elements. - template <class T> - static void CalculateLocationsFromSize(std::vector<T*>* elements) { - // Reset the layout width of each column. - int location = 0; - for (typename std::vector<T*>::iterator i = elements->begin(); - i != elements->end(); ++i) { - (*i)->SetLocation(location); - location += (*i)->Size(); - } - } - - // Distributes delta among the resizable elements. - // Each resizable element is given ResizePercent / total_percent * delta - // pixels extra of space. - template <class T> - static void DistributeDelta(int delta, std::vector<T*>* elements) { - if (delta == 0) - return; - - float total_percent = 0; - int resize_count = 0; - for (typename std::vector<T*>::iterator i = elements->begin(); - i != elements->end(); ++i) { - total_percent += (*i)->ResizePercent(); - resize_count++; - } - if (total_percent == 0) { - // None of the elements are resizable, return. - return; - } - int remaining = delta; - int resized = resize_count; - for (typename std::vector<T*>::iterator i = elements->begin(); - i != elements->end(); ++i) { - T* element = *i; - if (element->ResizePercent() > 0) { - int to_give; - if (--resized == 0) { - to_give = remaining; - } else { - to_give = static_cast<int>(delta * - (element->resize_percent_ / total_percent)); - remaining -= to_give; - } - element->SetSize(element->Size() + to_give); - } - } - } - - // Returns the sum of the size of the elements from start to start + length. - template <class T> - static int TotalSize(int start, int length, std::vector<T*>* elements) { - DCHECK(start >= 0 && length > 0 && - start + length <= static_cast<int>(elements->size())); - int size = 0; - for (int i = start, max = start + length; i < max; ++i) { - size += (*elements)[i]->Size(); - } - return size; - } - - explicit LayoutElement(float resize_percent) - : resize_percent_(resize_percent) { - DCHECK(resize_percent >= 0); - } - - virtual ~LayoutElement() {} - - void SetLocation(int location) { - location_ = location; - } - - int Location() { - return location_; - } - - // Adjusts the size of this LayoutElement to be the max of the current size - // and the specified size. - virtual void AdjustSize(int size) { - size_ = std::max(size_, size); - } - - // Resets the size to the initial size. This sets the size to 0, but - // subclasses that have a different initial size should override. - virtual void ResetSize() { - SetSize(0); - } - - void SetSize(int size) { - size_ = size; - } - - int Size() { - return size_; - } - - void SetResizePercent(float percent) { - resize_percent_ = percent; - } - - float ResizePercent() { - return resize_percent_; - } - - bool IsResizable() { - return resize_percent_ > 0; - } - - private: - float resize_percent_; - int location_; - int size_; - - DISALLOW_COPY_AND_ASSIGN(LayoutElement); -}; - -// Column ------------------------------------------------------------- - -// As the name implies, this represents a Column. Column contains default -// values for views originating in this column. -class Column : public LayoutElement { - public: - Column(GridLayout::Alignment h_align, - GridLayout::Alignment v_align, - float resize_percent, - GridLayout::SizeType size_type, - int fixed_width, - int min_width, - size_t index, - bool is_padding) - : LayoutElement(resize_percent), - h_align_(h_align), - v_align_(v_align), - size_type_(size_type), - same_size_column_(-1), - fixed_width_(fixed_width), - min_width_(min_width), - index_(index), - is_padding_(is_padding), - master_column_(NULL) {} - - virtual ~Column() {} - - GridLayout::Alignment h_align() { return h_align_; } - GridLayout::Alignment v_align() { return v_align_; } - - virtual void ResetSize(); - - private: - friend class ColumnSet; - friend class GridLayout; - - Column* GetLastMasterColumn(); - - // Determines the max size of all linked columns, and sets each column - // to that size. This should only be used for the master column. - void UnifySameSizedColumnSizes(); - - virtual void AdjustSize(int size); - - const GridLayout::Alignment h_align_; - const GridLayout::Alignment v_align_; - const GridLayout::SizeType size_type_; - int same_size_column_; - const int fixed_width_; - const int min_width_; - - // Index of this column in the ColumnSet. - const size_t index_; - - const bool is_padding_; - - // If multiple columns have their sizes linked, one is the - // master column. The master column is identified by the - // master_column field being equal to itself. The master columns - // same_size_columns field contains the set of Columns with the - // the same size. Columns who are linked to other columns, but - // are not the master column have their master_column pointing to - // one of the other linked columns. Use the method GetLastMasterColumn - // to resolve the true master column. - std::vector<Column*> same_size_columns_; - Column* master_column_; - - DISALLOW_COPY_AND_ASSIGN(Column); -}; - -void Column::ResetSize() { - if (size_type_ == GridLayout::FIXED) { - SetSize(fixed_width_); - } else { - SetSize(min_width_); - } -} - -Column* Column::GetLastMasterColumn() { - if (master_column_ == NULL) { - return NULL; - } - if (master_column_ == this) { - return this; - } - return master_column_->GetLastMasterColumn(); -} - -void Column::UnifySameSizedColumnSizes() { - DCHECK(master_column_ == this); - - // Accumulate the size first. - int size = 0; - for (std::vector<Column*>::iterator i = same_size_columns_.begin(); - i != same_size_columns_.end(); ++i) { - size = std::max(size, (*i)->Size()); - } - - // Then apply it. - for (std::vector<Column*>::iterator i = same_size_columns_.begin(); - i != same_size_columns_.end(); ++i) { - (*i)->SetSize(size); - } -} - -void Column::AdjustSize(int size) { - if (size_type_ == GridLayout::USE_PREF) - LayoutElement::AdjustSize(size); -} - -// Row ------------------------------------------------------------- - -class Row : public LayoutElement { - public: - Row(bool fixed_height, int height, float resize_percent, - ColumnSet* column_set) - : LayoutElement(resize_percent), - fixed_height_(fixed_height), - height_(height), - column_set_(column_set), - max_ascent_(0), - max_descent_(0) { - } - - virtual ~Row() {} - - virtual void ResetSize() { - max_ascent_ = max_descent_ = 0; - SetSize(height_); - } - - ColumnSet* column_set() { - return column_set_; - } - - // Adjusts the size to accomodate the specified ascent/descent. - void AdjustSizeForBaseline(int ascent, int descent) { - max_ascent_ = std::max(ascent, max_ascent_); - max_descent_ = std::max(descent, max_descent_); - AdjustSize(max_ascent_ + max_descent_); - } - - int max_ascent() const { - return max_ascent_; - } - - int max_descent() const { - return max_descent_; - } - - private: - const bool fixed_height_; - const int height_; - // The column set used for this row; null for padding rows. - ColumnSet* column_set_; - - int max_ascent_; - int max_descent_; - - DISALLOW_COPY_AND_ASSIGN(Row); -}; - -// ViewState ------------------------------------------------------------- - -// Identifies the location in the grid of a particular view, along with -// placement information and size information. -struct ViewState { - ViewState(ColumnSet* column_set, View* view, int start_col, int start_row, - int col_span, int row_span, GridLayout::Alignment h_align, - GridLayout::Alignment v_align, int pref_width, int pref_height) - : column_set(column_set), - view(view), - start_col(start_col), - start_row(start_row), - col_span(col_span), - row_span(row_span), - h_align(h_align), - v_align(v_align), - pref_width_fixed(pref_width > 0), - pref_height_fixed(pref_height > 0), - pref_width(pref_width), - pref_height(pref_height), - remaining_width(0), - remaining_height(0), - baseline(-1) { - DCHECK(view && start_col >= 0 && start_row >= 0 && col_span > 0 && - row_span > 0 && start_col < column_set->num_columns() && - (start_col + col_span) <= column_set->num_columns()); - } - - ColumnSet* const column_set; - View* const view; - const int start_col; - const int start_row; - const int col_span; - const int row_span; - const GridLayout::Alignment h_align; - const GridLayout::Alignment v_align; - - // If true, the pref_width/pref_height were explicitly set and the view's - // preferred size is ignored. - const bool pref_width_fixed; - const bool pref_height_fixed; - - // The preferred width/height. These are reset during the layout process. - int pref_width; - int pref_height; - - // Used during layout. Gives how much width/height has not yet been - // distributed to the columns/rows the view is in. - int remaining_width; - int remaining_height; - - // The baseline. Only used if the view is vertically aligned along the - // baseline. - int baseline; -}; - -static bool CompareByColumnSpan(const ViewState* v1, const ViewState* v2) { - return v1->col_span < v2->col_span; -} - -static bool CompareByRowSpan(const ViewState* v1, const ViewState* v2) { - return v1->row_span < v2->row_span; -} - -// ColumnSet ------------------------------------------------------------- - -ColumnSet::ColumnSet(int id) : id_(id) { -} - -ColumnSet::~ColumnSet() { - STLDeleteElements(&columns_); -} - -void ColumnSet::AddPaddingColumn(float resize_percent, int width) { - AddColumn(GridLayout::FILL, GridLayout::FILL, resize_percent, - GridLayout::FIXED, width, width, true); -} - -void ColumnSet::AddColumn(GridLayout::Alignment h_align, - GridLayout::Alignment v_align, - float resize_percent, - GridLayout::SizeType size_type, - int fixed_width, - int min_width) { - AddColumn(h_align, v_align, resize_percent, size_type, fixed_width, - min_width, false); -} - - -void ColumnSet::LinkColumnSizes(int first, ...) { - va_list marker; - va_start(marker, first); - DCHECK(first >= 0 && first < num_columns()); - for (int last = first, next = va_arg(marker, int); next != -1; - next = va_arg(marker, int)) { - DCHECK(next >= 0 && next < num_columns()); - columns_[last]->same_size_column_ = next; - last = next; - } - va_end(marker); -} - -void ColumnSet::AddColumn(GridLayout::Alignment h_align, - GridLayout::Alignment v_align, - float resize_percent, - GridLayout::SizeType size_type, - int fixed_width, - int min_width, - bool is_padding) { - Column* column = new Column(h_align, v_align, resize_percent, size_type, - fixed_width, min_width, columns_.size(), - is_padding); - columns_.push_back(column); -} - -void ColumnSet::AddViewState(ViewState* view_state) { - // view_states are ordered by column_span (in ascending order). - std::vector<ViewState*>::iterator i = lower_bound(view_states_.begin(), - view_states_.end(), - view_state, - CompareByColumnSpan); - view_states_.insert(i, view_state); -} - -void ColumnSet::CalculateMasterColumns() { - for (std::vector<Column*>::iterator i = columns_.begin(); - i != columns_.end(); ++i) { - Column* column = *i; - int same_size_column_index = column->same_size_column_; - if (same_size_column_index != -1) { - DCHECK(same_size_column_index >= 0 && - same_size_column_index < static_cast<int>(columns_.size())); - Column* master_column = column->master_column_; - Column* same_size_column = columns_[same_size_column_index]; - Column* same_size_column_master = same_size_column->master_column_; - if (master_column == NULL) { - // Current column is not linked to any other column. - if (same_size_column_master == NULL) { - // Both columns are not linked. - column->master_column_ = column; - same_size_column->master_column_ = column; - column->same_size_columns_.push_back(same_size_column); - column->same_size_columns_.push_back(column); - } else { - // Column to link to is linked with other columns. - // Add current column to list of linked columns in other columns - // master column. - same_size_column->GetLastMasterColumn()-> - same_size_columns_.push_back(column); - // And update the master column for the current column to that - // of the same sized column. - column->master_column_ = same_size_column; - } - } else { - // Current column is already linked with another column. - if (same_size_column_master == NULL) { - // Column to link with is not linked to any other columns. - // Update it's master_column. - same_size_column->master_column_ = column; - // Add linked column to list of linked column. - column->GetLastMasterColumn()->same_size_columns_. - push_back(same_size_column); - } else if (column->GetLastMasterColumn() != - same_size_column->GetLastMasterColumn()) { - // The two columns are already linked with other columns. - std::vector<Column*>* same_size_columns = - &(column->GetLastMasterColumn()->same_size_columns_); - std::vector<Column*>* other_same_size_columns = - &(same_size_column->GetLastMasterColumn()->same_size_columns_); - // Add all the columns from the others master to current columns - // master. - same_size_columns->insert(same_size_columns->end(), - other_same_size_columns->begin(), - other_same_size_columns->end()); - // The other master is no longer a master, clear its vector of - // linked columns, and reset its master_column. - other_same_size_columns->clear(); - same_size_column->GetLastMasterColumn()->master_column_ = column; - } - } - } - } - AccumulateMasterColumns(); -} - -void ColumnSet::AccumulateMasterColumns() { - DCHECK(master_columns_.empty()); - for (std::vector<Column*>::iterator i = columns_.begin(); - i != columns_.end(); ++i) { - Column* column = *i; - Column* master_column = column->GetLastMasterColumn(); - if (master_column && - find(master_columns_.begin(), master_columns_.end(), - master_column) == master_columns_.end()) { - master_columns_.push_back(master_column); - } - // At this point, GetLastMasterColumn may not == master_column - // (may have to go through a few Columns)_. Reset master_column to - // avoid hops. - column->master_column_ = master_column; - } -} - -void ColumnSet::UnifySameSizedColumnSizes() { - for (std::vector<Column*>::iterator i = master_columns_.begin(); - i != master_columns_.end(); ++i) { - (*i)->UnifySameSizedColumnSizes(); - } -} - -void ColumnSet::UpdateRemainingWidth(ViewState* view_state) { - for (int i = view_state->start_col; i < view_state->col_span; ++i) { - view_state->remaining_width -= columns_[i]->Size(); - } -} - -void ColumnSet::DistributeRemainingWidth(ViewState* view_state) { - // This is nearly the same as that for rows, but differs in so far as how - // Rows and Columns are treated. Rows have two states, resizable or not. - // Columns have three, resizable, USE_PREF or not resizable. This results - // in slightly different handling for distributing unaccounted size. - int width = view_state->remaining_width; - if (width <= 0) { - // The columns this view is in are big enough to accommodate it. - return; - } - - // Determine which columns are resizable, and which have a size type - // of USE_PREF. - int resizable_columns = 0; - int pref_size_columns = 0; - int start_col = view_state->start_col; - int max_col = view_state->start_col + view_state->col_span; - float total_resize = 0; - for (int i = start_col; i < max_col; ++i) { - if (columns_[i]->IsResizable()) { - total_resize += columns_[i]->ResizePercent(); - resizable_columns++; - } else if (columns_[i]->size_type_ == GridLayout::USE_PREF) { - pref_size_columns++; - } - } - - if (resizable_columns > 0) { - // There are resizable columns, give them the remaining width. The extra - // width is distributed using the resize values of each column. - int remaining_width = width; - for (int i = start_col, resize_i = 0; i < max_col; ++i) { - if (columns_[i]->IsResizable()) { - resize_i++; - int delta = (resize_i == resizable_columns) ? remaining_width : - static_cast<int>(width * columns_[i]->ResizePercent() / - total_resize); - remaining_width -= delta; - columns_[i]->SetSize(columns_[i]->Size() + delta); - } - } - } else if (pref_size_columns > 0) { - // None of the columns are resizable, distribute the width among those - // that use the preferred size. - int to_distribute = width / pref_size_columns; - for (int i = start_col; i < max_col; ++i) { - if (columns_[i]->size_type_ == GridLayout::USE_PREF) { - width -= to_distribute; - if (width < to_distribute) - to_distribute += width; - columns_[i]->SetSize(columns_[i]->Size() + to_distribute); - } - } - } -} - -int ColumnSet::LayoutWidth() { - int width = 0; - for (std::vector<Column*>::iterator i = columns_.begin(); - i != columns_.end(); ++i) { - width += (*i)->Size(); - } - return width; -} - -int ColumnSet::GetColumnWidth(int start_col, int col_span) { - return LayoutElement::TotalSize(start_col, col_span, &columns_); -} - -void ColumnSet::ResetColumnXCoordinates() { - LayoutElement::CalculateLocationsFromSize(&columns_); -} - -void ColumnSet::CalculateSize() { - gfx::Size pref; - // Reset the preferred and remaining sizes. - for (std::vector<ViewState*>::iterator i = view_states_.begin(); - i != view_states_.end(); ++i) { - ViewState* view_state = *i; - if (!view_state->pref_width_fixed || !view_state->pref_height_fixed) { - pref = view_state->view->GetPreferredSize(); - if (!view_state->pref_width_fixed) - view_state->pref_width = pref.width(); - if (!view_state->pref_height_fixed) - view_state->pref_height = pref.height(); - } - view_state->remaining_width = pref.width(); - view_state->remaining_height = pref.height(); - } - - // Let layout element reset the sizes for us. - LayoutElement::ResetSizes(&columns_); - - // Distribute the size of each view with a col span == 1. - std::vector<ViewState*>::iterator view_state_iterator = - view_states_.begin(); - for (; view_state_iterator != view_states_.end() && - (*view_state_iterator)->col_span == 1; ++view_state_iterator) { - ViewState* view_state = *view_state_iterator; - Column* column = columns_[view_state->start_col]; - column->AdjustSize(view_state->pref_width); - view_state->remaining_width -= column->Size(); - } - - // Make sure all linked columns have the same size. - UnifySameSizedColumnSizes(); - - // Distribute the size of each view with a column span > 1. - for (; view_state_iterator != view_states_.end(); ++view_state_iterator) { - ViewState* view_state = *view_state_iterator; - - // Update the remaining_width from columns this view_state touches. - UpdateRemainingWidth(view_state); - - // Distribute the remaining width. - DistributeRemainingWidth(view_state); - - // Update the size of linked columns. - // This may need to be combined with previous step. - UnifySameSizedColumnSizes(); - } -} - -void ColumnSet::Resize(int delta) { - LayoutElement::DistributeDelta(delta, &columns_); -} - -// GridLayout ------------------------------------------------------------- - -GridLayout::GridLayout(View* host) - : host_(host), - calculated_master_columns_(false), - remaining_row_span_(0), - current_row_(-1), - next_column_(0), - current_row_col_set_(NULL), - top_inset_(0), - bottom_inset_(0), - left_inset_(0), - right_inset_(0), - adding_view_(false) { - DCHECK(host); -} - -GridLayout::~GridLayout() { - STLDeleteElements(&column_sets_); - STLDeleteElements(&view_states_); - STLDeleteElements(&rows_); -} - -// static -GridLayout* GridLayout::CreatePanel(View* host) { - GridLayout* layout = new GridLayout(host); - layout->SetInsets(kPanelVertMargin, kPanelHorizMargin, - kPanelVertMargin, kPanelHorizMargin); - return layout; -} - -void GridLayout::SetInsets(int top, int left, int bottom, int right) { - top_inset_ = top; - bottom_inset_ = bottom; - left_inset_ = left; - right_inset_ = right; -} - -void GridLayout::SetInsets(const gfx::Insets& insets) { - SetInsets(insets.top(), insets.left(), insets.bottom(), insets.right()); -} - -ColumnSet* GridLayout::AddColumnSet(int id) { - DCHECK(GetColumnSet(id) == NULL); - ColumnSet* column_set = new ColumnSet(id); - column_sets_.push_back(column_set); - return column_set; -} - -void GridLayout::StartRowWithPadding(float vertical_resize, int column_set_id, - float padding_resize, int padding) { - AddPaddingRow(padding_resize, padding); - StartRow(vertical_resize, column_set_id); -} - -void GridLayout::StartRow(float vertical_resize, int column_set_id) { - ColumnSet* column_set = GetColumnSet(column_set_id); - DCHECK(column_set); - AddRow(new Row(false, 0, vertical_resize, column_set)); -} - -void GridLayout::AddPaddingRow(float vertical_resize, int pixel_count) { - AddRow(new Row(true, pixel_count, vertical_resize, NULL)); -} - -void GridLayout::SkipColumns(int col_count) { - DCHECK(col_count > 0); - next_column_ += col_count; - DCHECK(current_row_col_set_ && - next_column_ <= current_row_col_set_->num_columns()); - SkipPaddingColumns(); -} - -void GridLayout::AddView(View* view) { - AddView(view, 1, 1); -} - -void GridLayout::AddView(View* view, int col_span, int row_span) { - DCHECK(current_row_col_set_ && - next_column_ < current_row_col_set_->num_columns()); - Column* column = current_row_col_set_->columns_[next_column_]; - AddView(view, col_span, row_span, column->h_align(), column->v_align()); -} - -void GridLayout::AddView(View* view, int col_span, int row_span, - Alignment h_align, Alignment v_align) { - AddView(view, col_span, row_span, h_align, v_align, 0, 0); -} - -void GridLayout::AddView(View* view, int col_span, int row_span, - Alignment h_align, Alignment v_align, - int pref_width, int pref_height) { - DCHECK(current_row_col_set_ && col_span > 0 && row_span > 0 && - (next_column_ + col_span) <= current_row_col_set_->num_columns()); - // We don't support baseline alignment of views spanning rows. Please add if - // you need it. - DCHECK(v_align != BASELINE || row_span == 1); - ViewState* state = - new ViewState(current_row_col_set_, view, next_column_, current_row_, - col_span, row_span, h_align, v_align, pref_width, - pref_height); - AddViewState(state); -} - -static void CalculateSize(int pref_size, GridLayout::Alignment alignment, - int* location, int* size) { - if (alignment != GridLayout::FILL) { - int available_size = *size; - *size = std::min(*size, pref_size); - switch (alignment) { - case GridLayout::LEADING: - // Nothing to do, location already points to start. - break; - case GridLayout::BASELINE: // If we were asked to align on baseline, but - // the view doesn't have a baseline, fall back - // to center. - case GridLayout::CENTER: - *location += (available_size - *size) / 2; - break; - case GridLayout::TRAILING: - *location = *location + available_size - *size; - break; - default: - NOTREACHED(); - } - } -} - -void GridLayout::Installed(View* host) { - DCHECK(host_ == host); -} - -void GridLayout::Uninstalled(View* host) { - DCHECK(host_ == host); -} - -void GridLayout::ViewAdded(View* host, View* view) { - DCHECK(host_ == host && adding_view_); -} - -void GridLayout::ViewRemoved(View* host, View* view) { - DCHECK(host_ == host); -} - -void GridLayout::Layout(View* host) { - DCHECK(host_ == host); - // SizeRowsAndColumns sets the size and location of each row/column, but - // not of the views. - gfx::Size pref; - SizeRowsAndColumns(true, host_->width(), host_->height(), &pref); - - // Size each view. - for (std::vector<ViewState*>::iterator i = view_states_.begin(); - i != view_states_.end(); ++i) { - ViewState* view_state = *i; - ColumnSet* column_set = view_state->column_set; - View* view = (*i)->view; - DCHECK(view); - int x = column_set->columns_[view_state->start_col]->Location() + - left_inset_; - int width = column_set->GetColumnWidth(view_state->start_col, - view_state->col_span); - CalculateSize(view_state->pref_width, view_state->h_align, - &x, &width); - int y = rows_[view_state->start_row]->Location() + top_inset_; - int height = LayoutElement::TotalSize(view_state->start_row, - view_state->row_span, &rows_); - if (view_state->v_align == BASELINE && view_state->baseline != -1) { - y += rows_[view_state->start_row]->max_ascent() - view_state->baseline; - height = view_state->pref_height; - } else { - CalculateSize(view_state->pref_height, view_state->v_align, &y, &height); - } - view->SetBounds(x, y, width, height); - } -} - -gfx::Size GridLayout::GetPreferredSize(View* host) { - DCHECK(host_ == host); - gfx::Size out; - SizeRowsAndColumns(false, 0, 0, &out); - return out; -} - -int GridLayout::GetPreferredHeightForWidth(View* host, int width) { - DCHECK(host_ == host); - gfx::Size pref; - SizeRowsAndColumns(false, width, 0, &pref); - return pref.height(); -} - -void GridLayout::SizeRowsAndColumns(bool layout, int width, int height, - gfx::Size* pref) { - // Make sure the master columns have been calculated. - CalculateMasterColumnsIfNecessary(); - pref->SetSize(0, 0); - if (rows_.empty()) - return; - - // Calculate the preferred width of each of the columns. Some views' - // preferred heights are derived from their width, as such we need to - // calculate the size of the columns first. - for (std::vector<ColumnSet*>::iterator i = column_sets_.begin(); - i != column_sets_.end(); ++i) { - (*i)->CalculateSize(); - pref->set_width(std::max(pref->width(), (*i)->LayoutWidth())); - } - pref->set_width(pref->width() + left_inset_ + right_inset_); - - // Go over the columns again and set them all to the size we settled for. - width = width ? width : pref->width(); - for (std::vector<ColumnSet*>::iterator i = column_sets_.begin(); - i != column_sets_.end(); ++i) { - // We're doing a layout, divy up any extra space. - (*i)->Resize(width - (*i)->LayoutWidth() - left_inset_ - right_inset_); - // And reset the x coordinates. - (*i)->ResetColumnXCoordinates(); - } - - // Reset the height of each row. - LayoutElement::ResetSizes(&rows_); - - // Do the following: - // . If the view is aligned along it's baseline, obtain the baseline from the - // view and update the rows ascent/descent. - // . Reset the remaining_height of each view state. - // . If the width the view will be given is different than it's pref, ask - // for the height given a particularly width. - for (std::vector<ViewState*>::iterator i= view_states_.begin(); - i != view_states_.end() ; ++i) { - ViewState* view_state = *i; - view_state->remaining_height = view_state->pref_height; - - if (view_state->v_align == BASELINE) - view_state->baseline = view_state->view->GetBaseline(); - - if (view_state->h_align == FILL) { - // The view is resizable. As the pref height may vary with the width, - // ask for the pref again. - int actual_width = - view_state->column_set->GetColumnWidth(view_state->start_col, - view_state->col_span); - if (actual_width != view_state->pref_width && - !view_state->pref_height_fixed) { - // The width this view will get differs from it's preferred. Some Views - // pref height varies with it's width; ask for the preferred again. - view_state->pref_height = - view_state->view->GetHeightForWidth(actual_width); - view_state->remaining_height = view_state->pref_height; - } - } - } - - // Update the height/ascent/descent of each row from the views. - std::vector<ViewState*>::iterator view_states_iterator = view_states_.begin(); - for (; view_states_iterator != view_states_.end() && - (*view_states_iterator)->row_span == 1; ++view_states_iterator) { - ViewState* view_state = *view_states_iterator; - Row* row = rows_[view_state->start_row]; - row->AdjustSize(view_state->remaining_height); - if (view_state->baseline != -1 && - view_state->baseline <= view_state->pref_height) { - row->AdjustSizeForBaseline(view_state->baseline, - view_state->pref_height - view_state->baseline); - } - view_state->remaining_height = 0; - } - - // Distribute the height of each view with a row span > 1. - for (; view_states_iterator != view_states_.end(); ++view_states_iterator) { - ViewState* view_state = *view_states_iterator; - - // Update the remaining_width from columns this view_state touches. - UpdateRemainingHeightFromRows(view_state); - - // Distribute the remaining height. - DistributeRemainingHeight(view_state); - } - - // Update the location of each of the rows. - LayoutElement::CalculateLocationsFromSize(&rows_); - - // We now know the preferred height, set it here. - pref->set_height(rows_[rows_.size() - 1]->Location() + - rows_[rows_.size() - 1]->Size() + top_inset_ + bottom_inset_); - - if (layout && height != pref->height()) { - // We're doing a layout, and the height differs from the preferred height, - // divy up the extra space. - LayoutElement::DistributeDelta(height - pref->height(), &rows_); - - // Reset y locations. - LayoutElement::CalculateLocationsFromSize(&rows_); - } -} - -void GridLayout::CalculateMasterColumnsIfNecessary() { - if (!calculated_master_columns_) { - calculated_master_columns_ = true; - for (std::vector<ColumnSet*>::iterator i = column_sets_.begin(); - i != column_sets_.end(); ++i) { - (*i)->CalculateMasterColumns(); - } - } -} - -void GridLayout::AddViewState(ViewState* view_state) { - DCHECK(view_state->view && (view_state->view->parent() == NULL || - view_state->view->parent() == host_)); - if (!view_state->view->parent()) { - adding_view_ = true; - host_->AddChildView(view_state->view); - adding_view_ = false; - } - remaining_row_span_ = std::max(remaining_row_span_, view_state->row_span); - next_column_ += view_state->col_span; - current_row_col_set_->AddViewState(view_state); - // view_states are ordered by row_span (in ascending order). - std::vector<ViewState*>::iterator i = lower_bound(view_states_.begin(), - view_states_.end(), - view_state, - CompareByRowSpan); - view_states_.insert(i, view_state); - SkipPaddingColumns(); -} - -ColumnSet* GridLayout::GetColumnSet(int id) { - for (std::vector<ColumnSet*>::iterator i = column_sets_.begin(); - i != column_sets_.end(); ++i) { - if ((*i)->id_ == id) { - return *i; - } - } - return NULL; -} - -void GridLayout::AddRow(Row* row) { - current_row_++; - remaining_row_span_--; - DCHECK(remaining_row_span_ <= 0 || - row->column_set() == NULL || - row->column_set() == GetLastValidColumnSet()); - next_column_ = 0; - rows_.push_back(row); - current_row_col_set_ = row->column_set(); - SkipPaddingColumns(); -} - -void GridLayout::UpdateRemainingHeightFromRows(ViewState* view_state) { - for (int i = 0, start_row = view_state->start_row; - i < view_state->row_span; ++i) { - view_state->remaining_height -= rows_[i + start_row]->Size(); - } -} - -void GridLayout::DistributeRemainingHeight(ViewState* view_state) { - int height = view_state->remaining_height; - if (height <= 0) - return; - - // Determine the number of resizable rows the view touches. - int resizable_rows = 0; - int start_row = view_state->start_row; - int max_row = view_state->start_row + view_state->row_span; - for (int i = start_row; i < max_row; ++i) { - if (rows_[i]->IsResizable()) { - resizable_rows++; - } - } - - if (resizable_rows > 0) { - // There are resizable rows, give the remaining height to them. - int to_distribute = height / resizable_rows; - for (int i = start_row; i < max_row; ++i) { - if (rows_[i]->IsResizable()) { - height -= to_distribute; - if (height < to_distribute) { - // Give all slop to the last column. - to_distribute += height; - } - rows_[i]->SetSize(rows_[i]->Size() + to_distribute); - } - } - } else { - // None of the rows are resizable, divy the remaining height up equally - // among all rows the view touches. - int each_row_height = height / view_state->row_span; - for (int i = start_row; i < max_row; ++i) { - height -= each_row_height; - if (height < each_row_height) - each_row_height += height; - rows_[i]->SetSize(rows_[i]->Size() + each_row_height); - } - view_state->remaining_height = 0; - } -} - -void GridLayout::SkipPaddingColumns() { - if (!current_row_col_set_) - return; - while (next_column_ < current_row_col_set_->num_columns() && - current_row_col_set_->columns_[next_column_]->is_padding_) { - next_column_++; - } -} - -ColumnSet* GridLayout::GetLastValidColumnSet() { - for (int i = current_row_ - 1; i >= 0; --i) { - if (rows_[i]->column_set()) - return rows_[i]->column_set(); - } - return NULL; -} - -} // namespace views diff --git a/views/layout/grid_layout.h b/views/layout/grid_layout.h index ddfaf8e..790030e 100644 --- a/views/layout/grid_layout.h +++ b/views/layout/grid_layout.h @@ -6,366 +6,7 @@ #define VIEWS_LAYOUT_GRID_LAYOUT_H_ #pragma once -#include <string> -#include <vector> - -#include "views/layout/layout_manager.h" -#include "views/view.h" - -namespace gfx { -class Insets; -} - -// GridLayout is a LayoutManager that positions child Views in a grid. You -// define the structure of the Grid first, then add the Views. -// The following creates a trivial grid with two columns separated by -// a column with padding: -// ColumnSet* columns = layout->AddColumnSet(0); // Give this column an -// // identifier of 0. -// columns->AddColumn(FILL, // Views are horizontally resized to fill column. -// FILL, // Views starting in this column are vertically -// // resized. -// 1, // This column has a resize weight of 1. -// USE_PREF, // Use the preferred size of the view. -// 0, // Ignored for USE_PREF. -// 0); // A minimum width of 0. -// columns->AddPaddingColumn(0, // The padding column is not resizable. -// 10); // And has a width of 10 pixels. -// columns->AddColumn(FILL, FILL, 0, USE_PREF, 0, 0); -// Now add the views: -// // First start a row. -// layout->StartRow(0, // This row isn't vertically resizable. -// 0); // The column set to use for this row. -// layout->AddView(v1); -// Notice you need not skip over padding columns, that's done for you. -// layout->AddView(v2); -// -// When adding a Column you give it the default alignment for all views -// originating in that column. You can override this for specific views -// when adding them. For example, the following forces a View to have -// a horizontal and vertical alignment of leading regardless of that defined -// for the column: -// layout->AddView(v1, 1, 1, LEADING, LEADING); -// -// If the View using GridLayout is given a size bigger than the preferred, -// columns and rows with a resize percent > 0 are resized. Each column/row -// is given resize_percent / total_resize_percent * extra_pixels extra -// pixels. Only Views with an Alignment of FILL are given extra space, others -// are aligned in the provided space. -// -// GridLayout allows you to define multiple column sets. When you start a -// new row you specify the id of the column set the row is to use. -// -// GridLayout allows you to force columns to have the same width. This is -// done using the LinkColumnSizes method. -// -// AddView takes care of adding the View to the View the GridLayout was -// created with. -namespace views { - -class Column; -class ColumnSet; -class Row; -class View; - -struct ViewState; - -class VIEWS_EXPORT GridLayout : public LayoutManager { - public: - // An enumeration of the possible alignments supported by GridLayout. - enum Alignment { - // Leading equates to left along the horizontal axis, and top along the - // vertical axis. - LEADING, - - // Centers the view along the axis. - CENTER, - - // Trailing equals to right along the horizontal axis, and bottom along - // the vertical axis. - TRAILING, - - // The view is resized to fill the space. - FILL, - - // The view is aligned along the baseline. This is only valid for the - // vertical axis. - BASELINE - }; - - // An enumeration of the possible ways the size of a column may be obtained. - enum SizeType { - // The column size is fixed. - FIXED, - - // The preferred size of the view is used to determine the column size. - USE_PREF - }; - - explicit GridLayout(View* host); - virtual ~GridLayout(); - - // Creates a GridLayout with kPanel*Margin insets. - static GridLayout* CreatePanel(View* host); - - // Sets the insets. All views are placed relative to these offsets. - void SetInsets(int top, int left, int bottom, int right); - void SetInsets(const gfx::Insets& insets); - - // Creates a new column set with the specified id and returns it. - // The id is later used when starting a new row. - // GridLayout takes ownership of the ColumnSet and will delete it when - // the GridLayout is deleted. - ColumnSet* AddColumnSet(int id); - - // Adds a padding row. Padding rows typically don't have any views, and - // but are used to provide vertical white space between views. - // Size specifies the height of the row. - void AddPaddingRow(float vertical_resize, int size); - - // A convenience for AddPaddingRow followed by StartRow. - void StartRowWithPadding(float vertical_resize, int column_set_id, - float padding_resize, int padding); - - // Starts a new row with the specified column set. - void StartRow(float vertical_resize, int column_set_id); - - // Advances past columns. Use this when the current column should not - // contain any views. - void SkipColumns(int col_count); - - // Adds a view using the default alignment from the column. The added - // view has a column and row span of 1. - // As a convenience this adds the view to the host. The view becomes owned - // by the host, and NOT this GridLayout. - void AddView(View* view); - - // Adds a view using the default alignment from the column. - // As a convenience this adds the view to the host. The view becomes owned - // by the host, and NOT this GridLayout. - void AddView(View* view, int col_span, int row_span); - - // Adds a view with the specified alignment and spans. - // As a convenience this adds the view to the host. The view becomes owned - // by the host, and NOT this GridLayout. - void AddView(View* view, int col_span, int row_span, Alignment h_align, - Alignment v_align); - - // Adds a view with the specified alignment and spans. If - // pref_width/pref_height is > 0 then the preferred width/height of the view - // is fixed to the specified value. - // As a convenience this adds the view to the host. The view becomes owned - // by the host, and NOT this GridLayout. - void AddView(View* view, int col_span, int row_span, - Alignment h_align, Alignment v_align, - int pref_width, int pref_height); - - // Notification we've been installed on a particular host. Checks that host - // is the same as the View supplied in the constructor. - virtual void Installed(View* host); - - // Notification we've been uninstalled on a particular host. Checks that host - // is the same as the View supplied in the constructor. - virtual void Uninstalled(View* host); - - // Notification that a view has been added. - virtual void ViewAdded(View* host, View* view); - - // Notification that a view has been removed. - virtual void ViewRemoved(View* host, View* view); - - // Layouts out the components. - virtual void Layout(View* host); - - // Returns the preferred size for the GridLayout. - virtual gfx::Size GetPreferredSize(View* host); - - virtual int GetPreferredHeightForWidth(View* host, int width); - - private: - // As both Layout and GetPreferredSize need to do nearly the same thing, - // they both call into this method. This sizes the Columns/Rows as - // appropriate. If layout is true, width/height give the width/height the - // of the host, otherwise they are ignored. - void SizeRowsAndColumns(bool layout, int width, int height, gfx::Size* pref); - - // Calculates the master columns of all the column sets. See Column for - // a description of what a master column is. - void CalculateMasterColumnsIfNecessary(); - - // This is called internally from AddView. It adds the ViewState to the - // appropriate structures, and updates internal fields such as next_column_. - void AddViewState(ViewState* view_state); - - // Returns the column set for the specified id, or NULL if one doesn't exist. - ColumnSet* GetColumnSet(int id); - - // Adds the Row to rows_, as well as updating next_column_, - // current_row_col_set ... - void AddRow(Row* row); - - // As the name says, updates the remaining_height of the ViewState for - // all Rows the supplied ViewState touches. - void UpdateRemainingHeightFromRows(ViewState* state); - - // If the view state's remaining height is > 0, it is distributed among - // the rows the view state touches. This is used during layout to make - // sure the Rows can accommodate a view. - void DistributeRemainingHeight(ViewState* state); - - // Advances next_column_ past any padding columns. - void SkipPaddingColumns(); - - // Returns the column set of the last non-padding row. - ColumnSet* GetLastValidColumnSet(); - - // The view we were created with. We don't own this. - View* const host_; - - // Whether or not we've calculated the master/linked columns. - bool calculated_master_columns_; - - // Used to verify a view isn't added with a row span that expands into - // another column structure. - int remaining_row_span_; - - // Current row. - int current_row_; - - // Current column. - int next_column_; - - // Column set for the current row. This is null for padding rows. - ColumnSet* current_row_col_set_; - - // Insets. - int top_inset_; - int bottom_inset_; - int left_inset_; - int right_inset_; - - // Set to true when adding a View. - bool adding_view_; - - // ViewStates. This is ordered by row_span in ascending order. - std::vector<ViewState*> view_states_; - - // ColumnSets. - std::vector<ColumnSet*> column_sets_; - - // Rows. - std::vector<Row*> rows_; - - DISALLOW_COPY_AND_ASSIGN(GridLayout); -}; - -// ColumnSet is used to define a set of columns. GridLayout may have any -// number of ColumnSets. You don't create a ColumnSet directly, instead -// use the AddColumnSet method of GridLayout. -class VIEWS_EXPORT ColumnSet { - public: - ~ColumnSet(); - - // Adds a column for padding. When adding views, padding columns are - // automatically skipped. For example, if you create a column set with - // two columns separated by a padding column, the first AddView automatically - // skips past the padding column. That is, to add two views, do: - // layout->AddView(v1); layout->AddView(v2);, not: - // layout->AddView(v1); layout->SkipColumns(1); layout->AddView(v2); - void AddPaddingColumn(float resize_percent, int width); - - // Adds a column. The alignment gives the default alignment for views added - // with no explicit alignment. fixed_width gives a specific width for the - // column, and is only used if size_type == FIXED. min_width gives the - // minimum width for the column. - // - // If none of the columns in a columnset are resizable, the views are only - // made as wide as the widest views in each column, even if extra space is - // provided. In other words, GridLayout does not automatically resize views - // unless the column is marked as resizable. - void AddColumn(GridLayout::Alignment h_align, - GridLayout::Alignment v_align, - float resize_percent, - GridLayout::SizeType size_type, - int fixed_width, - int min_width); - - // Forces the specified columns to have the same size. The size of - // linked columns is that of the max of the specified columns. This - // must end with -1. For example, the following forces the first and - // second column to have the same size: - // LinkColumnSizes(0, 1, -1); - void LinkColumnSizes(int first, ...); - - // ID of this ColumnSet. - int id() const { return id_; } - - int num_columns() { return static_cast<int>(columns_.size()); } - - private: - friend class GridLayout; - - explicit ColumnSet(int id); - - void AddColumn(GridLayout::Alignment h_align, - GridLayout::Alignment v_align, - float resize_percent, - GridLayout::SizeType size_type, - int fixed_width, - int min_width, - bool is_padding); - - void AddViewState(ViewState* view_state); - - // Set description of these. - void CalculateMasterColumns(); - void AccumulateMasterColumns(); - - // Sets the size of each linked column to be the same. - void UnifySameSizedColumnSizes(); - - // Updates the remaining width field of the ViewState from that of the - // columns the view spans. - void UpdateRemainingWidth(ViewState* view_state); - - // Makes sure the columns touched by view state are big enough for the - // view. - void DistributeRemainingWidth(ViewState* view_state); - - // Returns the total size needed for this ColumnSet. - int LayoutWidth(); - - // Returns the width of the specified columns. - int GetColumnWidth(int start_col, int col_span); - - // Updates the x coordinate of each column from the previous ones. - // NOTE: this doesn't include the insets. - void ResetColumnXCoordinates(); - - // Calculate the preferred width of each view in this column set, as well - // as updating the remaining_width. - void CalculateSize(); - - // Distributes delta amoung the resizable columns. - void Resize(int delta); - - // ID for this columnset. - const int id_; - - // The columns. - std::vector<Column*> columns_; - - // The ViewStates. This is sorted based on column_span in ascending - // order. - std::vector<ViewState*> view_states_; - - // The master column of those columns that are linked. See Column - // for a description of what the master column is. - std::vector<Column*> master_columns_; - - DISALLOW_COPY_AND_ASSIGN(ColumnSet); -}; - -} // namespace views +#include "ui/views/layout/grid_layout.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_LAYOUT_GRID_LAYOUT_H_ diff --git a/views/layout/grid_layout_unittest.cc b/views/layout/grid_layout_unittest.cc deleted file mode 100644 index 542d7c5..0000000 --- a/views/layout/grid_layout_unittest.cc +++ /dev/null @@ -1,606 +0,0 @@ -// Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h" -#include "views/layout/grid_layout.h" -#include "views/view.h" - -using views::ColumnSet; -using views::GridLayout; -using views::View; - -static void ExpectViewBoundsEquals(int x, int y, int w, int h, - const View* view) { - EXPECT_EQ(x, view->x()); - EXPECT_EQ(y, view->y()); - EXPECT_EQ(w, view->width()); - EXPECT_EQ(h, view->height()); -} - -class SettableSizeView : public View { - public: - explicit SettableSizeView(const gfx::Size& pref) { - pref_ = pref; - } - - virtual gfx::Size GetPreferredSize() { - return pref_; - } - - private: - gfx::Size pref_; -}; - -// A view with fixed circumference that trades height for width. -class FlexibleView : public View { - public: - explicit FlexibleView(int circumference) { - circumference_ = circumference; - } - - virtual gfx::Size GetPreferredSize() { - return gfx::Size(0, circumference_ / 2); - } - - virtual int GetHeightForWidth(int width) { - return std::max(0, circumference_ / 2 - width); - } - - private: - int circumference_; -}; - -class GridLayoutTest : public testing::Test { - public: - virtual void SetUp() { - layout = new GridLayout(&host); - } - - virtual void TearDown() { - delete layout; - } - - virtual void RemoveAll() { - for (int i = host.child_count() - 1; i >= 0; i--) - host.RemoveChildView(host.child_at(i)); - } - - void GetPreferredSize() { - pref = layout->GetPreferredSize(&host); - } - - gfx::Size pref; - gfx::Rect bounds; - View host; - GridLayout* layout; -}; - -class GridLayoutAlignmentTest : public testing::Test { - public: - GridLayoutAlignmentTest() : - host(), - v1(gfx::Size(10, 20)), - layout(new GridLayout(&host)) {} - - virtual void SetUp() { - } - - virtual void TearDown() { - delete layout; - } - - virtual void RemoveAll() { - for (int i = host.child_count() - 1; i >= 0; i--) - host.RemoveChildView(host.child_at(i)); - } - - void TestAlignment(GridLayout::Alignment alignment, gfx::Rect* bounds) { - ColumnSet* c1 = layout->AddColumnSet(0); - c1->AddColumn(alignment, alignment, 1, GridLayout::USE_PREF, 0, 0); - layout->StartRow(1, 0); - layout->AddView(&v1); - gfx::Size pref = layout->GetPreferredSize(&host); - EXPECT_EQ(gfx::Size(10, 20), pref); - host.SetBounds(0, 0, 100, 100); - layout->Layout(&host); - *bounds = v1.bounds(); - RemoveAll(); - } - - View host; - SettableSizeView v1; - GridLayout* layout; -}; - -TEST_F(GridLayoutAlignmentTest, Fill) { - gfx::Rect bounds; - TestAlignment(GridLayout::FILL, &bounds); - EXPECT_EQ(gfx::Rect(0, 0, 100, 100), bounds); -} - -TEST_F(GridLayoutAlignmentTest, Leading) { - gfx::Rect bounds; - TestAlignment(GridLayout::LEADING, &bounds); - EXPECT_EQ(gfx::Rect(0, 0, 10, 20), bounds); -} - -TEST_F(GridLayoutAlignmentTest, Center) { - gfx::Rect bounds; - TestAlignment(GridLayout::CENTER, &bounds); - EXPECT_EQ(gfx::Rect(45, 40, 10, 20), bounds); -} - -TEST_F(GridLayoutAlignmentTest, Trailing) { - gfx::Rect bounds; - TestAlignment(GridLayout::TRAILING, &bounds); - EXPECT_EQ(gfx::Rect(90, 80, 10, 20), bounds); -} - -TEST_F(GridLayoutTest, TwoColumns) { - SettableSizeView v1(gfx::Size(10, 20)); - SettableSizeView v2(gfx::Size(20, 20)); - ColumnSet* c1 = layout->AddColumnSet(0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - layout->StartRow(0, 0); - layout->AddView(&v1); - layout->AddView(&v2); - - GetPreferredSize(); - EXPECT_EQ(gfx::Size(30, 20), pref); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 10, 20, &v1); - ExpectViewBoundsEquals(10, 0, 20, 20, &v2); - - RemoveAll(); -} - -TEST_F(GridLayoutTest, ColSpan1) { - SettableSizeView v1(gfx::Size(100, 20)); - SettableSizeView v2(gfx::Size(10, 40)); - ColumnSet* c1 = layout->AddColumnSet(0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 1, GridLayout::USE_PREF, 0, 0); - layout->StartRow(0, 0); - layout->AddView(&v1, 2, 1); - layout->StartRow(0, 0); - layout->AddView(&v2); - - GetPreferredSize(); - EXPECT_EQ(gfx::Size(100, 60), pref); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 100, 20, &v1); - ExpectViewBoundsEquals(0, 20, 10, 40, &v2); - - RemoveAll(); -} - -TEST_F(GridLayoutTest, ColSpan2) { - SettableSizeView v1(gfx::Size(100, 20)); - SettableSizeView v2(gfx::Size(10, 20)); - ColumnSet* c1 = layout->AddColumnSet(0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 1, GridLayout::USE_PREF, 0, 0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - layout->StartRow(0, 0); - layout->AddView(&v1, 2, 1); - layout->StartRow(0, 0); - layout->SkipColumns(1); - layout->AddView(&v2); - - GetPreferredSize(); - EXPECT_EQ(gfx::Size(100, 40), pref); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 100, 20, &v1); - ExpectViewBoundsEquals(90, 20, 10, 20, &v2); - - RemoveAll(); -} - -TEST_F(GridLayoutTest, ColSpan3) { - SettableSizeView v1(gfx::Size(100, 20)); - SettableSizeView v2(gfx::Size(10, 20)); - SettableSizeView v3(gfx::Size(10, 20)); - ColumnSet* c1 = layout->AddColumnSet(0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - layout->StartRow(0, 0); - layout->AddView(&v1, 2, 1); - layout->StartRow(0, 0); - layout->AddView(&v2); - layout->AddView(&v3); - - GetPreferredSize(); - EXPECT_EQ(gfx::Size(100, 40), pref); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 100, 20, &v1); - ExpectViewBoundsEquals(0, 20, 10, 20, &v2); - ExpectViewBoundsEquals(50, 20, 10, 20, &v3); - - RemoveAll(); -} - - -TEST_F(GridLayoutTest, ColSpan4) { - views::ColumnSet* set = layout->AddColumnSet(0); - - set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0, - GridLayout::USE_PREF, 0, 0); - set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0, - GridLayout::USE_PREF, 0, 0); - - SettableSizeView v1(gfx::Size(10, 10)); - SettableSizeView v2(gfx::Size(10, 10)); - SettableSizeView v3(gfx::Size(25, 20)); - layout->StartRow(0, 0); - layout->AddView(&v1); - layout->AddView(&v2); - layout->StartRow(0, 0); - layout->AddView(&v3, 2, 1); - - GetPreferredSize(); - EXPECT_EQ(gfx::Size(25, 30), pref); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 10, 10, &v1); - ExpectViewBoundsEquals(12, 0, 10, 10, &v2); - ExpectViewBoundsEquals(0, 10, 25, 20, &v3); - - RemoveAll(); -} - -TEST_F(GridLayoutTest, SameSizeColumns) { - SettableSizeView v1(gfx::Size(50, 20)); - SettableSizeView v2(gfx::Size(10, 10)); - ColumnSet* c1 = layout->AddColumnSet(0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - c1->LinkColumnSizes(0, 1, -1); - layout->StartRow(0, 0); - layout->AddView(&v1); - layout->AddView(&v2); - - gfx::Size pref = layout->GetPreferredSize(&host); - EXPECT_EQ(gfx::Size(100, 20), pref); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 50, 20, &v1); - ExpectViewBoundsEquals(50, 0, 10, 10, &v2); - - RemoveAll(); -} - -TEST_F(GridLayoutTest, HorizontalResizeTest1) { - SettableSizeView v1(gfx::Size(50, 20)); - SettableSizeView v2(gfx::Size(10, 10)); - ColumnSet* c1 = layout->AddColumnSet(0); - c1->AddColumn(GridLayout::FILL, GridLayout::LEADING, - 1, GridLayout::USE_PREF, 0, 0); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - layout->StartRow(0, 0); - layout->AddView(&v1); - layout->AddView(&v2); - - host.SetBounds(0, 0, 110, 20); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 100, 20, &v1); - ExpectViewBoundsEquals(100, 0, 10, 10, &v2); - - RemoveAll(); -} - -TEST_F(GridLayoutTest, HorizontalResizeTest2) { - SettableSizeView v1(gfx::Size(50, 20)); - SettableSizeView v2(gfx::Size(10, 10)); - ColumnSet* c1 = layout->AddColumnSet(0); - c1->AddColumn(GridLayout::FILL, GridLayout::LEADING, - 1, GridLayout::USE_PREF, 0, 0); - c1->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, - 1, GridLayout::USE_PREF, 0, 0); - layout->StartRow(0, 0); - layout->AddView(&v1); - layout->AddView(&v2); - - host.SetBounds(0, 0, 120, 20); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 80, 20, &v1); - ExpectViewBoundsEquals(110, 0, 10, 10, &v2); - - RemoveAll(); -} - -TEST_F(GridLayoutTest, TestVerticalResize1) { - SettableSizeView v1(gfx::Size(50, 20)); - SettableSizeView v2(gfx::Size(10, 10)); - ColumnSet* c1 = layout->AddColumnSet(0); - c1->AddColumn(GridLayout::FILL, GridLayout::FILL, - 1, GridLayout::USE_PREF, 0, 0); - layout->StartRow(1, 0); - layout->AddView(&v1); - layout->StartRow(0, 0); - layout->AddView(&v2); - - GetPreferredSize(); - EXPECT_EQ(gfx::Size(50, 30), pref); - - host.SetBounds(0, 0, 50, 100); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 50, 90, &v1); - ExpectViewBoundsEquals(0, 90, 50, 10, &v2); - - RemoveAll(); -} - -TEST_F(GridLayoutTest, Insets) { - SettableSizeView v1(gfx::Size(10, 20)); - ColumnSet* c1 = layout->AddColumnSet(0); - layout->SetInsets(1, 2, 3, 4); - c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - layout->StartRow(0, 0); - layout->AddView(&v1); - - GetPreferredSize(); - EXPECT_EQ(gfx::Size(16, 24), pref); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(2, 1, 10, 20, &v1); - - RemoveAll(); -} - -TEST_F(GridLayoutTest, FixedSize) { - layout->SetInsets(2, 2, 2, 2); - - views::ColumnSet* set = layout->AddColumnSet(0); - - int column_count = 4; - int title_width = 100; - int row_count = 2; - int pref_width = 10; - int pref_height = 20; - - for (int i = 0; i < column_count; ++i) { - set->AddColumn(views::GridLayout::CENTER, - views::GridLayout::CENTER, - 0, - views::GridLayout::FIXED, - title_width, - title_width); - } - - for (int row = 0; row < row_count; ++row) { - layout->StartRow(0, 0); - for (int col = 0; col < column_count; ++col) { - layout->AddView(new SettableSizeView(gfx::Size(pref_width, pref_height))); - } - } - - layout->Layout(&host); - - for (int i = 0; i < column_count; ++i) { - for (int row = 0; row < row_count; ++row) { - View* view = host.child_at(row * column_count + i); - ExpectViewBoundsEquals( - 2 + title_width * i + (title_width - pref_width) / 2, - 2 + pref_height * row, - pref_width, - pref_height, view); - } - } - - GetPreferredSize(); - EXPECT_EQ(gfx::Size(column_count * title_width + 4, - row_count * pref_height + 4), pref); -} - -TEST_F(GridLayoutTest, RowSpanWithPaddingRow) { - views::ColumnSet* set = layout->AddColumnSet(0); - - set->AddColumn(views::GridLayout::CENTER, - views::GridLayout::CENTER, - 0, - views::GridLayout::FIXED, - 10, - 10); - - layout->StartRow(0, 0); - layout->AddView(new SettableSizeView(gfx::Size(10, 10)), 1, 2); - layout->AddPaddingRow(0, 10); -} - -TEST_F(GridLayoutTest, RowSpan) { - views::ColumnSet* set = layout->AddColumnSet(0); - - set->AddColumn(views::GridLayout::LEADING, - views::GridLayout::LEADING, - 0, - views::GridLayout::USE_PREF, - 0, - 0); - set->AddColumn(views::GridLayout::LEADING, - views::GridLayout::LEADING, - 0, - views::GridLayout::USE_PREF, - 0, - 0); - - layout->StartRow(0, 0); - layout->AddView(new SettableSizeView(gfx::Size(20, 10))); - layout->AddView(new SettableSizeView(gfx::Size(20, 40)), 1, 2); - layout->StartRow(1, 0); - views::View* s3 = new SettableSizeView(gfx::Size(20, 10)); - layout->AddView(s3); - - GetPreferredSize(); - EXPECT_EQ(gfx::Size(40, 40), pref); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 10, 20, 10, s3); -} - -TEST_F(GridLayoutTest, RowSpan2) { - views::ColumnSet* set = layout->AddColumnSet(0); - - set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0,GridLayout::USE_PREF, 0, 0); - - layout->StartRow(0, 0); - layout->AddView(new SettableSizeView(gfx::Size(20, 20))); - views::View* s3 = new SettableSizeView(gfx::Size(64, 64)); - layout->AddView(s3, 1, 3); - - layout->AddPaddingRow(0, 10); - - layout->StartRow(0, 0); - layout->AddView(new SettableSizeView(gfx::Size(10, 20))); - - GetPreferredSize(); - EXPECT_EQ(gfx::Size(84, 64), pref); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(20, 0, 64, 64, s3); -} - -TEST_F(GridLayoutTest, FixedViewWidth) { - views::ColumnSet* set = layout->AddColumnSet(0); - - set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0,GridLayout::USE_PREF, 0, 0); - - layout->StartRow(0, 0); - View* view = new SettableSizeView(gfx::Size(30, 40)); - layout->AddView(view, 1, 1, GridLayout::LEADING, GridLayout::LEADING, 10, 0); - - GetPreferredSize(); - EXPECT_EQ(10, pref.width()); - EXPECT_EQ(40, pref.height()); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 10, 40, view); -} - -TEST_F(GridLayoutTest, FixedViewHeight) { - views::ColumnSet* set = layout->AddColumnSet(0); - - set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0, GridLayout::USE_PREF, 0, 0); - set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, - 0,GridLayout::USE_PREF, 0, 0); - - layout->StartRow(0, 0); - View* view = new SettableSizeView(gfx::Size(30, 40)); - layout->AddView(view, 1, 1, GridLayout::LEADING, GridLayout::LEADING, 0, 10); - - GetPreferredSize(); - EXPECT_EQ(30, pref.width()); - EXPECT_EQ(10, pref.height()); - - host.SetBounds(0, 0, pref.width(), pref.height()); - layout->Layout(&host); - ExpectViewBoundsEquals(0, 0, 30, 10, view); -} - -// Make sure that for views that span columns the underlying columns are resized -// based on the resize percent of the column. -TEST_F(GridLayoutTest, ColumnSpanResizing) { - views::ColumnSet* set = layout->AddColumnSet(0); - - set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, - 2, views::GridLayout::USE_PREF, 0, 0); - set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, - 4, views::GridLayout::USE_PREF, 0, 0); - - layout->StartRow(0, 0); - // span_view spans two columns and is twice as big the views added below. - View* span_view = new SettableSizeView(gfx::Size(12, 40)); - layout->AddView(span_view, 2, 1, GridLayout::LEADING, GridLayout::LEADING); - - layout->StartRow(0, 0); - View* view1 = new SettableSizeView(gfx::Size(2, 40)); - View* view2 = new SettableSizeView(gfx::Size(4, 40)); - layout->AddView(view1); - layout->AddView(view2); - - host.SetBounds(0, 0, 12, 80); - layout->Layout(&host); - - ExpectViewBoundsEquals(0, 0, 12, 40, span_view); - - // view1 should be 4 pixels wide - // column_pref + (remaining_width * column_resize / total_column_resize) = - // 2 + (6 * 2 / 6). - ExpectViewBoundsEquals(0, 40, 4, 40, view1); - - // And view2 should be 8 pixels wide: - // 4 + (6 * 4 / 6). - ExpectViewBoundsEquals(4, 40, 8, 40, view2); -} - -// Check that GetPreferredSize() takes resizing of columns into account when -// there is additional space in the case we have column sets of different -// preferred sizes. -TEST_F(GridLayoutTest, ColumnResizingOnGetPreferredSize) { - views::ColumnSet* set = layout->AddColumnSet(0); - set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, - 1, views::GridLayout::USE_PREF, 0, 0); - - set = layout->AddColumnSet(1); - set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, - 1, views::GridLayout::USE_PREF, 0, 0); - - set = layout->AddColumnSet(2); - set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, - 1, views::GridLayout::USE_PREF, 0, 0); - - // Make a row containing a flexible view that trades width for height. - layout->StartRow(0, 0); - View* view1 = new FlexibleView(100); - layout->AddView(view1, 1, 1, GridLayout::FILL, GridLayout::LEADING); - - // The second row contains a view of fixed size that will enforce a column - // width of 20 pixels. - layout->StartRow(0, 1); - View* view2 = new SettableSizeView(gfx::Size(20, 20)); - layout->AddView(view2, 1, 1, GridLayout::FILL, GridLayout::LEADING); - - // Add another flexible view in row three in order to ensure column set - // ordering doesn't influence sizing behaviour. - layout->StartRow(0, 2); - View* view3 = new FlexibleView(40); - layout->AddView(view3, 1, 1, GridLayout::FILL, GridLayout::LEADING); - - // We expect a height of 50: 30 from the variable width view in the first row - // plus 20 from the statically sized view in the second row. The flexible - // view in the third row should contribute no height. - EXPECT_EQ(gfx::Size(20, 50), layout->GetPreferredSize(&host)); -} diff --git a/views/layout/layout_constants.h b/views/layout/layout_constants.h index 85633d4..8e85bc0 100644 --- a/views/layout/layout_constants.h +++ b/views/layout/layout_constants.h @@ -6,66 +6,7 @@ #define VIEWS_LAYOUT_LAYOUT_CONSTANTS_H_ #pragma once -// This file contains some constants we use to implement our standard panel -// layout. -// see: spec 21/4 - -namespace views { - -// Left or right margin. -const int kPanelHorizMargin = 13; - -// Top or bottom margin. -const int kPanelVertMargin = 13; - -// If some UI has some sub UI. Indent horizontally by the following value. -const int kPanelHorizIndentation = 24; - -// When several controls are aligned vertically, the baseline should be spaced -// by the following number of pixels. -const int kPanelVerticalSpacing = 32; - -// Vertical spacing between sub UI. -const int kPanelSubVerticalSpacing = 24; - -// Vertical spacing between a label and some control. -const int kLabelToControlVerticalSpacing = 8; - -// Small horizontal spacing between controls that are logically related. -const int kRelatedControlSmallHorizontalSpacing = 8; - -// Horizontal spacing between controls that are logically related. -const int kRelatedControlHorizontalSpacing = 8; - -// Vertical spacing between controls that are logically related. -const int kRelatedControlVerticalSpacing = 8; - -// Small vertical spacing between controls that are logically related. -const int kRelatedControlSmallVerticalSpacing = 4; - -// Horizontal spacing between controls that are logically unrelated. -const int kUnrelatedControlHorizontalSpacing = 12; - -// Larger horizontal spacing between unrelated controls. -const int kUnrelatedControlLargeHorizontalSpacing = 20; - -// Vertical spacing between controls that are logically unrelated. -const int kUnrelatedControlVerticalSpacing = 20; - -// Larger vertical spacing between unrelated controls. -const int kUnrelatedControlLargeVerticalSpacing = 30; - -// Vertical spacing between the edge of the window and the -// top or bottom of a button. -const int kButtonVEdgeMargin = 6; - -// Vertical spacing between the edge of the window and the -// left or right of a button. -const int kButtonHEdgeMargin = 7; - -// Horizontal spacing between buttons that are logically related. -const int kRelatedButtonHSpacing = 6; - -} // namespace views +#include "ui/views/layout/layout_constants.h" +// TODO(tfarina): remove this file once all includes have been updated. #endif // VIEWS_LAYOUT_LAYOUT_CONSTANTS_H_ diff --git a/views/layout/layout_manager.cc b/views/layout/layout_manager.cc deleted file mode 100644 index c62c6bb..0000000 --- a/views/layout/layout_manager.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2011 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 "views/layout/layout_manager.h" - -#include "views/view.h" - -namespace views { - -LayoutManager::~LayoutManager() { -} - -void LayoutManager::Installed(View* host) { -} - -void LayoutManager::Uninstalled(View* host) { -} - -int LayoutManager::GetPreferredHeightForWidth(View* host, int width) { - return GetPreferredSize(host).height(); -} - -void LayoutManager::ViewAdded(View* host, View* view) { -} - -void LayoutManager::ViewRemoved(View* host, View* view) { -} - -} // namespace views diff --git a/views/layout/layout_manager.h b/views/layout/layout_manager.h index b34499c..e1944f1 100644 --- a/views/layout/layout_manager.h +++ b/views/layout/layout_manager.h @@ -2,60 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef VIEWS_LAYOUT_MANAGER_H_ -#define VIEWS_LAYOUT_MANAGER_H_ +#ifndef VIEWS_LAYOUT_LAYOUT_MANAGER_H_ +#define VIEWS_LAYOUT_LAYOUT_MANAGER_H_ #pragma once -#include "views/views_export.h" +#include "ui/views/layout/layout_manager.h" +// TODO(tfarina): remove this file once all includes have been updated. -namespace gfx { -class Size; -} - -namespace views { - -class View; - -///////////////////////////////////////////////////////////////////////////// -// -// LayoutManager interface -// -// The LayoutManager interface provides methods to handle the sizing of -// the children of a View according to implementation-specific heuristics. -// -///////////////////////////////////////////////////////////////////////////// -class VIEWS_EXPORT LayoutManager { - public: - virtual ~LayoutManager(); - - // Notification that this LayoutManager has been installed on a particular - // host. - virtual void Installed(View* host); - - // Notification that this LayoutManager has been uninstalled on a particular - // host. - virtual void Uninstalled(View* host); - - // Lay out the children of |host| according to implementation-specific - // heuristics. The graphics used during painting is provided to allow for - // string sizing. - virtual void Layout(View* host) = 0; - - // Return the preferred size which is the size required to give each - // children their respective preferred size. - virtual gfx::Size GetPreferredSize(View* host) = 0; - - // Returns the preferred height for the specified width. The default - // implementation returns the value from GetPreferredSize. - virtual int GetPreferredHeightForWidth(View* host, int width); - - // Notification that a view has been added. - virtual void ViewAdded(View* host, View* view); - - // Notification that a view has been removed. - virtual void ViewRemoved(View* host, View* view); -}; - -} // namespace views - -#endif // VIEWS_LAYOUT_MANAGER_H_ +#endif // VIEWS_LAYOUT_LAYOUT_MANAGER_H_ diff --git a/views/views.gyp b/views/views.gyp index d3e98b3..6a183c1 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -61,14 +61,6 @@ 'background.h', 'border.cc', 'border.h', - 'bubble/bubble_border.cc', - 'bubble/bubble_border.h', - 'bubble/border_contents_view.cc', - 'bubble/border_contents_view.h', - 'bubble/bubble_delegate.cc', - 'bubble/bubble_delegate.h', - 'bubble/bubble_frame_view.cc', - 'bubble/bubble_frame_view.h', 'context_menu_controller.h', 'controls/button/button.cc', 'controls/button/button.h', @@ -259,40 +251,6 @@ 'drag_utils_aura.cc', 'drag_utils_gtk.cc', 'drag_utils_win.cc', - 'events/event.cc', - 'events/event.h', - 'events/event_aura.cc', - 'events/event_gtk.cc', - 'events/event_wayland.cc', - 'events/event_win.cc', - 'events/event_x.cc', - 'focus/accelerator_handler.h', - 'focus/accelerator_handler_aura.cc', - 'focus/accelerator_handler_gtk.cc', - 'focus/accelerator_handler_touch.cc', - 'focus/accelerator_handler_wayland.cc', - 'focus/accelerator_handler_win.cc', - 'focus/external_focus_tracker.cc', - 'focus/external_focus_tracker.h', - 'focus/focus_manager.cc', - 'focus/focus_manager.h', - 'focus/focus_manager_factory.cc', - 'focus/focus_manager_factory.h', - 'focus/focus_search.cc', - 'focus/focus_search.h', - 'focus/view_storage.cc', - 'focus/view_storage.h', - 'focus/widget_focus_manager.cc', - 'focus/widget_focus_manager.h', - 'layout/box_layout.cc', - 'layout/box_layout.h', - 'layout/fill_layout.cc', - 'layout/fill_layout.h', - 'layout/grid_layout.cc', - 'layout/grid_layout.h', - 'layout/layout_constants.h', - 'layout/layout_manager.cc', - 'layout/layout_manager.h', 'metrics.cc', 'metrics.h', 'metrics_aura.cc', @@ -370,10 +328,43 @@ 'widget/widget_delegate.h', 'widget/window_manager.cc', 'widget/window_manager.h', - '../ui/views/animation/bounds_animator.cc', - '../ui/views/animation/bounds_animator.h', '../ui/views/accessibility/native_view_accessibility_win.cc', '../ui/views/accessibility/native_view_accessibility_win.h', + '../ui/views/animation/bounds_animator.cc', + '../ui/views/animation/bounds_animator.h', + '../ui/views/bubble/border_contents_view.cc', + '../ui/views/bubble/border_contents_view.h', + '../ui/views/bubble/bubble_border.cc', + '../ui/views/bubble/bubble_border.h', + '../ui/views/bubble/bubble_delegate.cc', + '../ui/views/bubble/bubble_delegate.h', + '../ui/views/bubble/bubble_frame_view.cc', + '../ui/views/bubble/bubble_frame_view.h', + '../ui/views/events/event.cc', + '../ui/views/events/event.h', + '../ui/views/events/event_aura.cc', + '../ui/views/events/event_gtk.cc', + '../ui/views/events/event_wayland.cc', + '../ui/views/events/event_win.cc', + '../ui/views/events/event_x.cc', + '../ui/views/focus/accelerator_handler.h', + '../ui/views/focus/accelerator_handler_aura.cc', + '../ui/views/focus/accelerator_handler_gtk.cc', + '../ui/views/focus/accelerator_handler_touch.cc', + '../ui/views/focus/accelerator_handler_wayland.cc', + '../ui/views/focus/accelerator_handler_win.cc', + '../ui/views/focus/external_focus_tracker.cc', + '../ui/views/focus/external_focus_tracker.h', + '../ui/views/focus/focus_manager.cc', + '../ui/views/focus/focus_manager.h', + '../ui/views/focus/focus_manager_factory.cc', + '../ui/views/focus/focus_manager_factory.h', + '../ui/views/focus/focus_search.cc', + '../ui/views/focus/focus_search.h', + '../ui/views/focus/view_storage.cc', + '../ui/views/focus/view_storage.h', + '../ui/views/focus/widget_focus_manager.cc', + '../ui/views/focus/widget_focus_manager.h', '../ui/views/ime/input_method_base.cc', '../ui/views/ime/input_method_base.h', '../ui/views/ime/input_method_delegate.h', @@ -390,6 +381,15 @@ '../ui/views/ime/mock_input_method.h', '../ui/views/ime/text_input_type_tracker.cc', '../ui/views/ime/text_input_type_tracker.h', + '../ui/views/layout/box_layout.cc', + '../ui/views/layout/box_layout.h', + '../ui/views/layout/fill_layout.cc', + '../ui/views/layout/fill_layout.h', + '../ui/views/layout/grid_layout.cc', + '../ui/views/layout/grid_layout.h', + '../ui/views/layout/layout_constants.h', + '../ui/views/layout/layout_manager.cc', + '../ui/views/layout/layout_manager.h', '../ui/views/touchui/gesture_manager.cc', '../ui/views/touchui/gesture_manager.h', '../ui/views/touchui/touch_selection_controller.cc', @@ -423,7 +423,7 @@ 'sources/': [ ['exclude', '_(gtk|x)\\.cc$'], ['exclude', '/(gtk|x)_[^/]*\\.cc$'], - ['exclude', 'focus/accelerator_handler_touch.cc'], + ['exclude', '../ui/views/focus/accelerator_handler_touch.cc'], ['include', 'controls/menu/native_menu_views.cc'], ['include', 'controls/menu/native_menu_views.h'], ['include', 'drag_utils_gtk.cc'], @@ -437,7 +437,7 @@ ['exclude', 'controls/menu/menu_2.*'], ], 'sources!': [ - 'drag_utils_win.cc', + '../ui/views/focus/accelerator_handler_touch.cc', 'controls/menu/menu_config_linux.cc', 'controls/menu/menu_item_view_linux.cc', 'controls/menu/menu_separator_linux.cc', @@ -457,7 +457,7 @@ 'controls/table/table_view_observer.h', 'controls/tree/tree_view.cc', 'controls/tree/tree_view.h', - 'focus/accelerator_handler_touch.cc', + 'drag_utils_win.cc', 'widget/aero_tooltip_manager.cc', 'widget/aero_tooltip_manager.h', 'widget/child_window_message_processor.cc', @@ -472,13 +472,13 @@ '../build/linux/system.gyp:xext', ], 'sources!': [ + '../ui/views/events/event_win.cc', 'accessibility/native_view_accessibility_win.cc', 'controls/scrollbar/bitmap_scroll_bar.cc', 'controls/native_control.cc', 'controls/table/group_table_view.cc', 'controls/table/table_view.cc', 'controls/tree/tree_view.cc', - 'events/event_win.cc', 'widget/aero_tooltip_manager.cc', 'widget/child_window_message_processor.cc', 'widget/child_window_message_processor.h', @@ -488,7 +488,7 @@ ['touchui==1', { 'defines': ['TOUCH_UI=1'], 'sources/': [ - ['exclude', 'focus/accelerator_handler_gtk.cc'], + ['exclude', '../ui/views/focus/accelerator_handler_gtk.cc'], ['exclude', 'controls/menu/native_menu_gtk.cc'], ['exclude', 'widget/tooltip_manager_gtk.cc'], ], @@ -531,7 +531,7 @@ }], ['use_x11==0', { 'sources!': [ - 'events/event_x.cc', + '../ui/views/events/event_x.cc', ], }], ], @@ -566,14 +566,19 @@ ], 'sources': [ '../ui/views/animation/bounds_animator_unittest.cc', + '../ui/views/bubble/bubble_delegate_unittest.cc', + '../ui/views/bubble/bubble_frame_view_unittest.cc', + '../ui/views/events/event_unittest.cc', + '../ui/views/focus/accelerator_handler_gtk_unittest.cc', + '../ui/views/focus/focus_manager_unittest.cc', + '../ui/views/layout/box_layout_unittest.cc', + '../ui/views/layout/grid_layout_unittest.cc', '../ui/views/touchui/touch_selection_controller_impl_unittest.cc', '../ui/views/test/test_views_delegate.cc', '../ui/views/test/test_views_delegate.h', '../ui/views/test/views_test_base.cc', '../ui/views/test/views_test_base.h', 'accessible_pane_view_unittest.cc', - 'bubble/bubble_delegate_unittest.cc', - 'bubble/bubble_frame_view_unittest.cc', 'controls/label_unittest.cc', 'controls/progress_bar_unittest.cc', 'controls/single_split_view_unittest.cc', @@ -584,11 +589,6 @@ 'controls/textfield/native_textfield_views_unittest.cc', 'controls/textfield/textfield_views_model_unittest.cc', 'controls/scrollbar/scrollbar_unittest.cc', - 'events/event_unittest.cc', - 'focus/accelerator_handler_gtk_unittest.cc', - 'focus/focus_manager_unittest.cc', - 'layout/grid_layout_unittest.cc', - 'layout/box_layout_unittest.cc', 'run_all_unittests.cc', 'view_unittest.cc', 'widget/native_widget_test_utils.h', @@ -616,7 +616,7 @@ }], [ 'touchui==1', { 'sources!': [ - 'focus/accelerator_handler_gtk_unittest.cc', + '../ui/views/focus/accelerator_handler_gtk_unittest.cc', 'controls/table/table_view_unittest.cc', 'controls/tabbed_pane/tabbed_pane_unittest.cc' ], @@ -644,11 +644,11 @@ '../ui/aura/aura.gyp:test_support_aura', ], 'sources/': [ - ['exclude', 'focus/focus_manager_unittest.cc'], # TODO(beng): - ['exclude', 'widget/native_widget_win_unittest.cc'], + ['exclude', '../ui/views/focus/focus_manager_unittest.cc'], # TODO(beng): ['exclude', 'controls/combobox/native_combobox_views_unittest.cc'], ['exclude', 'controls/table/table_view_unittest.cc'], ['exclude', 'controls/tabbed_pane/tabbed_pane_unittest.cc'], + ['exclude', 'widget/native_widget_win_unittest.cc'], ], }, { 'sources/': [ |