OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "chrome/browser/ui/views/toolbar/browser_actions_container.h" | 5 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
9 #include "chrome/browser/extensions/extension_action_manager.h" | 9 #include "chrome/browser/extensions/extension_action_manager.h" |
10 #include "chrome/browser/extensions/extension_util.h" | 10 #include "chrome/browser/extensions/extension_util.h" |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
267 DCHECK(!command.global()); | 267 DCHECK(!command.global()); |
268 extension_keybinding_registry_->ExecuteCommand(extension->id(), | 268 extension_keybinding_registry_->ExecuteCommand(extension->id(), |
269 command.accelerator()); | 269 command.accelerator()); |
270 } | 270 } |
271 | 271 |
272 bool BrowserActionsContainer::ShownInsideMenu() const { | 272 bool BrowserActionsContainer::ShownInsideMenu() const { |
273 return in_overflow_mode(); | 273 return in_overflow_mode(); |
274 } | 274 } |
275 | 275 |
276 void BrowserActionsContainer::OnBrowserActionViewDragDone() { | 276 void BrowserActionsContainer::OnBrowserActionViewDragDone() { |
277 // We notify here as well as in OnPerformDrop because the dragged view is | 277 ToolbarVisibleCountChanged(); |
278 // removed in OnPerformDrop, so it will never get its OnDragDone() call. | |
279 // TODO(devlin): we should see about fixing that. | |
280 FOR_EACH_OBSERVER(BrowserActionsContainerObserver, | 278 FOR_EACH_OBSERVER(BrowserActionsContainerObserver, |
281 observers_, | 279 observers_, |
282 OnBrowserActionDragDone()); | 280 OnBrowserActionDragDone()); |
283 } | 281 } |
284 | 282 |
285 views::View* BrowserActionsContainer::GetOverflowReferenceView() { | 283 views::View* BrowserActionsContainer::GetOverflowReferenceView() { |
286 // We should only need an overflow reference when using the traditional | 284 // We should only need an overflow reference when using the traditional |
287 // chevron overflow. | 285 // chevron overflow. |
288 DCHECK(chevron_); | 286 DCHECK(chevron_); |
289 return chevron_; | 287 return chevron_; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
417 return BrowserActionDragData::AreDropTypesRequired(); | 415 return BrowserActionDragData::AreDropTypesRequired(); |
418 } | 416 } |
419 | 417 |
420 bool BrowserActionsContainer::CanDrop(const OSExchangeData& data) { | 418 bool BrowserActionsContainer::CanDrop(const OSExchangeData& data) { |
421 return BrowserActionDragData::CanDrop(data, profile_); | 419 return BrowserActionDragData::CanDrop(data, profile_); |
422 } | 420 } |
423 | 421 |
424 int BrowserActionsContainer::OnDragUpdated( | 422 int BrowserActionsContainer::OnDragUpdated( |
425 const ui::DropTargetEvent& event) { | 423 const ui::DropTargetEvent& event) { |
426 // First check if we are above the chevron (overflow) menu. | 424 // First check if we are above the chevron (overflow) menu. |
427 if (GetEventHandlerForPoint(event.location()) == chevron_) { | 425 if (chevron_ && GetEventHandlerForPoint(event.location()) == chevron_) { |
428 if (!show_menu_task_factory_.HasWeakPtrs() && !overflow_menu_) | 426 if (!show_menu_task_factory_.HasWeakPtrs() && !overflow_menu_) |
429 StartShowFolderDropMenuTimer(); | 427 StartShowFolderDropMenuTimer(); |
430 return ui::DragDropTypes::DRAG_MOVE; | 428 return ui::DragDropTypes::DRAG_MOVE; |
431 } | 429 } |
432 StopShowFolderDropMenuTimer(); | 430 StopShowFolderDropMenuTimer(); |
433 | 431 |
434 // Figure out where to display the indicator. This is a complex calculation: | 432 // Figure out where to display the indicator. This is a complex calculation: |
435 | 433 |
436 // First, we figure out how much space is to the left of the icon area, so we | 434 // First, we figure out how much space is to the left of the icon area, so we |
437 // can calculate the true offset into the icon area. The easiest way to do | 435 // can calculate the true offset into the icon area. The easiest way to do |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
530 // correct when dragging an icon to the left. When dragging to the right, | 528 // correct when dragging an icon to the left. When dragging to the right, |
531 // however, we want the icon being dragged to get the index of the item to | 529 // however, we want the icon being dragged to get the index of the item to |
532 // the left of the drop indicator, so we subtract one. | 530 // the left of the drop indicator, so we subtract one. |
533 // * Well, it can also point to the end, but not when dragging to the left. :) | 531 // * Well, it can also point to the end, but not when dragging to the left. :) |
534 if (i > data.index()) | 532 if (i > data.index()) |
535 --i; | 533 --i; |
536 | 534 |
537 if (profile_->IsOffTheRecord()) | 535 if (profile_->IsOffTheRecord()) |
538 i = model_->IncognitoIndexToOriginal(i); | 536 i = model_->IncognitoIndexToOriginal(i); |
539 | 537 |
538 // Check if the size of the toolbar needs to be adjusted; this happens when | |
539 // dragging from overflow to main or vice versa. We can check if this happened | |
540 // by seeing if the view is visible - if it's not, then the drag originated | |
541 // from the other container. | |
542 int size_modifier = 0; | |
543 if (!browser_action_views_[data.index()]->visible()) { | |
544 if (i > data.index()) { | |
Finnur
2014/09/10 09:48:01
I understand why dragging an icon to the left subt
Devlin
2014/09/10 15:58:30
Wow. Yeah, that's easier. Shoulda seen that... t
| |
545 // Dragging to the right, so hiding one. | |
546 size_modifier = -1; | |
547 } else if (i < data.index()) { | |
548 // Dragging to the left, so showing one. | |
549 size_modifier = 1; | |
550 } else { // i == data.index() | |
551 // Edge case: dragging to the same index, but in the other menu. | |
552 // If this was *dropped* in the overflow container, then we're hiding one, | |
553 // otherwise we're showing one. | |
554 size_modifier = in_overflow_mode() ? -1 : 1; | |
555 } | |
556 } | |
557 | |
540 model_->MoveExtensionIcon( | 558 model_->MoveExtensionIcon( |
541 browser_action_views_[data.index()]->extension(), i); | 559 browser_action_views_[data.index()]->extension(), i); |
542 | 560 |
561 // Adjust the size of the container, if needed. | |
562 if (size_modifier) { | |
563 // Let the main container update the model. | |
564 if (in_overflow_mode()) { | |
565 main_container_->NotifyActionMovedToOverflow(); | |
566 } else if (!profile_->IsOffTheRecord()) { | |
567 model_->SetVisibleIconCount( | |
568 model_->GetVisibleIconCount() + size_modifier); | |
569 } | |
570 | |
571 // The size changed, so we need to animate. | |
572 Animate(gfx::Tween::EASE_OUT, GetIconCount()); | |
573 } | |
574 | |
543 OnDragExited(); // Perform clean up after dragging. | 575 OnDragExited(); // Perform clean up after dragging. |
544 FOR_EACH_OBSERVER(BrowserActionsContainerObserver, | |
545 observers_, | |
546 OnBrowserActionDragDone()); | |
547 return ui::DragDropTypes::DRAG_MOVE; | 576 return ui::DragDropTypes::DRAG_MOVE; |
548 } | 577 } |
549 | 578 |
550 void BrowserActionsContainer::GetAccessibleState( | 579 void BrowserActionsContainer::GetAccessibleState( |
551 ui::AXViewState* state) { | 580 ui::AXViewState* state) { |
552 state->role = ui::AX_ROLE_GROUP; | 581 state->role = ui::AX_ROLE_GROUP; |
553 state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS); | 582 state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS); |
554 } | 583 } |
555 | 584 |
556 void BrowserActionsContainer::OnMenuButtonClicked(views::View* source, | 585 void BrowserActionsContainer::OnMenuButtonClicked(views::View* source, |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
618 | 647 |
619 // Save off the desired number of visible icons. We do this now instead of at | 648 // Save off the desired number of visible icons. We do this now instead of at |
620 // the end of the animation so that even if the browser is shut down while | 649 // the end of the animation so that even if the browser is shut down while |
621 // animating, the right value will be restored on next run. | 650 // animating, the right value will be restored on next run. |
622 // NOTE: Don't save the icon count in incognito because there may be fewer | 651 // NOTE: Don't save the icon count in incognito because there may be fewer |
623 // icons in that mode. The result is that the container in a normal window is | 652 // icons in that mode. The result is that the container in a normal window is |
624 // always at least as wide as in an incognito window. | 653 // always at least as wide as in an incognito window. |
625 int visible_icons = WidthToIconCount(container_width_); | 654 int visible_icons = WidthToIconCount(container_width_); |
626 if (!profile_->IsOffTheRecord()) | 655 if (!profile_->IsOffTheRecord()) |
627 model_->SetVisibleIconCount(visible_icons); | 656 model_->SetVisibleIconCount(visible_icons); |
628 | |
629 Animate(gfx::Tween::EASE_OUT, visible_icons); | 657 Animate(gfx::Tween::EASE_OUT, visible_icons); |
630 } | 658 } |
631 | 659 |
632 void BrowserActionsContainer::AnimationProgressed( | 660 void BrowserActionsContainer::AnimationProgressed( |
633 const gfx::Animation* animation) { | 661 const gfx::Animation* animation) { |
634 DCHECK_EQ(resize_animation_.get(), animation); | 662 DCHECK_EQ(resize_animation_.get(), animation); |
635 resize_amount_ = static_cast<int>(resize_animation_->GetCurrentValue() * | 663 resize_amount_ = static_cast<int>(resize_animation_->GetCurrentValue() * |
636 (container_width_ - animation_target_size_)); | 664 (container_width_ - animation_target_size_)); |
637 OnBrowserActionVisibilityChanged(); | 665 OnBrowserActionVisibilityChanged(); |
638 } | 666 } |
(...skipping 10 matching lines...) Expand all Loading... | |
649 observers_, | 677 observers_, |
650 OnBrowserActionsContainerAnimationEnded()); | 678 OnBrowserActionsContainerAnimationEnded()); |
651 } | 679 } |
652 | 680 |
653 void BrowserActionsContainer::NotifyMenuDeleted( | 681 void BrowserActionsContainer::NotifyMenuDeleted( |
654 BrowserActionOverflowMenuController* controller) { | 682 BrowserActionOverflowMenuController* controller) { |
655 DCHECK_EQ(overflow_menu_, controller); | 683 DCHECK_EQ(overflow_menu_, controller); |
656 overflow_menu_ = NULL; | 684 overflow_menu_ = NULL; |
657 } | 685 } |
658 | 686 |
687 void BrowserActionsContainer::NotifyActionMovedToOverflow() { | |
688 // When an action is moved to overflow, we shrink the size of the container | |
689 // by 1. | |
690 if (!profile_->IsOffTheRecord()) | |
691 model_->SetVisibleIconCount(model_->GetVisibleIconCount() - 1); | |
692 Animate(gfx::Tween::EASE_OUT, | |
693 VisibleBrowserActionsAfterAnimation() - 1); | |
694 } | |
695 | |
659 content::WebContents* BrowserActionsContainer::GetCurrentWebContents() { | 696 content::WebContents* BrowserActionsContainer::GetCurrentWebContents() { |
660 return browser_->tab_strip_model()->GetActiveWebContents(); | 697 return browser_->tab_strip_model()->GetActiveWebContents(); |
661 } | 698 } |
662 | 699 |
663 extensions::ActiveTabPermissionGranter* | 700 extensions::ActiveTabPermissionGranter* |
664 BrowserActionsContainer::GetActiveTabPermissionGranter() { | 701 BrowserActionsContainer::GetActiveTabPermissionGranter() { |
665 content::WebContents* web_contents = | 702 content::WebContents* web_contents = |
666 browser_->tab_strip_model()->GetActiveWebContents(); | 703 browser_->tab_strip_model()->GetActiveWebContents(); |
667 if (!web_contents) | 704 if (!web_contents) |
668 return NULL; | 705 return NULL; |
669 return extensions::TabHelper::FromWebContents(web_contents)-> | 706 return extensions::TabHelper::FromWebContents(web_contents)-> |
670 active_tab_permission_granter(); | 707 active_tab_permission_granter(); |
671 } | 708 } |
672 | 709 |
673 size_t BrowserActionsContainer::GetFirstVisibleIconIndex() const { | 710 size_t BrowserActionsContainer::GetFirstVisibleIconIndex() const { |
674 return in_overflow_mode() ? model_->GetVisibleIconCount() : 0; | 711 return in_overflow_mode() ? model_->GetVisibleIconCount() : 0; |
675 } | 712 } |
676 | 713 |
677 ExtensionPopup* BrowserActionsContainer::TestGetPopup() { | 714 ExtensionPopup* BrowserActionsContainer::TestGetPopup() { |
678 return popup_owner_ ? popup_owner_->view_controller()->popup() : NULL; | 715 return popup_owner_ ? popup_owner_->view_controller()->popup() : NULL; |
679 } | 716 } |
680 | 717 |
681 void BrowserActionsContainer::TestSetIconVisibilityCount(size_t icons) { | 718 void BrowserActionsContainer::TestSetIconVisibilityCount(size_t icons) { |
682 model_->SetVisibleIconCount(icons); | 719 model_->SetVisibleIconCountForTest(icons); |
683 chevron_->SetVisible(icons < browser_action_views_.size()); | |
684 container_width_ = IconCountToWidth(icons, chevron_->visible()); | |
685 Layout(); | |
686 SchedulePaint(); | |
687 } | 720 } |
688 | 721 |
689 void BrowserActionsContainer::OnPaint(gfx::Canvas* canvas) { | 722 void BrowserActionsContainer::OnPaint(gfx::Canvas* canvas) { |
690 // If the views haven't been initialized yet, wait for the next call to | 723 // If the views haven't been initialized yet, wait for the next call to |
691 // paint (one will be triggered by entering highlight mode). | 724 // paint (one will be triggered by entering highlight mode). |
692 if (model_->is_highlighting() && !browser_action_views_.empty()) { | 725 if (model_->is_highlighting() && !browser_action_views_.empty()) { |
693 views::Painter::PaintPainterAt( | 726 views::Painter::PaintPainterAt( |
694 canvas, highlight_painter_.get(), GetLocalBounds()); | 727 canvas, highlight_painter_.get(), GetLocalBounds()); |
695 } | 728 } |
696 | 729 |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1010 (kChevronSpacing + chevron_->GetPreferredSize().width()) : 0; | 1043 (kChevronSpacing + chevron_->GetPreferredSize().width()) : 0; |
1011 return ToolbarView::kStandardSpacing + icons_size + chevron_size + | 1044 return ToolbarView::kStandardSpacing + icons_size + chevron_size + |
1012 ToolbarView::kStandardSpacing; | 1045 ToolbarView::kStandardSpacing; |
1013 } | 1046 } |
1014 | 1047 |
1015 size_t BrowserActionsContainer::WidthToIconCount(int pixels) const { | 1048 size_t BrowserActionsContainer::WidthToIconCount(int pixels) const { |
1016 // Check for widths large enough to show the entire icon set. | 1049 // Check for widths large enough to show the entire icon set. |
1017 if (pixels >= IconCountToWidth(-1, false)) | 1050 if (pixels >= IconCountToWidth(-1, false)) |
1018 return browser_action_views_.size(); | 1051 return browser_action_views_.size(); |
1019 | 1052 |
1020 // We need to reserve space for the resize area, chevron, and the spacing on | 1053 // We reserve space for the padding on either side of the toolbar... |
1021 // either side of the chevron. | 1054 int available_space = pixels - (ToolbarView::kStandardSpacing * 2); |
1022 int available_space = pixels - ToolbarView::kStandardSpacing - | 1055 // ... and, if the chevron is enabled, the chevron. |
1023 (chevron_ ? chevron_->GetPreferredSize().width() : 0) - | 1056 if (chevron_) |
1024 kChevronSpacing - ToolbarView::kStandardSpacing; | 1057 available_space -= (chevron_->GetPreferredSize().width() + kChevronSpacing); |
1058 | |
1025 // Now we add an extra between-item padding value so the space can be divided | 1059 // Now we add an extra between-item padding value so the space can be divided |
1026 // evenly by (size of icon with padding). | 1060 // evenly by (size of icon with padding). |
1027 return static_cast<size_t>( | 1061 return static_cast<size_t>( |
1028 std::max(0, available_space + kItemSpacing) / IconWidth(true)); | 1062 std::max(0, available_space + kItemSpacing) / IconWidth(true)); |
1029 } | 1063 } |
1030 | 1064 |
1031 int BrowserActionsContainer::MinimumNonemptyWidth() const { | 1065 int BrowserActionsContainer::MinimumNonemptyWidth() const { |
1032 if (!chevron_) | 1066 if (!chevron_) |
1033 return ToolbarView::kStandardSpacing; | 1067 return ToolbarView::kStandardSpacing; |
1034 return (ToolbarView::kStandardSpacing * 2) + kChevronSpacing + | 1068 return (ToolbarView::kStandardSpacing * 2) + kChevronSpacing + |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1074 size_t absolute_model_size = | 1108 size_t absolute_model_size = |
1075 model_size == -1 ? extensions.size() : model_size; | 1109 model_size == -1 ? extensions.size() : model_size; |
1076 | 1110 |
1077 // The main container will try to show |model_size| icons, but reduce if there | 1111 // The main container will try to show |model_size| icons, but reduce if there |
1078 // aren't enough displayable icons to do so. | 1112 // aren't enough displayable icons to do so. |
1079 size_t main_displayed = std::min(displayable_icon_count, absolute_model_size); | 1113 size_t main_displayed = std::min(displayable_icon_count, absolute_model_size); |
1080 // The overflow will display the extras, if any. | 1114 // The overflow will display the extras, if any. |
1081 return in_overflow_mode() ? | 1115 return in_overflow_mode() ? |
1082 displayable_icon_count - main_displayed : main_displayed; | 1116 displayable_icon_count - main_displayed : main_displayed; |
1083 } | 1117 } |
OLD | NEW |