blob: 22e5f767364ae4b37fde24d5d39c13fe28fd0ea7 [file] [log] [blame]
// 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 "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "ui/views/bubble/bubble_delegate.h"
#include "ui/views/mouse_watcher.h"
#include "ui/views/views_export.h"
// Specialized bubble view for bubbles associated with a tray icon (e.g. the
// Ash status area). Mostly this handles custom anchor location and arrow and
// border rendering. This also has its own delegate for handling mouse events
// and other implementation specific details.
namespace ui {
class LocatedEvent;
namespace views {
class View;
class Widget;
namespace views {
namespace internal {
class TrayBubbleBorder;
class TrayBubbleContentMask;
class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView,
public views::MouseWatcherListener {
// AnchorType differentiates between bubbles that are anchored on a tray
// element (ANCHOR_TYPE_TRAY) and display an arrow, or that are floating on
// the screen away from the tray (ANCHOR_TYPE_BUBBLE).
enum AnchorType {
// AnchorAlignment determines to which side of the anchor the bubble will
// align itself.
enum AnchorAlignment {
class VIEWS_EXPORT Delegate {
typedef TrayBubbleView::AnchorType AnchorType;
typedef TrayBubbleView::AnchorAlignment AnchorAlignment;
Delegate() {}
virtual ~Delegate() {}
// Called when the view is destroyed. Any pointers to the view should be
// cleared when this gets called.
virtual void BubbleViewDestroyed() = 0;
// Called when the mouse enters/exits the view.
// Note: This event will only be called if the mouse gets actively moved by
// the user to enter the view.
virtual void OnMouseEnteredView() = 0;
virtual void OnMouseExitedView() = 0;
// Called from GetAccessibleState(); should return the appropriate
// accessible name for the bubble.
virtual base::string16 GetAccessibleNameForBubble() = 0;
// Passes responsibility for BubbleDelegateView::GetAnchorRect to the
// delegate.
virtual gfx::Rect GetAnchorRect(
views::Widget* anchor_widget,
AnchorType anchor_type,
AnchorAlignment anchor_alignment) const = 0;
// Called when a bubble wants to hide/destroy itself (e.g. last visible
// child view was closed).
virtual void HideBubble(const TrayBubbleView* bubble_view) = 0;
struct VIEWS_EXPORT InitParams {
static const int kArrowDefaultOffset;
InitParams(AnchorType anchor_type,
AnchorAlignment anchor_alignment,
int min_width,
int max_width);
InitParams(const InitParams& other);
AnchorType anchor_type;
AnchorAlignment anchor_alignment;
int min_width;
int max_width;
int max_height;
bool can_activate;
bool close_on_deactivate;
SkColor arrow_color;
bool first_item_has_no_margin;
views::BubbleBorder::Arrow arrow;
int arrow_offset;
views::BubbleBorder::ArrowPaintType arrow_paint_type;
views::BubbleBorder::Shadow shadow;
views::BubbleBorder::BubbleAlignment arrow_alignment;
// Constructs and returns a TrayBubbleView. init_params may be modified.
static TrayBubbleView* Create(gfx::NativeView parent_window,
views::View* anchor,
Delegate* delegate,
InitParams* init_params);
~TrayBubbleView() override;
// Sets up animations, and show the bubble. Must occur after CreateBubble()
// is called.
void InitializeAndShowBubble();
// Called whenever the bubble size or location may have changed.
void UpdateBubble();
// Sets the maximum bubble height and resizes the bubble.
void SetMaxHeight(int height);
// Sets the bubble width.
void SetWidth(int width);
// Sets whether or not to paint the bubble border arrow.
void SetArrowPaintType(views::BubbleBorder::ArrowPaintType arrow_paint_type);
// Returns the border insets. Called by TrayEventFilter.
gfx::Insets GetBorderInsets() const;
// Called when the delegate is destroyed.
void reset_delegate() { delegate_ = NULL; }
Delegate* delegate() { return delegate_; }
void set_gesture_dragging(bool dragging) { is_gesture_dragging_ = dragging; }
bool is_gesture_dragging() const { return is_gesture_dragging_; }
// Overridden from views::WidgetDelegate.
bool CanActivate() const override;
views::NonClientFrameView* CreateNonClientFrameView(
views::Widget* widget) override;
bool WidgetHasHitTestMask() const override;
void GetWidgetHitTestMask(gfx::Path* mask) const override;
// Overridden from views::BubbleDelegateView.
gfx::Rect GetAnchorRect() const override;
// Overridden from views::View.
gfx::Size GetPreferredSize() const override;
gfx::Size GetMaximumSize() const override;
int GetHeightForWidth(int width) const override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
void GetAccessibleState(ui::AXViewState* state) override;
// Overridden from MouseWatcherListener
void MouseMovedOutOfHost() override;
TrayBubbleView(gfx::NativeView parent_window,
views::View* anchor,
Delegate* delegate,
const InitParams& init_params);
// Overridden from views::BubbleDelegateView.
void Init() override;
// Overridden from views::View.
void ChildPreferredSizeChanged(View* child) override;
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override;
InitParams params_;
Delegate* delegate_;
int preferred_width_;
// |bubble_border_| and |owned_bubble_border_| point to the same thing, but
// the latter ensures we don't leak it before passing off ownership.
internal::TrayBubbleBorder* bubble_border_;
scoped_ptr<views::BubbleBorder> owned_bubble_border_;
scoped_ptr<internal::TrayBubbleContentMask> bubble_content_mask_;
bool is_gesture_dragging_;
// True once the mouse cursor was actively moved by the user over the bubble.
// Only then the OnMouseExitedView() event will get passed on to listeners.
bool mouse_actively_entered_;
// Used to find any mouse movements.
scoped_ptr<MouseWatcher> mouse_watcher_;
} // namespace views