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 18 scoped_ptr<InfoBar> ConfirmInfoBarDelegate::CreateInfoBar( 19 scoped_ptr<ConfirmInfoBarDelegate> delegate) { 20 return scoped_ptr<InfoBar>(new ConfirmInfoBar(delegate.Pass())); 21 } 22 23 24 // ConfirmInfoBar ------------------------------------------------------------- 25 26 ConfirmInfoBar::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 34 ConfirmInfoBar::~ConfirmInfoBar() { 35 } 36 37 void 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 68 void 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 101 void 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 117 int 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 128 void 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 137 ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() { 138 return delegate()->AsConfirmInfoBarDelegate(); 139 } 140