text: // 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 "base/logging.h"
  #include "chrome/browser/infobars/confirm_infobar_delegate.h"
  #include "ui/base/window_open_disposition.h"
  #include "ui/views/controls/button/label_button.h"
  #include "ui/views/controls/label.h"
  #include "ui/views/controls/link.h"
  
  
  // ConfirmInfoBarDelegate -----------------------------------------------------
  
  InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
    return new ConfirmInfoBar(owner, this);
  }
  
  
  // ConfirmInfoBar -------------------------------------------------------------
  
  ConfirmInfoBar::ConfirmInfoBar(InfoBarService* owner,
                                 ConfirmInfoBarDelegate* delegate)
      : InfoBarView(owner, delegate),
        label_(NULL),
        ok_button_(NULL),
        cancel_button_(NULL),
        link_(NULL) {
  }
  
  ConfirmInfoBar::~ConfirmInfoBar() {
  }
  
  void ConfirmInfoBar::Layout() {
    InfoBarView::Layout();
  
    int available_width = std::max(0, EndX() - StartX() - ContentMinimumWidth());
    gfx::Size label_size = label_->GetPreferredSize();
    label_->SetBounds(StartX(), OffsetY(label_size),
        std::min(label_size.width(), available_width), label_size.height());
    available_width = std::max(0, available_width - label_size.width());
  
    int button_x = label_->bounds().right() + kEndOfLabelSpacing;
    if (ok_button_ != NULL) {
      gfx::Size ok_size = ok_button_->GetPreferredSize();
      ok_button_->SetBounds(button_x, OffsetY(ok_size), ok_size.width(),
                            ok_size.height());
      button_x += ok_size.width() + kButtonButtonSpacing;
    }
  
    if (cancel_button_ != NULL) {
      gfx::Size cancel_size = cancel_button_->GetPreferredSize();
      cancel_button_->SetBounds(button_x, OffsetY(cancel_size),
                                cancel_size.width(), cancel_size.height());
    }
  
    if (link_ != NULL) {
      gfx::Size link_size = link_->GetPreferredSize();
      int link_width = std::min(link_size.width(), available_width);
      link_->SetBounds(EndX() - link_width, OffsetY(link_size), link_width,
                       link_size.height());
    }
  }
  
  void ConfirmInfoBar::ViewHierarchyChanged(
      const ViewHierarchyChangedDetails& details) {
    if (details.is_add && details.child == this && (label_ == NULL)) {
      ConfirmInfoBarDelegate* delegate = GetDelegate();
      label_ = CreateLabel(delegate->GetMessageText());
      AddChildView(label_);
  
      if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) {
        ok_button_ = CreateLabelButton(this,
            delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK),
            delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_OK));
        AddChildView(ok_button_);
      }
  
      if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
        cancel_button_ = CreateLabelButton(this,
            delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL),
            delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_CANCEL));
        AddChildView(cancel_button_);
      }
  
      string16 link_text(delegate->GetLinkText());
      if (!link_text.empty()) {
        link_ = CreateLink(link_text, this);
        AddChildView(link_);
      }
    }
  
    // This must happen after adding all other children so InfoBarView can ensure
    // the close button is the last child.
    InfoBarView::ViewHierarchyChanged(details);
  }
  
  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 ((ok_button_ != NULL) && sender == ok_button_) {
      if (delegate->Accept())
        RemoveSelf();
    } else if ((cancel_button_ != NULL) && (sender == cancel_button_)) {
      if (delegate->Cancel())
        RemoveSelf();
    } else {
      InfoBarView::ButtonPressed(sender, event);
    }
  }
  
  int ConfirmInfoBar::ContentMinimumWidth() const {
    int width = (link_ == NULL) ? 0 : kEndOfLabelSpacing;  // Space before link
    int before_cancel_spacing = kEndOfLabelSpacing;
    if (ok_button_ != NULL) {
      width += kEndOfLabelSpacing + ok_button_->GetPreferredSize().width();
      before_cancel_spacing = kButtonButtonSpacing;
    }
    return width + ((cancel_button_ == NULL) ? 0 :
        (before_cancel_spacing + cancel_button_->GetPreferredSize().width()));
  }
  
  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(link_ != NULL);
    DCHECK_EQ(link_, source);
    if (GetDelegate()->LinkClicked(ui::DispositionFromEventFlags(event_flags)))
      RemoveSelf();
  }
  
  ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() {
    return delegate()->AsConfirmInfoBarDelegate();
  }
  