OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/launcher/launcher_view.h" | 5 #include "ash/launcher/launcher_view.h" |
6 | 6 |
7 #include "ash/launcher/launcher_button.h" | 7 #include "ash/launcher/launcher_button.h" |
8 #include "ash/launcher/launcher_delegate.h" | 8 #include "ash/launcher/launcher_delegate.h" |
9 #include "ash/launcher/launcher_model.h" | 9 #include "ash/launcher/launcher_model.h" |
10 #include "ash/launcher/tabbed_launcher_button.h" | 10 #include "ash/launcher/tabbed_launcher_button.h" |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 case STATUS_RUNNING: | 174 case STATUS_RUNNING: |
175 button->ClearState(LauncherButton::STATE_ACTIVE); | 175 button->ClearState(LauncherButton::STATE_ACTIVE); |
176 button->AddState(LauncherButton::STATE_RUNNING); | 176 button->AddState(LauncherButton::STATE_RUNNING); |
177 break; | 177 break; |
178 case STATUS_ACTIVE: | 178 case STATUS_ACTIVE: |
179 button->AddState(LauncherButton::STATE_ACTIVE); | 179 button->AddState(LauncherButton::STATE_ACTIVE); |
180 button->ClearState(LauncherButton::STATE_RUNNING); | 180 button->ClearState(LauncherButton::STATE_RUNNING); |
181 break; | 181 break; |
182 } | 182 } |
183 } | 183 } |
184 | |
185 // A class used by TestAPI to wait for animations. | |
186 class TestAPIAnimationObserver : public views::BoundsAnimatorObserver { | |
187 public: | |
188 TestAPIAnimationObserver() {} | |
189 virtual ~TestAPIAnimationObserver() {} | |
190 | |
191 // views::BoundsAnimatorObserver overrides: | |
192 virtual void OnBoundsAnimatorDone(views::BoundsAnimator* animator) OVERRIDE { | |
193 MessageLoop::current()->Quit(); | |
194 } | |
195 | |
196 private: | |
197 DISALLOW_COPY_AND_ASSIGN(TestAPIAnimationObserver); | |
198 }; | |
199 | |
184 } // namespace | 200 } // namespace |
185 | 201 |
186 // AnimationDelegate used when inserting a new item. This steadily decreased the | 202 // AnimationDelegate used when inserting a new item. This steadily decreased the |
187 // opacity of the layer as the animation progress. | 203 // opacity of the layer as the animation progress. |
188 class LauncherView::FadeOutAnimationDelegate : | 204 class LauncherView::FadeOutAnimationDelegate : |
189 public views::BoundsAnimator::OwnedAnimationDelegate { | 205 public views::BoundsAnimator::OwnedAnimationDelegate { |
190 public: | 206 public: |
191 FadeOutAnimationDelegate(LauncherView* host, views::View* view) | 207 FadeOutAnimationDelegate(LauncherView* host, views::View* view) |
192 : launcher_view_(host), | 208 : launcher_view_(host), |
193 view_(view) {} | 209 view_(view) {} |
(...skipping 24 matching lines...) Expand all Loading... | |
218 public views::BoundsAnimator::OwnedAnimationDelegate { | 234 public views::BoundsAnimator::OwnedAnimationDelegate { |
219 public: | 235 public: |
220 StartFadeAnimationDelegate(LauncherView* host, | 236 StartFadeAnimationDelegate(LauncherView* host, |
221 views::View* view) | 237 views::View* view) |
222 : launcher_view_(host), | 238 : launcher_view_(host), |
223 view_(view) {} | 239 view_(view) {} |
224 virtual ~StartFadeAnimationDelegate() {} | 240 virtual ~StartFadeAnimationDelegate() {} |
225 | 241 |
226 // AnimationDelegate overrides: | 242 // AnimationDelegate overrides: |
227 virtual void AnimationEnded(const Animation* animation) OVERRIDE { | 243 virtual void AnimationEnded(const Animation* animation) OVERRIDE { |
228 view_->SetVisible(true); | |
229 launcher_view_->FadeIn(view_); | 244 launcher_view_->FadeIn(view_); |
230 } | 245 } |
231 virtual void AnimationCanceled(const Animation* animation) OVERRIDE { | 246 virtual void AnimationCanceled(const Animation* animation) OVERRIDE { |
232 view_->SetVisible(true); | 247 view_->SetVisible(true); |
233 } | 248 } |
234 | 249 |
235 private: | 250 private: |
236 LauncherView* launcher_view_; | 251 LauncherView* launcher_view_; |
237 views::View* view_; | 252 views::View* view_; |
238 | 253 |
239 DISALLOW_COPY_AND_ASSIGN(StartFadeAnimationDelegate); | 254 DISALLOW_COPY_AND_ASSIGN(StartFadeAnimationDelegate); |
240 }; | 255 }; |
241 | 256 |
242 int LauncherView::TestAPI::GetButtonCount() { | 257 int LauncherView::TestAPI::GetButtonCount() { |
243 return launcher_view_->view_model_->view_size(); | 258 return launcher_view_->view_model_->view_size(); |
244 } | 259 } |
245 | 260 |
246 LauncherButton* LauncherView::TestAPI::GetButton(int index) { | 261 LauncherButton* LauncherView::TestAPI::GetButton(int index) { |
247 if (index == 0) | 262 // App list button is not a LauncherButton. |
263 if (index == GetButtonCount() - 1) | |
248 return NULL; | 264 return NULL; |
249 | 265 |
250 return static_cast<LauncherButton*>( | 266 return static_cast<LauncherButton*>( |
251 launcher_view_->view_model_->view_at(index)); | 267 launcher_view_->view_model_->view_at(index)); |
252 } | 268 } |
253 | 269 |
270 int LauncherView::TestAPI::GetLastVisibleIndex() { | |
271 return launcher_view_->last_visible_index_; | |
272 } | |
273 | |
274 bool LauncherView::TestAPI::IsOverflowButtonVisible() { | |
275 return launcher_view_->overflow_button_->visible(); | |
276 } | |
277 | |
278 void LauncherView::TestAPI::SetAnimationDuration(int duration_ms) { | |
279 launcher_view_->bounds_animator_->SetAnimationDuration(duration_ms); | |
280 } | |
281 | |
282 void LauncherView::TestAPI::RunMessageLoopUntilAnimationsDone() { | |
283 if (!launcher_view_->bounds_animator_->IsAnimating()) | |
284 return; | |
285 | |
286 scoped_ptr<TestAPIAnimationObserver> observer(new TestAPIAnimationObserver()); | |
287 launcher_view_->bounds_animator_->AddObserver(observer.get()); | |
288 | |
289 // This nest loop will quit when TestAPIAnimationObserver's | |
290 // OnBoundsAnimatorDone is called. | |
291 MessageLoop::current()->Run(); | |
292 | |
293 launcher_view_->bounds_animator_->RemoveObserver(observer.get()); | |
294 } | |
295 | |
254 LauncherView::LauncherView(LauncherModel* model, LauncherDelegate* delegate) | 296 LauncherView::LauncherView(LauncherModel* model, LauncherDelegate* delegate) |
255 : model_(model), | 297 : model_(model), |
256 delegate_(delegate), | 298 delegate_(delegate), |
257 view_model_(new views::ViewModel), | 299 view_model_(new views::ViewModel), |
300 last_visible_index_(-1), | |
258 overflow_button_(NULL), | 301 overflow_button_(NULL), |
259 dragging_(NULL), | 302 dragging_(NULL), |
260 drag_view_(NULL), | 303 drag_view_(NULL), |
261 drag_offset_(0), | 304 drag_offset_(0), |
262 start_drag_index_(-1), | 305 start_drag_index_(-1), |
263 context_menu_id_(0) { | 306 context_menu_id_(0) { |
264 DCHECK(model_); | 307 DCHECK(model_); |
265 bounds_animator_.reset(new views::BoundsAnimator(this)); | 308 bounds_animator_.reset(new views::BoundsAnimator(this)); |
266 set_context_menu_controller(this); | 309 set_context_menu_controller(this); |
267 focus_search_.reset(new LauncherFocusSearch(view_model_.get())); | 310 focus_search_.reset(new LauncherFocusSearch(view_model_.get())); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 } | 382 } |
340 | 383 |
341 View* LauncherView::GetFocusTraversableParentView() { | 384 View* LauncherView::GetFocusTraversableParentView() { |
342 return this; | 385 return this; |
343 } | 386 } |
344 | 387 |
345 void LauncherView::LayoutToIdealBounds() { | 388 void LauncherView::LayoutToIdealBounds() { |
346 IdealBounds ideal_bounds; | 389 IdealBounds ideal_bounds; |
347 CalculateIdealBounds(&ideal_bounds); | 390 CalculateIdealBounds(&ideal_bounds); |
348 views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); | 391 views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); |
392 views::ViewModelUtils::SetViewVisibilityToIdealVisibility(*view_model_); | |
349 overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds); | 393 overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds); |
350 } | 394 } |
351 | 395 |
352 void LauncherView::CalculateIdealBounds(IdealBounds* bounds) { | 396 void LauncherView::CalculateIdealBounds(IdealBounds* bounds) { |
353 int available_width = width(); | 397 int available_width = width(); |
354 if (!available_width) | 398 if (!available_width) |
355 return; | 399 return; |
356 | 400 |
357 int x = kLeadingInset; | 401 int x = kLeadingInset; |
358 for (int i = 0; i < view_model_->view_size(); ++i) { | 402 for (int i = 0; i < view_model_->view_size(); ++i) { |
359 gfx::Size pref(kButtonWidth, kButtonHeight); | 403 gfx::Size pref(kButtonWidth, kButtonHeight); |
360 view_model_->set_ideal_bounds(i, gfx::Rect( | 404 view_model_->set_ideal_bounds(i, gfx::Rect( |
361 x, (kLauncherPreferredHeight - pref.height()) / 2, pref.width(), | 405 x, (kLauncherPreferredHeight - pref.height()) / 2, pref.width(), |
362 pref.height())); | 406 pref.height())); |
363 x += pref.width() + kButtonSpacing; | 407 x += pref.width() + kButtonSpacing; |
364 } | 408 } |
365 | 409 |
366 bounds->overflow_bounds.set_size(gfx::Size(kButtonWidth, kButtonHeight)); | 410 bounds->overflow_bounds.set_size(gfx::Size(kButtonWidth, kButtonHeight)); |
367 int last_visible_index = DetermineLastVisibleIndex( | 411 last_visible_index_ = DetermineLastVisibleIndex( |
368 available_width - kLeadingInset - bounds->overflow_bounds.width() - | 412 available_width - kLeadingInset - bounds->overflow_bounds.width() - |
369 kButtonSpacing - kButtonWidth); | 413 kButtonSpacing - kButtonWidth); |
370 bool show_overflow = | |
371 (last_visible_index + 1 != view_model_->view_size()); | |
372 int app_list_index = view_model_->view_size() - 1; | 414 int app_list_index = view_model_->view_size() - 1; |
373 if (overflow_button_->visible() != show_overflow) { | 415 bool show_overflow = (last_visible_index_ + 1 < app_list_index); |
374 // Only change visibility of the views if the visibility of the overflow | 416 |
375 // button changes. Otherwise we'll effect the insertion animation, which | 417 for (int i = 0; i < view_model_->view_size(); ++i) { |
376 // changes the visibility. | 418 view_model_->set_ideal_visibility( |
377 for (int i = 0; i <= last_visible_index; ++i) | 419 i, |
378 view_model_->view_at(i)->SetVisible(true); | 420 i == app_list_index || i <= last_visible_index_); |
379 for (int i = last_visible_index + 1; i < view_model_->view_size(); ++i) { | |
380 if (i != app_list_index) | |
381 view_model_->view_at(i)->SetVisible(false); | |
382 } | |
383 } | 421 } |
422 | |
384 overflow_button_->SetVisible(show_overflow); | 423 overflow_button_->SetVisible(show_overflow); |
385 if (show_overflow) { | 424 if (show_overflow) { |
386 DCHECK_NE(0, view_model_->view_size()); | 425 DCHECK_NE(0, view_model_->view_size()); |
387 // We always want the app list visible. | 426 // We always want the app list visible. |
388 gfx::Rect app_list_bounds = view_model_->ideal_bounds(app_list_index); | 427 gfx::Rect app_list_bounds = view_model_->ideal_bounds(app_list_index); |
389 x = last_visible_index == -1 ? | 428 x = last_visible_index_ == -1 ? |
390 kLeadingInset : view_model_->ideal_bounds(last_visible_index).right(); | 429 kLeadingInset : view_model_->ideal_bounds(last_visible_index_).right(); |
391 app_list_bounds.set_x(x); | 430 app_list_bounds.set_x(x); |
392 view_model_->set_ideal_bounds(app_list_index, app_list_bounds); | 431 view_model_->set_ideal_bounds(app_list_index, app_list_bounds); |
393 x = app_list_bounds.right() + kButtonSpacing; | 432 x = app_list_bounds.right() + kButtonSpacing; |
394 bounds->overflow_bounds.set_x(x); | 433 bounds->overflow_bounds.set_x(x); |
395 bounds->overflow_bounds.set_y( | 434 bounds->overflow_bounds.set_y( |
396 (kLauncherPreferredHeight - bounds->overflow_bounds.height()) / 2); | 435 (kLauncherPreferredHeight - bounds->overflow_bounds.height()) / 2); |
397 } | 436 } |
398 } | 437 } |
399 | 438 |
400 int LauncherView::DetermineLastVisibleIndex(int max_x) { | 439 int LauncherView::DetermineLastVisibleIndex(int max_x) { |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
670 | 709 |
671 void LauncherView::LauncherItemAdded(int model_index) { | 710 void LauncherView::LauncherItemAdded(int model_index) { |
672 CancelDrag(NULL); | 711 CancelDrag(NULL); |
673 | 712 |
674 views::View* view = CreateViewForItem(model_->items()[model_index]); | 713 views::View* view = CreateViewForItem(model_->items()[model_index]); |
675 AddChildView(view); | 714 AddChildView(view); |
676 // Hide the view, it'll be made visible when the animation is done. | 715 // Hide the view, it'll be made visible when the animation is done. |
677 view->SetVisible(false); | 716 view->SetVisible(false); |
678 view_model_->Add(view, model_index); | 717 view_model_->Add(view, model_index); |
679 | 718 |
680 // Give the button it's ideal bounds. That way if we end up animating the | 719 // Give the button its ideal bounds. That way if we end up animating the |
681 // button before this animation completes it doesn't appear at some random | 720 // button before this animation completes it doesn't appear at some random |
682 // spot (because it was in the middle of animating from 0,0 0x0 to its | 721 // spot (because it was in the middle of animating from 0,0 0x0 to its |
683 // target). | 722 // target). |
684 IdealBounds ideal_bounds; | 723 IdealBounds ideal_bounds; |
685 CalculateIdealBounds(&ideal_bounds); | 724 CalculateIdealBounds(&ideal_bounds); |
686 view->SetBoundsRect(view_model_->ideal_bounds(model_index)); | 725 view->SetBoundsRect(view_model_->ideal_bounds(model_index)); |
687 | 726 |
688 // The first animation moves all the views to their target position. |view| is | 727 // The first animation moves all the views to their target position. |view| |
689 // hidden, so it visually appears as though we are providing space for | 728 // is hidden, so it visually appears as though we are providing space for |
690 // it. When done we'll fade the view in. | 729 // it. When done we'll fade the view in. |
691 AnimateToIdealBounds(); | 730 AnimateToIdealBounds(); |
692 if (!overflow_button_->visible()) { | 731 if (model_index <= last_visible_index_) { |
693 bounds_animator_->SetAnimationDelegate( | 732 bounds_animator_->SetAnimationDelegate( |
694 view, new StartFadeAnimationDelegate(this, view), true); | 733 view, new StartFadeAnimationDelegate(this, view), true); |
734 | |
735 // Hides view that should become invisible immediately. | |
sky
2012/04/13 22:00:04
If possible, I would rather change the visibility
xiyuan
2012/04/13 22:49:53
This causes flashes. When CalculateIdealBounds set
xiyuan
2012/04/23 18:08:53
Done. Set opacity to 0 work as expected and thus r
| |
736 for (int i = 0; i < view_model_->view_size(); ++i) { | |
737 if (!view_model_->ideal_visibility(i) && | |
738 view_model_->view_at(i)->visible()) { | |
739 view_model_->view_at(i)->SetVisible(false); | |
740 } | |
741 } | |
695 } | 742 } |
696 } | 743 } |
697 | 744 |
698 void LauncherView::LauncherItemRemoved(int model_index, LauncherID id) { | 745 void LauncherView::LauncherItemRemoved(int model_index, LauncherID id) { |
699 #if !defined(OS_MACOSX) | 746 #if !defined(OS_MACOSX) |
700 if (id == context_menu_id_) | 747 if (id == context_menu_id_) |
701 launcher_menu_runner_.reset(); | 748 launcher_menu_runner_.reset(); |
702 #endif | 749 #endif |
703 views::View* view = view_model_->view_at(model_index); | 750 views::View* view = view_model_->view_at(model_index); |
704 CancelDrag(view); | 751 CancelDrag(view); |
705 view_model_->Remove(model_index); | 752 view_model_->Remove(model_index); |
706 // The first animation fades out the view. When done we'll animate the rest of | 753 // The first animation fades out the view. When done we'll animate the rest of |
707 // the views to their target location. | 754 // the views to their target location. |
708 bounds_animator_->AnimateViewTo(view, view->bounds()); | 755 bounds_animator_->AnimateViewTo(view, view->bounds()); |
709 bounds_animator_->SetAnimationDelegate( | 756 bounds_animator_->SetAnimationDelegate( |
710 view, new FadeOutAnimationDelegate(this, view), true); | 757 view, new FadeOutAnimationDelegate(this, view), true); |
758 | |
759 IdealBounds ideal_bounds; | |
760 CalculateIdealBounds(&ideal_bounds); | |
761 if (model_index <= last_visible_index_) { | |
762 // Shows view that should become visible immediately. | |
763 for (int i = 0; i < view_model_->view_size(); ++i) { | |
764 if (view_model_->ideal_visibility(i) && | |
765 !view_model_->view_at(i)->visible()) { | |
766 view_model_->view_at(i)->SetVisible(true); | |
767 } | |
768 } | |
769 } | |
711 } | 770 } |
712 | 771 |
713 void LauncherView::LauncherItemChanged(int model_index, | 772 void LauncherView::LauncherItemChanged(int model_index, |
714 const ash::LauncherItem& old_item) { | 773 const ash::LauncherItem& old_item) { |
715 const LauncherItem& item(model_->items()[model_index]); | 774 const LauncherItem& item(model_->items()[model_index]); |
716 if (old_item.type != item.type) { | 775 if (old_item.type != item.type) { |
717 // Type changed, swap the views. | 776 // Type changed, swap the views. |
718 scoped_ptr<views::View> old_view(view_model_->view_at(model_index)); | 777 scoped_ptr<views::View> old_view(view_model_->view_at(model_index)); |
719 bounds_animator_->StopAnimatingView(old_view.get()); | 778 bounds_animator_->StopAnimatingView(old_view.get()); |
720 CancelDrag(old_view.get()); | 779 CancelDrag(old_view.get()); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
888 source->GetWidget(), NULL, gfx::Rect(point, gfx::Size()), | 947 source->GetWidget(), NULL, gfx::Rect(point, gfx::Size()), |
889 views::MenuItemView::TOPLEFT, 0) == views::MenuRunner::MENU_DELETED) | 948 views::MenuItemView::TOPLEFT, 0) == views::MenuRunner::MENU_DELETED) |
890 return; | 949 return; |
891 | 950 |
892 Shell::GetInstance()->UpdateShelfVisibility(); | 951 Shell::GetInstance()->UpdateShelfVisibility(); |
893 #endif | 952 #endif |
894 } | 953 } |
895 | 954 |
896 } // namespace internal | 955 } // namespace internal |
897 } // namespace ash | 956 } // namespace ash |
OLD | NEW |