123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef ASH_APP_LIST_VIEWS_RESULT_SELECTION_CONTROLLER_H_
- #define ASH_APP_LIST_VIEWS_RESULT_SELECTION_CONTROLLER_H_
- #include <memory>
- #include <string>
- #include <vector>
- #include "ash/app_list/views/search_result_base_view.h"
- #include "ash/app_list/views/search_result_container_view.h"
- #include "ash/ash_export.h"
- #include "base/callback.h"
- namespace ash {
- class SearchResultContainerView;
- // This alias is intended to clarify the intended use of this class within the
- // context of this controller.
- using ResultSelectionModel = std::vector<SearchResultContainerView*>;
- // Stores and organizes the details for the 'coordinates' of the selected
- // result. This includes all information to determine exactly where a result is,
- // including both inter- and intra-container details, along with the traversal
- // direction for the container.
- struct ASH_EXPORT ResultLocationDetails {
- ResultLocationDetails();
- ResultLocationDetails(int container_index,
- int container_count,
- int result_index,
- int result_count,
- bool container_is_horizontal);
- bool operator==(const ResultLocationDetails& other) const;
- bool operator!=(const ResultLocationDetails& other) const;
- // True if the result is the first(0th) in its container
- bool is_first_result() const { return result_index == 0; }
- // True if the result is the last in its container
- bool is_last_result() const { return result_index == (result_count - 1); }
- // Index of the container within the overall nest of containers.
- int container_index = 0;
- // Number of containers to traverse among.
- int container_count = 0;
- // Index of the result within the list of results inside a container.
- int result_index = 0;
- // Number of results within the current container.
- int result_count = 0;
- // Whether the container is horizontally traversable.
- bool container_is_horizontal = false;
- };
- // A controller class to manage result selection across containers.
- class ASH_EXPORT ResultSelectionController {
- public:
- enum class MoveResult {
- // The selection has not changed (excluding the case covered by
- // kSelectionCycleRejected).
- kNone,
- // The selection has not changed because the selection would cycle.
- kSelectionCycleRejected,
- // The currently selected result has changed.
- //
- // Note: As long as the selected result remains the same, the result action
- // changes will be reported as kNone, mainly because the code that uses
- // MoveSelection() treats them the same.
- kResultChanged,
- };
- ResultSelectionController(
- const ResultSelectionModel* result_container_views,
- const base::RepeatingClosure& selection_change_callback);
- ResultSelectionController(const ResultSelectionController&) = delete;
- ResultSelectionController& operator=(const ResultSelectionController&) =
- delete;
- ~ResultSelectionController();
- // Returns the currently selected result.
- // Note that the return view might contain null result if results are
- // currently being updated.
- // As long as |block_selection_changes_| gets set while results are changing,
- // it should be safe to assume the result is not null after call to
- // MoveSelection() changes the selected result.
- SearchResultBaseView* selected_result() { return selected_result_; }
- // Returns the |ResultLocationDetails| object for the |selected_result_|.
- ResultLocationDetails* selected_location_details() {
- return selected_location_details_.get();
- }
- // Calls |SetSelection| using the result of |GetNextResultLocation|.
- MoveResult MoveSelection(const ui::KeyEvent& event);
- // Resets the selection to the first result.
- // |key_event| - The key event that triggered reselect, if any. Used to
- // determine whether selection should start at the last element.
- // |default_selection| - True if it resets the first result as default
- // selection.
- void ResetSelection(const ui::KeyEvent* key_event, bool default_selection);
- // Clears the |selected_result_|, |selected_location_details_|.
- void ClearSelection();
- // Used to block selection changes while async search result updates are in
- // flight, i.e. while the result views might point to obsolete null results.
- // Should be set for a short time, and setting this to false should generally
- // be followed by ResetSelection().
- void set_block_selection_changes(bool block_selection_changes) {
- block_selection_changes_ = block_selection_changes;
- }
- private:
- // Calls |GetNextResultLocationForLocation| using |selected_location_details_|
- // as the location
- MoveResult GetNextResultLocation(const ui::KeyEvent& event,
- ResultLocationDetails* next_location);
- // Logic for next is separated for modular use. You can ask for the "next"
- // location to be generated using any starting location/event combination.
- MoveResult GetNextResultLocationForLocation(
- const ui::KeyEvent& event,
- const ResultLocationDetails& location,
- ResultLocationDetails* next_location);
- // Sets the current selection to the provided |location|.
- void SetSelection(const ResultLocationDetails& location,
- bool reverse_tab_order);
- // Returns the location for the first result in the first non-empty result
- // container. Returns nullptr if no results exist.
- std::unique_ptr<ResultLocationDetails> GetFirstAvailableResultLocation()
- const;
- SearchResultBaseView* GetResultAtLocation(
- const ResultLocationDetails& location);
- // Returns the location of a result with the provided ID.
- // Returns nullptr if the result cannot be found.
- std::unique_ptr<ResultLocationDetails> FindResultWithId(
- const std::string& id);
- // Updates a |ResultLocationDetails| to a new container, updating most
- // attributes based on |result_selection_model_|.
- void ChangeContainer(ResultLocationDetails* location_details,
- int new_container_index);
- // Container views to be traversed by this controller.
- // Owned by |SearchResultPageView|.
- const ResultSelectionModel* result_selection_model_;
- // Returns true if the container at the given |index| within
- // |result_selection_model_| responds true to
- // |SearchResultContainerView|->|IsHorizontallyTraversable|.
- bool IsContainerAtIndexHorizontallyTraversable(int index) const;
- // The callback run when the selected result changes (including when the
- // selected result is cleared).
- base::RepeatingClosure selection_change_callback_;
- // The currently selected result view.
- SearchResultBaseView* selected_result_ = nullptr;
- // The currently selected result ID.
- std::string selected_result_id_;
- // If set, any attempt to change current selection will be rejected.
- bool block_selection_changes_ = false;
- // The |ResultLocationDetails| for the currently selected result view
- std::unique_ptr<ResultLocationDetails> selected_location_details_;
- };
- } // namespace ash
- #endif // ASH_APP_LIST_VIEWS_RESULT_SELECTION_CONTROLLER_H_
|