1 // Copyright 2019 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_WM_DESKS_DESK_MINI_VIEW_H_
6 #define ASH_WM_DESKS_DESK_MINI_VIEW_H_
7 
8 #include <memory>
9 
10 #include "ash/ash_export.h"
11 #include "ash/wm/desks/desk.h"
12 #include "ash/wm/overview/overview_highlight_controller.h"
13 #include "base/macros.h"
14 #include "ui/views/controls/button/button.h"
15 #include "ui/views/controls/label.h"
16 #include "ui/views/controls/textfield/textfield_controller.h"
17 #include "ui/views/view_observer.h"
18 
19 namespace ash {
20 
21 class CloseDeskButton;
22 class DeskNameView;
23 class DeskPreviewView;
24 class DesksBarView;
25 
26 // A view that acts as a mini representation (a.k.a. desk thumbnail) of a
27 // virtual desk in the desk bar view when overview mode is active. This view
28 // shows a preview of the contents of the associated desk, its title, and
29 // supports desk activation and removal.
30 class ASH_EXPORT DeskMiniView
31     : public views::View,
32       public Desk::Observer,
33       public OverviewHighlightController::OverviewHighlightableView,
34       public views::TextfieldController,
35       public views::ViewObserver {
36  public:
37   DeskMiniView(DesksBarView* owner_bar, aura::Window* root_window, Desk* desk);
38   ~DeskMiniView() override;
39 
root_window()40   aura::Window* root_window() { return root_window_; }
41 
desk()42   Desk* desk() { return desk_; }
43 
desk_name_view()44   DeskNameView* desk_name_view() { return desk_name_view_; }
45 
close_desk_button()46   const CloseDeskButton* close_desk_button() const {
47     return close_desk_button_;
48   }
49 
50   // Returns the associated desk's container window on the display this
51   // mini_view resides on.
52   aura::Window* GetDeskContainer() const;
53 
54   // Returns true if the desk's name is being modified (i.e. the DeskNameView
55   // has the focus).
56   bool IsDeskNameBeingModified() const;
57 
58   // Updates the visibility state of the close button depending on whether this
59   // view is mouse hovered, or if switch access is enabled.
60   void UpdateCloseButtonVisibility();
61 
62   // Gesture tapping may affect the visibility of the close button. There's only
63   // one mini_view that shows the close button on long press at any time.
64   // This is useful for touch-only UIs.
65   void OnWidgetGestureTap(const gfx::Rect& screen_rect, bool is_long_gesture);
66 
67   // Updates the border color of the DeskPreviewView based on the activation
68   // state of the corresponding desk.
69   void UpdateBorderColor();
70 
71   // views::View:
72   const char* GetClassName() const override;
73   void Layout() override;
74   gfx::Size CalculatePreferredSize() const override;
75   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
76   void OnThemeChanged() override;
77 
78   // Desk::Observer:
79   void OnContentChanged() override;
80   void OnDeskDestroyed(const Desk* desk) override;
81   void OnDeskNameChanged(const base::string16& new_name) override;
82 
83   // OverviewHighlightController::OverviewHighlightableView:
84   views::View* GetView() override;
85   void MaybeActivateHighlightedView() override;
86   void MaybeCloseHighlightedView() override;
87   void OnViewHighlighted() override;
88   void OnViewUnhighlighted() override;
89 
90   // views::TextfieldController:
91   void ContentsChanged(views::Textfield* sender,
92                        const base::string16& new_contents) override;
93   bool HandleKeyEvent(views::Textfield* sender,
94                       const ui::KeyEvent& key_event) override;
95   bool HandleMouseEvent(views::Textfield* sender,
96                         const ui::MouseEvent& mouse_event) override;
97 
98   // views::ViewObserver:
99   void OnViewFocused(views::View* observed_view) override;
100   void OnViewBlurred(views::View* observed_view) override;
101 
102   bool IsPointOnMiniView(const gfx::Point& screen_location) const;
103 
104   // Gets the minimum width of this view to properly lay out all its contents in
105   // default layout.
106   // The view containing this object can use the width returned from this
107   // function to decide its own proper size or layout.
108   int GetMinWidthForDefaultLayout() const;
109 
110   bool IsDeskNameViewVisibleForTesting() const;
GetDeskPreviewForTesting()111   const DeskPreviewView* GetDeskPreviewForTesting() const {
112     return desk_preview_;
113   }
114 
115  private:
116   void OnCloseButtonPressed();
117 
118   void OnDeskPreviewPressed();
119 
120   // Layout |desk_name_view_| given the current bounds of the desk preview.
121   void LayoutDeskNameView(const gfx::Rect& preview_bounds);
122 
123   DesksBarView* const owner_bar_;
124 
125   // The root window on which this mini_view is created.
126   aura::Window* root_window_;
127 
128   // The associated desk. Can be null when the desk is deleted before this
129   // mini_view completes its removal animation. See comment above
130   // OnDeskRemoved().
131   Desk* desk_;  // Not owned.
132 
133   // The view that shows a preview of the desk contents.
134   DeskPreviewView* desk_preview_;
135 
136   // The editable desk name.
137   DeskNameView* desk_name_view_;
138 
139   // The close button that shows on hover.
140   CloseDeskButton* close_desk_button_;
141 
142   // We force showing the close button when the mini_view is long pressed or
143   // tapped using touch gestures.
144   bool force_show_close_button_ = false;
145 
146   // When the DeskNameView is focused, we select all its text. However, if it is
147   // focused via a mouse press event, on mouse release will clear the selection.
148   // Therefore, we defer selecting all text until we receive that mouse release.
149   bool defer_select_all_ = false;
150 
151   bool is_desk_name_being_modified_ = false;
152 
153   DISALLOW_COPY_AND_ASSIGN(DeskMiniView);
154 };
155 
156 }  // namespace ash
157 
158 #endif  // ASH_WM_DESKS_DESK_MINI_VIEW_H_
159