blob: ac92a428b466084e5c29bfb253bf90bb98d06dbe [file] [log] [blame]
// Copyright (c) 2012 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/infobars/confirm_infobar.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/elevation_icon_setter.h"
#include "ui/base/window_open_disposition.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/link.h"
#include "ui/views/view_class_properties.h"
// InfoBarService -------------------------------------------------------------
std::unique_ptr<infobars::InfoBar> InfoBarService::CreateConfirmInfoBar(
std::unique_ptr<ConfirmInfoBarDelegate> delegate) {
return std::make_unique<ConfirmInfoBar>(std::move(delegate));
}
// ConfirmInfoBar -------------------------------------------------------------
ConfirmInfoBar::ConfirmInfoBar(std::unique_ptr<ConfirmInfoBarDelegate> delegate)
: InfoBarView(std::move(delegate)) {
auto* delegate_ptr = GetDelegate();
label_ = CreateLabel(delegate_ptr->GetMessageText());
label_->SetElideBehavior(delegate_ptr->GetMessageElideBehavior());
AddChildView(label_);
const auto buttons = delegate_ptr->GetButtons();
if (buttons & ConfirmInfoBarDelegate::BUTTON_OK) {
ok_button_ = CreateButton(ConfirmInfoBarDelegate::BUTTON_OK);
ok_button_->SetProminent(true);
if (delegate_ptr->OKButtonTriggersUACPrompt()) {
elevation_icon_setter_.reset(new ElevationIconSetter(
ok_button_,
base::BindOnce(&ConfirmInfoBar::Layout, base::Unretained(this))));
}
}
if (buttons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
cancel_button_ = CreateButton(ConfirmInfoBarDelegate::BUTTON_CANCEL);
if (buttons == ConfirmInfoBarDelegate::BUTTON_CANCEL)
cancel_button_->SetProminent(true);
}
link_ = CreateLink(delegate_ptr->GetLinkText(), this);
AddChildView(link_);
}
ConfirmInfoBar::~ConfirmInfoBar() {
// Ensure |elevation_icon_setter_| is destroyed before |ok_button_|.
elevation_icon_setter_.reset();
}
void ConfirmInfoBar::Layout() {
InfoBarView::Layout();
int x = StartX();
Labels labels;
labels.push_back(label_);
labels.push_back(link_);
AssignWidths(&labels, std::max(0, EndX() - x - NonLabelWidth()));
ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get();
label_->SetPosition(gfx::Point(x, OffsetY(label_)));
if (!label_->text().empty())
x = label_->bounds().right() +
layout_provider->GetDistanceMetric(
views::DISTANCE_RELATED_LABEL_HORIZONTAL);
if (ok_button_) {
ok_button_->SetPosition(gfx::Point(x, OffsetY(ok_button_)));
x = ok_button_->bounds().right() +
layout_provider->GetDistanceMetric(
views::DISTANCE_RELATED_BUTTON_HORIZONTAL);
}
if (cancel_button_)
cancel_button_->SetPosition(gfx::Point(x, OffsetY(cancel_button_)));
link_->SetPosition(gfx::Point(EndX() - link_->width(), OffsetY(link_)));
}
void ConfirmInfoBar::ButtonPressed(views::Button* sender,
const ui::Event& event) {
if (!owner())
return; // We're closing; don't call anything, it might access the owner.
ConfirmInfoBarDelegate* delegate = GetDelegate();
if (sender == ok_button_) {
if (delegate->Accept())
RemoveSelf();
} else if (sender == cancel_button_) {
if (delegate->Cancel())
RemoveSelf();
} else {
InfoBarView::ButtonPressed(sender, event);
}
}
int ConfirmInfoBar::ContentMinimumWidth() const {
return label_->GetMinimumSize().width() + link_->GetMinimumSize().width() +
NonLabelWidth();
}
void ConfirmInfoBar::LinkClicked(views::Link* source, int event_flags) {
if (!owner())
return; // We're closing; don't call anything, it might access the owner.
DCHECK_EQ(link_, source);
if (GetDelegate()->LinkClicked(ui::DispositionFromEventFlags(event_flags)))
RemoveSelf();
}
ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() {
return delegate()->AsConfirmInfoBarDelegate();
}
views::MdTextButton* ConfirmInfoBar::CreateButton(
ConfirmInfoBarDelegate::InfoBarButton type) {
auto* button =
views::MdTextButton::Create(this, GetDelegate()->GetButtonLabel(type));
button->SetProperty(
views::kMarginsKey,
new gfx::Insets(ChromeLayoutProvider::Get()->GetDistanceMetric(
DISTANCE_TOAST_CONTROL_VERTICAL),
0));
AddChildView(button);
button->SizeToPreferredSize();
return button;
}
int ConfirmInfoBar::NonLabelWidth() const {
ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get();
const int label_spacing = layout_provider->GetDistanceMetric(
views::DISTANCE_RELATED_LABEL_HORIZONTAL);
const int button_spacing = layout_provider->GetDistanceMetric(
views::DISTANCE_RELATED_BUTTON_HORIZONTAL);
int width = (label_->text().empty() || (!ok_button_ && !cancel_button_))
? 0
: label_spacing;
if (ok_button_)
width += ok_button_->width() + (cancel_button_ ? button_spacing : 0);
width += cancel_button_ ? cancel_button_->width() : 0;
return width + ((link_->text().empty() || !width) ? 0 : label_spacing);
}