1 // Copyright 2018 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 ASH_SHORTCUT_VIEWER_VIEWS_KEYBOARD_SHORTCUT_VIEW_H_
6 #define ASH_SHORTCUT_VIEWER_VIEWS_KEYBOARD_SHORTCUT_VIEW_H_
7 
8 #include <map>
9 #include <memory>
10 #include <vector>
11 
12 #include "ash/search_box/search_box_view_delegate.h"
13 #include "base/macros.h"
14 #include "base/optional.h"
15 #include "base/timer/timer.h"
16 #include "ui/views/widget/widget_delegate.h"
17 
18 namespace aura {
19 class Window;
20 }
21 
22 namespace views {
23 class TabbedPane;
24 class Widget;
25 }  // namespace views
26 
27 namespace keyboard_shortcut_viewer {
28 
29 class KeyboardShortcutItemView;
30 class KSVSearchBoxView;
31 enum class ShortcutCategory;
32 
33 // The UI container for Ash and Chrome keyboard shortcuts.
34 class KeyboardShortcutView : public views::WidgetDelegateView,
35                              public ash::SearchBoxViewDelegate {
36  public:
37   ~KeyboardShortcutView() override;
38 
39   // Toggle the Keyboard Shortcut Viewer window.
40   // 1. Show the window if it is not open.
41   // 2. Activate the window if it is open but not active.
42   // 3. Close the window if it is open and active.
43   // |context| is used to determine which display to place the Window on.
44   static views::Widget* Toggle(aura::Window* context);
45 
46   // views::View:
47   const char* GetClassName() const override;
48   ax::mojom::Role GetAccessibleWindowRole() override;
49   base::string16 GetAccessibleWindowTitle() const override;
50   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
51   void Layout() override;
52   gfx::Size CalculatePreferredSize() const override;
53   void OnPaint(gfx::Canvas* canvas) override;
54 
55   // SearchBoxViewDelegate:
56   void QueryChanged(ash::SearchBoxViewBase* sender) override;
AssistantButtonPressed()57   void AssistantButtonPressed() override {}
58   void BackButtonPressed() override;
59   void ActiveChanged(ash::SearchBoxViewBase* sender) override;
SearchBoxFocusChanged(ash::SearchBoxViewBase * sender)60   void SearchBoxFocusChanged(ash::SearchBoxViewBase* sender) override {}
61 
62  private:
63   friend class KeyboardShortcutViewTest;
64 
65   KeyboardShortcutView();
66 
67   void InitViews();
68 
69   // Initialize |categories_tabbed_pane_| with category tabs and containers of
70   // |shortcut_views_|, called on construction and when exiting search mode.
71   // If |initial_category| has value, we will initialize the specified category,
72   // otherwise all the categories will be intialized.
73   void InitCategoriesTabbedPane(
74       base::Optional<ShortcutCategory> initial_category);
75 
76   // Update views' layout based on search box status.
77   void UpdateViewsLayout(bool is_search_box_active);
78 
79   // Show search results in |search_results_container_|.
80   void ShowSearchResults(const base::string16& search_query);
81 
82   // views::WidgetDelegate:
83   views::ClientView* CreateClientView(views::Widget* widget) override;
84 
85   static KeyboardShortcutView* GetInstanceForTesting();
86   size_t GetTabCountForTesting() const;
87   const std::vector<std::unique_ptr<KeyboardShortcutItemView>>&
88   GetShortcutViewsForTesting() const;
89   KSVSearchBoxView* GetSearchBoxViewForTesting();
90   const std::vector<KeyboardShortcutItemView*>&
91   GetFoundShortcutItemsForTesting() const;
92 
93   // Owned by views hierarchy.
94   // The container for category tabs and lists of KeyboardShortcutItemViews.
95   views::TabbedPane* categories_tabbed_pane_ = nullptr;
96   // The container for KeyboardShortcutItemViews matching a user's query.
97   views::View* search_results_container_ = nullptr;
98 
99   // SearchBoxViewBase is a WidgetDelegateView, which owns itself and cannot be
100   // deleted from the views hierarchy automatically.
101   std::unique_ptr<KSVSearchBoxView> search_box_view_;
102 
103   // Contains all the shortcut item views from all categories. This list is also
104   // used for searching. The views are not owned by the Views hierarchy to avoid
105   // KeyboardShortcutItemView layout when switching between tabs and search.
106   std::vector<std::unique_ptr<KeyboardShortcutItemView>> shortcut_views_;
107 
108   // Contains all the found shortcut items.
109   std::vector<KeyboardShortcutItemView*> found_shortcut_items_;
110 
111   // An illustration to indicate no search results found. Since this view need
112   // to be added and removed frequently from the |search_results_container_|, it
113   // is not owned by view hierarchy to avoid recreating it.
114   std::unique_ptr<views::View> search_no_result_view_;
115 
116   // Cached value of search box text status. When the status changes, need to
117   // update views' layout.
118   bool is_search_box_empty_ = true;
119 
120   // Cached value of active tab index before entering search mode.
121   size_t active_tab_index_ = 0;
122 
123   // Debounce for search queries.
124   base::OneShotTimer debounce_timer_;
125 
126   // Ture if need to initialize all the categories.
127   // False if only initialize the first category.
128   bool needs_init_all_categories_ = false;
129   // Indicates if recieved the first OnPaint event. Used to schedule
130   // initialization of background panes in the following frame.
131   bool did_first_paint_ = false;
132 
133   base::WeakPtrFactory<KeyboardShortcutView> weak_factory_{this};
134 
135   DISALLOW_COPY_AND_ASSIGN(KeyboardShortcutView);
136 };
137 
138 }  // namespace keyboard_shortcut_viewer
139 
140 #endif  // ASH_SHORTCUT_VIEWER_VIEWS_KEYBOARD_SHORTCUT_VIEW_H_
141