Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Unified Diff: ui/views/bubble/tray_bubble_view.cc

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/bubble/tray_bubble_view.h ('k') | ui/views/button_drag_utils.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/bubble/tray_bubble_view.cc
diff --git a/ui/views/bubble/tray_bubble_view.cc b/ui/views/bubble/tray_bubble_view.cc
deleted file mode 100644
index 53cb5265555d12021465d018541fa1760e87d090..0000000000000000000000000000000000000000
--- a/ui/views/bubble/tray_bubble_view.cc
+++ /dev/null
@@ -1,508 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/bubble/tray_bubble_view.h"
-
-#include <algorithm>
-
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkPaint.h"
-#include "third_party/skia/include/core/SkPath.h"
-#include "third_party/skia/include/effects/SkBlurImageFilter.h"
-#include "ui/accessibility/ax_view_state.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_delegate.h"
-#include "ui/events/event.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/insets.h"
-#include "ui/gfx/path.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/skia_util.h"
-#include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/bubble/bubble_window_targeter.h"
-#include "ui/views/layout/box_layout.h"
-#include "ui/views/widget/widget.h"
-
-namespace {
-
-// Inset the arrow a bit from the edge.
-const int kArrowMinOffset = 20;
-const int kBubbleSpacing = 20;
-
-// The new theme adjusts the menus / bubbles to be flush with the shelf when
-// there is no bubble. These are the offsets which need to be applied.
-const int kArrowOffsetTopBottom = 4;
-const int kArrowOffsetLeft = 9;
-const int kArrowOffsetRight = -5;
-const int kOffsetLeftRightForTopBottomOrientation = 5;
-
-// The sampling time for mouse position changes in ms - which is roughly a frame
-// time.
-const int kFrameTimeInMS = 30;
-} // namespace
-
-namespace views {
-
-namespace internal {
-
-// Detects any mouse movement. This is needed to detect mouse movements by the
-// user over the bubble if the bubble got created underneath the cursor.
-class MouseMoveDetectorHost : public MouseWatcherHost {
- public:
- MouseMoveDetectorHost();
- virtual ~MouseMoveDetectorHost();
-
- virtual bool Contains(const gfx::Point& screen_point,
- MouseEventType type) override;
- private:
- DISALLOW_COPY_AND_ASSIGN(MouseMoveDetectorHost);
-};
-
-MouseMoveDetectorHost::MouseMoveDetectorHost() {
-}
-
-MouseMoveDetectorHost::~MouseMoveDetectorHost() {
-}
-
-bool MouseMoveDetectorHost::Contains(const gfx::Point& screen_point,
- MouseEventType type) {
- return false;
-}
-
-// Custom border for TrayBubbleView. Contains special logic for GetBounds()
-// to stack bubbles with no arrows correctly. Also calculates the arrow offset.
-class TrayBubbleBorder : public BubbleBorder {
- public:
- TrayBubbleBorder(View* owner,
- View* anchor,
- TrayBubbleView::InitParams params)
- : BubbleBorder(params.arrow, params.shadow, params.arrow_color),
- owner_(owner),
- anchor_(anchor),
- tray_arrow_offset_(params.arrow_offset),
- first_item_has_no_margin_(params.first_item_has_no_margin) {
- set_alignment(params.arrow_alignment);
- set_background_color(params.arrow_color);
- set_paint_arrow(params.arrow_paint_type);
- }
-
- virtual ~TrayBubbleBorder() {}
-
- // Overridden from BubbleBorder.
- // Sets the bubble on top of the anchor when it has no arrow.
- virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to,
- const gfx::Size& contents_size) const override {
- if (has_arrow(arrow())) {
- gfx::Rect rect =
- BubbleBorder::GetBounds(position_relative_to, contents_size);
- if (first_item_has_no_margin_) {
- if (arrow() == BubbleBorder::BOTTOM_RIGHT ||
- arrow() == BubbleBorder::BOTTOM_LEFT) {
- rect.set_y(rect.y() + kArrowOffsetTopBottom);
- int rtl_factor = base::i18n::IsRTL() ? -1 : 1;
- rect.set_x(rect.x() +
- rtl_factor * kOffsetLeftRightForTopBottomOrientation);
- } else if (arrow() == BubbleBorder::LEFT_BOTTOM) {
- rect.set_x(rect.x() + kArrowOffsetLeft);
- } else if (arrow() == BubbleBorder::RIGHT_BOTTOM) {
- rect.set_x(rect.x() + kArrowOffsetRight);
- }
- }
- return rect;
- }
-
- gfx::Size border_size(contents_size);
- gfx::Insets insets = GetInsets();
- border_size.Enlarge(insets.width(), insets.height());
- const int x = position_relative_to.x() +
- position_relative_to.width() / 2 - border_size.width() / 2;
- // Position the bubble on top of the anchor.
- const int y = position_relative_to.y() - border_size.height() +
- insets.height() - kBubbleSpacing;
- return gfx::Rect(x, y, border_size.width(), border_size.height());
- }
-
- void UpdateArrowOffset() {
- int arrow_offset = 0;
- if (arrow() == BubbleBorder::BOTTOM_RIGHT ||
- arrow() == BubbleBorder::BOTTOM_LEFT) {
- // Note: tray_arrow_offset_ is relative to the anchor widget.
- if (tray_arrow_offset_ ==
- TrayBubbleView::InitParams::kArrowDefaultOffset) {
- arrow_offset = kArrowMinOffset;
- } else {
- const int width = owner_->GetWidget()->GetContentsView()->width();
- gfx::Point pt(tray_arrow_offset_, 0);
- View::ConvertPointToScreen(anchor_->GetWidget()->GetRootView(), &pt);
- View::ConvertPointFromScreen(owner_->GetWidget()->GetRootView(), &pt);
- arrow_offset = pt.x();
- if (arrow() == BubbleBorder::BOTTOM_RIGHT)
- arrow_offset = width - arrow_offset;
- arrow_offset = std::max(arrow_offset, kArrowMinOffset);
- }
- } else {
- if (tray_arrow_offset_ ==
- TrayBubbleView::InitParams::kArrowDefaultOffset) {
- arrow_offset = kArrowMinOffset;
- } else {
- gfx::Point pt(0, tray_arrow_offset_);
- View::ConvertPointToScreen(anchor_->GetWidget()->GetRootView(), &pt);
- View::ConvertPointFromScreen(owner_->GetWidget()->GetRootView(), &pt);
- arrow_offset = pt.y();
- arrow_offset = std::max(arrow_offset, kArrowMinOffset);
- }
- }
- set_arrow_offset(arrow_offset);
- }
-
- private:
- View* owner_;
- View* anchor_;
- const int tray_arrow_offset_;
-
- // If true the first item should not get any additional spacing against the
- // anchor (without the bubble tip the bubble should be flush to the shelf).
- const bool first_item_has_no_margin_;
-
- DISALLOW_COPY_AND_ASSIGN(TrayBubbleBorder);
-};
-
-// This mask layer clips the bubble's content so that it does not overwrite the
-// rounded bubble corners.
-// TODO(miket): This does not work on Windows. Implement layer masking or
-// alternate solutions if the TrayBubbleView is needed there in the future.
-class TrayBubbleContentMask : public ui::LayerDelegate {
- public:
- explicit TrayBubbleContentMask(int corner_radius);
- virtual ~TrayBubbleContentMask();
-
- ui::Layer* layer() { return &layer_; }
-
- // Overridden from LayerDelegate.
- virtual void OnPaintLayer(gfx::Canvas* canvas) override;
- virtual void OnDelegatedFrameDamage(
- const gfx::Rect& damage_rect_in_dip) override {}
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) override;
- virtual base::Closure PrepareForLayerBoundsChange() override;
-
- private:
- ui::Layer layer_;
- int corner_radius_;
-
- DISALLOW_COPY_AND_ASSIGN(TrayBubbleContentMask);
-};
-
-TrayBubbleContentMask::TrayBubbleContentMask(int corner_radius)
- : layer_(ui::LAYER_TEXTURED),
- corner_radius_(corner_radius) {
- layer_.set_delegate(this);
-}
-
-TrayBubbleContentMask::~TrayBubbleContentMask() {
- layer_.set_delegate(NULL);
-}
-
-void TrayBubbleContentMask::OnPaintLayer(gfx::Canvas* canvas) {
- SkPaint paint;
- paint.setAlpha(255);
- paint.setStyle(SkPaint::kFill_Style);
- gfx::Rect rect(layer()->bounds().size());
- canvas->DrawRoundRect(rect, corner_radius_, paint);
-}
-
-void TrayBubbleContentMask::OnDeviceScaleFactorChanged(
- float device_scale_factor) {
- // Redrawing will take care of scale factor change.
-}
-
-base::Closure TrayBubbleContentMask::PrepareForLayerBoundsChange() {
- return base::Closure();
-}
-
-// Custom layout for the bubble-view. Does the default box-layout if there is
-// enough height. Otherwise, makes sure the bottom rows are visible.
-class BottomAlignedBoxLayout : public BoxLayout {
- public:
- explicit BottomAlignedBoxLayout(TrayBubbleView* bubble_view)
- : BoxLayout(BoxLayout::kVertical, 0, 0, 0),
- bubble_view_(bubble_view) {
- }
-
- virtual ~BottomAlignedBoxLayout() {}
-
- private:
- virtual void Layout(View* host) override {
- if (host->height() >= host->GetPreferredSize().height() ||
- !bubble_view_->is_gesture_dragging()) {
- BoxLayout::Layout(host);
- return;
- }
-
- int consumed_height = 0;
- for (int i = host->child_count() - 1;
- i >= 0 && consumed_height < host->height(); --i) {
- View* child = host->child_at(i);
- if (!child->visible())
- continue;
- gfx::Size size = child->GetPreferredSize();
- child->SetBounds(0, host->height() - consumed_height - size.height(),
- host->width(), size.height());
- consumed_height += size.height();
- }
- }
-
- TrayBubbleView* bubble_view_;
-
- DISALLOW_COPY_AND_ASSIGN(BottomAlignedBoxLayout);
-};
-
-} // namespace internal
-
-using internal::TrayBubbleBorder;
-using internal::TrayBubbleContentMask;
-using internal::BottomAlignedBoxLayout;
-
-// static
-const int TrayBubbleView::InitParams::kArrowDefaultOffset = -1;
-
-TrayBubbleView::InitParams::InitParams(AnchorType anchor_type,
- AnchorAlignment anchor_alignment,
- int min_width,
- int max_width)
- : anchor_type(anchor_type),
- anchor_alignment(anchor_alignment),
- min_width(min_width),
- max_width(max_width),
- max_height(0),
- can_activate(false),
- close_on_deactivate(true),
- arrow_color(SK_ColorBLACK),
- first_item_has_no_margin(false),
- arrow(BubbleBorder::NONE),
- arrow_offset(kArrowDefaultOffset),
- arrow_paint_type(BubbleBorder::PAINT_NORMAL),
- shadow(BubbleBorder::BIG_SHADOW),
- arrow_alignment(BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE) {
-}
-
-// static
-TrayBubbleView* TrayBubbleView::Create(gfx::NativeView parent_window,
- View* anchor,
- Delegate* delegate,
- InitParams* init_params) {
- // Set arrow here so that it can be passed to the BubbleView constructor.
- if (init_params->anchor_type == ANCHOR_TYPE_TRAY) {
- if (init_params->anchor_alignment == ANCHOR_ALIGNMENT_BOTTOM) {
- init_params->arrow = base::i18n::IsRTL() ?
- BubbleBorder::BOTTOM_LEFT : BubbleBorder::BOTTOM_RIGHT;
- } else if (init_params->anchor_alignment == ANCHOR_ALIGNMENT_TOP) {
- init_params->arrow = BubbleBorder::TOP_LEFT;
- } else if (init_params->anchor_alignment == ANCHOR_ALIGNMENT_LEFT) {
- init_params->arrow = BubbleBorder::LEFT_BOTTOM;
- } else {
- init_params->arrow = BubbleBorder::RIGHT_BOTTOM;
- }
- } else {
- init_params->arrow = BubbleBorder::NONE;
- }
-
- return new TrayBubbleView(parent_window, anchor, delegate, *init_params);
-}
-
-TrayBubbleView::TrayBubbleView(gfx::NativeView parent_window,
- View* anchor,
- Delegate* delegate,
- const InitParams& init_params)
- : BubbleDelegateView(anchor, init_params.arrow),
- params_(init_params),
- delegate_(delegate),
- preferred_width_(init_params.min_width),
- bubble_border_(NULL),
- is_gesture_dragging_(false),
- mouse_actively_entered_(false) {
- set_parent_window(parent_window);
- set_notify_enter_exit_on_child(true);
- set_close_on_deactivate(init_params.close_on_deactivate);
- set_margins(gfx::Insets());
- bubble_border_ = new TrayBubbleBorder(this, GetAnchorView(), params_);
- SetPaintToLayer(true);
- SetFillsBoundsOpaquely(true);
-
- bubble_content_mask_.reset(
- new TrayBubbleContentMask(bubble_border_->GetBorderCornerRadius()));
-}
-
-TrayBubbleView::~TrayBubbleView() {
- mouse_watcher_.reset();
- // Inform host items (models) that their views are being destroyed.
- if (delegate_)
- delegate_->BubbleViewDestroyed();
-}
-
-void TrayBubbleView::InitializeAndShowBubble() {
- // Must occur after call to BubbleDelegateView::CreateBubble().
- SetAlignment(params_.arrow_alignment);
- bubble_border_->UpdateArrowOffset();
-
- layer()->parent()->SetMaskLayer(bubble_content_mask_->layer());
-
- GetWidget()->Show();
- GetWidget()->GetNativeWindow()->SetEventTargeter(
- scoped_ptr<ui::EventTargeter>(new BubbleWindowTargeter(this)));
- UpdateBubble();
-}
-
-void TrayBubbleView::UpdateBubble() {
- SizeToContents();
- bubble_content_mask_->layer()->SetBounds(layer()->bounds());
- GetWidget()->GetRootView()->SchedulePaint();
-}
-
-void TrayBubbleView::SetMaxHeight(int height) {
- params_.max_height = height;
- if (GetWidget())
- SizeToContents();
-}
-
-void TrayBubbleView::SetWidth(int width) {
- width = std::max(std::min(width, params_.max_width), params_.min_width);
- if (preferred_width_ == width)
- return;
- preferred_width_ = width;
- if (GetWidget())
- SizeToContents();
-}
-
-void TrayBubbleView::SetArrowPaintType(
- views::BubbleBorder::ArrowPaintType paint_type) {
- bubble_border_->set_paint_arrow(paint_type);
- UpdateBubble();
-}
-
-gfx::Insets TrayBubbleView::GetBorderInsets() const {
- return bubble_border_->GetInsets();
-}
-
-void TrayBubbleView::Init() {
- BoxLayout* layout = new BottomAlignedBoxLayout(this);
- layout->SetDefaultFlex(1);
- SetLayoutManager(layout);
-}
-
-gfx::Rect TrayBubbleView::GetAnchorRect() const {
- if (!delegate_)
- return gfx::Rect();
- return delegate_->GetAnchorRect(anchor_widget(),
- params_.anchor_type,
- params_.anchor_alignment);
-}
-
-bool TrayBubbleView::CanActivate() const {
- return params_.can_activate;
-}
-
-NonClientFrameView* TrayBubbleView::CreateNonClientFrameView(Widget* widget) {
- BubbleFrameView* frame = new BubbleFrameView(margins());
- frame->SetBubbleBorder(scoped_ptr<views::BubbleBorder>(bubble_border_));
- return frame;
-}
-
-bool TrayBubbleView::WidgetHasHitTestMask() const {
- return true;
-}
-
-void TrayBubbleView::GetWidgetHitTestMask(gfx::Path* mask) const {
- DCHECK(mask);
- mask->addRect(gfx::RectToSkRect(GetBubbleFrameView()->GetContentsBounds()));
-}
-
-gfx::Size TrayBubbleView::GetPreferredSize() const {
- return gfx::Size(preferred_width_, GetHeightForWidth(preferred_width_));
-}
-
-gfx::Size TrayBubbleView::GetMaximumSize() const {
- gfx::Size size = GetPreferredSize();
- size.set_width(params_.max_width);
- return size;
-}
-
-int TrayBubbleView::GetHeightForWidth(int width) const {
- int height = GetInsets().height();
- width = std::max(width - GetInsets().width(), 0);
- for (int i = 0; i < child_count(); ++i) {
- const View* child = child_at(i);
- if (child->visible())
- height += child->GetHeightForWidth(width);
- }
-
- return (params_.max_height != 0) ?
- std::min(height, params_.max_height) : height;
-}
-
-void TrayBubbleView::OnMouseEntered(const ui::MouseEvent& event) {
- mouse_watcher_.reset();
- if (delegate_ && !(event.flags() & ui::EF_IS_SYNTHESIZED)) {
- // Coming here the user was actively moving the mouse over the bubble and
- // we inform the delegate that we entered. This will prevent the bubble
- // to auto close.
- delegate_->OnMouseEnteredView();
- mouse_actively_entered_ = true;
- } else {
- // Coming here the bubble got shown and the mouse was 'accidentally' over it
- // which is not a reason to prevent the bubble to auto close. As such we
- // do not call the delegate, but wait for the first mouse move within the
- // bubble. The used MouseWatcher will notify use of a movement and call
- // |MouseMovedOutOfHost|.
- mouse_watcher_.reset(new MouseWatcher(
- new views::internal::MouseMoveDetectorHost(),
- this));
- // Set the mouse sampling frequency to roughly a frame time so that the user
- // cannot see a lag.
- mouse_watcher_->set_notify_on_exit_time(
- base::TimeDelta::FromMilliseconds(kFrameTimeInMS));
- mouse_watcher_->Start();
- }
-}
-
-void TrayBubbleView::OnMouseExited(const ui::MouseEvent& event) {
- // If there was a mouse watcher waiting for mouse movements we disable it
- // immediately since we now leave the bubble.
- mouse_watcher_.reset();
- // Do not notify the delegate of an exit if we never told it that we entered.
- if (delegate_ && mouse_actively_entered_)
- delegate_->OnMouseExitedView();
-}
-
-void TrayBubbleView::GetAccessibleState(ui::AXViewState* state) {
- if (delegate_ && params_.can_activate) {
- state->role = ui::AX_ROLE_WINDOW;
- state->name = delegate_->GetAccessibleNameForBubble();
- }
-}
-
-void TrayBubbleView::MouseMovedOutOfHost() {
- // The mouse was accidentally over the bubble when it opened and the AutoClose
- // logic was not activated. Now that the user did move the mouse we tell the
- // delegate to disable AutoClose.
- delegate_->OnMouseEnteredView();
- mouse_actively_entered_ = true;
- mouse_watcher_->Stop();
-}
-
-void TrayBubbleView::ChildPreferredSizeChanged(View* child) {
- SizeToContents();
-}
-
-void TrayBubbleView::ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) {
- if (details.is_add && details.child == this) {
- details.parent->SetPaintToLayer(true);
- details.parent->SetFillsBoundsOpaquely(true);
- details.parent->layer()->SetMasksToBounds(true);
- }
-}
-
-} // namespace views
« no previous file with comments | « ui/views/bubble/tray_bubble_view.h ('k') | ui/views/button_drag_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698