1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_VIEWS_BUBBLE_BUBBLE_DELEGATE_H_ 6 #define UI_VIEWS_BUBBLE_BUBBLE_DELEGATE_H_ 7 8 #include "base/gtest_prod_util.h" 9 #include "ui/base/animation/animation_delegate.h" 10 #include "ui/views/bubble/bubble_border.h" 11 #include "ui/views/widget/widget_delegate.h" 12 #include "ui/views/widget/widget_observer.h" 13 14 namespace gfx { 15 class Rect; 16 } 17 18 namespace ui { 19 class SlideAnimation; 20 } 21 22 namespace views { 23 24 class BubbleFrameView; 25 26 // BubbleDelegateView creates frame and client views for bubble Widgets. 27 // BubbleDelegateView itself is the client's contents view. 28 // 29 /////////////////////////////////////////////////////////////////////////////// 30 class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, 31 public ui::AnimationDelegate, 32 public WidgetObserver { 33 public: 34 BubbleDelegateView(); 35 BubbleDelegateView(View* anchor_view, BubbleBorder::Arrow arrow); 36 virtual ~BubbleDelegateView(); 37 38 // Create and initialize the bubble Widget(s) with proper bounds. 39 static Widget* CreateBubble(BubbleDelegateView* bubble_delegate); 40 41 // WidgetDelegate overrides: 42 virtual BubbleDelegateView* AsBubbleDelegate() OVERRIDE; 43 virtual bool CanActivate() const OVERRIDE; 44 virtual bool ShouldShowCloseButton() const OVERRIDE; 45 virtual View* GetContentsView() OVERRIDE; 46 virtual NonClientFrameView* CreateNonClientFrameView(Widget* widget) OVERRIDE; 47 48 // WidgetObserver overrides: 49 virtual void OnWidgetDestroying(Widget* widget) OVERRIDE; 50 virtual void OnWidgetVisibilityChanged(Widget* widget, bool visible) OVERRIDE; 51 virtual void OnWidgetActivationChanged(Widget* widget, bool active) OVERRIDE; 52 virtual void OnWidgetBoundsChanged(Widget* widget, 53 const gfx::Rect& new_bounds) OVERRIDE; 54 55 bool close_on_esc() const { return close_on_esc_; } 56 void set_close_on_esc(bool close_on_esc) { close_on_esc_ = close_on_esc; } 57 58 bool close_on_deactivate() const { return close_on_deactivate_; } 59 void set_close_on_deactivate(bool close) { close_on_deactivate_ = close; } 60 61 View* anchor_view() const { return anchor_view_; } 62 Widget* anchor_widget() const { return anchor_widget_; } 63 64 // The anchor rect is used in the absence of an anchor view. 65 const gfx::Rect& anchor_rect() const { return anchor_rect_; } 66 67 BubbleBorder::Arrow arrow() const { return arrow_; } 68 void set_arrow(BubbleBorder::Arrow arrow) { arrow_ = arrow; } 69 70 BubbleBorder::Shadow shadow() const { return shadow_; } 71 void set_shadow(BubbleBorder::Shadow shadow) { shadow_ = shadow; } 72 73 SkColor color() const { return color_; } 74 void set_color(SkColor color) { 75 color_ = color; 76 color_explicitly_set_ = true; 77 } 78 79 const gfx::Insets& margins() const { return margins_; } 80 void set_margins(const gfx::Insets& margins) { margins_ = margins; } 81 82 const gfx::Insets& anchor_view_insets() const { return anchor_view_insets_; } 83 void set_anchor_view_insets(const gfx::Insets& i) { anchor_view_insets_ = i; } 84 85 gfx::NativeView parent_window() const { return parent_window_; } 86 void set_parent_window(gfx::NativeView window) { parent_window_ = window; } 87 88 bool use_focusless() const { return use_focusless_; } 89 void set_use_focusless(bool focusless) { use_focusless_ = focusless; } 90 91 bool accept_events() const { return accept_events_; } 92 void set_accept_events(bool accept_events) { accept_events_ = accept_events; } 93 94 bool border_accepts_events() const { return border_accepts_events_; } 95 void set_border_accepts_events(bool event) { border_accepts_events_ = event; } 96 97 bool adjust_if_offscreen() const { return adjust_if_offscreen_; } 98 void set_adjust_if_offscreen(bool adjust) { adjust_if_offscreen_ = adjust; } 99 100 bool move_with_anchor() const { return move_with_anchor_; } 101 void set_move_with_anchor(bool move) { move_with_anchor_ = move; } 102 103 // Get the arrow's anchor rect in screen space. 104 virtual gfx::Rect GetAnchorRect(); 105 106 // Fade the bubble in or out by animation Widget transparency. 107 // Fade-in calls Widget::Show; fade-out calls Widget::Close upon completion. 108 void StartFade(bool fade_in); 109 110 // Restores bubble opacity to its value before StartFade() was called. 111 void ResetFade(); 112 113 // Sets the bubble alignment relative to the anchor. This may only be called 114 // after calling CreateBubble. 115 void SetAlignment(BubbleBorder::BubbleAlignment alignment); 116 117 // Sets the bubble arrow paint type. 118 void SetArrowPaintType(BubbleBorder::ArrowPaintType paint_type); 119 120 // Call this method when the anchor view bounds have changed to reposition 121 // the bubble. The bubble is automatically repositioned when the anchor view 122 // bounds change as a result of the widget's bounds changing. 123 void OnAnchorViewBoundsChanged(); 124 125 protected: 126 // Get bubble bounds from the anchor rect and client view's preferred size. 127 virtual gfx::Rect GetBubbleBounds(); 128 129 // Returns the duration in milliseconds for the fade animation. 130 virtual int GetFadeDuration(); 131 132 // View overrides: 133 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; 134 virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE; 135 136 // ui::AnimationDelegate overrides: 137 virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; 138 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; 139 140 // Perform view initialization on the contents for bubble sizing. 141 virtual void Init(); 142 143 // Set the anchor view or rect; set these before CreateBubble or Show. 144 void set_anchor_view(View* anchor_view) { anchor_view_ = anchor_view; } 145 void set_anchor_rect(const gfx::Rect& rect) { anchor_rect_ = rect; } 146 147 // Resize and potentially move the bubble to fit the content's preferred size. 148 void SizeToContents(); 149 150 BubbleFrameView* GetBubbleFrameView() const; 151 152 private: 153 FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CreateDelegate); 154 FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, NonClientHitTest); 155 156 // Update the bubble color from |theme|, unless it was explicitly set. 157 void UpdateColorsFromTheme(const ui::NativeTheme* theme); 158 159 #if defined(OS_WIN) && !defined(USE_AURA) 160 // Get bounds for the Windows-only widget that hosts the bubble's contents. 161 gfx::Rect GetBubbleClientBounds() const; 162 #endif 163 164 // Fade animation for bubble. 165 scoped_ptr<ui::SlideAnimation> fade_animation_; 166 167 // Flags controlling bubble closure on the escape key and deactivation. 168 bool close_on_esc_; 169 bool close_on_deactivate_; 170 171 // The view and widget to which this bubble is anchored. 172 View* anchor_view_; 173 Widget* anchor_widget_; 174 175 // The anchor rect used in the absence of an anchor view. 176 gfx::Rect anchor_rect_; 177 178 // If true, the bubble will re-anchor (and may resize) with |anchor_widget_|. 179 bool move_with_anchor_; 180 181 // The arrow's location on the bubble. 182 BubbleBorder::Arrow arrow_; 183 184 // Bubble border shadow to use. 185 BubbleBorder::Shadow shadow_; 186 187 // The background color of the bubble; and flag for when it's explicitly set. 188 SkColor color_; 189 bool color_explicitly_set_; 190 191 // The margins between the content and the inside of the border. 192 gfx::Insets margins_; 193 194 // Insets applied to the |anchor_view_| bounds. 195 gfx::Insets anchor_view_insets_; 196 197 // Original opacity of the bubble. 198 int original_opacity_; 199 200 // The widget hosting the border for this bubble (non-Aura Windows only). 201 Widget* border_widget_; 202 203 // If true, the bubble does not take focus on display; default is false. 204 bool use_focusless_; 205 206 // Specifies whether the bubble (or its border) handles mouse events, etc. 207 bool accept_events_; 208 bool border_accepts_events_; 209 210 // If true (defaults to true), the arrow may be mirrored and moved to fit the 211 // bubble on screen better. It would be a no-op if the bubble has no arrow. 212 bool adjust_if_offscreen_; 213 214 // Parent native window of the bubble. 215 gfx::NativeView parent_window_; 216 217 DISALLOW_COPY_AND_ASSIGN(BubbleDelegateView); 218 }; 219 220 } // namespace views 221 222 #endif // UI_VIEWS_BUBBLE_BUBBLE_DELEGATE_H_ 223