Home | History | Annotate | Download | only in views
      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 
     17 class BrowserView;
     18 class DropdownBarHostDelegate;
     19 class DropdownBarView;
     20 
     21 namespace content {
     22 class WebContents;
     23 }
     24 
     25 namespace ui {
     26 class SlideAnimation;
     27 }  // namespace ui
     28 
     29 namespace views {
     30 class ExternalFocusTracker;
     31 class View;
     32 class 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 ////////////////////////////////////////////////////////////////////////////////
     45 class 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