Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/toolbar/toolbar_actions_bar.h" | 5 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "chrome/browser/extensions/extension_action_manager.h" | 8 #include "chrome/browser/extensions/extension_action_manager.h" |
| 9 #include "chrome/browser/profiles/profile.h" | 9 #include "chrome/browser/profiles/profile.h" |
| 10 #include "chrome/browser/sessions/session_tab_helper.h" | 10 #include "chrome/browser/sessions/session_tab_helper.h" |
| 11 #include "chrome/browser/ui/browser.h" | 11 #include "chrome/browser/ui/browser.h" |
| 12 #include "chrome/browser/ui/browser_window.h" | 12 #include "chrome/browser/ui/browser_window.h" |
| 13 #include "chrome/browser/ui/extensions/extension_action_view_controller.h" | 13 #include "chrome/browser/ui/extensions/extension_action_view_controller.h" |
| 14 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 14 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 15 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" | |
| 15 #include "chrome/browser/ui/toolbar/component_toolbar_actions_factory.h" | 16 #include "chrome/browser/ui/toolbar/component_toolbar_actions_factory.h" |
| 16 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" | 17 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" |
| 17 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h" | 18 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h" |
| 18 #include "components/crx_file/id_util.h" | 19 #include "components/crx_file/id_util.h" |
| 19 #include "extensions/browser/extension_system.h" | 20 #include "extensions/browser/extension_system.h" |
| 20 #include "extensions/browser/runtime_data.h" | 21 #include "extensions/browser/runtime_data.h" |
| 21 #include "extensions/common/extension.h" | 22 #include "extensions/common/extension.h" |
| 22 #include "extensions/common/feature_switch.h" | 23 #include "extensions/common/feature_switch.h" |
| 23 #include "grit/theme_resources.h" | 24 #include "grit/theme_resources.h" |
| 24 #include "ui/base/resource/resource_bundle.h" | 25 #include "ui/base/resource/resource_bundle.h" |
| 25 #include "ui/gfx/image/image_skia.h" | 26 #include "ui/gfx/image/image_skia.h" |
| 26 | 27 |
| 27 namespace { | 28 namespace { |
| 28 | 29 |
| 30 using WeakToolbarActions = std::vector<ToolbarActionViewController*>; | |
| 31 | |
| 29 #if defined(OS_MACOSX) | 32 #if defined(OS_MACOSX) |
| 30 const int kItemSpacing = 2; | 33 const int kItemSpacing = 2; |
| 31 const int kLeftPadding = kItemSpacing + 1; | 34 const int kLeftPadding = kItemSpacing + 1; |
| 32 const int kRightPadding = 0; | 35 const int kRightPadding = 0; |
| 33 const int kOverflowLeftPadding = kItemSpacing; | 36 const int kOverflowLeftPadding = kItemSpacing; |
| 34 const int kOverflowRightPadding = kItemSpacing; | 37 const int kOverflowRightPadding = kItemSpacing; |
| 35 #else | 38 #else |
| 36 // Matches ToolbarView::kStandardSpacing; | 39 // Matches ToolbarView::kStandardSpacing; |
| 37 const int kLeftPadding = 3; | 40 const int kLeftPadding = 3; |
| 38 const int kRightPadding = kLeftPadding; | 41 const int kRightPadding = kLeftPadding; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 52 initialized = true; | 55 initialized = true; |
| 53 gfx::ImageSkia* skia = | 56 gfx::ImageSkia* skia = |
| 54 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | 57 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
| 55 IDR_BROWSER_ACTION); | 58 IDR_BROWSER_ACTION); |
| 56 icon_height = skia->height(); | 59 icon_height = skia->height(); |
| 57 icon_width = skia->width(); | 60 icon_width = skia->width(); |
| 58 } | 61 } |
| 59 return type == WIDTH ? icon_width : icon_height; | 62 return type == WIDTH ? icon_width : icon_height; |
| 60 } | 63 } |
| 61 | 64 |
| 65 // Takes a reference vector |reference| of length n, where n is less than or | |
| 66 // equal to the length of |to_sort|, and rearranges |to_sort| so that | |
| 67 // |to_sort|'s first n elements match the n elements of |reference| (the order | |
| 68 // of any remaining elements in |to_sort| is unspecified). | |
| 69 // |equal| is used to compare the elements of |to_sort| and |reference|. | |
| 70 // This allows us to sort a vector to match another vector of two different | |
| 71 // types without needing to construct a more cumbersome comparator class. | |
| 72 // |FunctionType| should equate to (something similar to) | |
| 73 // bool Equal(const Type1&, const Type2&), but we can't enforce this | |
| 74 // because of MSVC compilation limitations. | |
| 75 template<typename Type1, typename Type2, typename FunctionType> | |
| 76 void SortContainer(std::vector<Type1>* to_sort, | |
| 77 const std::vector<Type2>& reference, | |
| 78 FunctionType equal) { | |
| 79 DCHECK_GE(to_sort->size(), reference.size()) << | |
|
sky
2014/12/16 00:53:46
This made me think too much. Did you consider the
Devlin
2014/12/16 01:01:18
I don't quite follow - |to_sort| and |reference| a
| |
| 80 "|to_sort| must contain all elements in |reference|."; | |
| 81 if (reference.empty()) | |
| 82 return; | |
| 83 // Run through the each element and compare it to the reference. If something | |
| 84 // is out of place, find the correct spot for it. | |
| 85 for (size_t i = 0; i < reference.size() - 1; ++i) { | |
| 86 if (!equal(to_sort->at(i), reference[i])) { | |
| 87 // Find the correct index (it's guaranteed to be after our current | |
| 88 // index, since everything up to this point is correct), and swap. | |
| 89 size_t j = i + 1; | |
| 90 while (!equal(to_sort->at(j), reference[i])) { | |
| 91 ++j; | |
| 92 DCHECK_LE(j, to_sort->size()) << | |
| 93 "Item in |reference| not found in |to_sort|."; | |
| 94 } | |
| 95 std::swap(to_sort->at(i), to_sort->at(j)); | |
| 96 } | |
| 97 } | |
| 98 } | |
| 99 | |
| 62 } // namespace | 100 } // namespace |
| 63 | 101 |
| 64 // static | 102 // static |
| 65 bool ToolbarActionsBar::disable_animations_for_testing_ = false; | 103 bool ToolbarActionsBar::disable_animations_for_testing_ = false; |
| 66 | 104 |
| 105 // static | |
| 106 bool ToolbarActionsBar::pop_out_actions_to_run = false; | |
| 107 | |
| 108 // A class to implement an optional tab ordering that "pops out" actions that | |
| 109 // want to run on a particular page, as part of our experimentation with how to | |
| 110 // best signal that actions like extension page actions want to run. | |
| 111 // TODO(devlin): Once we finally settle on the right behavior, determine if | |
| 112 // we need this. | |
| 113 class ToolbarActionsBar::TabOrderHelper | |
| 114 : public TabStripModelObserver { | |
| 115 public: | |
| 116 TabOrderHelper(ToolbarActionsBar* toolbar, | |
| 117 Browser* browser, | |
| 118 extensions::ExtensionToolbarModel* model); | |
| 119 ~TabOrderHelper() override; | |
| 120 | |
| 121 // Returns the number of extra icons that should appear on the given |tab_id| | |
| 122 // because of actions that are going to pop out. | |
| 123 size_t GetExtraIconCount(int tab_id); | |
| 124 | |
| 125 // Returns the item order of actions for the tab with the given | |
| 126 // |web_contents|. | |
| 127 WeakToolbarActions GetActionOrder(content::WebContents* web_contents); | |
| 128 | |
| 129 // Notifies the TabOrderHelper that a given |action| does/doesn't want to run | |
| 130 // on the tab indicated by |tab_id|. | |
| 131 void SetActionWantsToRun(ToolbarActionViewController* action, | |
| 132 int tab_id, | |
| 133 bool wants_to_run); | |
| 134 | |
| 135 // Notifies the TabOrderHelper that a given |action| has been removed. | |
| 136 void ActionRemoved(ToolbarActionViewController* action); | |
| 137 | |
| 138 // Handles a resize, including updating any actions that want to act and | |
| 139 // updating the model. | |
| 140 void HandleResize(size_t resized_count, int tab_id); | |
| 141 | |
| 142 // Handles a drag and drop, including updating any actions that want to act | |
| 143 // and updating the model. | |
| 144 void HandleDragDrop(int dragged, | |
| 145 int dropped, | |
| 146 ToolbarActionsBar::DragType drag_type, | |
| 147 int tab_id); | |
| 148 | |
| 149 private: | |
| 150 // TabStripModelObserver: | |
| 151 void TabInsertedAt(content::WebContents* web_contents, | |
| 152 int index, | |
| 153 bool foreground) override; | |
| 154 void TabDetachedAt(content::WebContents* web_contents, int index) override; | |
| 155 void TabStripModelDeleted() override; | |
| 156 | |
| 157 // The set of tabs for the given action (the key) is currently "popped out". | |
| 158 // "Popped out" actions are those that were in the overflow menu normally, but | |
| 159 // want to run and are moved to the main bar so the user can see them. | |
| 160 std::map<ToolbarActionViewController*, std::set<int>> popped_out_in_tabs_; | |
| 161 | |
| 162 // The set of tab ids that have been checked for whether actions need to be | |
| 163 // popped out or not. | |
| 164 std::set<int> tabs_checked_for_pop_out_; | |
| 165 | |
| 166 // The owning ToolbarActionsBar. | |
| 167 ToolbarActionsBar* toolbar_; | |
| 168 | |
| 169 // The associated toolbar model. | |
| 170 extensions::ExtensionToolbarModel* model_; | |
| 171 | |
| 172 // A scoped tab strip observer so we can clean up |tabs_checked_for_popout_|. | |
| 173 ScopedObserver<TabStripModel, TabStripModelObserver> tab_strip_observer_; | |
| 174 | |
| 175 DISALLOW_COPY_AND_ASSIGN(TabOrderHelper); | |
| 176 }; | |
| 177 | |
| 178 ToolbarActionsBar::TabOrderHelper::TabOrderHelper( | |
| 179 ToolbarActionsBar* toolbar, | |
| 180 Browser* browser, | |
| 181 extensions::ExtensionToolbarModel* model) | |
| 182 : toolbar_(toolbar), | |
| 183 model_(model), | |
| 184 tab_strip_observer_(this) { | |
| 185 tab_strip_observer_.Add(browser->tab_strip_model()); | |
| 186 } | |
| 187 | |
| 188 ToolbarActionsBar::TabOrderHelper::~TabOrderHelper() { | |
| 189 } | |
| 190 | |
| 191 size_t ToolbarActionsBar::TabOrderHelper::GetExtraIconCount(int tab_id) { | |
| 192 size_t extra_icons = 0; | |
| 193 const WeakToolbarActions& toolbar_actions = toolbar_->toolbar_actions(); | |
| 194 for (ToolbarActionViewController* action : toolbar_actions) { | |
| 195 auto actions_tabs = popped_out_in_tabs_.find(action); | |
| 196 if (actions_tabs != popped_out_in_tabs_.end() && | |
| 197 actions_tabs->second.count(tab_id)) | |
| 198 ++extra_icons; | |
| 199 } | |
| 200 return extra_icons; | |
| 201 } | |
| 202 | |
| 203 void ToolbarActionsBar::TabOrderHelper::HandleResize(size_t resized_count, | |
| 204 int tab_id) { | |
| 205 int extra = GetExtraIconCount(tab_id); | |
| 206 size_t tab_icon_count = model_->visible_icon_count() + extra; | |
| 207 bool reorder_necessary = false; | |
| 208 const WeakToolbarActions& toolbar_actions = toolbar_->toolbar_actions(); | |
| 209 if (resized_count < tab_icon_count) { | |
| 210 for (int i = resized_count; i < extra; ++i) { | |
| 211 // If an extension that was popped out to act is overflowed, then it | |
| 212 // should no longer be popped out, and it also doesn't count for adjusting | |
| 213 // the visible count (since it wasn't really out to begin with). | |
| 214 if (popped_out_in_tabs_[toolbar_actions[i]].count(tab_id)) { | |
| 215 reorder_necessary = true; | |
| 216 popped_out_in_tabs_[toolbar_actions[i]].erase(tab_id); | |
| 217 ++(resized_count); | |
|
sky
2014/12/16 00:53:46
nit: no need for () here.
| |
| 218 } | |
| 219 } | |
| 220 } else { | |
| 221 // If the user increases the toolbar size while actions that popped out are | |
| 222 // visible, we need to re-arrange the icons in other windows to be | |
| 223 // consistent with what the user sees. | |
| 224 // That is, if the normal order is A, B, [C, D] (with C and D hidden), C | |
| 225 // pops out to act, and then the user increases the size of the toolbar, | |
| 226 // the user sees uncovering D (since C is already out). This is what should | |
| 227 // happen in all windows. | |
| 228 for (size_t i = tab_icon_count; i < resized_count; ++i) { | |
| 229 if (toolbar_actions[i]->GetId() != | |
| 230 model_->toolbar_items()[i - extra]->id()) | |
| 231 model_->MoveExtensionIcon(toolbar_actions[i]->GetId(), i - extra); | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 resized_count -= extra; | |
| 236 model_->SetVisibleIconCount(resized_count); | |
| 237 if (reorder_necessary) | |
| 238 toolbar_->ReorderActions(); | |
| 239 } | |
| 240 | |
| 241 void ToolbarActionsBar::TabOrderHelper::HandleDragDrop( | |
| 242 int dragged_index, | |
| 243 int dropped_index, | |
| 244 ToolbarActionsBar::DragType drag_type, | |
| 245 int tab_id) { | |
| 246 const WeakToolbarActions& toolbar_actions = toolbar_->toolbar_actions(); | |
| 247 ToolbarActionViewController* action = toolbar_actions[dragged_index]; | |
| 248 int delta = 0; | |
| 249 switch (drag_type) { | |
| 250 case ToolbarActionsBar::DRAG_TO_OVERFLOW: | |
| 251 // If the user moves an action back into overflow, then we don't adjust | |
| 252 // the base visible count, but do stop popping that action out. | |
| 253 if (popped_out_in_tabs_[action].count(tab_id)) | |
| 254 popped_out_in_tabs_[action].erase(tab_id); | |
| 255 else | |
| 256 delta = -1; | |
| 257 break; | |
| 258 case ToolbarActionsBar::DRAG_TO_MAIN: | |
| 259 delta = 1; | |
| 260 break; | |
| 261 case ToolbarActionsBar::DRAG_TO_SAME: | |
| 262 // If the user moves an action that had popped out to be on the toolbar, | |
| 263 // then we treat it as "pinning" the action, and adjust the base visible | |
| 264 // count to accommodate. | |
| 265 if (popped_out_in_tabs_[action].count(tab_id)) { | |
| 266 delta = 1; | |
| 267 popped_out_in_tabs_[action].erase(tab_id); | |
| 268 } | |
| 269 break; | |
| 270 } | |
| 271 | |
| 272 // If there are any actions that are in front of the dropped index only | |
| 273 // because they were popped out, decrement the dropped index. | |
| 274 for (int i = 0; i < dropped_index; ++i) { | |
| 275 if (i != dragged_index && | |
| 276 model_->GetIndexForId(toolbar_actions[i]->GetId()) >= dropped_index) | |
| 277 --dropped_index; | |
| 278 } | |
| 279 | |
| 280 model_->MoveExtensionIcon(action->GetId(), dropped_index); | |
| 281 | |
| 282 if (delta) | |
| 283 model_->SetVisibleIconCount(model_->visible_icon_count() + delta); | |
| 284 } | |
| 285 | |
| 286 void ToolbarActionsBar::TabOrderHelper::SetActionWantsToRun( | |
| 287 ToolbarActionViewController* action, | |
| 288 int tab_id, | |
| 289 bool wants_to_run) { | |
| 290 bool is_overflowed = model_->GetIndexForId(action->GetId()) >= | |
| 291 static_cast<int>(model_->visible_icon_count()); | |
| 292 bool reorder_necessary = false; | |
| 293 if (wants_to_run && is_overflowed) { | |
| 294 popped_out_in_tabs_[action].insert(tab_id); | |
| 295 reorder_necessary = true; | |
| 296 } else if (!wants_to_run && popped_out_in_tabs_[action].count(tab_id)) { | |
| 297 popped_out_in_tabs_[action].erase(tab_id); | |
| 298 reorder_necessary = true; | |
| 299 } | |
| 300 if (reorder_necessary) | |
| 301 toolbar_->ReorderActions(); | |
| 302 } | |
| 303 | |
| 304 void ToolbarActionsBar::TabOrderHelper::ActionRemoved( | |
| 305 ToolbarActionViewController* action) { | |
| 306 popped_out_in_tabs_.erase(action); | |
| 307 } | |
| 308 | |
| 309 WeakToolbarActions ToolbarActionsBar::TabOrderHelper::GetActionOrder( | |
| 310 content::WebContents* web_contents) { | |
| 311 WeakToolbarActions toolbar_actions = toolbar_->toolbar_actions(); | |
| 312 // First, make sure that we've checked any actions that want to run. | |
| 313 int tab_id = SessionTabHelper::IdForTab(web_contents); | |
| 314 if (!tabs_checked_for_pop_out_.count(tab_id)) { | |
| 315 tabs_checked_for_pop_out_.insert(tab_id); | |
| 316 for (ToolbarActionViewController* toolbar_action : toolbar_actions) { | |
| 317 if (toolbar_action->WantsToRun(web_contents)) | |
| 318 popped_out_in_tabs_[toolbar_action].insert(tab_id); | |
| 319 } | |
| 320 } | |
| 321 | |
| 322 // Then, shift any actions that want to run to the front. | |
| 323 size_t insert_at = 0; | |
| 324 // Rotate any actions that want to run to the boundary between visible and | |
| 325 // overflowed actions. | |
| 326 for (WeakToolbarActions::iterator iter = | |
| 327 toolbar_actions.begin() + model_->visible_icon_count(); | |
| 328 iter != toolbar_actions.end(); ++iter) { | |
| 329 if (popped_out_in_tabs_[(*iter)].count(tab_id)) { | |
| 330 std::rotate(toolbar_actions.begin() + insert_at, iter, iter + 1); | |
| 331 ++insert_at; | |
| 332 } | |
| 333 } | |
| 334 | |
| 335 return toolbar_actions; | |
| 336 } | |
| 337 | |
| 338 void ToolbarActionsBar::TabOrderHelper::TabInsertedAt( | |
| 339 content::WebContents* web_contents, | |
| 340 int index, | |
| 341 bool foreground) { | |
| 342 if (foreground) | |
| 343 toolbar_->ReorderActions(); | |
| 344 } | |
| 345 | |
| 346 void ToolbarActionsBar::TabOrderHelper::TabDetachedAt( | |
| 347 content::WebContents* web_contents, | |
| 348 int index) { | |
| 349 int tab_id = SessionTabHelper::IdForTab(web_contents); | |
| 350 for (auto& tabs : popped_out_in_tabs_) | |
| 351 tabs.second.erase(tab_id); | |
| 352 tabs_checked_for_pop_out_.erase(tab_id); | |
| 353 } | |
| 354 | |
| 355 void ToolbarActionsBar::TabOrderHelper::TabStripModelDeleted() { | |
| 356 tab_strip_observer_.RemoveAll(); | |
| 357 } | |
| 358 | |
| 67 ToolbarActionsBar::PlatformSettings::PlatformSettings(bool in_overflow_mode) | 359 ToolbarActionsBar::PlatformSettings::PlatformSettings(bool in_overflow_mode) |
| 68 : left_padding(in_overflow_mode ? kOverflowLeftPadding : kLeftPadding), | 360 : left_padding(in_overflow_mode ? kOverflowLeftPadding : kLeftPadding), |
| 69 right_padding(in_overflow_mode ? kOverflowRightPadding : kRightPadding), | 361 right_padding(in_overflow_mode ? kOverflowRightPadding : kRightPadding), |
| 70 item_spacing(kItemSpacing), | 362 item_spacing(kItemSpacing), |
| 71 icons_per_overflow_menu_row(1), | 363 icons_per_overflow_menu_row(1), |
| 72 chevron_enabled(!extensions::FeatureSwitch::extension_action_redesign()-> | 364 chevron_enabled(!extensions::FeatureSwitch::extension_action_redesign()-> |
| 73 IsEnabled()) { | 365 IsEnabled()) { |
| 74 } | 366 } |
| 75 | 367 |
| 76 ToolbarActionsBar::ToolbarActionsBar(ToolbarActionsBarDelegate* delegate, | 368 ToolbarActionsBar::ToolbarActionsBar(ToolbarActionsBarDelegate* delegate, |
| 77 Browser* browser, | 369 Browser* browser, |
| 78 bool in_overflow_mode) | 370 ToolbarActionsBar* main_bar) |
| 79 : delegate_(delegate), | 371 : delegate_(delegate), |
| 80 browser_(browser), | 372 browser_(browser), |
| 81 model_(extensions::ExtensionToolbarModel::Get(browser_->profile())), | 373 model_(extensions::ExtensionToolbarModel::Get(browser_->profile())), |
| 82 in_overflow_mode_(in_overflow_mode), | 374 main_bar_(main_bar), |
| 83 platform_settings_(in_overflow_mode), | 375 overflow_bar_(nullptr), |
| 376 platform_settings_(main_bar != nullptr), | |
| 84 model_observer_(this), | 377 model_observer_(this), |
| 85 tab_strip_observer_(this), | |
| 86 suppress_layout_(false), | 378 suppress_layout_(false), |
| 87 suppress_animation_(true) { | 379 suppress_animation_(true) { |
| 88 if (model_) // |model_| can be null in unittests. | 380 if (model_) // |model_| can be null in unittests. |
| 89 model_observer_.Add(model_); | 381 model_observer_.Add(model_); |
| 90 tab_strip_observer_.Add(browser_->tab_strip_model()); | 382 if (in_overflow_mode()) |
| 383 main_bar_->overflow_bar_ = this; | |
| 384 else if (pop_out_actions_to_run) | |
| 385 tab_order_helper_.reset(new TabOrderHelper(this, browser_, model_)); | |
| 91 } | 386 } |
| 92 | 387 |
| 93 ToolbarActionsBar::~ToolbarActionsBar() { | 388 ToolbarActionsBar::~ToolbarActionsBar() { |
| 94 // We don't just call DeleteActions() here because it makes assumptions about | 389 // We don't just call DeleteActions() here because it makes assumptions about |
| 95 // the order of deletion between the views and the ToolbarActionsBar. | 390 // the order of deletion between the views and the ToolbarActionsBar. |
| 96 DCHECK(toolbar_actions_.empty()) << | 391 DCHECK(toolbar_actions_.empty()) << |
| 97 "Must call DeleteActions() before destruction."; | 392 "Must call DeleteActions() before destruction."; |
| 393 if (in_overflow_mode()) | |
| 394 main_bar_->overflow_bar_ = nullptr; | |
| 395 DCHECK(overflow_bar_ == nullptr) << "Overflow bar cannot outlive main bar"; | |
| 98 } | 396 } |
| 99 | 397 |
| 100 // static | 398 // static |
| 101 int ToolbarActionsBar::IconWidth(bool include_padding) { | 399 int ToolbarActionsBar::IconWidth(bool include_padding) { |
| 102 return GetIconDimension(WIDTH) + (include_padding ? kItemSpacing : 0); | 400 return GetIconDimension(WIDTH) + (include_padding ? kItemSpacing : 0); |
| 103 } | 401 } |
| 104 | 402 |
| 105 // static | 403 // static |
| 106 int ToolbarActionsBar::IconHeight() { | 404 int ToolbarActionsBar::IconHeight() { |
| 107 return GetIconDimension(HEIGHT); | 405 return GetIconDimension(HEIGHT); |
| 108 } | 406 } |
| 109 | 407 |
| 110 gfx::Size ToolbarActionsBar::GetPreferredSize() const { | 408 gfx::Size ToolbarActionsBar::GetPreferredSize() const { |
| 111 int icon_count = GetIconCount(); | 409 int icon_count = GetIconCount(); |
| 112 if (in_overflow_mode_) { | 410 if (in_overflow_mode()) { |
| 113 // In overflow, we always have a preferred size of a full row (even if we | 411 // In overflow, we always have a preferred size of a full row (even if we |
| 114 // don't use it), and always of at least one row. The parent may decide to | 412 // don't use it), and always of at least one row. The parent may decide to |
| 115 // show us even when empty, e.g. as a drag target for dragging in icons from | 413 // show us even when empty, e.g. as a drag target for dragging in icons from |
| 116 // the main container. | 414 // the main container. |
| 117 int row_count = ((std::max(0, icon_count - 1)) / | 415 int row_count = ((std::max(0, icon_count - 1)) / |
| 118 platform_settings_.icons_per_overflow_menu_row) + 1; | 416 platform_settings_.icons_per_overflow_menu_row) + 1; |
| 119 return gfx::Size( | 417 return gfx::Size( |
| 120 IconCountToWidth(platform_settings_.icons_per_overflow_menu_row), | 418 IconCountToWidth(platform_settings_.icons_per_overflow_menu_row), |
| 121 row_count * IconHeight()); | 419 row_count * IconHeight()); |
| 122 } | 420 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 // Now we add an extra between-item padding value so the space can be divided | 468 // Now we add an extra between-item padding value so the space can be divided |
| 171 // evenly by (size of icon with padding). | 469 // evenly by (size of icon with padding). |
| 172 return static_cast<size_t>(std::max( | 470 return static_cast<size_t>(std::max( |
| 173 0, available_space + platform_settings_.item_spacing) / IconWidth(true)); | 471 0, available_space + platform_settings_.item_spacing) / IconWidth(true)); |
| 174 } | 472 } |
| 175 | 473 |
| 176 size_t ToolbarActionsBar::GetIconCount() const { | 474 size_t ToolbarActionsBar::GetIconCount() const { |
| 177 if (!model_) | 475 if (!model_) |
| 178 return 0u; | 476 return 0u; |
| 179 | 477 |
| 180 size_t visible_icons = model_->visible_icon_count(); | 478 size_t extra_icons = 0; |
| 479 if (tab_order_helper_) { | |
| 480 extra_icons = tab_order_helper_->GetExtraIconCount( | |
| 481 SessionTabHelper::IdForTab( | |
| 482 browser_->tab_strip_model()->GetActiveWebContents())); | |
| 483 } | |
| 484 | |
| 485 size_t visible_icons = in_overflow_mode() ? | |
| 486 toolbar_actions_.size() - main_bar_->GetIconCount() : | |
| 487 model_->visible_icon_count() + extra_icons; | |
| 488 | |
| 181 #if DCHECK_IS_ON | 489 #if DCHECK_IS_ON |
| 182 // Good time for some sanity checks: We should never try to display more | 490 // Good time for some sanity checks: We should never try to display more |
| 183 // icons than we have, and we should always have a view per item in the model. | 491 // icons than we have, and we should always have a view per item in the model. |
| 184 // (The only exception is if this is in initialization.) | 492 // (The only exception is if this is in initialization.) |
| 185 if (!toolbar_actions_.empty() && !suppress_layout_ && | 493 if (!toolbar_actions_.empty() && !suppress_layout_ && |
| 186 model_->extensions_initialized()) { | 494 model_->extensions_initialized()) { |
| 187 size_t num_extension_actions = 0u; | 495 size_t num_extension_actions = 0u; |
| 188 for (ToolbarActionViewController* action : toolbar_actions_) { | 496 for (ToolbarActionViewController* action : toolbar_actions_) { |
| 189 // No component action should ever have a valid extension id, so we can | 497 // No component action should ever have a valid extension id, so we can |
| 190 // use this to check the extension amount. | 498 // use this to check the extension amount. |
| 191 // TODO(devlin): Fix this to just check model size when the model also | 499 // TODO(devlin): Fix this to just check model size when the model also |
| 192 // includes component actions. | 500 // includes component actions. |
| 193 if (crx_file::id_util::IdIsValid(action->GetId())) | 501 if (crx_file::id_util::IdIsValid(action->GetId())) |
| 194 ++num_extension_actions; | 502 ++num_extension_actions; |
| 195 } | 503 } |
| 196 DCHECK_LE(visible_icons, num_extension_actions); | 504 DCHECK_LE(visible_icons, num_extension_actions); |
| 197 DCHECK_EQ(model_->toolbar_items().size(), num_extension_actions); | 505 DCHECK_EQ(model_->toolbar_items().size(), num_extension_actions); |
| 198 } | 506 } |
| 199 #endif | 507 #endif |
| 200 | 508 |
| 201 int tab_id = SessionTabHelper::IdForTab( | 509 return visible_icons; |
| 202 browser_->tab_strip_model()->GetActiveWebContents()); | |
| 203 for (ToolbarActionViewController* action : toolbar_actions_) { | |
| 204 auto actions_tabs = popped_out_in_tabs_.find(action); | |
| 205 if (actions_tabs != popped_out_in_tabs_.end() && | |
| 206 actions_tabs->second.count(tab_id)) | |
| 207 ++visible_icons; | |
| 208 } | |
| 209 | |
| 210 // The overflow displays any icons not shown by the main bar. | |
| 211 return in_overflow_mode_ ? | |
| 212 model_->toolbar_items().size() - visible_icons : visible_icons; | |
| 213 } | 510 } |
| 214 | 511 |
| 215 void ToolbarActionsBar::CreateActions() { | 512 void ToolbarActionsBar::CreateActions() { |
| 216 DCHECK(toolbar_actions_.empty()); | 513 DCHECK(toolbar_actions_.empty()); |
| 217 // We wait for the extension system to be initialized before we add any | 514 // We wait for the extension system to be initialized before we add any |
| 218 // actions, as they rely on the extension system to function. | 515 // actions, as they rely on the extension system to function. |
| 219 if (!model_ || !model_->extensions_initialized()) | 516 if (!model_ || !model_->extensions_initialized()) |
| 220 return; | 517 return; |
| 221 | 518 |
| 222 { | 519 { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 242 ComponentToolbarActionsFactory::GetInstance()-> | 539 ComponentToolbarActionsFactory::GetInstance()-> |
| 243 GetComponentToolbarActions(); | 540 GetComponentToolbarActions(); |
| 244 DCHECK(component_actions.empty() || | 541 DCHECK(component_actions.empty() || |
| 245 extensions::FeatureSwitch::extension_action_redesign()->IsEnabled()); | 542 extensions::FeatureSwitch::extension_action_redesign()->IsEnabled()); |
| 246 toolbar_actions_.insert(toolbar_actions_.end(), | 543 toolbar_actions_.insert(toolbar_actions_.end(), |
| 247 component_actions.begin(), | 544 component_actions.begin(), |
| 248 component_actions.end()); | 545 component_actions.end()); |
| 249 component_actions.weak_clear(); | 546 component_actions.weak_clear(); |
| 250 } | 547 } |
| 251 | 548 |
| 252 if (!toolbar_actions_.empty()) | 549 if (!toolbar_actions_.empty()) { |
| 253 ReorderActions(); | 550 if (in_overflow_mode()) |
| 551 CopyActionOrder(); | |
| 552 else | |
| 553 ReorderActions(); | |
| 554 } | |
| 254 | 555 |
| 255 for (size_t i = 0; i < toolbar_actions_.size(); ++i) | 556 for (size_t i = 0; i < toolbar_actions_.size(); ++i) |
| 256 delegate_->AddViewForAction(toolbar_actions_[i], i); | 557 delegate_->AddViewForAction(toolbar_actions_[i], i); |
| 257 } | 558 } |
| 258 | 559 |
| 259 // Once the actions are created, we should animate the changes. | 560 // Once the actions are created, we should animate the changes. |
| 260 suppress_animation_ = false; | 561 suppress_animation_ = false; |
| 261 } | 562 } |
| 262 | 563 |
| 263 void ToolbarActionsBar::DeleteActions() { | 564 void ToolbarActionsBar::DeleteActions() { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 278 // Don't layout until the end. | 579 // Don't layout until the end. |
| 279 base::AutoReset<bool> layout_resetter(&suppress_layout_, true); | 580 base::AutoReset<bool> layout_resetter(&suppress_layout_, true); |
| 280 for (ToolbarActionViewController* action : toolbar_actions_) | 581 for (ToolbarActionViewController* action : toolbar_actions_) |
| 281 action->UpdateState(); | 582 action->UpdateState(); |
| 282 } | 583 } |
| 283 | 584 |
| 284 ReorderActions(); // Also triggers a draw. | 585 ReorderActions(); // Also triggers a draw. |
| 285 } | 586 } |
| 286 | 587 |
| 287 void ToolbarActionsBar::SetOverflowRowWidth(int width) { | 588 void ToolbarActionsBar::SetOverflowRowWidth(int width) { |
| 288 DCHECK(in_overflow_mode_); | 589 DCHECK(in_overflow_mode()); |
| 289 platform_settings_.icons_per_overflow_menu_row = | 590 platform_settings_.icons_per_overflow_menu_row = |
| 290 std::max((width - kItemSpacing) / IconWidth(true), 1); | 591 std::max((width - kItemSpacing) / IconWidth(true), 1); |
| 291 } | 592 } |
| 292 | 593 |
| 293 void ToolbarActionsBar::OnResizeComplete(int width) { | 594 void ToolbarActionsBar::OnResizeComplete(int width) { |
| 294 DCHECK(!in_overflow_mode_); // The user can't resize the overflow container. | 595 DCHECK(!in_overflow_mode()); // The user can't resize the overflow container. |
| 295 size_t resized_count = WidthToIconCount(width); | 596 size_t resized_count = WidthToIconCount(width); |
| 296 size_t tab_icon_count = GetIconCount(); | 597 // Save off the desired number of visible icons. We do this now instead of |
| 297 int tab_id = SessionTabHelper::IdForTab(GetCurrentWebContents()); | 598 // at the end of the animation so that even if the browser is shut down |
| 298 int delta = tab_icon_count - model_->visible_icon_count(); | 599 // while animating, the right value will be restored on next run. |
| 299 bool reorder_necessary = false; | 600 if (tab_order_helper_) { |
| 300 if (resized_count < tab_icon_count) { | 601 tab_order_helper_->HandleResize( |
| 301 for (int i = resized_count; i < delta; ++i) { | 602 resized_count, |
| 302 // If an extension that was popped out to act is overflowed, then it | 603 SessionTabHelper::IdForTab(GetCurrentWebContents())); |
| 303 // should no longer be popped out, and it also doesn't count for adjusting | |
| 304 // the visible count (since it wasn't really out to begin with). | |
| 305 if (popped_out_in_tabs_[toolbar_actions_[i]].count(tab_id)) { | |
| 306 reorder_necessary = true; | |
| 307 popped_out_in_tabs_[toolbar_actions_[i]].erase(tab_id); | |
| 308 ++resized_count; | |
| 309 } | |
| 310 } | |
| 311 } else { | 604 } else { |
| 312 // If the user increases the toolbar size while actions that popped out are | 605 model_->SetVisibleIconCount(resized_count); |
| 313 // visible, we need to re-arrange the icons in other windows to be | |
| 314 // consistent with what the user sees. | |
| 315 // That is, if the normal order is A, B, [C, D] (with C and D hidden), C | |
| 316 // pops out to act, and then the user increases the size of the toolbar, | |
| 317 // the user sees uncovering D (since C is already out). This is what should | |
| 318 // happen in all windows. | |
| 319 for (size_t i = tab_icon_count; i < resized_count; ++i) { | |
| 320 if (toolbar_actions_[i]->GetId() != | |
| 321 model_->toolbar_items()[i - delta]->id()) | |
| 322 model_->MoveExtensionIcon(toolbar_actions_[i]->GetId(), i - delta); | |
| 323 } | |
| 324 } | 606 } |
| 325 resized_count -= delta; | |
| 326 // Save off the desired number of visible icons. We do this now instead of at | |
| 327 // the end of the animation so that even if the browser is shut down while | |
| 328 // animating, the right value will be restored on next run. | |
| 329 model_->SetVisibleIconCount(resized_count); | |
| 330 if (reorder_necessary) | |
| 331 ReorderActions(); | |
| 332 } | 607 } |
| 333 | 608 |
| 334 void ToolbarActionsBar::OnDragDrop(int dragged_index, | 609 void ToolbarActionsBar::OnDragDrop(int dragged_index, |
| 335 int dropped_index, | 610 int dropped_index, |
| 336 DragType drag_type) { | 611 DragType drag_type) { |
| 337 ToolbarActionViewController* action = toolbar_actions_[dragged_index]; | 612 // All drag-and-drop commands should go to the main bar. |
| 338 int tab_id = SessionTabHelper::IdForTab(GetCurrentWebContents()); | 613 DCHECK(!in_overflow_mode()); |
| 339 int delta = 0; | 614 |
| 340 switch (drag_type) { | 615 if (tab_order_helper_) { |
| 341 case DRAG_TO_OVERFLOW: | 616 tab_order_helper_->HandleDragDrop( |
| 342 // If the user moves an action back into overflow, then we don't adjust | 617 dragged_index, |
| 343 // the base visible count, but do stop popping that action out. | 618 dropped_index, |
| 344 if (popped_out_in_tabs_[action].count(tab_id)) | 619 drag_type, |
| 345 popped_out_in_tabs_[action].erase(tab_id); | 620 SessionTabHelper::IdForTab(GetCurrentWebContents())); |
| 346 else | 621 } else { |
| 347 delta = -1; | 622 int delta = 0; |
| 348 break; | 623 if (drag_type == DRAG_TO_OVERFLOW) |
| 349 case DRAG_TO_MAIN: | 624 delta = -1; |
| 625 else if (drag_type == DRAG_TO_MAIN) | |
| 350 delta = 1; | 626 delta = 1; |
| 351 break; | 627 model_->MoveExtensionIcon(toolbar_actions_[dragged_index]->GetId(), |
| 352 case DRAG_TO_SAME: | 628 dropped_index); |
| 353 // If the user moves an action that had popped out to be on the toolbar, | 629 if (delta) |
| 354 // then we treat it as "pinning" the action, and adjust the base visible | 630 model_->SetVisibleIconCount(model_->visible_icon_count() + delta); |
| 355 // count to accommodate. | |
| 356 if (popped_out_in_tabs_[action].count(tab_id)) { | |
| 357 delta = 1; | |
| 358 popped_out_in_tabs_[action].erase(tab_id); | |
| 359 } | |
| 360 break; | |
| 361 } | 631 } |
| 362 | |
| 363 // If there are any actions that are in front of the dropped index only | |
| 364 // because they were popped out, decrement the dropped index. | |
| 365 for (int i = 0; i < dropped_index; ++i) { | |
| 366 if (i != dragged_index && | |
| 367 model_->GetIndexForId(toolbar_actions_[i]->GetId()) >= dropped_index) | |
| 368 --dropped_index; | |
| 369 } | |
| 370 | |
| 371 model_->MoveExtensionIcon(action->GetId(), dropped_index); | |
| 372 | |
| 373 if (delta) | |
| 374 model_->SetVisibleIconCount(model_->visible_icon_count() + delta); | |
| 375 } | 632 } |
| 376 | 633 |
| 377 void ToolbarActionsBar::ToolbarExtensionAdded( | 634 void ToolbarActionsBar::ToolbarExtensionAdded( |
| 378 const extensions::Extension* extension, | 635 const extensions::Extension* extension, |
| 379 int index) { | 636 int index) { |
| 380 DCHECK(GetActionForId(extension->id()) == nullptr) << | 637 DCHECK(GetActionForId(extension->id()) == nullptr) << |
| 381 "Asked to add a toolbar action view for an extension that already exists"; | 638 "Asked to add a toolbar action view for an extension that already exists"; |
| 382 | 639 |
| 383 toolbar_actions_.insert( | 640 toolbar_actions_.insert( |
| 384 toolbar_actions_.begin() + index, | 641 toolbar_actions_.begin() + index, |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 410 void ToolbarActionsBar::ToolbarExtensionRemoved( | 667 void ToolbarActionsBar::ToolbarExtensionRemoved( |
| 411 const extensions::Extension* extension) { | 668 const extensions::Extension* extension) { |
| 412 ToolbarActions::iterator iter = toolbar_actions_.begin(); | 669 ToolbarActions::iterator iter = toolbar_actions_.begin(); |
| 413 while (iter != toolbar_actions_.end() && (*iter)->GetId() != extension->id()) | 670 while (iter != toolbar_actions_.end() && (*iter)->GetId() != extension->id()) |
| 414 ++iter; | 671 ++iter; |
| 415 | 672 |
| 416 if (iter == toolbar_actions_.end()) | 673 if (iter == toolbar_actions_.end()) |
| 417 return; | 674 return; |
| 418 | 675 |
| 419 delegate_->RemoveViewForAction(*iter); | 676 delegate_->RemoveViewForAction(*iter); |
| 420 popped_out_in_tabs_.erase(*iter); | 677 if (tab_order_helper_) |
| 678 tab_order_helper_->ActionRemoved(*iter); | |
| 421 toolbar_actions_.erase(iter); | 679 toolbar_actions_.erase(iter); |
| 422 | 680 |
| 423 // If the extension is being upgraded we don't want the bar to shrink | 681 // If the extension is being upgraded we don't want the bar to shrink |
| 424 // because the icon is just going to get re-added to the same location. | 682 // because the icon is just going to get re-added to the same location. |
| 425 if (!extensions::ExtensionSystem::Get(browser_->profile())->runtime_data()-> | 683 if (!extensions::ExtensionSystem::Get(browser_->profile())->runtime_data()-> |
| 426 IsBeingUpgraded(extension->id())) { | 684 IsBeingUpgraded(extension->id())) { |
| 427 if (toolbar_actions_.size() > model_->visible_icon_count()) { | 685 if (toolbar_actions_.size() > model_->visible_icon_count()) { |
| 428 // If we have more icons than we can show, then we must not be changing | 686 // If we have more icons than we can show, then we must not be changing |
| 429 // the container size (since we either removed an icon from the main | 687 // the container size (since we either removed an icon from the main |
| 430 // area and one from the overflow list will have shifted in, or we | 688 // area and one from the overflow list will have shifted in, or we |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 450 } | 708 } |
| 451 | 709 |
| 452 void ToolbarActionsBar::ToolbarExtensionUpdated( | 710 void ToolbarActionsBar::ToolbarExtensionUpdated( |
| 453 const extensions::Extension* extension) { | 711 const extensions::Extension* extension) { |
| 454 ToolbarActionViewController* action = GetActionForId(extension->id()); | 712 ToolbarActionViewController* action = GetActionForId(extension->id()); |
| 455 // There might not be a view in cases where we are highlighting or if we | 713 // There might not be a view in cases where we are highlighting or if we |
| 456 // haven't fully initialized the actions. | 714 // haven't fully initialized the actions. |
| 457 if (action) { | 715 if (action) { |
| 458 content::WebContents* web_contents = GetCurrentWebContents(); | 716 content::WebContents* web_contents = GetCurrentWebContents(); |
| 459 action->UpdateState(); | 717 action->UpdateState(); |
| 460 bool wants_to_run = action->WantsToRun(web_contents); | |
| 461 | 718 |
| 462 // The action may need to be popped in or out of overflow. | 719 if (tab_order_helper_) { |
| 463 int index = std::find(toolbar_actions_.begin(), | 720 tab_order_helper_->SetActionWantsToRun( |
| 464 toolbar_actions_.end(), | 721 action, |
| 465 action) - toolbar_actions_.begin(); | 722 SessionTabHelper::IdForTab(web_contents), |
| 466 bool reorder_necessary = false; | 723 action->WantsToRun(web_contents)); |
| 467 int tab_id = SessionTabHelper::IdForTab(web_contents); | |
| 468 if (wants_to_run && static_cast<size_t>(index) >= GetIconCount()) { | |
| 469 popped_out_in_tabs_[action].insert(tab_id); | |
| 470 reorder_necessary = true; | |
| 471 } else if (!wants_to_run && popped_out_in_tabs_[action].count(tab_id)) { | |
| 472 popped_out_in_tabs_[action].erase(tab_id); | |
| 473 reorder_necessary = true; | |
| 474 } | 724 } |
| 475 if (reorder_necessary) | |
| 476 ReorderActions(); | |
| 477 } | 725 } |
| 478 } | 726 } |
| 479 | 727 |
| 480 bool ToolbarActionsBar::ShowExtensionActionPopup( | 728 bool ToolbarActionsBar::ShowExtensionActionPopup( |
| 481 const extensions::Extension* extension, | 729 const extensions::Extension* extension, |
| 482 bool grant_active_tab) { | 730 bool grant_active_tab) { |
| 483 // Don't override another popup, and only show in the active window. | 731 // Don't override another popup, and only show in the active window. |
| 484 if (delegate_->IsPopupRunning() || !browser_->window()->IsActive()) | 732 if (delegate_->IsPopupRunning() || !browser_->window()->IsActive()) |
| 485 return false; | 733 return false; |
| 486 | 734 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 528 // We shouldn't have any actions before the model is initialized. | 776 // We shouldn't have any actions before the model is initialized. |
| 529 DCHECK(toolbar_actions_.empty()); | 777 DCHECK(toolbar_actions_.empty()); |
| 530 CreateActions(); | 778 CreateActions(); |
| 531 ResizeDelegate(gfx::Tween::EASE_OUT, false); | 779 ResizeDelegate(gfx::Tween::EASE_OUT, false); |
| 532 } | 780 } |
| 533 | 781 |
| 534 Browser* ToolbarActionsBar::GetBrowser() { | 782 Browser* ToolbarActionsBar::GetBrowser() { |
| 535 return browser_; | 783 return browser_; |
| 536 } | 784 } |
| 537 | 785 |
| 538 void ToolbarActionsBar::TabInsertedAt(content::WebContents* web_contents, | |
| 539 int index, | |
| 540 bool foreground) { | |
| 541 if (foreground) | |
| 542 ReorderActions(); | |
| 543 } | |
| 544 | |
| 545 void ToolbarActionsBar::TabDetachedAt(content::WebContents* web_contents, | |
| 546 int index) { | |
| 547 int tab_id = SessionTabHelper::IdForTab(web_contents); | |
| 548 for (auto& tabs : popped_out_in_tabs_) | |
| 549 tabs.second.erase(tab_id); | |
| 550 tabs_checked_for_pop_out_.erase(tab_id); | |
| 551 } | |
| 552 | |
| 553 void ToolbarActionsBar::TabStripModelDeleted() { | |
| 554 tab_strip_observer_.RemoveAll(); | |
| 555 } | |
| 556 | |
| 557 void ToolbarActionsBar::ReorderActions() { | 786 void ToolbarActionsBar::ReorderActions() { |
| 558 if (toolbar_actions_.empty()) | 787 if (toolbar_actions_.empty() || in_overflow_mode()) |
| 559 return; | 788 return; |
| 560 | 789 |
| 561 // First, reset the order to that of the model. Run through the views and | 790 // First, reset the order to that of the model. |
| 562 // compare them to the model; if something is out of place, find the correct | 791 auto compare = [](ToolbarActionViewController* const& action, |
| 563 // spot for it. | 792 const scoped_refptr<const extensions::Extension>& ext) { |
| 564 const extensions::ExtensionList& model_order = model_->toolbar_items(); | 793 return action->GetId() == ext->id(); |
| 565 for (int i = 0; i < static_cast<int>(model_order.size() - 1); ++i) { | 794 }; |
| 566 if (model_order[i]->id() != toolbar_actions_[i]->GetId()) { | 795 SortContainer(&toolbar_actions_.get(), model_->toolbar_items(), compare); |
| 567 // Find where the correct view is (it's guaranteed to be after our current | |
| 568 // index, since everything up to this point is correct). | |
| 569 size_t j = i + 1; | |
| 570 while (model_order[i]->id() != toolbar_actions_[j]->GetId()) | |
| 571 ++j; | |
| 572 std::swap(toolbar_actions_[i], toolbar_actions_[j]); | |
| 573 } | |
| 574 } | |
| 575 | 796 |
| 576 // Only adjust the order if the model isn't highlighting a particular subset. | 797 // Only adjust the order if the model isn't highlighting a particular |
| 577 if (!model_->is_highlighting()) { | 798 // subset (and the specialized tab order is enabled). |
| 578 // First, make sure that we've checked any actions that want to run. | 799 if (!model_->is_highlighting() && tab_order_helper_) { |
| 579 content::WebContents* web_contents = GetCurrentWebContents(); | 800 WeakToolbarActions new_order = |
| 580 int tab_id = SessionTabHelper::IdForTab(web_contents); | 801 tab_order_helper_->GetActionOrder(GetCurrentWebContents()); |
| 581 if (!tabs_checked_for_pop_out_.count(tab_id)) { | 802 auto compare = [](ToolbarActionViewController* const& first, |
| 582 tabs_checked_for_pop_out_.insert(tab_id); | 803 ToolbarActionViewController* const& second) { |
| 583 for (ToolbarActionViewController* toolbar_action : toolbar_actions_) { | 804 return first == second; |
| 584 if (toolbar_action->WantsToRun(web_contents)) | 805 }; |
| 585 popped_out_in_tabs_[toolbar_action].insert(tab_id); | 806 SortContainer( |
| 586 } | 807 &toolbar_actions_.get(), new_order, compare); |
| 587 } | |
| 588 | |
| 589 // Then, shift any actions that want to run to the front. | |
| 590 size_t insert_at = 0; | |
| 591 // Rotate any actions that want to run to the boundary between visible and | |
| 592 // overflowed actions. | |
| 593 for (ToolbarActions::iterator iter = | |
| 594 toolbar_actions_.begin() + model_->visible_icon_count(); | |
| 595 iter != toolbar_actions_.end(); ++iter) { | |
| 596 if (popped_out_in_tabs_[(*iter)].count(tab_id)) { | |
| 597 std::rotate(toolbar_actions_.begin() + insert_at, iter, iter + 1); | |
| 598 ++insert_at; | |
| 599 } | |
| 600 } | |
| 601 } | 808 } |
| 602 | 809 |
| 603 // Our visible browser actions may have changed - re-Layout() and check the | 810 // Our visible browser actions may have changed - re-Layout() and check the |
| 604 // size (if we aren't suppressing the layout). | 811 // size (if we aren't suppressing the layout). |
| 605 if (!suppress_layout_) { | 812 if (!suppress_layout_) { |
| 606 ResizeDelegate(gfx::Tween::EASE_OUT, false); | 813 ResizeDelegate(gfx::Tween::EASE_OUT, false); |
| 607 delegate_->Redraw(true); | 814 delegate_->Redraw(true); |
| 608 } | 815 } |
| 816 | |
| 817 if (overflow_bar_) | |
| 818 overflow_bar_->CopyActionOrder(); | |
| 819 } | |
| 820 | |
| 821 void ToolbarActionsBar::CopyActionOrder() { | |
| 822 DCHECK(in_overflow_mode()); | |
| 823 if (!main_bar_->toolbar_actions().empty()) { | |
| 824 auto compare = [](ToolbarActionViewController* const& first, | |
| 825 ToolbarActionViewController* const& second) { | |
| 826 return first->GetId() == second->GetId(); | |
| 827 }; | |
| 828 SortContainer( | |
| 829 &toolbar_actions_.get(), main_bar_->toolbar_actions(), compare); | |
| 830 if (!suppress_layout_) { | |
| 831 ResizeDelegate(gfx::Tween::EASE_OUT, false); | |
| 832 delegate_->Redraw(true); | |
| 833 } | |
| 834 } | |
| 609 } | 835 } |
| 610 | 836 |
| 611 ToolbarActionViewController* ToolbarActionsBar::GetActionForId( | 837 ToolbarActionViewController* ToolbarActionsBar::GetActionForId( |
| 612 const std::string& id) { | 838 const std::string& id) { |
| 613 for (ToolbarActionViewController* action : toolbar_actions_) { | 839 for (ToolbarActionViewController* action : toolbar_actions_) { |
| 614 if (action->GetId() == id) | 840 if (action->GetId() == id) |
| 615 return action; | 841 return action; |
| 616 } | 842 } |
| 617 return nullptr; | 843 return nullptr; |
| 618 } | 844 } |
| 619 | 845 |
| 620 content::WebContents* ToolbarActionsBar::GetCurrentWebContents() { | 846 content::WebContents* ToolbarActionsBar::GetCurrentWebContents() { |
| 621 return browser_->tab_strip_model()->GetActiveWebContents(); | 847 return browser_->tab_strip_model()->GetActiveWebContents(); |
| 622 } | 848 } |
| OLD | NEW |