dropdown_bar_host.h revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
1// Copyright (c) 2011 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 CHROME_BROWSER_UI_VIEWS_DROPDOWN_BAR_HOST_H_
6#define CHROME_BROWSER_UI_VIEWS_DROPDOWN_BAR_HOST_H_
7
8#include "base/compiler_specific.h"
9#include "base/memory/scoped_ptr.h"
10#include "content/public/browser/native_web_keyboard_event.h"
11#include "ui/base/animation/animation_delegate.h"
12#include "ui/gfx/native_widget_types.h"
13#include "ui/gfx/rect.h"
14#include "ui/views/controls/textfield/textfield.h"
15#include "ui/views/focus/focus_manager.h"
16
17class BrowserView;
18class DropdownBarHostDelegate;
19class DropdownBarView;
20
21namespace content {
22class WebContents;
23}
24
25namespace ui {
26class SlideAnimation;
27}  // namespace ui
28
29namespace views {
30class ExternalFocusTracker;
31class View;
32class Widget;
33}  // namespace views
34
35////////////////////////////////////////////////////////////////////////////////
36//
37// The DropdownBarHost implements the container widget for the UI that
38// is shown at the top of browser contents. It uses the appropriate
39// implementation from dropdown_bar_host_win.cc or dropdown_bar_host_aura.cc to
40// draw its content and is responsible for showing, hiding, animating, closing,
41// and moving the bar if needed, for example if the widget is
42// obscuring the selection results in FindBar.
43//
44////////////////////////////////////////////////////////////////////////////////
45class DropdownBarHost : public ui::AcceleratorTarget,
46                        public views::FocusChangeListener,
47                        public ui::AnimationDelegate {
48 public:
49  explicit DropdownBarHost(BrowserView* browser_view);
50  virtual ~DropdownBarHost();
51
52  // Initializes the DropdownBarHost. This creates the widget that |view| paints
53  // into.
54  // |host_view| is the view whose position in the |browser_view_| view
55  // hierarchy determines the z-order of the widget relative to views with
56  // layers and views with associated NativeViews.
57  void Init(views::View* host_view,
58            views::View* view,
59            DropdownBarHostDelegate* delegate);
60
61  // Whether we are animating the position of the dropdown widget.
62  bool IsAnimating() const;
63  // Returns true if the dropdown bar view is visible, or false otherwise.
64  bool IsVisible() const;
65  // Selects text in the entry field and set focus.
66  void SetFocusAndSelection();
67  // Stops the animation.
68  void StopAnimation();
69
70  // Shows the dropdown bar.
71  virtual void Show(bool animate);
72  // Hides the dropdown bar.
73  virtual void Hide(bool animate);
74
75  // Returns the rectangle representing where to position the dropdown widget.
76  virtual gfx::Rect GetDialogPosition(gfx::Rect avoid_overlapping_rect) = 0;
77
78  // Moves the widget to the provided location, moves it to top
79  // in the z-order (HWND_TOP, not HWND_TOPMOST for windows) and shows
80  // the widget (if hidden).
81  virtual void SetDialogPosition(const gfx::Rect& new_pos, bool no_redraw) = 0;
82
83  // Overridden from views::FocusChangeListener:
84  virtual void OnWillChangeFocus(views::View* focused_before,
85                                 views::View* focused_now) OVERRIDE;
86  virtual void OnDidChangeFocus(views::View* focused_before,
87                                views::View* focused_now) OVERRIDE;
88
89  // Overridden from ui::AcceleratorTarget:
90  virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) = 0;
91  virtual bool CanHandleAccelerators() const = 0;
92
93  // ui::AnimationDelegate implementation:
94  virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
95  virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE;
96
97  // During testing we can disable animations by setting this flag to true,
98  // so that opening and closing the dropdown bar is shown instantly, instead of
99  // having to poll it while it animates to open/closed status.
100  static bool disable_animations_during_testing_;
101
102  // Returns the browser view that the dropdown belongs to.
103  BrowserView* browser_view() const { return browser_view_; }
104
105  // Registers this class as the handler for when Escape is pressed. Once we
106  // loose focus we will unregister Escape and (any accelerators the derived
107  // classes registers by using overrides of RegisterAccelerators). See also:
108  // SetFocusChangeListener().
109  virtual void RegisterAccelerators();
110
111  // When we loose focus, we unregister all accelerator handlers. See also:
112  // SetFocusChangeListener().
113  virtual void UnregisterAccelerators();
114
115 protected:
116  // Called when the drop down bar visibility, aka the value of IsVisible(),
117  // changes.
118  virtual void OnVisibilityChanged();
119
120  // Returns the dropdown bar view.
121  views::View* view() const { return view_; }
122
123  // Returns the focus tracker.
124  views::ExternalFocusTracker* focus_tracker() const {
125    return focus_tracker_.get();
126  }
127
128  // Resets the focus tracker.
129  void ResetFocusTracker();
130
131  // The focus manager we register with to keep track of focus changes.
132  views::FocusManager* focus_manager() const { return focus_manager_; }
133
134  // Returns the host widget.
135  views::Widget* host() const { return host_.get(); }
136
137  // Returns the animation offset.
138  int animation_offset() const { return animation_offset_; }
139
140  // Retrieves the boundary that the dropdown widget has to work with
141  // within the Chrome frame window. The boundary differs depending on
142  // the dropdown bar implementation. The default implementation
143  // returns the boundary of browser_view and the drop down
144  // can be shown in any client area.
145  virtual void GetWidgetBounds(gfx::Rect* bounds);
146
147  // The find bar widget needs rounded edges, so we create a polygon
148  // that corresponds to the background images for this window (and
149  // make the polygon only contain the pixels that we want to
150  // draw). The polygon is then given to SetWindowRgn which changes
151  // the window from being a rectangle in shape, to being a rect with
152  // curved edges. We also check to see if the region should be
153  // truncated to prevent from drawing onto Chrome's window border.
154  void UpdateWindowEdges(const gfx::Rect& new_pos);
155
156  // Allows implementation to tweak widget position.
157  void SetWidgetPositionNative(const gfx::Rect& new_pos, bool no_redraw);
158
159  // Returns a keyboard event suitable for forwarding.
160  content::NativeWebKeyboardEvent GetKeyboardEvent(
161      const content::WebContents* contents,
162      const ui::KeyEvent& key_event);
163
164  // Returns the animation for the dropdown.
165  ui::SlideAnimation* animation() {
166    return animation_.get();
167  }
168
169 private:
170  // Set the view whose position in the |browser_view_| view hierarchy
171  // determines the z-order of |host_| relative to views with layers and
172  // views with associated NativeViews.
173  void SetHostViewNative(views::View* host_view);
174
175  // The BrowserView that created us.
176  BrowserView* browser_view_;
177
178  // Our view, which is responsible for drawing the UI.
179  views::View* view_;
180  DropdownBarHostDelegate* delegate_;
181
182  // The y position pixel offset of the widget while animating the
183  // dropdown widget.
184  int animation_offset_;
185
186  // The animation class to use when opening the Dropdown widget.
187  scoped_ptr<ui::SlideAnimation> animation_;
188
189  // The focus manager we register with to keep track of focus changes.
190  views::FocusManager* focus_manager_;
191
192  // True if the accelerator target for Esc key is registered.
193  bool esc_accel_target_registered_;
194
195  // Tracks and stores the last focused view which is not the DropdownBarView
196  // or any of its children. Used to restore focus once the DropdownBarView is
197  // closed.
198  scoped_ptr<views::ExternalFocusTracker> focus_tracker_;
199
200  // Host is the Widget implementation that is created and maintained by the
201  // dropdown bar. It contains the DropdownBarView.
202  scoped_ptr<views::Widget> host_;
203
204  // A flag to manually manage visibility. GTK/X11 is asynchronous and
205  // the state of the widget can be out of sync.
206  bool is_visible_;
207
208  DISALLOW_COPY_AND_ASSIGN(DropdownBarHost);
209};
210
211#endif  // CHROME_BROWSER_UI_VIEWS_DROPDOWN_BAR_HOST_H_
212