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 |