1// Copyright (c) 2011 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 "chrome/browser/tab_contents/confirm_infobar_delegate.h"
8#include "chrome/browser/ui/views/event_utils.h"
9#include "views/controls/button/text_button.h"
10#include "views/controls/label.h"
11
12// ConfirmInfoBarDelegate -----------------------------------------------------
13
14InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
15  return new ConfirmInfoBar(this);
16}
17
18// ConfirmInfoBar -------------------------------------------------------------
19
20ConfirmInfoBar::ConfirmInfoBar(ConfirmInfoBarDelegate* delegate)
21    : InfoBarView(delegate),
22      label_(NULL),
23      ok_button_(NULL),
24      cancel_button_(NULL),
25      link_(NULL) {
26}
27
28ConfirmInfoBar::~ConfirmInfoBar() {
29}
30
31void ConfirmInfoBar::Layout() {
32  InfoBarView::Layout();
33
34  int available_width = std::max(0, EndX() - StartX() - ContentMinimumWidth());
35  gfx::Size label_size = label_->GetPreferredSize();
36  label_->SetBounds(StartX(), OffsetY(label_size),
37      std::min(label_size.width(), available_width), label_size.height());
38  available_width = std::max(0, available_width - label_size.width());
39
40  int button_x = label_->bounds().right() + kEndOfLabelSpacing;
41  if (ok_button_ != NULL) {
42    gfx::Size ok_size = ok_button_->GetPreferredSize();
43    ok_button_->SetBounds(button_x, OffsetY(ok_size), ok_size.width(),
44                          ok_size.height());
45    button_x += ok_size.width() + kButtonButtonSpacing;
46  }
47
48  if (cancel_button_ != NULL) {
49    gfx::Size cancel_size = cancel_button_->GetPreferredSize();
50    cancel_button_->SetBounds(button_x, OffsetY(cancel_size),
51                              cancel_size.width(), cancel_size.height());
52  }
53
54  if (link_ != NULL) {
55    gfx::Size link_size = link_->GetPreferredSize();
56    int link_width = std::min(link_size.width(), available_width);
57    link_->SetBounds(EndX() - link_width, OffsetY(link_size), link_width,
58                     link_size.height());
59  }
60}
61
62void ConfirmInfoBar::ViewHierarchyChanged(bool is_add,
63                                          View* parent,
64                                          View* child) {
65  if (is_add && child == this && (label_ == NULL)) {
66    ConfirmInfoBarDelegate* delegate = GetDelegate();
67    label_ = CreateLabel(delegate->GetMessageText());
68    AddChildView(label_);
69
70    if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) {
71      ok_button_ = CreateTextButton(this,
72          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK),
73          delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_OK));
74      AddChildView(ok_button_);
75    }
76
77    if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
78      cancel_button_ = CreateTextButton(this,
79          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL),
80          delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_CANCEL));
81      AddChildView(cancel_button_);
82    }
83
84    string16 link_text(delegate->GetLinkText());
85    if (!link_text.empty()) {
86      link_ = CreateLink(link_text, this, background()->get_color());
87      AddChildView(link_);
88    }
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(is_add, parent, child);
94}
95
96void ConfirmInfoBar::ButtonPressed(views::Button* sender,
97                                   const views::Event& event) {
98  ConfirmInfoBarDelegate* delegate = GetDelegate();
99  if ((ok_button_ != NULL) && sender == ok_button_) {
100    if (delegate->Accept())
101      RemoveInfoBar();
102  } else if ((cancel_button_ != NULL) && (sender == cancel_button_)) {
103    if (delegate->Cancel())
104      RemoveInfoBar();
105  } else {
106    InfoBarView::ButtonPressed(sender, event);
107  }
108}
109
110int ConfirmInfoBar::ContentMinimumWidth() const {
111  int width = (link_ == NULL) ? 0 : kEndOfLabelSpacing;  // Space before link
112  int before_cancel_spacing = kEndOfLabelSpacing;
113  if (ok_button_ != NULL) {
114    width += kEndOfLabelSpacing + ok_button_->GetPreferredSize().width();
115    before_cancel_spacing = kButtonButtonSpacing;
116  }
117  return width + ((cancel_button_ == NULL) ? 0 :
118      (before_cancel_spacing + cancel_button_->GetPreferredSize().width()));
119}
120
121void ConfirmInfoBar::LinkActivated(views::Link* source, int event_flags) {
122  DCHECK(link_ != NULL);
123  DCHECK_EQ(link_, source);
124  if (GetDelegate()->LinkClicked(
125      event_utils::DispositionFromEventFlags(event_flags)))
126    RemoveInfoBar();
127}
128
129ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() {
130  return delegate()->AsConfirmInfoBarDelegate();
131}
132