Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Side by Side Diff: ui/app_list/shower/app_list_shower_impl.cc

Issue 1830293002: AppListController refactoring part 1: AppListShower implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixing target names in .isolate. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 #include "ui/app_list/shower/app_list_shower_impl.h"
6
7 #include "ui/app_list/app_list_constants.h"
8 #include "ui/app_list/app_list_switches.h"
9 #include "ui/app_list/pagination_model.h"
10 #include "ui/app_list/shower/app_list_shower_delegate_factory.h"
11 #include "ui/app_list/views/app_list_view.h"
12 #include "ui/aura/client/focus_client.h"
13 #include "ui/aura/window.h"
14 #include "ui/compositor/layer.h"
15 #include "ui/compositor/scoped_layer_animation_settings.h"
16 #include "ui/views/widget/widget.h"
17
18 namespace app_list {
19 namespace {
20
21 // Duration for show/hide animation in milliseconds.
22 const int kAnimationDurationMs = 200;
23
24 // The maximum shift in pixels when over-scroll happens.
25 const int kMaxOverScrollShift = 48;
26
27 ui::Layer* GetLayer(views::Widget* widget) {
28 return widget->GetNativeView()->layer();
29 }
30
31 } // namespace
32
33 AppListShowerImpl::AppListShowerImpl(AppListShowerDelegateFactory* factory)
34 : factory_(factory) {
35 DCHECK(factory);
36 }
37
38 AppListShowerImpl::~AppListShowerImpl() {
39 shower_delegate_.reset();
40 // Ensures app list view goes before the controller since pagination model
41 // lives in the controller and app list view would access it on destruction.
42 if (view_) {
43 view_->GetAppsPaginationModel()->RemoveObserver(this);
44 if (view_->GetWidget())
45 view_->GetWidget()->CloseNow();
46 }
47 }
48
49 aura::Window* AppListShowerImpl::GetWindow() {
50 return is_visible_ && view_ ? view_->GetWidget()->GetNativeWindow() : nullptr;
51 }
52
53 void AppListShowerImpl::Show(aura::Window* window) {
54 if (is_visible_)
55 return;
56
57 DCHECK(window);
58 is_visible_ = true;
59 aura::Window* root_window = window->GetRootWindow();
60 if (view_) {
61 ScheduleAnimation();
62 } else {
63 shower_delegate_ = factory_->GetDelegate(this);
64 AppListViewDelegate* view_delegate = shower_delegate_->GetViewDelegate();
65 DCHECK(view_delegate);
66 // Note the AppListViewDelegate outlives the AppListView. For Ash, the view
67 // is destroyed when dismissed.
68 AppListView* view = new AppListView(view_delegate);
69 shower_delegate_->Init(view, root_window, current_apps_page_);
70 SetView(view);
71 }
72 shower_delegate_->OnShown(root_window);
73 }
74
75 void AppListShowerImpl::Dismiss() {
76 if (!is_visible_)
77 return;
78
79 // If the app list is currently visible, there should be an existing view.
80 DCHECK(view_);
81
82 is_visible_ = false;
83
84 // Our widget is currently active. When the animation completes we'll hide
85 // the widget, changing activation. If a menu is shown before the animation
86 // completes then the activation change triggers the menu to close. By
87 // deactivating now we ensure there is no activation change when the
88 // animation completes and any menus stay open.
89 view_->GetWidget()->Deactivate();
90
91 shower_delegate_->OnDismissed();
92 ScheduleAnimation();
93 }
94
95 bool AppListShowerImpl::IsVisible() const {
96 return view_ && view_->GetWidget()->IsVisible();
97 }
98
99 bool AppListShowerImpl::GetTargetVisibility() const {
100 return is_visible_;
101 }
102
103 ////////////////////////////////////////////////////////////////////////////////
104 // AppListShowerImpl, private:
105
106 void AppListShowerImpl::SetView(AppListView* view) {
107 DCHECK(view_ == nullptr);
108 DCHECK(is_visible_);
109
110 view_ = view;
111 views::Widget* widget = view_->GetWidget();
112 widget->AddObserver(this);
113 widget->GetNativeView()->GetRootWindow()->AddObserver(this);
114 aura::client::GetFocusClient(widget->GetNativeView())->AddObserver(this);
115 view_->GetAppsPaginationModel()->AddObserver(this);
116 view_->ShowWhenReady();
117 }
118
119 void AppListShowerImpl::ResetView() {
120 if (!view_)
121 return;
122
123 views::Widget* widget = view_->GetWidget();
124 widget->RemoveObserver(this);
125 GetLayer(widget)->GetAnimator()->RemoveObserver(this);
126 shower_delegate_.reset();
127 widget->GetNativeView()->GetRootWindow()->RemoveObserver(this);
128 aura::client::GetFocusClient(widget->GetNativeView())->RemoveObserver(this);
129
130 view_->GetAppsPaginationModel()->RemoveObserver(this);
131
132 view_ = nullptr;
133 }
134
135 void AppListShowerImpl::ScheduleAnimation() {
136 // Stop observing previous animation.
137 StopObservingImplicitAnimations();
138
139 views::Widget* widget = view_->GetWidget();
140 ui::Layer* layer = GetLayer(widget);
141 layer->GetAnimator()->StopAnimating();
142
143 gfx::Rect target_bounds;
144 gfx::Vector2d offset = shower_delegate_->GetVisibilityAnimationOffset(
145 widget->GetNativeView()->GetRootWindow());
146 if (is_visible_) {
147 target_bounds = widget->GetWindowBoundsInScreen();
148 gfx::Rect start_bounds = gfx::Rect(target_bounds);
149 start_bounds.Offset(offset);
150 widget->SetBounds(start_bounds);
151 } else {
152 target_bounds = widget->GetWindowBoundsInScreen();
153 target_bounds.Offset(offset);
154 }
155
156 ui::ScopedLayerAnimationSettings animation(layer->GetAnimator());
157 animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
158 is_visible_ ? 0 : kAnimationDurationMs));
159 animation.AddObserver(this);
160
161 layer->SetOpacity(is_visible_ ? 1.0 : 0.0);
162 widget->SetBounds(target_bounds);
163 }
164
165 ////////////////////////////////////////////////////////////////////////////////
166 // AppListShowerImpl, aura::client::FocusChangeObserver implementation:
167
168 void AppListShowerImpl::OnWindowFocused(aura::Window* gained_focus,
169 aura::Window* lost_focus) {
170 if (view_ && is_visible_) {
171 aura::Window* applist_window = view_->GetWidget()->GetNativeView();
172 aura::Window* applist_container = applist_window->parent();
173 if (applist_container->Contains(lost_focus) &&
174 (!gained_focus || !applist_container->Contains(gained_focus)) &&
175 !switches::ShouldNotDismissOnBlur()) {
176 Dismiss();
177 }
178 }
179 }
180
181 ////////////////////////////////////////////////////////////////////////////////
182 // AppListShowerImpl, aura::WindowObserver implementation:
183 void AppListShowerImpl::OnWindowBoundsChanged(aura::Window* root,
184 const gfx::Rect& old_bounds,
185 const gfx::Rect& new_bounds) {
186 if (shower_delegate_)
187 shower_delegate_->UpdateBounds();
188 }
189
190 ////////////////////////////////////////////////////////////////////////////////
191 // AppListShowerImpl, ui::ImplicitAnimationObserver implementation:
192
193 void AppListShowerImpl::OnImplicitAnimationsCompleted() {
194 if (is_visible_)
195 view_->GetWidget()->Activate();
196 else
197 view_->GetWidget()->Close();
198 }
199
200 ////////////////////////////////////////////////////////////////////////////////
201 // AppListShowerImpl, views::WidgetObserver implementation:
202
203 void AppListShowerImpl::OnWidgetDestroying(views::Widget* widget) {
204 DCHECK(view_->GetWidget() == widget);
205 if (is_visible_)
206 Dismiss();
207 ResetView();
208 }
209
210 ////////////////////////////////////////////////////////////////////////////////
211 // AppListShowerImpl, PaginationModelObserver implementation:
212
213 void AppListShowerImpl::TotalPagesChanged() {}
214
215 void AppListShowerImpl::SelectedPageChanged(int old_selected,
216 int new_selected) {
217 current_apps_page_ = new_selected;
218 }
219
220 void AppListShowerImpl::TransitionStarted() {}
221
222 void AppListShowerImpl::TransitionChanged() {
223 // |view_| could be NULL when app list is closed with a running transition.
224 if (!view_)
225 return;
226
227 PaginationModel* pagination_model = view_->GetAppsPaginationModel();
228
229 const PaginationModel::Transition& transition =
230 pagination_model->transition();
231 if (pagination_model->is_valid_page(transition.target_page))
232 return;
233
234 views::Widget* widget = view_->GetWidget();
235 ui::LayerAnimator* widget_animator =
236 widget->GetNativeView()->layer()->GetAnimator();
237 if (!pagination_model->IsRevertingCurrentTransition()) {
238 // Update cached |view_bounds_| if it is the first over-scroll move and
239 // widget does not have running animations.
240 if (!should_snap_back_ && !widget_animator->is_animating())
241 view_bounds_ = widget->GetWindowBoundsInScreen();
242
243 const int current_page = pagination_model->selected_page();
244 const int dir = transition.target_page > current_page ? -1 : 1;
245
246 const double progress = 1.0 - pow(1.0 - transition.progress, 4);
247 const int shift = kMaxOverScrollShift * progress * dir;
248
249 gfx::Rect shifted(view_bounds_);
250 shifted.set_x(shifted.x() + shift);
251
252 widget->SetBounds(shifted);
253
254 should_snap_back_ = true;
255 } else if (should_snap_back_) {
256 should_snap_back_ = false;
257 ui::ScopedLayerAnimationSettings animation(widget_animator);
258 animation.SetTransitionDuration(
259 base::TimeDelta::FromMilliseconds(kOverscrollPageTransitionDurationMs));
260 widget->SetBounds(view_bounds_);
261 }
262 }
263
264 } // namespace app_list
OLDNEW
« no previous file with comments | « ui/app_list/shower/app_list_shower_impl.h ('k') | ui/app_list/shower/app_list_shower_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698