15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef UI_VIEWS_FOCUS_FOCUS_SEARCH_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UI_VIEWS_FOCUS_FOCUS_SEARCH_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FocusTraversable;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FocusSearch is an object that implements the algorithm to find the
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// next view to focus.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VIEWS_EXPORT FocusSearch {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The direction in which the focus traversal is going.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO (jcampan): add support for lateral (left, right) focus traversal. The
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // goal is to switch to focusable views on the same level when using the arrow
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keys (ala Windows: in a dialog box, arrow keys typically move between the
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dialog OK, Cancel buttons).
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Direction {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UP = 0,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DOWN
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Constructor.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - |root| is the root of the view hierarchy to traverse. Focus will be
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   trapped inside.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - |cycle| should be true if you want FindNextFocusableView to cycle back
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //           to the first view within this root when the traversal reaches
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //           the end. If this is true, then if you pass a valid starting
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //           view to FindNextFocusableView you will always get a valid view
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //           out, even if it's the same view.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - |accessibility_mode| should be true if full keyboard accessibility is
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   needed and you want to check IsAccessibilityFocusable(), rather than
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   IsFocusable().
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FocusSearch(View* root, bool cycle, bool accessibility_mode);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~FocusSearch() {}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finds the next view that should be focused and returns it. If a
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FocusTraversable is found while searching for the focusable view,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns NULL and sets |focus_traversable| to the FocusTraversable
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and |focus_traversable_view| to the view associated with the
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FocusTraversable.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return NULL if the end of the focus loop is reached, unless this object
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was initialized with |cycle|=true, in which case it goes back to the
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // beginning when it reaches the end of the traversal.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - |starting_view| is the view that should be used as the starting point
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   when looking for the previous/next view. It may be NULL (in which case
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the first/last view should be used depending if normal/reverse).
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - |reverse| whether we should find the next (reverse is false) or the
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   previous (reverse is true) view.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - |direction| specifies whether we are traversing down (meaning we should
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   look into child views) or traversing up (don't look at child views).
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - |check_starting_view| is true if starting_view may obtain the next focus.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - |focus_traversable| is set to the focus traversable that should be
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   traversed if one is found (in which case the call returns NULL).
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - |focus_traversable_view| is set to the view associated with the
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   FocusTraversable set in the previous parameter (it is used as the
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   starting view when looking for the next focusable view).
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual View* FindNextFocusableView(View* starting_view,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      bool reverse,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      Direction direction,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      bool check_starting_view,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      FocusTraversable** focus_traversable,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      View** focus_traversable_view);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the parent, but stay within the root. Returns NULL if asked for
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the parent of |root_|. Subclasses can override this if they need custom
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // focus search behavior.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual View* GetParent(View* v);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if |v| is contained within the hierarchy rooted at |root|.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Subclasses can override this if they need custom focus search behavior.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Contains(View* root, const View* v);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  View* root() const { return root_; }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convenience method that returns true if a view is focusable and does not
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // belong to the specified group.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsViewFocusableCandidate(View* v, int skip_group_id);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convenience method; returns true if a view is not NULL and is focusable
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (checking IsAccessibilityFocusable() if |accessibility_mode_| is true).
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsFocusable(View* v);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the view selected for the group of the selected view. If the view
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // does not belong to a group or if no view is selected in the group, the
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // specified view is returned.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  View* FindSelectedViewForGroup(View* view);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the next focusable view or view containing a FocusTraversable
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (NULL if none was found), starting at the starting_view.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |check_starting_view|, |can_go_up| and |can_go_down| controls the
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // traversal of the views hierarchy. |skip_group_id| specifies a group_id,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -1 means no group. All views from a group are traversed in one pass.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  View* FindNextFocusableViewImpl(View* starting_view,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool check_starting_view,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool can_go_up,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool can_go_down,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int skip_group_id,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  FocusTraversable** focus_traversable,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  View** focus_traversable_view);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same as FindNextFocusableViewImpl but returns the previous focusable view.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  View* FindPreviousFocusableViewImpl(View* starting_view,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      bool check_starting_view,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      bool can_go_up,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      bool can_go_down,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int skip_group_id,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      FocusTraversable** focus_traversable,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      View** focus_traversable_view);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  View* root_;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool cycle_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool accessibility_mode_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FocusSearch);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace views
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // UI_VIEWS_FOCUS_FOCUS_SEARCH_H_
129