confirm_infobar.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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/infobars/confirm_infobar_delegate.h"
9#include "ui/base/window_open_disposition.h"
10#include "ui/views/controls/button/label_button.h"
11#include "ui/views/controls/label.h"
12#include "ui/views/controls/link.h"
13
14
15// ConfirmInfoBarDelegate -----------------------------------------------------
16
17// static
18scoped_ptr<InfoBar> ConfirmInfoBarDelegate::CreateInfoBar(
19    scoped_ptr<ConfirmInfoBarDelegate> delegate) {
20  return scoped_ptr<InfoBar>(new ConfirmInfoBar(delegate.Pass()));
21}
22
23
24// ConfirmInfoBar -------------------------------------------------------------
25
26ConfirmInfoBar::ConfirmInfoBar(scoped_ptr<ConfirmInfoBarDelegate> delegate)
27    : InfoBarView(delegate.PassAs<InfoBarDelegate>()),
28      label_(NULL),
29      ok_button_(NULL),
30      cancel_button_(NULL),
31      link_(NULL) {
32}
33
34ConfirmInfoBar::~ConfirmInfoBar() {
35}
36
37void ConfirmInfoBar::Layout() {
38  InfoBarView::Layout();
39
40  int available_width = std::max(0, EndX() - StartX() - ContentMinimumWidth());
41  gfx::Size label_size = label_->GetPreferredSize();
42  label_->SetBounds(StartX(), OffsetY(label_size),
43      std::min(label_size.width(), available_width), label_size.height());
44  available_width = std::max(0, available_width - label_size.width());
45
46  int button_x = label_->bounds().right() + kEndOfLabelSpacing;
47  if (ok_button_ != NULL) {
48    gfx::Size ok_size = ok_button_->GetPreferredSize();
49    ok_button_->SetBounds(button_x, OffsetY(ok_size), ok_size.width(),
50                          ok_size.height());
51    button_x += ok_size.width() + kButtonButtonSpacing;
52  }
53
54  if (cancel_button_ != NULL) {
55    gfx::Size cancel_size = cancel_button_->GetPreferredSize();
56    cancel_button_->SetBounds(button_x, OffsetY(cancel_size),
57                              cancel_size.width(), cancel_size.height());
58  }
59
60  if (link_ != NULL) {
61    gfx::Size link_size = link_->GetPreferredSize();
62    int link_width = std::min(link_size.width(), available_width);
63    link_->SetBounds(EndX() - link_width, OffsetY(link_size), link_width,
64                     link_size.height());
65  }
66}
67
68void ConfirmInfoBar::ViewHierarchyChanged(
69    const ViewHierarchyChangedDetails& details) {
70  if (details.is_add && details.child == this && (label_ == NULL)) {
71    ConfirmInfoBarDelegate* delegate = GetDelegate();
72    label_ = CreateLabel(delegate->GetMessageText());
73    AddChildView(label_);
74
75    if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) {
76      ok_button_ = CreateLabelButton(this,
77          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK),
78          delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_OK));
79      AddChildView(ok_button_);
80    }
81
82    if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
83      cancel_button_ = CreateLabelButton(this,
84          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL),
85          delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_CANCEL));
86      AddChildView(cancel_button_);
87    }
88
89    base::string16 link_text(delegate->GetLinkText());
90    if (!link_text.empty()) {
91      link_ = CreateLink(link_text, this);
92      AddChildView(link_);
93    }
94  }
95
96  // This must happen after adding all other children so InfoBarView can ensure
97  // the close button is the last child.
98  InfoBarView::ViewHierarchyChanged(details);
99}
100
101void ConfirmInfoBar::ButtonPressed(views::Button* sender,
102                                   const ui::Event& event) {
103  if (!owner())
104    return;  // We're closing; don't call anything, it might access the owner.
105  ConfirmInfoBarDelegate* delegate = GetDelegate();
106  if ((ok_button_ != NULL) && sender == ok_button_) {
107    if (delegate->Accept())
108      RemoveSelf();
109  } else if ((cancel_button_ != NULL) && (sender == cancel_button_)) {
110    if (delegate->Cancel())
111      RemoveSelf();
112  } else {
113    InfoBarView::ButtonPressed(sender, event);
114  }
115}
116
117int ConfirmInfoBar::ContentMinimumWidth() const {
118  int width = (link_ == NULL) ? 0 : kEndOfLabelSpacing;  // Space before link
119  int before_cancel_spacing = kEndOfLabelSpacing;
120  if (ok_button_ != NULL) {
121    width += kEndOfLabelSpacing + ok_button_->GetPreferredSize().width();
122    before_cancel_spacing = kButtonButtonSpacing;
123  }
124  return width + ((cancel_button_ == NULL) ? 0 :
125      (before_cancel_spacing + cancel_button_->GetPreferredSize().width()));
126}
127
128void ConfirmInfoBar::LinkClicked(views::Link* source, int event_flags) {
129  if (!owner())
130    return;  // We're closing; don't call anything, it might access the owner.
131  DCHECK(link_ != NULL);
132  DCHECK_EQ(link_, source);
133  if (GetDelegate()->LinkClicked(ui::DispositionFromEventFlags(event_flags)))
134    RemoveSelf();
135}
136
137ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() {
138  return delegate()->AsConfirmInfoBarDelegate();
139}
140