| 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 "base/profiler/scoped_tracker.h" | 8 #include "base/profiler/scoped_tracker.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_message_bubble_controller.h" | 10 #include "chrome/browser/extensions/extension_message_bubble_controller.h" |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 browser_(browser), | 118 browser_(browser), |
| 119 model_(extensions::ExtensionToolbarModel::Get(browser_->profile())), | 119 model_(extensions::ExtensionToolbarModel::Get(browser_->profile())), |
| 120 main_bar_(main_bar), | 120 main_bar_(main_bar), |
| 121 platform_settings_(main_bar != nullptr), | 121 platform_settings_(main_bar != nullptr), |
| 122 popup_owner_(nullptr), | 122 popup_owner_(nullptr), |
| 123 model_observer_(this), | 123 model_observer_(this), |
| 124 suppress_layout_(false), | 124 suppress_layout_(false), |
| 125 suppress_animation_(true), | 125 suppress_animation_(true), |
| 126 overflowed_action_wants_to_run_(false), | 126 overflowed_action_wants_to_run_(false), |
| 127 checked_extension_bubble_(false), | 127 checked_extension_bubble_(false), |
| 128 popped_out_action_(nullptr), |
| 128 weak_ptr_factory_(this) { | 129 weak_ptr_factory_(this) { |
| 129 if (model_) // |model_| can be null in unittests. | 130 if (model_) // |model_| can be null in unittests. |
| 130 model_observer_.Add(model_); | 131 model_observer_.Add(model_); |
| 131 } | 132 } |
| 132 | 133 |
| 133 ToolbarActionsBar::~ToolbarActionsBar() { | 134 ToolbarActionsBar::~ToolbarActionsBar() { |
| 134 // We don't just call DeleteActions() here because it makes assumptions about | 135 // We don't just call DeleteActions() here because it makes assumptions about |
| 135 // the order of deletion between the views and the ToolbarActionsBar. | 136 // the order of deletion between the views and the ToolbarActionsBar. |
| 136 DCHECK(toolbar_actions_.empty()) << | 137 DCHECK(toolbar_actions_.empty()) << |
| 137 "Must call DeleteActions() before destruction."; | 138 "Must call DeleteActions() before destruction."; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 // Now we add an extra between-item padding value so the space can be divided | 224 // Now we add an extra between-item padding value so the space can be divided |
| 224 // evenly by (size of icon with padding). | 225 // evenly by (size of icon with padding). |
| 225 return static_cast<size_t>(std::max( | 226 return static_cast<size_t>(std::max( |
| 226 0, available_space + platform_settings_.item_spacing) / IconWidth(true)); | 227 0, available_space + platform_settings_.item_spacing) / IconWidth(true)); |
| 227 } | 228 } |
| 228 | 229 |
| 229 size_t ToolbarActionsBar::GetIconCount() const { | 230 size_t ToolbarActionsBar::GetIconCount() const { |
| 230 if (!model_) | 231 if (!model_) |
| 231 return 0u; | 232 return 0u; |
| 232 | 233 |
| 234 // We purposefully do not account for any "popped out" actions in overflow |
| 235 // mode. This is because the popup cannot be showing while the overflow menu |
| 236 // is open, so there's no concern there. Also, if the user has a popped out |
| 237 // action, and immediately opens the overflow menu, we *want* the action there |
| 238 // (since it will close the popup, but do so asynchronously, and we don't |
| 239 // want to "slide" the action back in. |
| 233 size_t visible_icons = in_overflow_mode() ? | 240 size_t visible_icons = in_overflow_mode() ? |
| 234 toolbar_actions_.size() - main_bar_->GetIconCount() : | 241 toolbar_actions_.size() - model_->visible_icon_count() : |
| 235 model_->visible_icon_count(); | 242 model_->visible_icon_count() + (popped_out_action_ ? 1 : 0); |
| 236 | 243 |
| 237 #if DCHECK_IS_ON() | 244 #if DCHECK_IS_ON() |
| 238 // Good time for some sanity checks: We should never try to display more | 245 // Good time for some sanity checks: We should never try to display more |
| 239 // icons than we have, and we should always have a view per item in the model. | 246 // icons than we have, and we should always have a view per item in the model. |
| 240 // (The only exception is if this is in initialization.) | 247 // (The only exception is if this is in initialization.) |
| 241 if (!toolbar_actions_.empty() && !suppress_layout_ && | 248 if (!toolbar_actions_.empty() && !suppress_layout_ && |
| 242 model_->extensions_initialized()) { | 249 model_->extensions_initialized()) { |
| 243 size_t num_extension_actions = 0u; | 250 size_t num_extension_actions = 0u; |
| 244 for (ToolbarActionViewController* action : toolbar_actions_) { | 251 for (ToolbarActionViewController* action : toolbar_actions_) { |
| 245 // No component action should ever have a valid extension id, so we can | 252 // No component action should ever have a valid extension id, so we can |
| 246 // use this to check the extension amount. | 253 // use this to check the extension amount. |
| 247 if (crx_file::id_util::IdIsValid(action->GetId())) | 254 if (crx_file::id_util::IdIsValid(action->GetId())) |
| 248 ++num_extension_actions; | 255 ++num_extension_actions; |
| 249 } | 256 } |
| 250 | 257 |
| 251 int num_component_actions = | 258 int num_component_actions = |
| 252 ComponentToolbarActionsFactory::GetInstance()-> | 259 ComponentToolbarActionsFactory::GetInstance()-> |
| 253 GetNumComponentActions(); | 260 GetNumComponentActions(); |
| 254 size_t num_total_actions = num_extension_actions + num_component_actions; | 261 size_t num_total_actions = num_extension_actions + num_component_actions; |
| 255 | 262 |
| 256 DCHECK_LE(visible_icons, num_total_actions); | 263 DCHECK_LE(visible_icons, num_total_actions); |
| 257 DCHECK_EQ(model_->toolbar_items().size(), num_extension_actions); | 264 DCHECK_EQ(model_->toolbar_items().size(), num_extension_actions); |
| 258 } | 265 } |
| 259 #endif | 266 #endif |
| 260 | 267 |
| 261 return visible_icons; | 268 return visible_icons; |
| 262 } | 269 } |
| 263 | 270 |
| 271 std::vector<ToolbarActionViewController*> |
| 272 ToolbarActionsBar::GetActions() const { |
| 273 std::vector<ToolbarActionViewController*> actions = toolbar_actions_.get(); |
| 274 |
| 275 // If there is an action that should be popped out, and it's not visible by |
| 276 // default, make it the final action in the list. |
| 277 if (popped_out_action_) { |
| 278 size_t index = |
| 279 std::find(actions.begin(), actions.end(), popped_out_action_) - |
| 280 actions.begin(); |
| 281 DCHECK_NE(actions.size(), index); |
| 282 size_t visible = GetIconCount(); |
| 283 if (index >= visible) { |
| 284 size_t rindex = actions.size() - index - 1; |
| 285 std::rotate(actions.rbegin() + rindex, |
| 286 actions.rbegin() + rindex + 1, |
| 287 actions.rend() - visible + 1); |
| 288 } |
| 289 } |
| 290 |
| 291 return actions; |
| 292 } |
| 293 |
| 264 void ToolbarActionsBar::CreateActions() { | 294 void ToolbarActionsBar::CreateActions() { |
| 265 DCHECK(toolbar_actions_.empty()); | 295 DCHECK(toolbar_actions_.empty()); |
| 266 // We wait for the extension system to be initialized before we add any | 296 // We wait for the extension system to be initialized before we add any |
| 267 // actions, as they rely on the extension system to function. | 297 // actions, as they rely on the extension system to function. |
| 268 if (!model_ || !model_->extensions_initialized()) | 298 if (!model_ || !model_->extensions_initialized()) |
| 269 return; | 299 return; |
| 270 | 300 |
| 271 { | 301 { |
| 272 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/463337 | 302 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/463337 |
| 273 // is fixed. | 303 // is fixed. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 if (drag_type == DRAG_TO_OVERFLOW) | 419 if (drag_type == DRAG_TO_OVERFLOW) |
| 390 delta = -1; | 420 delta = -1; |
| 391 else if (drag_type == DRAG_TO_MAIN) | 421 else if (drag_type == DRAG_TO_MAIN) |
| 392 delta = 1; | 422 delta = 1; |
| 393 model_->MoveExtensionIcon(toolbar_actions_[dragged_index]->GetId(), | 423 model_->MoveExtensionIcon(toolbar_actions_[dragged_index]->GetId(), |
| 394 dropped_index); | 424 dropped_index); |
| 395 if (delta) | 425 if (delta) |
| 396 model_->SetVisibleIconCount(model_->visible_icon_count() + delta); | 426 model_->SetVisibleIconCount(model_->visible_icon_count() + delta); |
| 397 } | 427 } |
| 398 | 428 |
| 429 void ToolbarActionsBar::OnAnimationEnded() { |
| 430 // Check if we were waiting for animation to finish to run a popup. |
| 431 if (!popped_out_closure_.is_null()) { |
| 432 popped_out_closure_.Run(); |
| 433 popped_out_closure_.Reset(); |
| 434 } |
| 435 } |
| 436 |
| 437 bool ToolbarActionsBar::IsActionVisible( |
| 438 const ToolbarActionViewController* action) const { |
| 439 size_t index = std::find(toolbar_actions_.begin(), |
| 440 toolbar_actions_.end(), |
| 441 action) - toolbar_actions_.begin(); |
| 442 return index < GetIconCount() || action == popped_out_action_; |
| 443 } |
| 444 |
| 445 void ToolbarActionsBar::PopOutAction(ToolbarActionViewController* controller, |
| 446 const base::Closure& closure) { |
| 447 bool needs_redraw = !IsActionVisible(controller); |
| 448 popped_out_action_ = controller; |
| 449 if (needs_redraw) { |
| 450 // We suppress animation for this draw, because we need the action to get |
| 451 // into position immediately, since it's about to show its popup. |
| 452 base::AutoReset<bool> layout_resetter(&suppress_animation_, false); |
| 453 delegate_->Redraw(true); |
| 454 } |
| 455 |
| 456 ResizeDelegate(gfx::Tween::LINEAR, false); |
| 457 if (!delegate_->IsAnimating()) { |
| 458 // Don't call the closure re-entrantly. |
| 459 base::MessageLoop::current()->PostTask(FROM_HERE, closure); |
| 460 } else { |
| 461 popped_out_closure_ = closure; |
| 462 } |
| 463 } |
| 464 |
| 465 void ToolbarActionsBar::PopInAction() { |
| 466 DCHECK(popped_out_action_); |
| 467 popped_out_action_ = nullptr; |
| 468 popped_out_closure_.Reset(); |
| 469 delegate_->Redraw(true); |
| 470 ResizeDelegate(gfx::Tween::LINEAR, false); |
| 471 } |
| 472 |
| 399 void ToolbarActionsBar::SetPopupOwner( | 473 void ToolbarActionsBar::SetPopupOwner( |
| 400 ToolbarActionViewController* popup_owner) { | 474 ToolbarActionViewController* popup_owner) { |
| 401 // We should never be setting a popup owner when one already exists, and | 475 // We should never be setting a popup owner when one already exists, and |
| 402 // never unsetting one when one wasn't set. | 476 // never unsetting one when one wasn't set. |
| 403 DCHECK((!popup_owner_ && popup_owner) || | 477 DCHECK((!popup_owner_ && popup_owner) || |
| 404 (popup_owner_ && !popup_owner)); | 478 (popup_owner_ && !popup_owner)); |
| 405 popup_owner_ = popup_owner; | 479 popup_owner_ = popup_owner; |
| 406 } | 480 } |
| 407 | 481 |
| 408 void ToolbarActionsBar::HideActivePopup() { | 482 void ToolbarActionsBar::HideActivePopup() { |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 for (ToolbarActionViewController* action : toolbar_actions_) { | 705 for (ToolbarActionViewController* action : toolbar_actions_) { |
| 632 if (action->GetId() == id) | 706 if (action->GetId() == id) |
| 633 return action; | 707 return action; |
| 634 } | 708 } |
| 635 return nullptr; | 709 return nullptr; |
| 636 } | 710 } |
| 637 | 711 |
| 638 content::WebContents* ToolbarActionsBar::GetCurrentWebContents() { | 712 content::WebContents* ToolbarActionsBar::GetCurrentWebContents() { |
| 639 return browser_->tab_strip_model()->GetActiveWebContents(); | 713 return browser_->tab_strip_model()->GetActiveWebContents(); |
| 640 } | 714 } |
| OLD | NEW |