| 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/tab_helper.h" | 10 #include "chrome/browser/extensions/tab_helper.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 // TODO(devlin): We should move this to the model, once it supports component | 52 // TODO(devlin): We should move this to the model, once it supports component |
| 53 // actions. | 53 // actions. |
| 54 ScopedVector<ToolbarActionViewController> GetToolbarActions( | 54 ScopedVector<ToolbarActionViewController> GetToolbarActions( |
| 55 extensions::ExtensionToolbarModel* model, | 55 extensions::ExtensionToolbarModel* model, |
| 56 Browser* browser) { | 56 Browser* browser) { |
| 57 ScopedVector<ToolbarActionViewController> actions; | 57 ScopedVector<ToolbarActionViewController> actions; |
| 58 | 58 |
| 59 // Extension actions come first. | 59 // Extension actions come first. |
| 60 extensions::ExtensionActionManager* action_manager = | 60 extensions::ExtensionActionManager* action_manager = |
| 61 extensions::ExtensionActionManager::Get(browser->profile()); | 61 extensions::ExtensionActionManager::Get(browser->profile()); |
| 62 const extensions::ExtensionList& toolbar_items = model->toolbar_items(); | 62 const extensions::ExtensionList& toolbar_items = model->GetItemOrderForTab( |
| 63 browser->tab_strip_model()->GetActiveWebContents()); |
| 63 for (const scoped_refptr<const Extension>& extension : toolbar_items) { | 64 for (const scoped_refptr<const Extension>& extension : toolbar_items) { |
| 64 actions.push_back(new ExtensionActionViewController( | 65 actions.push_back(new ExtensionActionViewController( |
| 65 extension.get(), | 66 extension.get(), |
| 66 browser, | 67 browser, |
| 67 action_manager->GetExtensionAction(*extension))); | 68 action_manager->GetExtensionAction(*extension))); |
| 68 } | 69 } |
| 69 | 70 |
| 70 // Component actions come second. | 71 // Component actions come second. |
| 71 ScopedVector<ToolbarActionViewController> component_actions = | 72 ScopedVector<ToolbarActionViewController> component_actions = |
| 72 ComponentToolbarActionsFactory::GetInstance()-> | 73 ComponentToolbarActionsFactory::GetInstance()-> |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 : initialized_(false), | 118 : initialized_(false), |
| 118 profile_(browser->profile()), | 119 profile_(browser->profile()), |
| 119 browser_(browser), | 120 browser_(browser), |
| 120 main_container_(main_container), | 121 main_container_(main_container), |
| 121 popup_owner_(NULL), | 122 popup_owner_(NULL), |
| 122 model_(extensions::ExtensionToolbarModel::Get(browser->profile())), | 123 model_(extensions::ExtensionToolbarModel::Get(browser->profile())), |
| 123 container_width_(0), | 124 container_width_(0), |
| 124 resize_area_(NULL), | 125 resize_area_(NULL), |
| 125 chevron_(NULL), | 126 chevron_(NULL), |
| 126 suppress_chevron_(false), | 127 suppress_chevron_(false), |
| 128 suppress_animation_(false), |
| 129 suppress_layout_(false), |
| 127 resize_amount_(0), | 130 resize_amount_(0), |
| 128 animation_target_size_(0) { | 131 animation_target_size_(0) { |
| 129 set_id(VIEW_ID_BROWSER_ACTION_TOOLBAR); | 132 set_id(VIEW_ID_BROWSER_ACTION_TOOLBAR); |
| 130 if (model_) // |model_| can be NULL in views unittests. | 133 if (model_) // |model_| can be NULL in views unittests. |
| 131 model_->AddObserver(this); | 134 model_->AddObserver(this); |
| 132 | 135 |
| 133 bool overflow_experiment = | 136 bool overflow_experiment = |
| 134 extensions::FeatureSwitch::extension_action_redesign()->IsEnabled(); | 137 extensions::FeatureSwitch::extension_action_redesign()->IsEnabled(); |
| 135 DCHECK(!in_overflow_mode() || overflow_experiment); | 138 DCHECK(!in_overflow_mode() || overflow_experiment); |
| 136 | 139 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 BrowserActionView* BrowserActionsContainer::GetViewForExtension( | 189 BrowserActionView* BrowserActionsContainer::GetViewForExtension( |
| 187 const Extension* extension) { | 190 const Extension* extension) { |
| 188 for (BrowserActionView* view : browser_action_views_) { | 191 for (BrowserActionView* view : browser_action_views_) { |
| 189 if (view->view_controller()->GetId() == extension->id()) | 192 if (view->view_controller()->GetId() == extension->id()) |
| 190 return view; | 193 return view; |
| 191 } | 194 } |
| 192 return NULL; | 195 return NULL; |
| 193 } | 196 } |
| 194 | 197 |
| 195 void BrowserActionsContainer::RefreshBrowserActionViews() { | 198 void BrowserActionsContainer::RefreshBrowserActionViews() { |
| 199 if (browser_action_views_.empty()) |
| 200 return; // Nothing to do. |
| 201 |
| 202 // When we do a bulk-refresh of views (such as when we switch tabs), we don't |
| 203 // animate the difference. We only animate when it's a change driven by the |
| 204 // action. |
| 205 suppress_animation_ = true; |
| 206 // Don't layout until the end. |
| 207 suppress_layout_ = true; |
| 208 |
| 196 for (BrowserActionView* view : browser_action_views_) | 209 for (BrowserActionView* view : browser_action_views_) |
| 197 view->UpdateState(); | 210 view->UpdateState(); |
| 211 |
| 212 suppress_layout_ = false; |
| 213 ReorderViews(); // Also triggers a layout. |
| 214 |
| 215 suppress_animation_ = false; |
| 198 } | 216 } |
| 199 | 217 |
| 200 void BrowserActionsContainer::CreateBrowserActionViews() { | 218 void BrowserActionsContainer::CreateBrowserActionViews() { |
| 201 DCHECK(browser_action_views_.empty()); | 219 DCHECK(browser_action_views_.empty()); |
| 202 if (!model_) | 220 if (!model_) |
| 203 return; | 221 return; |
| 204 | 222 |
| 223 // We don't Layout while creating views. Instead, Layout() once at the end. |
| 224 suppress_layout_ = true; |
| 225 |
| 205 ScopedVector<ToolbarActionViewController> actions = | 226 ScopedVector<ToolbarActionViewController> actions = |
| 206 GetToolbarActions(model_, browser_); | 227 GetToolbarActions(model_, browser_); |
| 207 for (ToolbarActionViewController* controller : actions) { | 228 for (ToolbarActionViewController* controller : actions) { |
| 208 BrowserActionView* view = | 229 BrowserActionView* view = |
| 209 new BrowserActionView(make_scoped_ptr(controller), browser_, this); | 230 new BrowserActionView(make_scoped_ptr(controller), browser_, this); |
| 210 browser_action_views_.push_back(view); | 231 browser_action_views_.push_back(view); |
| 211 AddChildView(view); | 232 AddChildView(view); |
| 212 } | 233 } |
| 213 actions.weak_clear(); | 234 actions.weak_clear(); |
| 235 |
| 236 suppress_layout_ = false; |
| 237 |
| 238 Layout(); |
| 239 SchedulePaint(); |
| 214 } | 240 } |
| 215 | 241 |
| 216 void BrowserActionsContainer::DeleteBrowserActionViews() { | 242 void BrowserActionsContainer::DeleteBrowserActionViews() { |
| 217 HideActivePopup(); | 243 HideActivePopup(); |
| 218 STLDeleteElements(&browser_action_views_); | 244 STLDeleteElements(&browser_action_views_); |
| 219 } | 245 } |
| 220 | 246 |
| 221 size_t BrowserActionsContainer::VisibleBrowserActions() const { | 247 size_t BrowserActionsContainer::VisibleBrowserActions() const { |
| 222 size_t visible_actions = 0; | 248 size_t visible_actions = 0; |
| 223 for (const BrowserActionView* view : browser_action_views_) { | 249 for (const BrowserActionView* view : browser_action_views_) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 int min_width = std::min(MinimumNonemptyWidth(), IconCountToWidth(-1)); | 380 int min_width = std::min(MinimumNonemptyWidth(), IconCountToWidth(-1)); |
| 355 return gfx::Size(min_width, IconHeight()); | 381 return gfx::Size(min_width, IconHeight()); |
| 356 } | 382 } |
| 357 | 383 |
| 358 void BrowserActionsContainer::Layout() { | 384 void BrowserActionsContainer::Layout() { |
| 359 if (browser_action_views_.empty()) { | 385 if (browser_action_views_.empty()) { |
| 360 SetVisible(false); | 386 SetVisible(false); |
| 361 return; | 387 return; |
| 362 } | 388 } |
| 363 | 389 |
| 390 if (suppress_layout_) |
| 391 return; |
| 392 |
| 364 SetVisible(true); | 393 SetVisible(true); |
| 365 if (resize_area_) | 394 if (resize_area_) |
| 366 resize_area_->SetBounds(0, 0, kItemSpacing, height()); | 395 resize_area_->SetBounds(0, 0, kItemSpacing, height()); |
| 367 | 396 |
| 368 // If the icons don't all fit, show the chevron (unless suppressed). | 397 // If the icons don't all fit, show the chevron (unless suppressed). |
| 369 int max_x = GetPreferredSize().width(); | 398 int max_x = GetPreferredSize().width(); |
| 370 if (IconCountToWidth(-1) > max_x && !suppress_chevron_ && chevron_) { | 399 if (IconCountToWidth(-1) > max_x && !suppress_chevron_ && chevron_) { |
| 371 chevron_->SetVisible(true); | 400 chevron_->SetVisible(true); |
| 372 gfx::Size chevron_size(chevron_->GetPreferredSize()); | 401 gfx::Size chevron_size(chevron_->GetPreferredSize()); |
| 373 max_x -= chevron_size.width() + kChevronSpacing; | 402 max_x -= chevron_size.width() + kChevronSpacing; |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 resize_amount_ = 0; | 658 resize_amount_ = 0; |
| 630 suppress_chevron_ = false; | 659 suppress_chevron_ = false; |
| 631 SetChevronVisibility(); | 660 SetChevronVisibility(); |
| 632 OnBrowserActionVisibilityChanged(); | 661 OnBrowserActionVisibilityChanged(); |
| 633 | 662 |
| 634 FOR_EACH_OBSERVER(BrowserActionsContainerObserver, | 663 FOR_EACH_OBSERVER(BrowserActionsContainerObserver, |
| 635 observers_, | 664 observers_, |
| 636 OnBrowserActionsContainerAnimationEnded()); | 665 OnBrowserActionsContainerAnimationEnded()); |
| 637 } | 666 } |
| 638 | 667 |
| 639 content::WebContents* BrowserActionsContainer::GetCurrentWebContents() { | 668 content::WebContents* BrowserActionsContainer::GetCurrentWebContents() const { |
| 640 return browser_->tab_strip_model()->GetActiveWebContents(); | 669 return browser_->tab_strip_model()->GetActiveWebContents(); |
| 641 } | 670 } |
| 642 | 671 |
| 643 extensions::ActiveTabPermissionGranter* | 672 extensions::ActiveTabPermissionGranter* |
| 644 BrowserActionsContainer::GetActiveTabPermissionGranter() { | 673 BrowserActionsContainer::GetActiveTabPermissionGranter() { |
| 645 content::WebContents* web_contents = GetCurrentWebContents(); | 674 content::WebContents* web_contents = GetCurrentWebContents(); |
| 646 if (!web_contents) | 675 if (!web_contents) |
| 647 return NULL; | 676 return NULL; |
| 648 return extensions::TabHelper::FromWebContents(web_contents)-> | 677 return extensions::TabHelper::FromWebContents(web_contents)-> |
| 649 active_tab_permission_granter(); | 678 active_tab_permission_granter(); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 bool grant_active_tab) { | 906 bool grant_active_tab) { |
| 878 // Don't override another popup, and only show in the active window. | 907 // Don't override another popup, and only show in the active window. |
| 879 if (popup_owner_ || !browser_->window()->IsActive()) | 908 if (popup_owner_ || !browser_->window()->IsActive()) |
| 880 return false; | 909 return false; |
| 881 | 910 |
| 882 BrowserActionView* view = GetViewForExtension(extension); | 911 BrowserActionView* view = GetViewForExtension(extension); |
| 883 return view && view->view_controller()->ExecuteAction(grant_active_tab); | 912 return view && view->view_controller()->ExecuteAction(grant_active_tab); |
| 884 } | 913 } |
| 885 | 914 |
| 886 void BrowserActionsContainer::ToolbarVisibleCountChanged() { | 915 void BrowserActionsContainer::ToolbarVisibleCountChanged() { |
| 887 if (GetPreferredWidth() != container_width_) | 916 if (GetPreferredWidth() != container_width_) { |
| 888 Animate(gfx::Tween::EASE_OUT, GetIconCount()); | 917 Animate(gfx::Tween::EASE_OUT, GetIconCount()); |
| 918 } else if (animation_target_size_ != 0) { |
| 919 // It's possible that we're right where we're supposed to be in terms of |
| 920 // icon count, but that we're also currently resizing. If this is the case, |
| 921 // end the current animation with the current width. |
| 922 animation_target_size_ = container_width_; |
| 923 resize_animation_->Reset(); |
| 924 } |
| 889 } | 925 } |
| 890 | 926 |
| 891 void BrowserActionsContainer::ToolbarHighlightModeChanged( | 927 void BrowserActionsContainer::ToolbarHighlightModeChanged( |
| 892 bool is_highlighting) { | 928 bool is_highlighting) { |
| 893 // The visual highlighting is done in OnPaint(). It's a bit of a pain that | 929 // The visual highlighting is done in OnPaint(). It's a bit of a pain that |
| 894 // we delete and recreate everything here, but given everything else going on | 930 // we delete and recreate everything here, but given everything else going on |
| 895 // (the lack of highlight, n more extensions appearing, etc), it's not worth | 931 // (the lack of highlight, n more extensions appearing, etc), it's not worth |
| 896 // the extra complexity to create and insert only the new extensions. | 932 // the extra complexity to create and insert only the new extensions. |
| 897 DeleteBrowserActionViews(); | 933 DeleteBrowserActionViews(); |
| 898 CreateBrowserActionViews(); | 934 CreateBrowserActionViews(); |
| 899 Animate(gfx::Tween::LINEAR, GetIconCount()); | 935 Animate(gfx::Tween::LINEAR, GetIconCount()); |
| 900 } | 936 } |
| 901 | 937 |
| 938 void BrowserActionsContainer::ToolbarReorderNecessary( |
| 939 content::WebContents* web_contents) { |
| 940 if (GetCurrentWebContents() == web_contents) |
| 941 ReorderViews(); |
| 942 } |
| 943 |
| 902 Browser* BrowserActionsContainer::GetBrowser() { | 944 Browser* BrowserActionsContainer::GetBrowser() { |
| 903 return browser_; | 945 return browser_; |
| 904 } | 946 } |
| 905 | 947 |
| 906 void BrowserActionsContainer::LoadImages() { | 948 void BrowserActionsContainer::LoadImages() { |
| 907 if (in_overflow_mode()) | 949 if (in_overflow_mode()) |
| 908 return; // Overflow mode has neither a chevron nor highlighting. | 950 return; // Overflow mode has neither a chevron nor highlighting. |
| 909 | 951 |
| 910 ui::ThemeProvider* tp = GetThemeProvider(); | 952 ui::ThemeProvider* tp = GetThemeProvider(); |
| 911 if (tp && chevron_) { | 953 if (tp && chevron_) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 int BrowserActionsContainer::MinimumNonemptyWidth() const { | 1019 int BrowserActionsContainer::MinimumNonemptyWidth() const { |
| 978 if (!chevron_) | 1020 if (!chevron_) |
| 979 return ToolbarView::kStandardSpacing; | 1021 return ToolbarView::kStandardSpacing; |
| 980 return (ToolbarView::kStandardSpacing * 2) + kChevronSpacing + | 1022 return (ToolbarView::kStandardSpacing * 2) + kChevronSpacing + |
| 981 chevron_->GetPreferredSize().width(); | 1023 chevron_->GetPreferredSize().width(); |
| 982 } | 1024 } |
| 983 | 1025 |
| 984 void BrowserActionsContainer::Animate(gfx::Tween::Type tween_type, | 1026 void BrowserActionsContainer::Animate(gfx::Tween::Type tween_type, |
| 985 size_t num_visible_icons) { | 1027 size_t num_visible_icons) { |
| 986 int target_size = IconCountToWidth(num_visible_icons); | 1028 int target_size = IconCountToWidth(num_visible_icons); |
| 987 if (resize_animation_ && !disable_animations_during_testing_) { | 1029 if (resize_animation_ && !disable_animations_during_testing_ && |
| 1030 !suppress_animation_) { |
| 988 // Animate! We have to set the animation_target_size_ after calling Reset(), | 1031 // Animate! We have to set the animation_target_size_ after calling Reset(), |
| 989 // because that could end up calling AnimationEnded which clears the value. | 1032 // because that could end up calling AnimationEnded which clears the value. |
| 990 resize_animation_->Reset(); | 1033 resize_animation_->Reset(); |
| 991 resize_animation_->SetTweenType(tween_type); | 1034 resize_animation_->SetTweenType(tween_type); |
| 992 animation_target_size_ = target_size; | 1035 animation_target_size_ = target_size; |
| 993 resize_animation_->Show(); | 1036 resize_animation_->Show(); |
| 994 } else { | 1037 } else { |
| 995 animation_target_size_ = target_size; | 1038 animation_target_size_ = target_size; |
| 996 AnimationEnded(resize_animation_.get()); | 1039 AnimationEnded(resize_animation_.get()); |
| 997 } | 1040 } |
| 998 } | 1041 } |
| 999 | 1042 |
| 1043 void BrowserActionsContainer::ReorderViews() { |
| 1044 extensions::ExtensionList new_order = |
| 1045 model_->GetItemOrderForTab(GetCurrentWebContents()); |
| 1046 if (new_order.empty()) |
| 1047 return; // Nothing to do. |
| 1048 |
| 1049 // Run through the views and compare them to the desired order. If something |
| 1050 // is out of place, find the correct spot for it. |
| 1051 for (size_t i = 0; i < new_order.size() - 1; ++i) { |
| 1052 if (new_order[i]->id() != |
| 1053 browser_action_views_[i]->view_controller()->GetId()) { |
| 1054 // Find where the correct view is (it's guaranteed to be after our current |
| 1055 // index, since everything up to this point is correct). |
| 1056 size_t j = i + 1; |
| 1057 while (new_order[i]->id() != |
| 1058 browser_action_views_[j]->view_controller()->GetId()) |
| 1059 ++j; |
| 1060 std::swap(browser_action_views_[i], browser_action_views_[j]); |
| 1061 } |
| 1062 } |
| 1063 |
| 1064 // Our visible browser actions may have changed - re-Layout() and check the |
| 1065 // size. |
| 1066 ToolbarVisibleCountChanged(); |
| 1067 OnBrowserActionVisibilityChanged(); |
| 1068 } |
| 1069 |
| 1000 size_t BrowserActionsContainer::GetIconCount() const { | 1070 size_t BrowserActionsContainer::GetIconCount() const { |
| 1001 if (!model_) | 1071 if (!model_) |
| 1002 return 0u; | 1072 return 0u; |
| 1003 | 1073 |
| 1004 // Find the absolute value for the model's visible count. | 1074 // Find the absolute value for the model's visible count. |
| 1005 int model_visible_size = model_->GetVisibleIconCount(); | 1075 int model_visible_size = |
| 1076 model_->GetVisibleIconCountForTab(GetCurrentWebContents()); |
| 1006 size_t absolute_model_visible_size = model_visible_size == -1 ? | 1077 size_t absolute_model_visible_size = model_visible_size == -1 ? |
| 1007 model_->toolbar_items().size() : model_visible_size; | 1078 model_->toolbar_items().size() : model_visible_size; |
| 1008 | 1079 |
| 1009 #if defined(DEBUG) | 1080 #if defined(DEBUG) |
| 1010 // Good time for some sanity checks: We should never try to display more | 1081 // Good time for some sanity checks: We should never try to display more |
| 1011 // icons than we have, and we should always have a view per item in the model. | 1082 // icons than we have, and we should always have a view per item in the model. |
| 1012 // (The only exception is if this is in initialization.) | 1083 // (The only exception is if this is in initialization.) |
| 1013 if (initialized_) { | 1084 if (initialized_) { |
| 1014 size_t num_extension_actions = 0u; | 1085 size_t num_extension_actions = 0u; |
| 1015 for (const BrowserActionView* view : browser_action_views_) { | 1086 for (const BrowserActionView* view : browser_action_views_) { |
| 1016 num_extension_actions += | 1087 num_extension_actions += |
| 1017 view->view_controller()->GetType() == | 1088 view->view_controller()->GetType() == |
| 1018 ToolbarActionViewController::TYPE_EXTENSION_ACTION ? 1 : 0; | 1089 ToolbarActionViewController::TYPE_EXTENSION_ACTION ? 1 : 0; |
| 1019 } | 1090 } |
| 1020 DCHECK_LE(absolute_model_visible_size, browser_action_views_.size()); | 1091 DCHECK_LE(absolute_model_visible_size, browser_action_views_.size()); |
| 1021 DCHECK_EQ(model_->toolbar_items().size(), browser_action_views_.size()); | 1092 DCHECK_EQ(model_->toolbar_items().size(), browser_action_views_.size()); |
| 1022 } | 1093 } |
| 1023 #endif | 1094 #endif |
| 1024 | 1095 |
| 1025 // The overflow displays any icons not shown by the main bar. | 1096 // The overflow displays any icons not shown by the main bar. |
| 1026 return in_overflow_mode() ? | 1097 return in_overflow_mode() ? |
| 1027 model_->toolbar_items().size() - absolute_model_visible_size : | 1098 model_->toolbar_items().size() - absolute_model_visible_size : |
| 1028 absolute_model_visible_size; | 1099 absolute_model_visible_size; |
| 1029 } | 1100 } |
| OLD | NEW |