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