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