blob: 3a42b08842b8dfbc8310c9c4b188eb8174eda472 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_view.h"
#include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h"
ExtensionsToolbarContainer::ExtensionsToolbarContainer(Browser* browser)
: ToolbarIconContainerView(/*uses_highlight=*/true),
browser_(browser),
model_(ToolbarActionsModel::Get(browser_->profile())),
model_observer_(this),
extensions_button_(new ExtensionsToolbarButton(browser_, this)) {
model_observer_.Add(model_);
AddMainView(extensions_button_);
CreateActions();
}
ExtensionsToolbarContainer::~ExtensionsToolbarContainer() = default;
void ExtensionsToolbarContainer::UpdateAllIcons() {
extensions_button_->UpdateIcon();
}
ToolbarActionViewController* ExtensionsToolbarContainer::GetActionForId(
const std::string& action_id) {
for (const auto& action : actions_) {
if (action->GetId() == action_id)
return action.get();
}
return nullptr;
}
ToolbarActionViewController* ExtensionsToolbarContainer::GetPoppedOutAction()
const {
return popped_out_action_;
}
bool ExtensionsToolbarContainer::IsActionVisibleOnToolbar(
const ToolbarActionViewController* action) const {
return false;
}
void ExtensionsToolbarContainer::UndoPopOut() {
DCHECK(popped_out_action_);
ToolbarActionViewController* const popped_out_action = popped_out_action_;
popped_out_action_ = nullptr;
// Note that we only hide this view if it was not pinned while being popped
// out.
icons_[popped_out_action->GetId()]->SetVisible(
IsActionVisibleOnToolbar(popped_out_action));
}
void ExtensionsToolbarContainer::SetPopupOwner(
ToolbarActionViewController* popup_owner) {
// We should never be setting a popup owner when one already exists, and
// never unsetting one when one wasn't set.
DCHECK((popup_owner_ != nullptr) ^ (popup_owner != nullptr));
popup_owner_ = popup_owner;
}
void ExtensionsToolbarContainer::HideActivePopup() {
if (popup_owner_)
popup_owner_->HidePopup();
DCHECK(!popup_owner_);
}
bool ExtensionsToolbarContainer::CloseOverflowMenuIfOpen() {
if (ExtensionsMenuView::IsShowing()) {
ExtensionsMenuView::Hide();
return true;
}
return false;
}
void ExtensionsToolbarContainer::PopOutAction(
ToolbarActionViewController* action,
bool is_sticky,
const base::Closure& closure) {
// TODO(pbos): Animate popout.
// TODO(pbos): Highlight popout differently.
DCHECK(!popped_out_action_);
popped_out_action_ = action;
icons_[popped_out_action_->GetId()]->SetVisible(true);
ReorderViews();
closure.Run();
}
void ExtensionsToolbarContainer::OnToolbarActionAdded(
const ToolbarActionsModel::ActionId& action_id,
int index) {
CreateActionForId(action_id);
ReorderViews();
}
void ExtensionsToolbarContainer::OnToolbarActionRemoved(
const ToolbarActionsModel::ActionId& action_id) {
// TODO(pbos): Handle extension upgrades, see ToolbarActionsBar. Arguably this
// could be handled inside the model and be invisible to the container when
// permissions are unchanged.
// Delete the icon first so it unregisters it from the action.
icons_.erase(action_id);
base::EraseIf(
actions_,
[action_id](const std::unique_ptr<ToolbarActionViewController>& item) {
return item->GetId() == action_id;
});
}
void ExtensionsToolbarContainer::OnToolbarActionMoved(
const ToolbarActionsModel::ActionId& action_id,
int index) {}
void ExtensionsToolbarContainer::OnToolbarActionLoadFailed() {}
void ExtensionsToolbarContainer::OnToolbarActionUpdated(
const ToolbarActionsModel::ActionId& action_id) {
ToolbarActionViewController* action = GetActionForId(action_id);
if (action)
action->UpdateState();
}
void ExtensionsToolbarContainer::OnToolbarVisibleCountChanged() {}
void ExtensionsToolbarContainer::OnToolbarHighlightModeChanged(
bool is_highlighting) {}
void ExtensionsToolbarContainer::OnToolbarModelInitialized() {
CreateActions();
}
void ExtensionsToolbarContainer::ReorderViews() {
// TODO(pbos): Reorder pinned actions here once they exist.
// Popped out actions should be at the end.
if (popped_out_action_)
ReorderChildView(icons_[popped_out_action_->GetId()].get(), -1);
// The extension button is always last.
ReorderChildView(extensions_button_, -1);
}
void ExtensionsToolbarContainer::CreateActions() {
DCHECK(icons_.empty());
DCHECK(actions_.empty());
// If the model isn't initialized, wait for it.
if (!model_->actions_initialized())
return;
for (auto& action_id : model_->action_ids())
CreateActionForId(action_id);
ReorderViews();
}
void ExtensionsToolbarContainer::CreateActionForId(
const ToolbarActionsModel::ActionId& action_id) {
actions_.push_back(
model_->CreateActionForId(browser_, this, false, action_id));
auto icon = std::make_unique<ToolbarActionView>(actions_.back().get(), this);
icon->set_owned_by_client();
icon->SetVisible(IsActionVisibleOnToolbar(actions_.back().get()));
AddChildView(icon.get());
icons_[action_id] = std::move(icon);
}
content::WebContents* ExtensionsToolbarContainer::GetCurrentWebContents() {
return browser_->tab_strip_model()->GetActiveWebContents();
}
bool ExtensionsToolbarContainer::ShownInsideMenu() const {
return false;
}
void ExtensionsToolbarContainer::OnToolbarActionViewDragDone() {}
views::LabelButton* ExtensionsToolbarContainer::GetOverflowReferenceView() {
return extensions_button_;
}
gfx::Size ExtensionsToolbarContainer::GetToolbarActionSize() {
gfx::Rect rect(gfx::Size(28, 28));
rect.Inset(-GetLayoutInsets(TOOLBAR_ACTION_VIEW));
return rect.size();
}
void ExtensionsToolbarContainer::WriteDragDataForView(
View* sender,
const gfx::Point& press_pt,
ui::OSExchangeData* data) {}
int ExtensionsToolbarContainer::GetDragOperationsForView(View* sender,
const gfx::Point& p) {
return ui::DragDropTypes::DRAG_MOVE;
}
bool ExtensionsToolbarContainer::CanStartDragForView(View* sender,
const gfx::Point& press_pt,
const gfx::Point& p) {
// TODO(pbos): Implement
return false;
}