| // Copyright 2021 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_APP_LIST_BUBBLE_VIEW_H_ |
| #define ASH_APP_LIST_VIEWS_APP_LIST_BUBBLE_VIEW_H_ |
| |
| #include <memory> |
| |
| #include "ash/app_list/app_list_view_provider.h" |
| #include "ash/app_list/views/app_list_folder_controller.h" |
| #include "ash/ash_export.h" |
| #include "ash/public/cpp/app_list/app_list_types.h" |
| #include "ash/search_box/search_box_view_delegate.h" |
| #include "base/callback_forward.h" |
| #include "base/memory/weak_ptr.h" |
| #include "ui/views/view.h" |
| |
| namespace ash { |
| |
| class ApplicationDragAndDropHost; |
| class AppListA11yAnnouncer; |
| class AppListBubbleAppsPage; |
| class AppListBubbleAssistantPage; |
| class AppListBubbleSearchPage; |
| class AppListFolderItem; |
| class AppListFolderView; |
| class AppListViewDelegate; |
| class ButtonFocusSkipper; |
| class FolderBackgroundView; |
| class SearchBoxView; |
| class SearchResultPageDialogController; |
| class ViewShadow; |
| |
| // Contains the views for the bubble version of the launcher. It looks like a |
| // system tray bubble. It does not derive from TrayBubbleView because it takes |
| // focus by default, uses a different EventHandler for closing, and isn't tied |
| // to the system tray area. |
| class ASH_EXPORT AppListBubbleView : public views::View, |
| public SearchBoxViewDelegate, |
| public AppListFolderController { |
| public: |
| AppListBubbleView(AppListViewDelegate* view_delegate, |
| ApplicationDragAndDropHost* drag_and_drop_host); |
| AppListBubbleView(const AppListBubbleView&) = delete; |
| AppListBubbleView& operator=(const AppListBubbleView&) = delete; |
| ~AppListBubbleView() override; |
| |
| // If |drag_and_drop_host| is not nullptr it will be called upon drag and drop |
| // operations outside the app list (e.g. to the shelf). |
| void SetDragAndDropHostOfCurrentAppList( |
| ApplicationDragAndDropHost* drag_and_drop_host); |
| |
| // Updates continue tasks and recent apps. |
| void UpdateSuggestions(); |
| |
| // Starts the bubble show animation. Pass `is_side_shelf` true for left or |
| // right aligned shelf. |
| void StartShowAnimation(bool is_side_shelf); |
| |
| // Starts the bubble hide animation. Pass `is_side_shelf` true for left or |
| // right aligned shelf. `on_hide_animation_ended` is called on end or abort. |
| void StartHideAnimation(bool is_side_shelf, |
| base::OnceClosure on_hide_animation_ended); |
| |
| // Aborts all layer animations started by StartShowAnimation() or |
| // StartHideAnimation(). This invokes their cleanup callbacks. |
| void AbortAllAnimations(); |
| |
| // Handles back action if it we have a use for it besides dismissing. |
| bool Back(); |
| |
| // Shows a sub-page. |
| void ShowPage(AppListBubblePage page); |
| |
| // Returns true if the assistant page is showing. |
| bool IsShowingEmbeddedAssistantUI() const; |
| |
| // Shows the assistant page. |
| void ShowEmbeddedAssistantUI(); |
| |
| // Returns the required height for this view in DIPs to show all apps in the |
| // apps grid. Used for computing the bubble height on large screens. |
| int GetHeightToFitAllApps() const; |
| |
| // Updates the continue section visibility based on user preference. |
| void UpdateContinueSectionVisibility(); |
| |
| // Handles `AppListController::UpdateAppListWithNewSortingOrder()` for the |
| // app list bubble view. |
| void UpdateForNewSortingOrder( |
| const absl::optional<AppListSortOrder>& new_order, |
| bool animate, |
| base::OnceClosure update_position_closure); |
| |
| // views::View: |
| const char* GetClassName() const override; |
| bool AcceleratorPressed(const ui::Accelerator& accelerator) override; |
| void OnThemeChanged() override; |
| void Layout() override; |
| |
| // SearchBoxViewDelegate: |
| void QueryChanged(SearchBoxViewBase* sender) override; |
| void AssistantButtonPressed() override; |
| void CloseButtonPressed() override; |
| void ActiveChanged(SearchBoxViewBase* sender) override {} |
| void OnSearchBoxKeyEvent(ui::KeyEvent* event) override; |
| bool CanSelectSearchResults() override; |
| |
| // AppListFolderController: |
| void ShowFolderForItemView(AppListItemView* folder_item_view, |
| bool focus_name_input, |
| base::OnceClosure hide_callback) override; |
| void ShowApps(AppListItemView* folder_item_view, bool select_folder) override; |
| void ReparentFolderItemTransit(AppListFolderItem* folder_item) override; |
| void ReparentDragEnded() override; |
| |
| // Initialize Assistant UIs for bubble view. Assistant UIs |
| // (AppListAssistantMainStage, SuggestionContainerView) expect that their |
| // OnUiVisibilityChanged methods get called via value update in |
| // AssistantUiModel. |
| // |
| // But it does not happen for bubble view as AppListBubblePresenter have an |
| // async call for OnZeroStateSearchDone. AppListBubbleView is instantiated |
| // after the async call and those UIs will miss the event. |
| // |
| // This is a helper method to manually trigger the UI initialization. |
| // |
| // This method is designed to be explicitly called from AppListBubblePresenter |
| // (i.e. instead of doing this in the constructor of AppListBubbleView) to |
| // make the intention clear. |
| // |
| // TODO(b/239754561): Clean up: refactor Assistant UI initialization |
| void InitializeUIForBubbleView(); |
| |
| AppListBubblePage current_page_for_test() { return current_page_; } |
| ViewShadow* view_shadow_for_test() { return view_shadow_.get(); } |
| SearchBoxView* search_box_view_for_test() { return search_box_view_; } |
| views::View* separator_for_test() { return separator_; } |
| bool showing_folder_for_test() { return showing_folder_; } |
| AppListBubbleAppsPage* apps_page_for_test() { return apps_page_; } |
| AppListFolderView* folder_view_for_test() { return folder_view_; } |
| |
| private: |
| friend class AppListTestHelper; |
| friend class AssistantTestApiImpl; |
| |
| // Initializes the main contents (search box, apps page, and search page). |
| void InitContentsView(ApplicationDragAndDropHost* drag_and_drop_host); |
| |
| // Initializes the folder view, which appears on top of all other views. |
| void InitFolderView(ApplicationDragAndDropHost* drag_and_drop_host); |
| |
| // Makes the root apps grid view and other top-level views unfocusable if |
| // `disabled` is true, such that focus is contained in the folder view. |
| void DisableFocusForShowingActiveFolder(bool disabled); |
| |
| // Called when the show animation ends or aborts. |
| void OnShowAnimationEnded(const gfx::Rect& layer_bounds); |
| |
| // Called when the hide animation ends or aborts. |
| void OnHideAnimationEnded(const gfx::Rect& layer_bounds); |
| |
| // Hides the folder view if it's currently shown. It can be called if the |
| // folder is not currently shown. |
| // `animate` - Whether the folder view should be hidden using an animation. |
| // `hide_for_reparent` - Whether the folder view is being hidden to initiate |
| // item reparent user action (e.g. when dragging folder item out of the folder |
| // view bounds). |
| void HideFolderView(bool animate, bool hide_for_reparent); |
| |
| // Called when the reorder animation completes. |
| void OnAppListReorderAnimationDone(); |
| |
| // Focuses the search box if the view is not hiding. |
| void MaybeFocusAndActivateSearchBox(); |
| |
| AppListViewDelegate* const view_delegate_; |
| |
| std::unique_ptr<AppListA11yAnnouncer> a11y_announcer_; |
| |
| // Controller for showing a modal dialog in search results page. |
| std::unique_ptr<SearchResultPageDialogController> |
| search_page_dialog_controller_; |
| |
| // Explicitly store the current page because multiple pages can be visible |
| // during animations. |
| AppListBubblePage current_page_ = AppListBubblePage::kNone; |
| |
| std::unique_ptr<ViewShadow> view_shadow_; |
| |
| // The individual views are implementation details and are intentionally not |
| // exposed via getters (except for tests). |
| SearchBoxView* search_box_view_ = nullptr; |
| views::View* separator_ = nullptr; |
| AppListBubbleAppsPage* apps_page_ = nullptr; |
| AppListBubbleSearchPage* search_page_ = nullptr; |
| AppListBubbleAssistantPage* assistant_page_ = nullptr; |
| |
| // Lives in this class because it can overlap the search box. |
| AppListFolderView* folder_view_ = nullptr; |
| |
| // Used to close an open folder view. |
| FolderBackgroundView* folder_background_view_ = nullptr; |
| |
| // Whether we're showing the folder view. This is different from |
| // folder_view_->GetVisible() because the view is "visible" but hidden when |
| // dragging an item out of a folder. |
| bool showing_folder_ = false; |
| |
| // Whether the view is animating hidden. |
| bool is_hiding_ = false; |
| |
| // Called after the hide animation ends or aborts. |
| base::OnceClosure on_hide_animation_ended_; |
| |
| // See class comment in .cc file. |
| std::unique_ptr<ButtonFocusSkipper> button_focus_skipper_; |
| |
| base::WeakPtrFactory<AppListBubbleView> weak_factory_{this}; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_APP_LIST_VIEWS_APP_LIST_BUBBLE_VIEW_H_ |