Chromium Code Reviews| 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 |