diff options
author | stevenjb@google.com <stevenjb@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-11 18:55:29 +0000 |
---|---|---|
committer | stevenjb@google.com <stevenjb@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-11 18:55:29 +0000 |
commit | 88a7f3be9f324fece01f29ef1d2f249c646167e1 (patch) | |
tree | aed8cb2fa3619de1abe2d363dbf93d64954dab01 /ash | |
parent | 8781235cf8cd5182744de1f50cc1fc26eeb75af9 (diff) | |
download | chromium_src-88a7f3be9f324fece01f29ef1d2f249c646167e1.zip chromium_src-88a7f3be9f324fece01f29ef1d2f249c646167e1.tar.gz chromium_src-88a7f3be9f324fece01f29ef1d2f249c646167e1.tar.bz2 |
Move SystemTrayBubbleView to TrayBubbleView in its own file.
There are no non-whitespace code changes, this just moves the code.
BUG=124914
TEST=System tray bubble views and borders should look the same.
TBR=ben@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10532075
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141447 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/ash.gyp | 2 | ||||
-rw-r--r-- | ash/system/tray/system_tray_bubble.cc | 289 | ||||
-rw-r--r-- | ash/system/tray/system_tray_bubble.h | 76 | ||||
-rw-r--r-- | ash/system/tray/tray_bubble_view.cc | 304 | ||||
-rw-r--r-- | ash/system/tray/tray_bubble_view.h | 90 |
5 files changed, 401 insertions, 360 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index af2f46e..8337b4c 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -164,6 +164,8 @@ 'system/tray/system_tray_item.h', 'system/tray/tray_background_view.cc', 'system/tray/tray_background_view.h', + 'system/tray/tray_bubble_view.cc', + 'system/tray/tray_bubble_view.h', 'system/tray/tray_constants.cc', 'system/tray/tray_constants.h', 'system/tray/tray_details_view.cc', diff --git a/ash/system/tray/system_tray_bubble.cc b/ash/system/tray/system_tray_bubble.cc index 6a1f70c..ff3430f 100644 --- a/ash/system/tray/system_tray_bubble.cc +++ b/ash/system/tray/system_tray_bubble.cc @@ -5,51 +5,25 @@ #include "ash/system/tray/system_tray_bubble.h" #include "ash/shell.h" -#include "ash/shell_window_ids.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_delegate.h" #include "ash/system/tray/system_tray_item.h" #include "ash/system/tray/tray_constants.h" -#include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_animations.h" #include "base/message_loop.h" -#include "grit/ash_strings.h" -#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/aura/event.h" #include "ui/aura/window.h" -#include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/canvas.h" -#include "ui/gfx/screen.h" -#include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/layout/box_layout.h" -#include "ui/views/layout/fill_layout.h" #include "ui/views/view.h" namespace ash { namespace { -const int kShadowThickness = 4; - -const int kBottomLineHeight = 1; - -const int kSystemTrayBubbleHorizontalInset = 1; -const int kSystemTrayBubbleVerticalInset = 1; - -const int kArrowHeight = 10; -const int kArrowWidth = 20; - -// Inset the arrow a bit from the edge. -const int kArrowMinOffset = kArrowWidth / 2 + 4; - const int kAnimationDurationForPopupMS = 200; // Normally a detailed view is the same size as the default view. However, @@ -59,34 +33,6 @@ const int kAnimationDurationForPopupMS = 200; // detailed view. const int kDetailedBubbleMaxHeight = kTrayPopupItemHeight * 5; -const SkColor kShadowColor = SkColorSetARGB(0xff, 0, 0, 0); - -void DrawBlurredShadowAroundView(gfx::Canvas* canvas, - int top, - int bottom, - int width, - const gfx::Insets& inset) { - SkPath path; - path.incReserve(4); - path.moveTo(SkIntToScalar(inset.left() + kShadowThickness), - SkIntToScalar(top + kShadowThickness + 1)); - path.lineTo(SkIntToScalar(inset.left() + kShadowThickness), - SkIntToScalar(bottom)); - path.lineTo(SkIntToScalar(width), - SkIntToScalar(bottom)); - path.lineTo(SkIntToScalar(width), - SkIntToScalar(top + kShadowThickness + 1)); - - SkPaint paint; - paint.setColor(kShadowColor); - paint.setStyle(SkPaint::kStroke_Style); - paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); - paint.setStrokeWidth(SkIntToScalar(3)); - paint.setImageFilter(new SkBlurImageFilter( - SkIntToScalar(3), SkIntToScalar(3)))->unref(); - canvas->sk_canvas()->drawPath(path, paint); -} - // A view with some special behaviour for tray items in the popup: // - changes background color on hover. class TrayPopupItemContainer : public views::View { @@ -147,117 +93,6 @@ class TrayPopupItemContainer : public views::View { DISALLOW_COPY_AND_ASSIGN(TrayPopupItemContainer); }; -class SystemTrayBubbleBorder : public views::BubbleBorder { - public: - SystemTrayBubbleBorder(views::View* owner, - views::BubbleBorder::ArrowLocation arrow_location, - int arrow_offset) - : views::BubbleBorder(arrow_location, - views::BubbleBorder::NO_SHADOW), - owner_(owner), - tray_arrow_offset_(arrow_offset) { - set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); - } - - virtual ~SystemTrayBubbleBorder() {} - - private: - // Overridden from views::BubbleBorder. - // Override views::BubbleBorder to set 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 (arrow_location() != NONE) { - return views::BubbleBorder::GetBounds(position_relative_to, - contents_size); - } - - gfx::Size border_size(contents_size); - gfx::Insets insets; - GetInsets(&insets); - border_size.Enlarge(insets.width(), insets.height()); - - const int kArrowOverlap = 3; - int x = position_relative_to.x() + - position_relative_to.width() / 2 - border_size.width() / 2; - // Position the bubble on top of the anchor. - int y = position_relative_to.y() + - kArrowOverlap - border_size.height(); - return gfx::Rect(x, y, border_size.width(), border_size.height()); - } - - // Overridden from views::Border. - virtual void Paint(const views::View& view, - gfx::Canvas* canvas) const OVERRIDE { - gfx::Insets inset; - GetInsets(&inset); - DrawBlurredShadowAroundView(canvas, 0, owner_->height(), owner_->width(), - inset); - - // Draw the bottom line. - int y = owner_->height() + 1; - canvas->FillRect(gfx::Rect(inset.left(), y, owner_->width(), - kBottomLineHeight), kBorderDarkColor); - - if (!Shell::GetInstance()->shelf()->IsVisible() || - arrow_location() == views::BubbleBorder::NONE) - return; - - // Draw the arrow after drawing child borders, so that the arrow can cover - // the its overlap section with child border. - SkPath path; - path.incReserve(4); - if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT) { - int tip_x = base::i18n::IsRTL() ? tray_arrow_offset_ : - owner_->width() - tray_arrow_offset_; - tip_x = std::min(std::max(kArrowMinOffset, tip_x), - owner_->width() - kArrowMinOffset); - int left_base_x = tip_x - kArrowWidth / 2; - int left_base_y = y; - int tip_y = left_base_y + kArrowHeight; - path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); - path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); - path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), - SkIntToScalar(left_base_y)); - } else { - int tip_y = y - tray_arrow_offset_; - tip_y = std::min(std::max(kArrowMinOffset, tip_y), - owner_->height() - kArrowMinOffset); - int top_base_y = tip_y - kArrowWidth / 2; - int top_base_x, tip_x; - if (arrow_location() == views::BubbleBorder::LEFT_BOTTOM) { - top_base_x = inset.left() + kSystemTrayBubbleHorizontalInset; - tip_x = top_base_x - kArrowHeight; - } else { - DCHECK(arrow_location() == views::BubbleBorder::RIGHT_BOTTOM); - top_base_x = inset.left() + owner_->width() - - kSystemTrayBubbleHorizontalInset; - tip_x = top_base_x + kArrowHeight; - } - path.moveTo(SkIntToScalar(top_base_x), SkIntToScalar(top_base_y)); - path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); - path.lineTo(SkIntToScalar(top_base_x), - SkIntToScalar(top_base_y + kArrowWidth)); - } - - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(kHeaderBackgroundColorDark); - canvas->DrawPath(path, paint); - - // Now draw the arrow border. - paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(kBorderDarkColor); - canvas->DrawPath(path, paint); - - } - - views::View* owner_; - const int tray_arrow_offset_; - - DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleBorder); -}; - // Implicit animation observer that deletes itself and the layer at the end of // the animation. class AnimationObserverDeleteLayer : public ui::ImplicitAnimationObserver { @@ -283,128 +118,6 @@ class AnimationObserverDeleteLayer : public ui::ImplicitAnimationObserver { namespace internal { -// SystemTrayBubbleView - -SystemTrayBubbleView::SystemTrayBubbleView( - views::View* anchor, - views::BubbleBorder::ArrowLocation arrow_location, - Host* host, - bool can_activate, - int bubble_width) - : views::BubbleDelegateView(anchor, arrow_location), - host_(host), - can_activate_(can_activate), - max_height_(0), - bubble_width_(bubble_width) { - set_margin(0); - set_parent_window(Shell::GetContainer( - anchor->GetWidget()->GetNativeWindow()->GetRootWindow(), - internal::kShellWindowId_SettingBubbleContainer)); - set_notify_enter_exit_on_child(true); - SetPaintToLayer(true); - SetFillsBoundsOpaquely(true); -} - -SystemTrayBubbleView::~SystemTrayBubbleView() { - // Inform host items (models) that their views are being destroyed. - if (host_) - host_->BubbleViewDestroyed(); -} - -void SystemTrayBubbleView::SetBubbleBorder(int arrow_offset) { - DCHECK(GetWidget()); - SystemTrayBubbleBorder* bubble_border = new SystemTrayBubbleBorder( - this, arrow_location(), arrow_offset); - GetBubbleFrameView()->SetBubbleBorder(bubble_border); - // Recalculate size with new border. - SizeToContents(); -} - -void SystemTrayBubbleView::UpdateAnchor() { - SizeToContents(); - GetWidget()->GetRootView()->SchedulePaint(); -} - -void SystemTrayBubbleView::SetMaxHeight(int height) { - max_height_ = height; - if (GetWidget()) - SizeToContents(); -} - -void SystemTrayBubbleView::Init() { - views::BoxLayout* layout = - new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); - layout->set_spread_blank_space(true); - SetLayoutManager(layout); - set_background(NULL); -} - -gfx::Rect SystemTrayBubbleView::GetAnchorRect() { - gfx::Rect rect; - if (host_) - rect = host_->GetAnchorRect(); - // TODO(jennyz): May need to add left/right alignment in the following code. - if (rect.IsEmpty()) { - rect = gfx::Screen::GetPrimaryMonitor().bounds(); - rect = gfx::Rect( - base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreenBottomAlignment : - rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, - rect.height() - kPaddingFromBottomOfScreenBottomAlignment, - 0, 0); - } - return rect; -} - -gfx::Rect SystemTrayBubbleView::GetBubbleBounds() { - // Same as BubbleDelegateView implementation, but don't try mirroring. - return GetBubbleFrameView()->GetUpdatedWindowBounds( - GetAnchorRect(), GetPreferredSize(), false /*try_mirroring_arrow*/); -} - -bool SystemTrayBubbleView::CanActivate() const { - return can_activate_; -} - -gfx::Size SystemTrayBubbleView::GetPreferredSize() { - gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); - int height = size.height(); - if (max_height_ != 0 && height > max_height_) - height = max_height_; - return gfx::Size(bubble_width_, height); -} - -void SystemTrayBubbleView::OnMouseEntered(const views::MouseEvent& event) { - if (host_) - host_->OnMouseEnteredView(); -} - -void SystemTrayBubbleView::OnMouseExited(const views::MouseEvent& event) { - if (host_) - host_->OnMouseExitedView(); -} - -void SystemTrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { - if (can_activate_) { - state->role = ui::AccessibilityTypes::ROLE_WINDOW; - state->name = l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); - } -} - -void SystemTrayBubbleView::ChildPreferredSizeChanged(View* child) { - SizeToContents(); -} - -void SystemTrayBubbleView::ViewHierarchyChanged(bool is_add, - views::View* parent, - views::View* child) { - if (is_add && child == this) { - parent->SetPaintToLayer(true); - parent->SetFillsBoundsOpaquely(true); - parent->layer()->SetMasksToBounds(true); - } -} - // SystemTrayBubble::InitParams SystemTrayBubble::InitParams::InitParams( SystemTrayBubble::AnchorType anchor_type, @@ -545,7 +258,7 @@ void SystemTrayBubble::InitView(const InitParams& init_params) { } else { arrow_location = views::BubbleBorder::NONE; } - bubble_view_ = new SystemTrayBubbleView( + bubble_view_ = new TrayBubbleView( init_params.anchor, arrow_location, this, init_params.can_activate, kTrayPopupWidth); if (bubble_type_ == BUBBLE_TYPE_NOTIFICATION) diff --git a/ash/system/tray/system_tray_bubble.h b/ash/system/tray/system_tray_bubble.h index 2ef75d2..bdc138e 100644 --- a/ash/system/tray/system_tray_bubble.h +++ b/ash/system/tray/system_tray_bubble.h @@ -6,12 +6,12 @@ #define ASH_SYSTEM_TRAY_SYSTEM_TRAY_BUBBLE_H_ #pragma once +#include "ash/system/tray/tray_bubble_view.h" #include "ash/system/user/login_status.h" #include "ash/wm/shelf_auto_hide_behavior.h" #include "base/base_export.h" #include "base/timer.h" #include "ui/aura/event_filter.h" -#include "ui/views/bubble/bubble_delegate.h" #include "ui/views/widget/widget.h" #include <vector> @@ -27,77 +27,9 @@ class SystemTrayItem; namespace internal { -class SystemTrayBubble; - -class SystemTrayBubbleView : public views::BubbleDelegateView { - public: - class Host { - public: - Host() {} - virtual ~Host() {} - - virtual void BubbleViewDestroyed() = 0; - virtual gfx::Rect GetAnchorRect() const = 0; - virtual void OnMouseEnteredView() = 0; - virtual void OnMouseExitedView() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Host); - }; - - SystemTrayBubbleView(views::View* anchor, - views::BubbleBorder::ArrowLocation arrow_location, - Host* host, - bool can_activate, - int bubble_width); - virtual ~SystemTrayBubbleView(); - - // Creates a bubble border with the specified arrow offset. - void SetBubbleBorder(int arrow_offset); - - // Called whenever the bubble anchor location may have moved. - void UpdateAnchor(); - - // Sets the maximum bubble height and resizes the bubble. - void SetMaxHeight(int height); - - // Called when the host is destroyed. - void reset_host() { host_ = NULL; } - - // Overridden from views::WidgetDelegate. - virtual bool CanActivate() const OVERRIDE; - - // Overridden from views::BubbleDelegateView. - virtual gfx::Rect GetAnchorRect() OVERRIDE; - - // Overridden from views::View. - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE; - virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE; - virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; - - protected: - // Overridden from views::BubbleDelegateView. - virtual void Init() OVERRIDE; - virtual gfx::Rect GetBubbleBounds() OVERRIDE; - - // Overridden from views::View. - virtual void ChildPreferredSizeChanged(View* child) OVERRIDE; - virtual void ViewHierarchyChanged(bool is_add, - views::View* parent, - views::View* child) OVERRIDE; - - Host* host_; - bool can_activate_; - int max_height_; - int bubble_width_; - - DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleView); -}; - class SystemTrayBubble : public aura::EventFilter, public views::Widget::Observer, - public SystemTrayBubbleView::Host { + public TrayBubbleView::Host { public: enum BubbleType { BUBBLE_TYPE_DEFAULT, @@ -141,7 +73,7 @@ class SystemTrayBubble : public aura::EventFilter, virtual void OnMouseExitedView() OVERRIDE; BubbleType bubble_type() const { return bubble_type_; } - SystemTrayBubbleView* bubble_view() const { return bubble_view_; } + TrayBubbleView* bubble_view() const { return bubble_view_; } void DestroyItemViews(); void StartAutoCloseTimer(int seconds); @@ -171,7 +103,7 @@ class SystemTrayBubble : public aura::EventFilter, virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE; ash::SystemTray* tray_; - SystemTrayBubbleView* bubble_view_; + TrayBubbleView* bubble_view_; views::Widget* bubble_widget_; std::vector<ash::SystemTrayItem*> items_; BubbleType bubble_type_; diff --git a/ash/system/tray/tray_bubble_view.cc b/ash/system/tray/tray_bubble_view.cc new file mode 100644 index 0000000..cbb074b --- /dev/null +++ b/ash/system/tray/tray_bubble_view.cc @@ -0,0 +1,304 @@ +// 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 "ash/system/tray/tray_bubble_view.h" + +#include "ash/shell.h" +#include "ash/shell_window_ids.h" +#include "ash/system/tray/tray_constants.h" +#include "ash/wm/shelf_layout_manager.h" +#include "grit/ash_strings.h" +#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/aura/window.h" +#include "ui/base/accessibility/accessible_view_state.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/screen.h" +#include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/layout/box_layout.h" + +namespace ash { + +namespace { + +const int kShadowThickness = 4; +const int kBottomLineHeight = 1; +const int kSystemTrayBubbleHorizontalInset = 1; +const int kSystemTrayBubbleVerticalInset = 1; + +const int kArrowHeight = 10; +const int kArrowWidth = 20; + +// Inset the arrow a bit from the edge. +const int kArrowMinOffset = kArrowWidth / 2 + 4; + +const SkColor kShadowColor = SkColorSetARGB(0xff, 0, 0, 0); + +void DrawBlurredShadowAroundView(gfx::Canvas* canvas, + int top, + int bottom, + int width, + const gfx::Insets& inset) { + SkPath path; + path.incReserve(4); + path.moveTo(SkIntToScalar(inset.left() + kShadowThickness), + SkIntToScalar(top + kShadowThickness + 1)); + path.lineTo(SkIntToScalar(inset.left() + kShadowThickness), + SkIntToScalar(bottom)); + path.lineTo(SkIntToScalar(width), + SkIntToScalar(bottom)); + path.lineTo(SkIntToScalar(width), + SkIntToScalar(top + kShadowThickness + 1)); + + SkPaint paint; + paint.setColor(kShadowColor); + paint.setStyle(SkPaint::kStroke_Style); + paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); + paint.setStrokeWidth(SkIntToScalar(3)); + paint.setImageFilter(new SkBlurImageFilter( + SkIntToScalar(3), SkIntToScalar(3)))->unref(); + canvas->sk_canvas()->drawPath(path, paint); +} + +class TrayBubbleBorder : public views::BubbleBorder { + public: + TrayBubbleBorder(views::View* owner, + views::BubbleBorder::ArrowLocation arrow_location, + int arrow_offset) + : views::BubbleBorder(arrow_location, + views::BubbleBorder::NO_SHADOW), + owner_(owner), + tray_arrow_offset_(arrow_offset) { + set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); + } + + virtual ~TrayBubbleBorder() {} + + private: + // Overridden from views::BubbleBorder. + // Override views::BubbleBorder to set 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 (arrow_location() != NONE) { + return views::BubbleBorder::GetBounds(position_relative_to, + contents_size); + } + + gfx::Size border_size(contents_size); + gfx::Insets insets; + GetInsets(&insets); + border_size.Enlarge(insets.width(), insets.height()); + + const int kArrowOverlap = 3; + int x = position_relative_to.x() + + position_relative_to.width() / 2 - border_size.width() / 2; + // Position the bubble on top of the anchor. + int y = position_relative_to.y() + + kArrowOverlap - border_size.height(); + return gfx::Rect(x, y, border_size.width(), border_size.height()); + } + + // Overridden from views::Border. + virtual void Paint(const views::View& view, + gfx::Canvas* canvas) const OVERRIDE { + gfx::Insets inset; + GetInsets(&inset); + DrawBlurredShadowAroundView( + canvas, 0, owner_->height(), owner_->width(), inset); + + // Draw the bottom line. + int y = owner_->height() + 1; + canvas->FillRect(gfx::Rect(inset.left(), y, owner_->width(), + kBottomLineHeight), kBorderDarkColor); + + if (!Shell::GetInstance()->shelf()->IsVisible() || + arrow_location() == views::BubbleBorder::NONE) + return; + + // Draw the arrow after drawing child borders, so that the arrow can cover + // the its overlap section with child border. + SkPath path; + path.incReserve(4); + if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT) { + int tip_x = base::i18n::IsRTL() ? tray_arrow_offset_ : + owner_->width() - tray_arrow_offset_; + tip_x = std::min(std::max(kArrowMinOffset, tip_x), + owner_->width() - kArrowMinOffset); + int left_base_x = tip_x - kArrowWidth / 2; + int left_base_y = y; + int tip_y = left_base_y + kArrowHeight; + path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); + path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); + path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), + SkIntToScalar(left_base_y)); + } else { + int tip_y = y - tray_arrow_offset_; + tip_y = std::min(std::max(kArrowMinOffset, tip_y), + owner_->height() - kArrowMinOffset); + int top_base_y = tip_y - kArrowWidth / 2; + int top_base_x, tip_x; + if (arrow_location() == views::BubbleBorder::LEFT_BOTTOM) { + top_base_x = inset.left() + kSystemTrayBubbleHorizontalInset; + tip_x = top_base_x - kArrowHeight; + } else { + DCHECK(arrow_location() == views::BubbleBorder::RIGHT_BOTTOM); + top_base_x = inset.left() + owner_->width() - + kSystemTrayBubbleHorizontalInset; + tip_x = top_base_x + kArrowHeight; + } + path.moveTo(SkIntToScalar(top_base_x), SkIntToScalar(top_base_y)); + path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); + path.lineTo(SkIntToScalar(top_base_x), + SkIntToScalar(top_base_y + kArrowWidth)); + } + + SkPaint paint; + paint.setStyle(SkPaint::kFill_Style); + paint.setColor(kHeaderBackgroundColorDark); + canvas->DrawPath(path, paint); + + // Now draw the arrow border. + paint.setStyle(SkPaint::kStroke_Style); + paint.setColor(kBorderDarkColor); + canvas->DrawPath(path, paint); + + } + + views::View* owner_; + const int tray_arrow_offset_; + + DISALLOW_COPY_AND_ASSIGN(TrayBubbleBorder); +}; + +} // namespace + +namespace internal { + +TrayBubbleView::TrayBubbleView( + views::View* anchor, + views::BubbleBorder::ArrowLocation arrow_location, + Host* host, + bool can_activate, + int bubble_width) + : views::BubbleDelegateView(anchor, arrow_location), + host_(host), + can_activate_(can_activate), + max_height_(0), + bubble_width_(bubble_width) { + set_margin(0); + set_parent_window(Shell::GetContainer( + anchor->GetWidget()->GetNativeWindow()->GetRootWindow(), + internal::kShellWindowId_SettingBubbleContainer)); + set_notify_enter_exit_on_child(true); + SetPaintToLayer(true); + SetFillsBoundsOpaquely(true); +} + +TrayBubbleView::~TrayBubbleView() { + // Inform host items (models) that their views are being destroyed. + if (host_) + host_->BubbleViewDestroyed(); +} + +void TrayBubbleView::SetBubbleBorder(int arrow_offset) { + DCHECK(GetWidget()); + TrayBubbleBorder* bubble_border = new TrayBubbleBorder( + this, arrow_location(), arrow_offset); + GetBubbleFrameView()->SetBubbleBorder(bubble_border); + // Recalculate size with new border. + SizeToContents(); +} + +void TrayBubbleView::UpdateAnchor() { + SizeToContents(); + GetWidget()->GetRootView()->SchedulePaint(); +} + +void TrayBubbleView::SetMaxHeight(int height) { + max_height_ = height; + if (GetWidget()) + SizeToContents(); +} + +void TrayBubbleView::Init() { + views::BoxLayout* layout = + new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); + layout->set_spread_blank_space(true); + SetLayoutManager(layout); + set_background(NULL); +} + +gfx::Rect TrayBubbleView::GetAnchorRect() { + gfx::Rect rect; + if (host_) + rect = host_->GetAnchorRect(); + // TODO(jennyz): May need to add left/right alignment in the following code. + if (rect.IsEmpty()) { + rect = gfx::Screen::GetPrimaryMonitor().bounds(); + rect = gfx::Rect( + base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreenBottomAlignment : + rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, + rect.height() - kPaddingFromBottomOfScreenBottomAlignment, + 0, 0); + } + return rect; +} + +gfx::Rect TrayBubbleView::GetBubbleBounds() { + // Same as BubbleDelegateView implementation, but don't try mirroring. + return GetBubbleFrameView()->GetUpdatedWindowBounds( + GetAnchorRect(), GetPreferredSize(), false /*try_mirroring_arrow*/); +} + +bool TrayBubbleView::CanActivate() const { + return can_activate_; +} + +gfx::Size TrayBubbleView::GetPreferredSize() { + gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); + int height = size.height(); + if (max_height_ != 0 && height > max_height_) + height = max_height_; + return gfx::Size(bubble_width_, height); +} + +void TrayBubbleView::OnMouseEntered(const views::MouseEvent& event) { + if (host_) + host_->OnMouseEnteredView(); +} + +void TrayBubbleView::OnMouseExited(const views::MouseEvent& event) { + if (host_) + host_->OnMouseExitedView(); +} + +void TrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { + if (can_activate_) { + state->role = ui::AccessibilityTypes::ROLE_WINDOW; + state->name = l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); + } +} + +void TrayBubbleView::ChildPreferredSizeChanged(View* child) { + SizeToContents(); +} + +void TrayBubbleView::ViewHierarchyChanged(bool is_add, + views::View* parent, + views::View* child) { + if (is_add && child == this) { + parent->SetPaintToLayer(true); + parent->SetFillsBoundsOpaquely(true); + parent->layer()->SetMasksToBounds(true); + } +} + +} // namespace internal +} // namespace ash diff --git a/ash/system/tray/tray_bubble_view.h b/ash/system/tray/tray_bubble_view.h new file mode 100644 index 0000000..1d9008f --- /dev/null +++ b/ash/system/tray/tray_bubble_view.h @@ -0,0 +1,90 @@ +// 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. + +#ifndef ASH_SYSTEM_TRAY_TRAY_BUBBLE_VIEW_H_ +#define ASH_SYSTEM_TRAY_TRAY_BUBBLE_VIEW_H_ +#pragma once + +#include "ui/views/bubble/bubble_delegate.h" + +namespace views { +class View; +} + +namespace ash { +namespace internal { + +// Specialized bubble view for status area tray bubbles. +// Mostly this handles custom anchor location and arrow and border rendering. +class TrayBubbleView : public views::BubbleDelegateView { + public: + class Host { + public: + Host() {} + virtual ~Host() {} + + virtual void BubbleViewDestroyed() = 0; + virtual gfx::Rect GetAnchorRect() const = 0; + virtual void OnMouseEnteredView() = 0; + virtual void OnMouseExitedView() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(Host); + }; + + TrayBubbleView(views::View* anchor, + views::BubbleBorder::ArrowLocation arrow_location, + Host* host, + bool can_activate, + int bubble_width); + virtual ~TrayBubbleView(); + + // Creates a bubble border with the specified arrow offset. + void SetBubbleBorder(int arrow_offset); + + // Called whenever the bubble anchor location may have moved. + void UpdateAnchor(); + + // Sets the maximum bubble height and resizes the bubble. + void SetMaxHeight(int height); + + // Called when the host is destroyed. + void reset_host() { host_ = NULL; } + + // Overridden from views::WidgetDelegate. + virtual bool CanActivate() const OVERRIDE; + + // Overridden from views::BubbleDelegateView. + virtual gfx::Rect GetAnchorRect() OVERRIDE; + + // Overridden from views::View. + virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE; + virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE; + virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; + + protected: + // Overridden from views::BubbleDelegateView. + virtual void Init() OVERRIDE; + virtual gfx::Rect GetBubbleBounds() OVERRIDE; + + // Overridden from views::View. + virtual void ChildPreferredSizeChanged(View* child) OVERRIDE; + virtual void ViewHierarchyChanged(bool is_add, + views::View* parent, + views::View* child) OVERRIDE; + + private: + Host* host_; + bool can_activate_; + int max_height_; + int bubble_width_; + + DISALLOW_COPY_AND_ASSIGN(TrayBubbleView); +}; + +} // namespace internal +} // namespace ash + +#endif // ASH_SYSTEM_TRAY_TRAY_BUBBLE_VIEW_H_ |