1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/views/infobars/confirm_infobar.h"
6
7#include "base/logging.h"
8#include "chrome/browser/ui/views/elevation_icon_setter.h"
9#include "components/infobars/core/confirm_infobar_delegate.h"
10#include "ui/base/window_open_disposition.h"
11#include "ui/views/controls/button/label_button.h"
12#include "ui/views/controls/label.h"
13#include "ui/views/controls/link.h"
14
15
16// ConfirmInfoBarDelegate -----------------------------------------------------
17
18// static
19scoped_ptr<infobars::InfoBar> ConfirmInfoBarDelegate::CreateInfoBar(
20    scoped_ptr<ConfirmInfoBarDelegate> delegate) {
21  return scoped_ptr<infobars::InfoBar>(new ConfirmInfoBar(delegate.Pass()));
22}
23
24
25// ConfirmInfoBar -------------------------------------------------------------
26
27ConfirmInfoBar::ConfirmInfoBar(scoped_ptr<ConfirmInfoBarDelegate> delegate)
28    : InfoBarView(delegate.PassAs<infobars::InfoBarDelegate>()),
29      label_(NULL),
30      ok_button_(NULL),
31      cancel_button_(NULL),
32      link_(NULL) {
33}
34
35ConfirmInfoBar::~ConfirmInfoBar() {
36  // Ensure |elevation_icon_setter_| is destroyed before |ok_button_|.
37  elevation_icon_setter_.reset();
38}
39
40void ConfirmInfoBar::Layout() {
41  InfoBarView::Layout();
42
43  int x = StartX();
44  Labels labels;
45  labels.push_back(label_);
46  labels.push_back(link_);
47  AssignWidths(&labels, std::max(0, EndX() - x - NonLabelWidth()));
48
49  label_->SetPosition(gfx::Point(x, OffsetY(label_)));
50  if (!label_->text().empty())
51    x = label_->bounds().right() + kEndOfLabelSpacing;
52
53  if (ok_button_) {
54    ok_button_->SetPosition(gfx::Point(x, OffsetY(ok_button_)));
55    x = ok_button_->bounds().right() + kButtonButtonSpacing;
56  }
57
58  if (cancel_button_)
59    cancel_button_->SetPosition(gfx::Point(x, OffsetY(cancel_button_)));
60
61  link_->SetPosition(gfx::Point(EndX() - link_->width(), OffsetY(link_)));
62}
63
64void ConfirmInfoBar::ViewHierarchyChanged(
65    const ViewHierarchyChangedDetails& details) {
66  if (details.is_add && details.child == this && (label_ == NULL)) {
67    ConfirmInfoBarDelegate* delegate = GetDelegate();
68    label_ = CreateLabel(delegate->GetMessageText());
69    AddChildView(label_);
70
71    if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) {
72      ok_button_ = CreateLabelButton(
73          this, delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK));
74      if (delegate->OKButtonTriggersUACPrompt())
75        elevation_icon_setter_.reset(new ElevationIconSetter(ok_button_));
76      AddChildView(ok_button_);
77    }
78
79    if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
80      cancel_button_ = CreateLabelButton(
81          this,
82          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL));
83      AddChildView(cancel_button_);
84    }
85
86    base::string16 link_text(delegate->GetLinkText());
87    link_ = CreateLink(link_text, this);
88    AddChildView(link_);
89  }
90
91  // This must happen after adding all other children so InfoBarView can ensure
92  // the close button is the last child.
93  InfoBarView::ViewHierarchyChanged(details);
94}
95
96void ConfirmInfoBar::ButtonPressed(views::Button* sender,
97                                   const ui::Event& event) {
98  if (!owner())
99    return;  // We're closing; don't call anything, it might access the owner.
100  ConfirmInfoBarDelegate* delegate = GetDelegate();
101  if ((ok_button_ != NULL) && sender == ok_button_) {
102    if (delegate->Accept())
103      RemoveSelf();
104  } else if ((cancel_button_ != NULL) && (sender == cancel_button_)) {
105    if (delegate->Cancel())
106      RemoveSelf();
107  } else {
108    InfoBarView::ButtonPressed(sender, event);
109  }
110}
111
112int ConfirmInfoBar::ContentMinimumWidth() const {
113  return label_->GetMinimumSize().width() + link_->GetMinimumSize().width() +
114      NonLabelWidth();
115}
116
117void ConfirmInfoBar::LinkClicked(views::Link* source, int event_flags) {
118  if (!owner())
119    return;  // We're closing; don't call anything, it might access the owner.
120  DCHECK_EQ(link_, source);
121  if (GetDelegate()->LinkClicked(ui::DispositionFromEventFlags(event_flags)))
122    RemoveSelf();
123}
124
125ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() {
126  return delegate()->AsConfirmInfoBarDelegate();
127}
128
129int ConfirmInfoBar::NonLabelWidth() const {
130  int width = (label_->text().empty() || (!ok_button_ && !cancel_button_)) ?
131      0 : kEndOfLabelSpacing;
132  if (ok_button_)
133    width += ok_button_->width() + (cancel_button_ ? kButtonButtonSpacing : 0);
134  width += (cancel_button_ ? cancel_button_->width() : 0);
135  return width + ((link_->text().empty() || !width) ? 0 : kEndOfLabelSpacing);
136}
137