Home | History | Annotate | Download | only in focus
      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 UI_VIEWS_FOCUS_FOCUS_SEARCH_H_
      6 #define UI_VIEWS_FOCUS_FOCUS_SEARCH_H_
      7 
      8 #include "ui/views/view.h"
      9 
     10 namespace views {
     11 
     12 class FocusTraversable;
     13 
     14 // FocusSearch is an object that implements the algorithm to find the
     15 // next view to focus.
     16 class VIEWS_EXPORT FocusSearch {
     17  public:
     18   // The direction in which the focus traversal is going.
     19   // TODO (jcampan): add support for lateral (left, right) focus traversal. The
     20   // goal is to switch to focusable views on the same level when using the arrow
     21   // keys (ala Windows: in a dialog box, arrow keys typically move between the
     22   // dialog OK, Cancel buttons).
     23   enum Direction {
     24     UP = 0,
     25     DOWN
     26   };
     27 
     28   // Constructor.
     29   // - |root| is the root of the view hierarchy to traverse. Focus will be
     30   //   trapped inside.
     31   // - |cycle| should be true if you want FindNextFocusableView to cycle back
     32   //           to the first view within this root when the traversal reaches
     33   //           the end. If this is true, then if you pass a valid starting
     34   //           view to FindNextFocusableView you will always get a valid view
     35   //           out, even if it's the same view.
     36   // - |accessibility_mode| should be true if full keyboard accessibility is
     37   //   needed and you want to check IsAccessibilityFocusable(), rather than
     38   //   IsFocusable().
     39   FocusSearch(View* root, bool cycle, bool accessibility_mode);
     40   virtual ~FocusSearch() {}
     41 
     42   // Finds the next view that should be focused and returns it. If a
     43   // FocusTraversable is found while searching for the focusable view,
     44   // returns NULL and sets |focus_traversable| to the FocusTraversable
     45   // and |focus_traversable_view| to the view associated with the
     46   // FocusTraversable.
     47   //
     48   // Return NULL if the end of the focus loop is reached, unless this object
     49   // was initialized with |cycle|=true, in which case it goes back to the
     50   // beginning when it reaches the end of the traversal.
     51   // - |starting_view| is the view that should be used as the starting point
     52   //   when looking for the previous/next view. It may be NULL (in which case
     53   //   the first/last view should be used depending if normal/reverse).
     54   // - |reverse| whether we should find the next (reverse is false) or the
     55   //   previous (reverse is true) view.
     56   // - |direction| specifies whether we are traversing down (meaning we should
     57   //   look into child views) or traversing up (don't look at child views).
     58   // - |check_starting_view| is true if starting_view may obtain the next focus.
     59   // - |focus_traversable| is set to the focus traversable that should be
     60   //   traversed if one is found (in which case the call returns NULL).
     61   // - |focus_traversable_view| is set to the view associated with the
     62   //   FocusTraversable set in the previous parameter (it is used as the
     63   //   starting view when looking for the next focusable view).
     64   virtual View* FindNextFocusableView(View* starting_view,
     65                                       bool reverse,
     66                                       Direction direction,
     67                                       bool check_starting_view,
     68                                       FocusTraversable** focus_traversable,
     69                                       View** focus_traversable_view);
     70 
     71  protected:
     72   // Get the parent, but stay within the root. Returns NULL if asked for
     73   // the parent of |root_|. Subclasses can override this if they need custom
     74   // focus search behavior.
     75   virtual View* GetParent(View* v);
     76 
     77   // Returns true if |v| is contained within the hierarchy rooted at |root|.
     78   // Subclasses can override this if they need custom focus search behavior.
     79   virtual bool Contains(View* root, const View* v);
     80 
     81   View* root() const { return root_; }
     82 
     83  private:
     84   // Convenience method that returns true if a view is focusable and does not
     85   // belong to the specified group.
     86   bool IsViewFocusableCandidate(View* v, int skip_group_id);
     87 
     88   // Convenience method; returns true if a view is not NULL and is focusable
     89   // (checking IsAccessibilityFocusable() if |accessibility_mode_| is true).
     90   bool IsFocusable(View* v);
     91 
     92   // Returns the view selected for the group of the selected view. If the view
     93   // does not belong to a group or if no view is selected in the group, the
     94   // specified view is returned.
     95   View* FindSelectedViewForGroup(View* view);
     96 
     97   // Returns the next focusable view or view containing a FocusTraversable
     98   // (NULL if none was found), starting at the starting_view.
     99   // |check_starting_view|, |can_go_up| and |can_go_down| controls the
    100   // traversal of the views hierarchy. |skip_group_id| specifies a group_id,
    101   // -1 means no group. All views from a group are traversed in one pass.
    102   View* FindNextFocusableViewImpl(View* starting_view,
    103                                   bool check_starting_view,
    104                                   bool can_go_up,
    105                                   bool can_go_down,
    106                                   int skip_group_id,
    107                                   FocusTraversable** focus_traversable,
    108                                   View** focus_traversable_view);
    109 
    110   // Same as FindNextFocusableViewImpl but returns the previous focusable view.
    111   View* FindPreviousFocusableViewImpl(View* starting_view,
    112                                       bool check_starting_view,
    113                                       bool can_go_up,
    114                                       bool can_go_down,
    115                                       int skip_group_id,
    116                                       FocusTraversable** focus_traversable,
    117                                       View** focus_traversable_view);
    118 
    119   View* root_;
    120   bool cycle_;
    121   bool accessibility_mode_;
    122 
    123   DISALLOW_COPY_AND_ASSIGN(FocusSearch);
    124 };
    125 
    126 }  // namespace views
    127 
    128 #endif  // UI_VIEWS_FOCUS_FOCUS_SEARCH_H_
    129