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

Side by Side Diff: ash/shelf/shelf_view.cc

Issue 1816753002: Enable mash shelf tooltips. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address destructor comment. Created 4 years, 9 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
« no previous file with comments | « ash/shelf/shelf_view.h ('k') | ash/shelf/shelf_view_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/shelf/shelf_view.h" 5 #include "ash/shelf/shelf_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "ash/ash_constants.h" 9 #include "ash/ash_constants.h"
10 #include "ash/ash_switches.h" 10 #include "ash/ash_switches.h"
11 #include "ash/drag_drop/drag_image_view.h" 11 #include "ash/drag_drop/drag_image_view.h"
12 #include "ash/metrics/user_metrics_recorder.h" 12 #include "ash/metrics/user_metrics_recorder.h"
13 #include "ash/scoped_target_root_window.h" 13 #include "ash/scoped_target_root_window.h"
14 #include "ash/shelf/app_list_button.h" 14 #include "ash/shelf/app_list_button.h"
15 #include "ash/shelf/overflow_bubble.h" 15 #include "ash/shelf/overflow_bubble.h"
16 #include "ash/shelf/overflow_bubble_view.h" 16 #include "ash/shelf/overflow_bubble_view.h"
17 #include "ash/shelf/overflow_button.h" 17 #include "ash/shelf/overflow_button.h"
18 #include "ash/shelf/shelf.h" 18 #include "ash/shelf/shelf.h"
19 #include "ash/shelf/shelf_button.h" 19 #include "ash/shelf/shelf_button.h"
20 #include "ash/shelf/shelf_constants.h" 20 #include "ash/shelf/shelf_constants.h"
21 #include "ash/shelf/shelf_delegate.h" 21 #include "ash/shelf/shelf_delegate.h"
22 #include "ash/shelf/shelf_icon_observer.h" 22 #include "ash/shelf/shelf_icon_observer.h"
23 #include "ash/shelf/shelf_item_delegate_manager.h" 23 #include "ash/shelf/shelf_item_delegate_manager.h"
24 #include "ash/shelf/shelf_menu_model.h" 24 #include "ash/shelf/shelf_menu_model.h"
25 #include "ash/shelf/shelf_model.h" 25 #include "ash/shelf/shelf_model.h"
26 #include "ash/shelf/shelf_tooltip_manager.h"
27 #include "ash/shelf/shelf_widget.h" 26 #include "ash/shelf/shelf_widget.h"
28 #include "ash/shell.h" 27 #include "ash/shell.h"
29 #include "ash/shell_delegate.h" 28 #include "ash/shell_delegate.h"
30 #include "ash/wm/coordinate_conversion.h" 29 #include "ash/wm/coordinate_conversion.h"
31 #include "base/auto_reset.h" 30 #include "base/auto_reset.h"
32 #include "base/memory/scoped_ptr.h" 31 #include "base/memory/scoped_ptr.h"
33 #include "base/metrics/histogram.h" 32 #include "base/metrics/histogram.h"
34 #include "grit/ash_strings.h" 33 #include "grit/ash_strings.h"
35 #include "ui/accessibility/ax_view_state.h" 34 #include "ui/accessibility/ax_view_state.h"
36 #include "ui/aura/client/screen_position_client.h" 35 #include "ui/aura/client/screen_position_client.h"
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 216
218 bool ShelfMenuModelAdapter::ShouldReserveSpaceForSubmenuIndicator() const { 217 bool ShelfMenuModelAdapter::ShouldReserveSpaceForSubmenuIndicator() const {
219 return false; 218 return false;
220 } 219 }
221 220
222 // Custom FocusSearch used to navigate the shelf in the order items are in 221 // Custom FocusSearch used to navigate the shelf in the order items are in
223 // the ViewModel. 222 // the ViewModel.
224 class ShelfFocusSearch : public views::FocusSearch { 223 class ShelfFocusSearch : public views::FocusSearch {
225 public: 224 public:
226 explicit ShelfFocusSearch(views::ViewModel* view_model) 225 explicit ShelfFocusSearch(views::ViewModel* view_model)
227 : FocusSearch(NULL, true, true), 226 : FocusSearch(nullptr, true, true), view_model_(view_model) {}
228 view_model_(view_model) {}
229 ~ShelfFocusSearch() override {} 227 ~ShelfFocusSearch() override {}
230 228
231 // views::FocusSearch overrides: 229 // views::FocusSearch overrides:
232 View* FindNextFocusableView(View* starting_view, 230 View* FindNextFocusableView(View* starting_view,
233 bool reverse, 231 bool reverse,
234 Direction direction, 232 Direction direction,
235 bool check_starting_view, 233 bool check_starting_view,
236 views::FocusTraversable** focus_traversable, 234 views::FocusTraversable** focus_traversable,
237 View** focus_traversable_view) override { 235 View** focus_traversable_view) override {
238 int index = view_model_->GetIndexOfView(starting_view); 236 int index = view_model_->GetIndexOfView(starting_view);
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 DISALLOW_COPY_AND_ASSIGN(StartFadeAnimationDelegate); 361 DISALLOW_COPY_AND_ASSIGN(StartFadeAnimationDelegate);
364 }; 362 };
365 363
366 ShelfView::ShelfView(ShelfModel* model, ShelfDelegate* delegate, Shelf* shelf) 364 ShelfView::ShelfView(ShelfModel* model, ShelfDelegate* delegate, Shelf* shelf)
367 : model_(model), 365 : model_(model),
368 delegate_(delegate), 366 delegate_(delegate),
369 shelf_(shelf), 367 shelf_(shelf),
370 view_model_(new views::ViewModel), 368 view_model_(new views::ViewModel),
371 first_visible_index_(0), 369 first_visible_index_(0),
372 last_visible_index_(-1), 370 last_visible_index_(-1),
373 overflow_button_(NULL), 371 overflow_button_(nullptr),
374 owner_overflow_bubble_(NULL), 372 owner_overflow_bubble_(nullptr),
373 tooltip_(this),
375 drag_pointer_(NONE), 374 drag_pointer_(NONE),
376 drag_view_(NULL), 375 drag_view_(nullptr),
377 start_drag_index_(-1), 376 start_drag_index_(-1),
378 context_menu_id_(0), 377 context_menu_id_(0),
379 leading_inset_(kDefaultLeadingInset), 378 leading_inset_(kDefaultLeadingInset),
380 cancelling_drag_model_changed_(false), 379 cancelling_drag_model_changed_(false),
381 last_hidden_index_(0), 380 last_hidden_index_(0),
382 closing_event_time_(base::TimeDelta()), 381 closing_event_time_(base::TimeDelta()),
383 got_deleted_(NULL), 382 got_deleted_(nullptr),
384 drag_and_drop_item_pinned_(false), 383 drag_and_drop_item_pinned_(false),
385 drag_and_drop_shelf_id_(0), 384 drag_and_drop_shelf_id_(0),
386 drag_replaced_view_(nullptr), 385 drag_replaced_view_(nullptr),
387 dragged_off_shelf_(false), 386 dragged_off_shelf_(false),
388 snap_back_from_rip_off_view_(NULL), 387 snap_back_from_rip_off_view_(nullptr),
389 item_manager_(Shell::GetInstance()->shelf_item_delegate_manager()), 388 item_manager_(Shell::GetInstance()->shelf_item_delegate_manager()),
390 overflow_mode_(false), 389 overflow_mode_(false),
391 main_shelf_(NULL), 390 main_shelf_(nullptr),
392 dragged_off_from_overflow_to_shelf_(false), 391 dragged_off_from_overflow_to_shelf_(false),
393 is_repost_event_(false), 392 is_repost_event_(false),
394 last_pressed_index_(-1) { 393 last_pressed_index_(-1) {
395 DCHECK(model_); 394 DCHECK(model_);
396 bounds_animator_.reset(new views::BoundsAnimator(this)); 395 bounds_animator_.reset(new views::BoundsAnimator(this));
397 bounds_animator_->AddObserver(this); 396 bounds_animator_->AddObserver(this);
398 set_context_menu_controller(this); 397 set_context_menu_controller(this);
399 focus_search_.reset(new ShelfFocusSearch(view_model_.get())); 398 focus_search_.reset(new ShelfFocusSearch(view_model_.get()));
400 tooltip_.reset(new ShelfTooltipManager(shelf->shelf_layout_manager(), this));
401 } 399 }
402 400
403 ShelfView::~ShelfView() { 401 ShelfView::~ShelfView() {
404 bounds_animator_->RemoveObserver(this); 402 bounds_animator_->RemoveObserver(this);
405 model_->RemoveObserver(this); 403 model_->RemoveObserver(this);
406 // If we are inside the MenuRunner, we need to know if we were getting 404 // If we are inside the MenuRunner, we need to know if we were getting
407 // deleted while it was running. 405 // deleted while it was running.
408 if (got_deleted_) 406 if (got_deleted_)
409 *got_deleted_ = true; 407 *got_deleted_ = true;
410 } 408 }
(...skipping 16 matching lines...) Expand all
427 // We'll layout when our bounds change. 425 // We'll layout when our bounds change.
428 } 426 }
429 427
430 void ShelfView::OnShelfAlignmentChanged() { 428 void ShelfView::OnShelfAlignmentChanged() {
431 overflow_button_->OnShelfAlignmentChanged(); 429 overflow_button_->OnShelfAlignmentChanged();
432 LayoutToIdealBounds(); 430 LayoutToIdealBounds();
433 for (int i = 0; i < view_model_->view_size(); ++i) { 431 for (int i = 0; i < view_model_->view_size(); ++i) {
434 if (i >= first_visible_index_ && i <= last_visible_index_) 432 if (i >= first_visible_index_ && i <= last_visible_index_)
435 view_model_->view_at(i)->Layout(); 433 view_model_->view_at(i)->Layout();
436 } 434 }
437 tooltip_->Close(); 435 tooltip_.Close();
438 if (overflow_bubble_) 436 if (overflow_bubble_)
439 overflow_bubble_->Hide(); 437 overflow_bubble_->Hide();
440 } 438 }
441 439
442 void ShelfView::SchedulePaintForAllButtons() { 440 void ShelfView::SchedulePaintForAllButtons() {
443 for (int i = 0; i < view_model_->view_size(); ++i) { 441 for (int i = 0; i < view_model_->view_size(); ++i) {
444 if (i >= first_visible_index_ && i <= last_visible_index_) 442 if (i >= first_visible_index_ && i <= last_visible_index_)
445 view_model_->view_at(i)->SchedulePaint(); 443 view_model_->view_at(i)->SchedulePaint();
446 } 444 }
447 if (overflow_button_ && overflow_button_->visible()) 445 if (overflow_button_ && overflow_button_->visible())
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 return overflow_bubble_.get() && overflow_bubble_->IsShowing(); 508 return overflow_bubble_.get() && overflow_bubble_->IsShowing();
511 } 509 }
512 510
513 views::View* ShelfView::GetAppListButtonView() const { 511 views::View* ShelfView::GetAppListButtonView() const {
514 for (int i = 0; i < model_->item_count(); ++i) { 512 for (int i = 0; i < model_->item_count(); ++i) {
515 if (model_->items()[i].type == TYPE_APP_LIST) 513 if (model_->items()[i].type == TYPE_APP_LIST)
516 return view_model_->view_at(i); 514 return view_model_->view_at(i);
517 } 515 }
518 516
519 NOTREACHED() << "Applist button not found"; 517 NOTREACHED() << "Applist button not found";
520 return NULL; 518 return nullptr;
519 }
520
521 bool ShelfView::ShouldHideTooltip(const gfx::Point& cursor_location) const {
522 gfx::Rect tooltip_bounds;
523 for (int i = 0; i < child_count(); ++i) {
524 const views::View* child = child_at(i);
525 if (child != overflow_button_ && ShouldShowTooltipForView(child))
526 tooltip_bounds.Union(child->GetMirroredBounds());
527 }
528 return !tooltip_bounds.Contains(cursor_location);
529 }
530
531 bool ShelfView::ShouldShowTooltipForView(const views::View* view) const {
532 if (view == GetAppListButtonView() &&
533 Shell::GetInstance()->GetAppListWindow()) {
534 return false;
535 }
536 const ShelfItem* item = ShelfItemForView(view);
537 if (!item)
538 return false;
539 return item_manager_->GetShelfItemDelegate(item->id)->ShouldShowTooltip();
540 }
541
542 base::string16 ShelfView::GetTitleForView(const views::View* view) const {
543 const ShelfItem* item = ShelfItemForView(view);
544 if (!item)
545 return base::string16();
546 return item_manager_->GetShelfItemDelegate(item->id)->GetTitle();
547 }
548
549 gfx::Rect ShelfView::GetVisibleItemsBoundsInScreen() {
550 gfx::Size preferred_size = GetPreferredSize();
551 gfx::Point origin(GetMirroredXWithWidthInView(0, preferred_size.width()), 0);
552 ConvertPointToScreen(this, &origin);
553 return gfx::Rect(origin, preferred_size);
521 } 554 }
522 555
523 //////////////////////////////////////////////////////////////////////////////// 556 ////////////////////////////////////////////////////////////////////////////////
524 // ShelfView, FocusTraversable implementation: 557 // ShelfView, FocusTraversable implementation:
525 558
526 views::FocusSearch* ShelfView::GetFocusSearch() { 559 views::FocusSearch* ShelfView::GetFocusSearch() {
527 return focus_search_.get(); 560 return focus_search_.get();
528 } 561 }
529 562
530 views::FocusTraversable* ShelfView::GetFocusTraversableParent() { 563 views::FocusTraversable* ShelfView::GetFocusTraversableParent() {
(...skipping 22 matching lines...) Expand all
553 cursor_offset_from_center; 586 cursor_offset_from_center;
554 gfx::Rect drag_image_bounds( 587 gfx::Rect drag_image_bounds(
555 location_in_screen_coordinates - drag_image_offset_, 588 location_in_screen_coordinates - drag_image_offset_,
556 size); 589 size);
557 drag_image_->SetBoundsInScreen(drag_image_bounds); 590 drag_image_->SetBoundsInScreen(drag_image_bounds);
558 drag_image_->SetWidgetVisible(true); 591 drag_image_->SetWidgetVisible(true);
559 } 592 }
560 593
561 void ShelfView::UpdateDragIconProxy( 594 void ShelfView::UpdateDragIconProxy(
562 const gfx::Point& location_in_screen_coordinates) { 595 const gfx::Point& location_in_screen_coordinates) {
563 // TODO(jennyz): Investigate why drag_image_ becomes NULL at this point per 596 // TODO(jennyz): Investigate why drag_image_ becomes null at this point per
564 // crbug.com/34722, while the app list item is still being dragged around. 597 // crbug.com/34722, while the app list item is still being dragged around.
565 if (drag_image_) { 598 if (drag_image_) {
566 drag_image_->SetScreenPosition( 599 drag_image_->SetScreenPosition(
567 location_in_screen_coordinates - drag_image_offset_); 600 location_in_screen_coordinates - drag_image_offset_);
568 } 601 }
569 } 602 }
570 603
571 void ShelfView::DestroyDragIconProxy() { 604 void ShelfView::DestroyDragIconProxy() {
572 drag_image_.reset(); 605 drag_image_.reset();
573 drag_image_offset_ = gfx::Vector2d(0, 0); 606 drag_image_offset_ = gfx::Vector2d(0, 0);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 drag_and_drop_view->SetSize(gfx::Size()); 647 drag_and_drop_view->SetSize(gfx::Size());
615 648
616 // First we have to center the mouse cursor over the item. 649 // First we have to center the mouse cursor over the item.
617 gfx::Point pt = drag_and_drop_view->GetBoundsInScreen().CenterPoint(); 650 gfx::Point pt = drag_and_drop_view->GetBoundsInScreen().CenterPoint();
618 views::View::ConvertPointFromScreen(drag_and_drop_view, &pt); 651 views::View::ConvertPointFromScreen(drag_and_drop_view, &pt);
619 gfx::Point point_in_root = location_in_screen_coordinates; 652 gfx::Point point_in_root = location_in_screen_coordinates;
620 ::wm::ConvertPointFromScreen( 653 ::wm::ConvertPointFromScreen(
621 ash::wm::GetRootWindowAt(location_in_screen_coordinates), &point_in_root); 654 ash::wm::GetRootWindowAt(location_in_screen_coordinates), &point_in_root);
622 ui::MouseEvent event(ui::ET_MOUSE_PRESSED, pt, point_in_root, 655 ui::MouseEvent event(ui::ET_MOUSE_PRESSED, pt, point_in_root,
623 ui::EventTimeForNow(), 0, 0); 656 ui::EventTimeForNow(), 0, 0);
624 PointerPressedOnButton(drag_and_drop_view, 657 PointerPressedOnButton(drag_and_drop_view, DRAG_AND_DROP, event);
625 ShelfButtonHost::DRAG_AND_DROP,
626 event);
627 658
628 // Drag the item where it really belongs. 659 // Drag the item where it really belongs.
629 Drag(location_in_screen_coordinates); 660 Drag(location_in_screen_coordinates);
630 return true; 661 return true;
631 } 662 }
632 663
633 bool ShelfView::Drag(const gfx::Point& location_in_screen_coordinates) { 664 bool ShelfView::Drag(const gfx::Point& location_in_screen_coordinates) {
634 if (!drag_and_drop_shelf_id_ || 665 if (!drag_and_drop_shelf_id_ ||
635 !GetBoundsInScreen().Contains(location_in_screen_coordinates)) 666 !GetBoundsInScreen().Contains(location_in_screen_coordinates))
636 return false; 667 return false;
637 668
638 gfx::Point pt = location_in_screen_coordinates; 669 gfx::Point pt = location_in_screen_coordinates;
639 views::View* drag_and_drop_view = view_model_->view_at( 670 views::View* drag_and_drop_view = view_model_->view_at(
640 model_->ItemIndexByID(drag_and_drop_shelf_id_)); 671 model_->ItemIndexByID(drag_and_drop_shelf_id_));
641 ConvertPointFromScreen(drag_and_drop_view, &pt); 672 ConvertPointFromScreen(drag_and_drop_view, &pt);
642 gfx::Point point_in_root = location_in_screen_coordinates; 673 gfx::Point point_in_root = location_in_screen_coordinates;
643 ::wm::ConvertPointFromScreen( 674 ::wm::ConvertPointFromScreen(
644 ash::wm::GetRootWindowAt(location_in_screen_coordinates), &point_in_root); 675 ash::wm::GetRootWindowAt(location_in_screen_coordinates), &point_in_root);
645 ui::MouseEvent event(ui::ET_MOUSE_DRAGGED, pt, point_in_root, 676 ui::MouseEvent event(ui::ET_MOUSE_DRAGGED, pt, point_in_root,
646 ui::EventTimeForNow(), 0, 0); 677 ui::EventTimeForNow(), 0, 0);
647 PointerDraggedOnButton(drag_and_drop_view, 678 PointerDraggedOnButton(drag_and_drop_view, DRAG_AND_DROP, event);
648 ShelfButtonHost::DRAG_AND_DROP,
649 event);
650 return true; 679 return true;
651 } 680 }
652 681
653 void ShelfView::EndDrag(bool cancel) { 682 void ShelfView::EndDrag(bool cancel) {
654 if (!drag_and_drop_shelf_id_) 683 if (!drag_and_drop_shelf_id_)
655 return; 684 return;
656 685
657 views::View* drag_and_drop_view = view_model_->view_at( 686 views::View* drag_and_drop_view = view_model_->view_at(
658 model_->ItemIndexByID(drag_and_drop_shelf_id_)); 687 model_->ItemIndexByID(drag_and_drop_shelf_id_));
659 PointerReleasedOnButton( 688 PointerReleasedOnButton(drag_and_drop_view, DRAG_AND_DROP, cancel);
660 drag_and_drop_view, ShelfButtonHost::DRAG_AND_DROP, cancel);
661 689
662 // Either destroy the temporarily created item - or - make the item visible. 690 // Either destroy the temporarily created item - or - make the item visible.
663 if (drag_and_drop_item_pinned_ && cancel) { 691 if (drag_and_drop_item_pinned_ && cancel) {
664 delegate_->UnpinAppWithID(drag_and_drop_app_id_); 692 delegate_->UnpinAppWithID(drag_and_drop_app_id_);
665 } else if (drag_and_drop_view) { 693 } else if (drag_and_drop_view) {
666 if (cancel) { 694 if (cancel) {
667 // When a hosted drag gets canceled, the item can remain in the same slot 695 // When a hosted drag gets canceled, the item can remain in the same slot
668 // and it might have moved within the bounds. In that case the item need 696 // and it might have moved within the bounds. In that case the item need
669 // to animate back to its correct location. 697 // to animate back to its correct location.
670 AnimateToIdealBounds(); 698 AnimateToIdealBounds();
671 } else { 699 } else {
672 drag_and_drop_view->SetSize(pre_drag_and_drop_size_); 700 drag_and_drop_view->SetSize(pre_drag_and_drop_size_);
673 } 701 }
674 } 702 }
675 703
676 drag_and_drop_shelf_id_ = 0; 704 drag_and_drop_shelf_id_ = 0;
677 } 705 }
678 706
707 void ShelfView::PointerPressedOnButton(views::View* view,
708 Pointer pointer,
709 const ui::LocatedEvent& event) {
710 if (drag_view_)
711 return;
712
713 int index = view_model_->GetIndexOfView(view);
714 if (index == -1)
715 return;
716
717 ShelfItemDelegate* item_delegate =
718 item_manager_->GetShelfItemDelegate(model_->items()[index].id);
719 if (view_model_->view_size() <= 1 || !item_delegate->IsDraggable())
720 return; // View is being deleted or not draggable, ignore request.
721
722 // Only when the repost event occurs on the same shelf item, we should ignore
723 // the call in ShelfView::ButtonPressed(...).
724 is_repost_event_ = IsRepostEvent(event) && (last_pressed_index_ == index);
725
726 CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
727 drag_view_ = static_cast<ShelfButton*>(view);
728 drag_origin_ = gfx::Point(event.x(), event.y());
729 UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentUsage",
730 shelf_->SelectValueForShelfAlignment(
731 SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM,
732 SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT,
733 SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT, -1),
734 SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT);
735 }
736
737 void ShelfView::PointerDraggedOnButton(views::View* view,
738 Pointer pointer,
739 const ui::LocatedEvent& event) {
740 // To prepare all drag types (moving an item in the shelf and dragging off),
741 // we should check the x-axis and y-axis offset.
742 if (!dragging() && drag_view_ &&
743 ((std::abs(event.x() - drag_origin_.x()) >= kMinimumDragDistance) ||
744 (std::abs(event.y() - drag_origin_.y()) >= kMinimumDragDistance))) {
745 PrepareForDrag(pointer, event);
746 }
747 if (drag_pointer_ == pointer)
748 ContinueDrag(event);
749 }
750
751 void ShelfView::PointerReleasedOnButton(views::View* view,
752 Pointer pointer,
753 bool canceled) {
754 // Reset |is_repost_event| to false.
755 is_repost_event_ = false;
756
757 if (canceled) {
758 CancelDrag(-1);
759 } else if (drag_pointer_ == pointer) {
760 FinalizeRipOffDrag(false);
761 drag_pointer_ = NONE;
762 AnimateToIdealBounds();
763 }
764 // If the drag pointer is NONE, no drag operation is going on and the
765 // drag_view can be released.
766 if (drag_pointer_ == NONE)
767 drag_view_ = nullptr;
768 }
769
679 void ShelfView::LayoutToIdealBounds() { 770 void ShelfView::LayoutToIdealBounds() {
680 if (bounds_animator_->IsAnimating()) { 771 if (bounds_animator_->IsAnimating()) {
681 AnimateToIdealBounds(); 772 AnimateToIdealBounds();
682 return; 773 return;
683 } 774 }
684 775
685 IdealBounds ideal_bounds; 776 IdealBounds ideal_bounds;
686 CalculateIdealBounds(&ideal_bounds); 777 CalculateIdealBounds(&ideal_bounds);
687 views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); 778 views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_);
688 overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds); 779 overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
876 bounds_animator_->AnimateViewTo(view, view_model_->ideal_bounds(i)); 967 bounds_animator_->AnimateViewTo(view, view_model_->ideal_bounds(i));
877 // Now that the item animation starts, we have to make sure that the 968 // Now that the item animation starts, we have to make sure that the
878 // padding of the first gets properly transferred to the new first item. 969 // padding of the first gets properly transferred to the new first item.
879 if (i && view->border()) 970 if (i && view->border())
880 view->SetBorder(views::Border::NullBorder()); 971 view->SetBorder(views::Border::NullBorder());
881 } 972 }
882 overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds); 973 overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds);
883 } 974 }
884 975
885 views::View* ShelfView::CreateViewForItem(const ShelfItem& item) { 976 views::View* ShelfView::CreateViewForItem(const ShelfItem& item) {
886 views::View* view = NULL; 977 views::View* view = nullptr;
887 switch (item.type) { 978 switch (item.type) {
888 case TYPE_BROWSER_SHORTCUT: 979 case TYPE_BROWSER_SHORTCUT:
889 case TYPE_APP_SHORTCUT: 980 case TYPE_APP_SHORTCUT:
890 case TYPE_WINDOWED_APP: 981 case TYPE_WINDOWED_APP:
891 case TYPE_PLATFORM_APP: 982 case TYPE_PLATFORM_APP:
892 case TYPE_DIALOG: 983 case TYPE_DIALOG:
893 case TYPE_APP_PANEL: { 984 case TYPE_APP_PANEL: {
894 ShelfButton* button = ShelfButton::Create(this, this, shelf_); 985 ShelfButton* button = new ShelfButton(this);
895 button->SetImage(item.image); 986 button->SetImage(item.image);
896 ReflectItemStatus(item, button); 987 ReflectItemStatus(item, button);
897 view = button; 988 view = button;
898 break; 989 break;
899 } 990 }
900 991
901 case TYPE_APP_LIST: { 992 case TYPE_APP_LIST: {
902 view = new AppListButton(this, this, shelf_->shelf_widget()); 993 view = new AppListButton(this);
903 break; 994 break;
904 } 995 }
905 996
906 default: 997 case TYPE_UNDEFINED:
907 break; 998 return nullptr;
908 } 999 }
1000
909 view->set_context_menu_controller(this); 1001 view->set_context_menu_controller(this);
910
911 DCHECK(view);
912 ConfigureChildView(view); 1002 ConfigureChildView(view);
913 return view; 1003 return view;
914 } 1004 }
915 1005
916 void ShelfView::FadeIn(views::View* view) { 1006 void ShelfView::FadeIn(views::View* view) {
917 view->SetVisible(true); 1007 view->SetVisible(true);
918 view->layer()->SetOpacity(0); 1008 view->layer()->SetOpacity(0);
919 AnimateToIdealBounds(); 1009 AnimateToIdealBounds();
920 bounds_animator_->SetAnimationDelegate( 1010 bounds_animator_->SetAnimationDelegate(
921 view, 1011 view,
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
1288 void ShelfView::UpdateOverflowRange(ShelfView* overflow_view) const { 1378 void ShelfView::UpdateOverflowRange(ShelfView* overflow_view) const {
1289 const int first_overflow_index = last_visible_index_ + 1; 1379 const int first_overflow_index = last_visible_index_ + 1;
1290 const int last_overflow_index = last_hidden_index_; 1380 const int last_overflow_index = last_hidden_index_;
1291 DCHECK_LE(first_overflow_index, last_overflow_index); 1381 DCHECK_LE(first_overflow_index, last_overflow_index);
1292 DCHECK_LT(last_overflow_index, view_model_->view_size()); 1382 DCHECK_LT(last_overflow_index, view_model_->view_size());
1293 1383
1294 overflow_view->first_visible_index_ = first_overflow_index; 1384 overflow_view->first_visible_index_ = first_overflow_index;
1295 overflow_view->last_visible_index_ = last_overflow_index; 1385 overflow_view->last_visible_index_ = last_overflow_index;
1296 } 1386 }
1297 1387
1298 bool ShelfView::ShouldHideTooltip(const gfx::Point& cursor_location) {
1299 gfx::Rect active_bounds;
1300
1301 for (int i = 0; i < child_count(); ++i) {
1302 views::View* child = child_at(i);
1303 if (child == overflow_button_)
1304 continue;
1305 if (!ShouldShowTooltipForView(child))
1306 continue;
1307
1308 gfx::Rect child_bounds = child->GetMirroredBounds();
1309 active_bounds.Union(child_bounds);
1310 }
1311
1312 return !active_bounds.Contains(cursor_location);
1313 }
1314
1315 gfx::Rect ShelfView::GetVisibleItemsBoundsInScreen() {
1316 gfx::Size preferred_size = GetPreferredSize();
1317 gfx::Point origin(GetMirroredXWithWidthInView(0, preferred_size.width()), 0);
1318 ConvertPointToScreen(this, &origin);
1319 return gfx::Rect(origin, preferred_size);
1320 }
1321
1322 gfx::Rect ShelfView::GetBoundsForDragInsertInScreen() { 1388 gfx::Rect ShelfView::GetBoundsForDragInsertInScreen() {
1323 gfx::Size preferred_size; 1389 gfx::Size preferred_size;
1324 if (is_overflow_mode()) { 1390 if (is_overflow_mode()) {
1325 DCHECK(owner_overflow_bubble_); 1391 DCHECK(owner_overflow_bubble_);
1326 gfx::Rect bubble_bounds = 1392 gfx::Rect bubble_bounds =
1327 owner_overflow_bubble_->bubble_view()->GetBubbleBounds(); 1393 owner_overflow_bubble_->bubble_view()->GetBubbleBounds();
1328 preferred_size = bubble_bounds.size(); 1394 preferred_size = bubble_bounds.size();
1329 } else { 1395 } else {
1330 const int last_button_index = view_model_->view_size() - 1; 1396 const int last_button_index = view_model_->view_size() - 1;
1331 gfx::Rect last_button_bounds = 1397 gfx::Rect last_button_bounds =
(...skipping 27 matching lines...) Expand all
1359 return gfx::Rect(origin, preferred_size); 1425 return gfx::Rect(origin, preferred_size);
1360 } 1426 }
1361 1427
1362 int ShelfView::CancelDrag(int modified_index) { 1428 int ShelfView::CancelDrag(int modified_index) {
1363 FinalizeRipOffDrag(true); 1429 FinalizeRipOffDrag(true);
1364 if (!drag_view_) 1430 if (!drag_view_)
1365 return modified_index; 1431 return modified_index;
1366 bool was_dragging = dragging(); 1432 bool was_dragging = dragging();
1367 int drag_view_index = view_model_->GetIndexOfView(drag_view_); 1433 int drag_view_index = view_model_->GetIndexOfView(drag_view_);
1368 drag_pointer_ = NONE; 1434 drag_pointer_ = NONE;
1369 drag_view_ = NULL; 1435 drag_view_ = nullptr;
1370 if (drag_view_index == modified_index) { 1436 if (drag_view_index == modified_index) {
1371 // The view that was being dragged is being modified. Don't do anything. 1437 // The view that was being dragged is being modified. Don't do anything.
1372 return modified_index; 1438 return modified_index;
1373 } 1439 }
1374 if (!was_dragging) 1440 if (!was_dragging)
1375 return modified_index; 1441 return modified_index;
1376 1442
1377 // Restore previous position, tracking the position of the modified view. 1443 // Restore previous position, tracking the position of the modified view.
1378 bool at_end = modified_index == view_model_->view_size(); 1444 bool at_end = modified_index == view_model_->view_size();
1379 views::View* modified_view = 1445 views::View* modified_view = (modified_index >= 0 && !at_end)
1380 (modified_index >= 0 && !at_end) ? 1446 ? view_model_->view_at(modified_index)
1381 view_model_->view_at(modified_index) : NULL; 1447 : nullptr;
1382 model_->Move(drag_view_index, start_drag_index_); 1448 model_->Move(drag_view_index, start_drag_index_);
1383 1449
1384 // If the modified view will be at the end of the list, return the new end of 1450 // If the modified view will be at the end of the list, return the new end of
1385 // the list. 1451 // the list.
1386 if (at_end) 1452 if (at_end)
1387 return view_model_->view_size(); 1453 return view_model_->view_size();
1388 return modified_view ? view_model_->GetIndexOfView(modified_view) : -1; 1454 return modified_view ? view_model_->GetIndexOfView(modified_view) : -1;
1389 } 1455 }
1390 1456
1391 gfx::Size ShelfView::GetPreferredSize() const { 1457 gfx::Size ShelfView::GetPreferredSize() const {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 1500
1435 views::FocusTraversable* ShelfView::GetPaneFocusTraversable() { 1501 views::FocusTraversable* ShelfView::GetPaneFocusTraversable() {
1436 return this; 1502 return this;
1437 } 1503 }
1438 1504
1439 void ShelfView::GetAccessibleState(ui::AXViewState* state) { 1505 void ShelfView::GetAccessibleState(ui::AXViewState* state) {
1440 state->role = ui::AX_ROLE_TOOLBAR; 1506 state->role = ui::AX_ROLE_TOOLBAR;
1441 state->name = l10n_util::GetStringUTF16(IDS_ASH_SHELF_ACCESSIBLE_NAME); 1507 state->name = l10n_util::GetStringUTF16(IDS_ASH_SHELF_ACCESSIBLE_NAME);
1442 } 1508 }
1443 1509
1510 void ShelfView::ViewHierarchyChanged(
1511 const ViewHierarchyChangedDetails& details) {
1512 if (details.is_add && details.child == this && GetWidget())
1513 tooltip_.Init();
1514 }
1515
1444 void ShelfView::OnGestureEvent(ui::GestureEvent* event) { 1516 void ShelfView::OnGestureEvent(ui::GestureEvent* event) {
1445 aura::Window* target_window = static_cast<views::View*>(event->target()) 1517 aura::Window* target_window = static_cast<views::View*>(event->target())
1446 ->GetWidget() 1518 ->GetWidget()
1447 ->GetNativeWindow(); 1519 ->GetNativeWindow();
1448 if (gesture_handler_.ProcessGestureEvent(*event, target_window)) 1520 if (gesture_handler_.ProcessGestureEvent(*event, target_window))
1449 event->StopPropagation(); 1521 event->StopPropagation();
1450 } 1522 }
1451 1523
1452 void ShelfView::ShelfItemAdded(int model_index) { 1524 void ShelfView::ShelfItemAdded(int model_index) {
1453 { 1525 {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 bounds_animator_->SetAnimationDelegate( 1588 bounds_animator_->SetAnimationDelegate(
1517 view, 1589 view,
1518 scoped_ptr<gfx::AnimationDelegate>( 1590 scoped_ptr<gfx::AnimationDelegate>(
1519 new FadeOutAnimationDelegate(this, view))); 1591 new FadeOutAnimationDelegate(this, view)));
1520 } else { 1592 } else {
1521 // We don't need to show a fade out animation for invisible |view|. When an 1593 // We don't need to show a fade out animation for invisible |view|. When an
1522 // item is ripped out from the shelf, its |view| is already invisible. 1594 // item is ripped out from the shelf, its |view| is already invisible.
1523 AnimateToIdealBounds(); 1595 AnimateToIdealBounds();
1524 } 1596 }
1525 1597
1526 // Close the tooltip because it isn't needed any longer and its anchor view 1598 if (view == tooltip_.GetCurrentAnchorView())
1527 // will be deleted soon. 1599 tooltip_.Close();
1528 if (tooltip_->GetCurrentAnchorView() == view)
1529 tooltip_->Close();
1530 } 1600 }
1531 1601
1532 void ShelfView::ShelfItemChanged(int model_index, const ShelfItem& old_item) { 1602 void ShelfView::ShelfItemChanged(int model_index, const ShelfItem& old_item) {
1533 const ShelfItem& item(model_->items()[model_index]); 1603 const ShelfItem& item(model_->items()[model_index]);
1534 if (old_item.type != item.type) { 1604 if (old_item.type != item.type) {
1535 // Type changed, swap the views. 1605 // Type changed, swap the views.
1536 model_index = CancelDrag(model_index); 1606 model_index = CancelDrag(model_index);
1537 scoped_ptr<views::View> old_view(view_model_->view_at(model_index)); 1607 scoped_ptr<views::View> old_view(view_model_->view_at(model_index));
1538 bounds_animator_->StopAnimatingView(old_view.get()); 1608 bounds_animator_->StopAnimatingView(old_view.get());
1539 // Removing and re-inserting a view in our view model will strip the ideal 1609 // Removing and re-inserting a view in our view model will strip the ideal
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 void ShelfView::ShelfItemMoved(int start_index, int target_index) { 1648 void ShelfView::ShelfItemMoved(int start_index, int target_index) {
1579 view_model_->Move(start_index, target_index); 1649 view_model_->Move(start_index, target_index);
1580 // When cancelling a drag due to a shelf item being added, the currently 1650 // When cancelling a drag due to a shelf item being added, the currently
1581 // dragged item is moved back to its initial position. AnimateToIdealBounds 1651 // dragged item is moved back to its initial position. AnimateToIdealBounds
1582 // will be called again when the new item is added to the |view_model_| but 1652 // will be called again when the new item is added to the |view_model_| but
1583 // at this time the |view_model_| is inconsistent with the |model_|. 1653 // at this time the |view_model_| is inconsistent with the |model_|.
1584 if (!cancelling_drag_model_changed_) 1654 if (!cancelling_drag_model_changed_)
1585 AnimateToIdealBounds(); 1655 AnimateToIdealBounds();
1586 } 1656 }
1587 1657
1588 void ShelfView::PointerPressedOnButton(views::View* view,
1589 Pointer pointer,
1590 const ui::LocatedEvent& event) {
1591 if (drag_view_)
1592 return;
1593
1594 int index = view_model_->GetIndexOfView(view);
1595 if (index == -1)
1596 return;
1597
1598 ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate(
1599 model_->items()[index].id);
1600 if (view_model_->view_size() <= 1 || !item_delegate->IsDraggable())
1601 return; // View is being deleted or not draggable, ignore request.
1602
1603 // Only when the repost event occurs on the same shelf item, we should ignore
1604 // the call in ShelfView::ButtonPressed(...).
1605 is_repost_event_ = IsRepostEvent(event) && (last_pressed_index_ == index);
1606
1607 CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
1608 drag_view_ = static_cast<ShelfButton*>(view);
1609 drag_origin_ = gfx::Point(event.x(), event.y());
1610 UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentUsage",
1611 shelf_->SelectValueForShelfAlignment(
1612 SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM,
1613 SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT,
1614 SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT, -1),
1615 SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT);
1616 }
1617
1618 void ShelfView::PointerDraggedOnButton(views::View* view,
1619 Pointer pointer,
1620 const ui::LocatedEvent& event) {
1621 // To prepare all drag types (moving an item in the shelf and dragging off),
1622 // we should check the x-axis and y-axis offset.
1623 if (!dragging() && drag_view_ &&
1624 ((std::abs(event.x() - drag_origin_.x()) >= kMinimumDragDistance) ||
1625 (std::abs(event.y() - drag_origin_.y()) >= kMinimumDragDistance))) {
1626 PrepareForDrag(pointer, event);
1627 }
1628 if (drag_pointer_ == pointer)
1629 ContinueDrag(event);
1630 }
1631
1632 void ShelfView::PointerReleasedOnButton(views::View* view,
1633 Pointer pointer,
1634 bool canceled) {
1635 // Reset |is_repost_event| to false.
1636 is_repost_event_ = false;
1637
1638 if (canceled) {
1639 CancelDrag(-1);
1640 } else if (drag_pointer_ == pointer) {
1641 FinalizeRipOffDrag(false);
1642 drag_pointer_ = NONE;
1643 AnimateToIdealBounds();
1644 }
1645 // If the drag pointer is NONE, no drag operation is going on and the
1646 // drag_view can be released.
1647 if (drag_pointer_ == NONE)
1648 drag_view_ = NULL;
1649 }
1650
1651 void ShelfView::MouseMovedOverButton(views::View* view) {
1652 if (!ShouldShowTooltipForView(view))
1653 return;
1654
1655 if (!tooltip_->IsVisible())
1656 tooltip_->ResetTimer();
1657 }
1658
1659 void ShelfView::MouseEnteredButton(views::View* view) {
1660 if (!ShouldShowTooltipForView(view))
1661 return;
1662
1663 if (tooltip_->IsVisible()) {
1664 tooltip_->ShowImmediately(view, GetAccessibleName(view));
1665 } else {
1666 tooltip_->ShowDelayed(view, GetAccessibleName(view));
1667 }
1668 }
1669
1670 void ShelfView::MouseExitedButton(views::View* view) {
1671 if (!tooltip_->IsVisible())
1672 tooltip_->StopTimer();
1673 }
1674
1675 base::string16 ShelfView::GetAccessibleName(const views::View* view) {
1676 int view_index = view_model_->GetIndexOfView(view);
1677 // May be -1 while in the process of animating closed.
1678 if (view_index == -1)
1679 return base::string16();
1680
1681 ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate(
1682 model_->items()[view_index].id);
1683 return item_delegate->GetTitle();
1684 }
1685
1686 void ShelfView::ButtonPressed(views::Button* sender, const ui::Event& event) { 1658 void ShelfView::ButtonPressed(views::Button* sender, const ui::Event& event) {
1687 // Do not handle mouse release during drag. 1659 // Do not handle mouse release during drag.
1688 if (dragging()) 1660 if (dragging())
1689 return; 1661 return;
1690 1662
1691 if (sender == overflow_button_) { 1663 if (sender == overflow_button_) {
1692 ToggleOverflowBubble(); 1664 ToggleOverflowBubble();
1693 shelf_button_pressed_metric_tracker_.ButtonPressed( 1665 shelf_button_pressed_metric_tracker_.ButtonPressed(
1694 event, sender, ShelfItemDelegate::kNoAction); 1666 event, sender, ShelfItemDelegate::kNoAction);
1695 return; 1667 return;
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1875 // is still in the shelf and show its status again. 1847 // is still in the shelf and show its status again.
1876 for (int index = 0; index < view_model_->view_size(); index++) { 1848 for (int index = 0; index < view_model_->view_size(); index++) {
1877 views::View* view = view_model_->view_at(index); 1849 views::View* view = view_model_->view_at(index);
1878 if (view == snap_back_from_rip_off_view_) { 1850 if (view == snap_back_from_rip_off_view_) {
1879 CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName()); 1851 CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
1880 ShelfButton* button = static_cast<ShelfButton*>(view); 1852 ShelfButton* button = static_cast<ShelfButton*>(view);
1881 button->ClearState(ShelfButton::STATE_HIDDEN); 1853 button->ClearState(ShelfButton::STATE_HIDDEN);
1882 break; 1854 break;
1883 } 1855 }
1884 } 1856 }
1885 snap_back_from_rip_off_view_ = NULL; 1857 snap_back_from_rip_off_view_ = nullptr;
1886 } 1858 }
1887 } 1859 }
1888 } 1860 }
1889 1861
1890 bool ShelfView::IsRepostEvent(const ui::Event& event) { 1862 bool ShelfView::IsRepostEvent(const ui::Event& event) {
1891 if (closing_event_time_ == base::TimeDelta()) 1863 if (closing_event_time_ == base::TimeDelta())
1892 return false; 1864 return false;
1893 1865
1894 base::TimeDelta delta = 1866 base::TimeDelta delta =
1895 base::TimeDelta(event.time_stamp() - closing_event_time_); 1867 base::TimeDelta(event.time_stamp() - closing_event_time_);
1896 closing_event_time_ = base::TimeDelta(); 1868 closing_event_time_ = base::TimeDelta();
1897 // If the current (press down) event is a repost event, the time stamp of 1869 // If the current (press down) event is a repost event, the time stamp of
1898 // these two events should be the same. 1870 // these two events should be the same.
1899 return (delta.InMilliseconds() == 0); 1871 return (delta.InMilliseconds() == 0);
1900 } 1872 }
1901 1873
1902 const ShelfItem* ShelfView::ShelfItemForView(const views::View* view) const { 1874 const ShelfItem* ShelfView::ShelfItemForView(const views::View* view) const {
1903 const int view_index = view_model_->GetIndexOfView(view); 1875 const int view_index = view_model_->GetIndexOfView(view);
1904 return (view_index < 0) ? nullptr : &(model_->items()[view_index]); 1876 return (view_index < 0) ? nullptr : &(model_->items()[view_index]);
1905 } 1877 }
1906 1878
1907 bool ShelfView::ShouldShowTooltipForView(const views::View* view) const {
1908 if (view == GetAppListButtonView() &&
1909 Shell::GetInstance()->GetAppListTargetVisibility())
1910 return false;
1911 const ShelfItem* item = ShelfItemForView(view);
1912 if (!item)
1913 return true;
1914 ShelfItemDelegate* item_delegate =
1915 item_manager_->GetShelfItemDelegate(item->id);
1916 return item_delegate->ShouldShowTooltip();
1917 }
1918
1919 int ShelfView::CalculateShelfDistance(const gfx::Point& coordinate) const { 1879 int ShelfView::CalculateShelfDistance(const gfx::Point& coordinate) const {
1920 const gfx::Rect bounds = GetBoundsInScreen(); 1880 const gfx::Rect bounds = GetBoundsInScreen();
1921 int distance = shelf_->SelectValueForShelfAlignment( 1881 int distance = shelf_->SelectValueForShelfAlignment(
1922 bounds.y() - coordinate.y(), coordinate.x() - bounds.right(), 1882 bounds.y() - coordinate.y(), coordinate.x() - bounds.right(),
1923 bounds.x() - coordinate.x(), coordinate.y() - bounds.bottom()); 1883 bounds.x() - coordinate.x(), coordinate.y() - bounds.bottom());
1924 return distance > 0 ? distance : 0; 1884 return distance > 0 ? distance : 0;
1925 } 1885 }
1926 1886
1927 } // namespace ash 1887 } // namespace ash
OLDNEW
« no previous file with comments | « ash/shelf/shelf_view.h ('k') | ash/shelf/shelf_view_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698