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