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/after_translate_infobar.h"
  
  #include "base/strings/utf_string_conversions.h"
  #include "chrome/browser/translate/options_menu_model.h"
  #include "chrome/browser/translate/translate_infobar_delegate.h"
  #include "chrome/browser/ui/views/infobars/translate_language_menu_model.h"
  #include "grit/generated_resources.h"
  #include "ui/base/l10n/l10n_util.h"
  #include "ui/views/controls/button/label_button.h"
  #include "ui/views/controls/button/menu_button.h"
  #include "ui/views/controls/label.h"
  #include "ui/views/controls/menu/menu_item_view.h"
  
  AfterTranslateInfoBar::AfterTranslateInfoBar(
      scoped_ptr<TranslateInfoBarDelegate> delegate)
      : TranslateInfoBarBase(delegate.Pass()),
        label_1_(NULL),
        label_2_(NULL),
        label_3_(NULL),
        original_language_menu_button_(NULL),
        target_language_menu_button_(NULL),
        revert_button_(NULL),
        options_menu_button_(NULL),
        swapped_language_buttons_(false) {
    autodetermined_source_language_ =
        GetDelegate()->original_language_index() ==
        TranslateInfoBarDelegate::kNoIndex;
  }
  
  AfterTranslateInfoBar::~AfterTranslateInfoBar() {
  }
  
  void AfterTranslateInfoBar::Layout() {
    TranslateInfoBarBase::Layout();
  
    int available_width = std::max(0, EndX() - StartX() - ContentMinimumWidth());
    gfx::Size label_1_size = label_1_->GetPreferredSize();
    label_1_->SetBounds(StartX(), OffsetY(label_1_size),
        std::min(label_1_size.width(), available_width), label_1_size.height());
    available_width = std::max(0, available_width - label_1_size.width());
  
    views::MenuButton* first_button, * second_button;
    GetButtons(&first_button, &second_button);
    gfx::Size first_button_size = first_button->GetPreferredSize();
    first_button->SetBounds(label_1_->bounds().right() + kButtonInLabelSpacing,
        OffsetY(first_button_size), first_button_size.width(),
        first_button_size.height());
  
    gfx::Size label_2_size = label_2_->GetPreferredSize();
    label_2_->SetBounds(first_button->bounds().right() + kButtonInLabelSpacing,
        OffsetY(label_2_size), std::min(label_2_size.width(), available_width),
        label_2_size.height());
    available_width = std::max(0, available_width - label_2_size.width());
  
    if (!autodetermined_source_language_) {
      gfx::Size second_button_size = second_button->GetPreferredSize();
      second_button->SetBounds(label_2_->bounds().right() + kButtonInLabelSpacing,
          OffsetY(second_button_size), second_button_size.width(),
          second_button_size.height());
  
      gfx::Size label_3_size = label_3_->GetPreferredSize();
      label_3_->SetBounds(second_button->bounds().right() + kButtonInLabelSpacing,
          OffsetY(label_3_size), std::min(label_3_size.width(), available_width),
          label_3_size.height());
    }
  
    gfx::Size revert_button_size = revert_button_->GetPreferredSize();
    revert_button_->SetBounds(
        (autodetermined_source_language_ ?
            label_2_ : label_3_)->bounds().right() + kButtonInLabelSpacing,
        OffsetY(revert_button_size),
        revert_button_size.width(),
        revert_button_size.height());
  
    gfx::Size options_size = options_menu_button_->GetPreferredSize();
    options_menu_button_->SetBounds(EndX() - options_size.width(),
        OffsetY(options_size), options_size.width(), options_size.height());
  }
  
  void AfterTranslateInfoBar::ViewHierarchyChanged(
      const ViewHierarchyChangedDetails& details) {
    if (!details.is_add || (details.child != this) || (label_1_ != NULL)) {
      TranslateInfoBarBase::ViewHierarchyChanged(details);
      return;
    }
  
    std::vector<base::string16> strings;
    TranslateInfoBarDelegate::GetAfterTranslateStrings(
        &strings, &swapped_language_buttons_, autodetermined_source_language_);
    DCHECK_EQ(autodetermined_source_language_ ? 2U : 3U, strings.size());
  
    label_1_ = CreateLabel(strings[0]);
    AddChildView(label_1_);
  
    TranslateInfoBarDelegate* delegate = GetDelegate();
    original_language_menu_button_ = CreateMenuButton(base::string16(), this);
    original_language_menu_model_.reset(new TranslateLanguageMenuModel(
        TranslateLanguageMenuModel::ORIGINAL, delegate, this,
        original_language_menu_button_, true));
    target_language_menu_button_ = CreateMenuButton(base::string16(), this);
    target_language_menu_model_.reset(new TranslateLanguageMenuModel(
        TranslateLanguageMenuModel::TARGET, delegate, this,
        target_language_menu_button_, true));
  
    views::MenuButton* first_button, * second_button;
    GetButtons(&first_button, &second_button);
    AddChildView(first_button);
  
    label_2_ = CreateLabel(strings[1]);
    AddChildView(label_2_);
  
    // These views may not always be shown, but adding them unconditionally
    // prevents leaks and reduces NULL-checking elsewhere.
    AddChildView(second_button);
    if (autodetermined_source_language_)
      second_button->SetVisible(false);
    label_3_ =
        CreateLabel(autodetermined_source_language_ ? string16() : strings[2]);
    AddChildView(label_3_);
  
    revert_button_ = CreateLabelButton(this,
        l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_REVERT), false);
    AddChildView(revert_button_);
  
    options_menu_button_ = CreateMenuButton(
        l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS), this);
    options_menu_model_.reset(new OptionsMenuModel(delegate));
    AddChildView(options_menu_button_);
  
    // This must happen after adding all other children so InfoBarView can ensure
    // the close button is the last child.
    TranslateInfoBarBase::ViewHierarchyChanged(details);
  
    // These must happen after adding all children because they trigger layout,
    // which assumes that particular children (e.g. the close button) have already
    // been added.
    UpdateLanguageButtonText(original_language_menu_button_,
        delegate->language_name_at(delegate->original_language_index()));
    UpdateLanguageButtonText(target_language_menu_button_,
        delegate->language_name_at(delegate->target_language_index()));
  }
  
  void AfterTranslateInfoBar::ButtonPressed(views::Button* sender,
                                            const ui::Event& event) {
    if (!owner())
      return;  // We're closing; don't call anything, it might access the owner.
    if (sender == revert_button_)
      GetDelegate()->RevertTranslation();
    else
      TranslateInfoBarBase::ButtonPressed(sender, event);
  }
  
  int AfterTranslateInfoBar::ContentMinimumWidth() const {
    return
        (kButtonInLabelSpacing +
             original_language_menu_button_->GetPreferredSize().width() +
             kButtonInLabelSpacing) +
        (kButtonInLabelSpacing +
             target_language_menu_button_->GetPreferredSize().width() +
             kButtonInLabelSpacing) +
        (kButtonInLabelSpacing + revert_button_->GetPreferredSize().width()) +
        (kEndOfLabelSpacing + options_menu_button_->GetPreferredSize().width());
  }
  
  void AfterTranslateInfoBar::OnMenuButtonClicked(views::View* source,
                                                  const gfx::Point& point) {
    if (!owner())
      return;  // We're closing; don't call anything, it might access the owner.
    if (source == original_language_menu_button_) {
      RunMenuAt(original_language_menu_model_.get(),
                original_language_menu_button_, views::MenuItemView::TOPLEFT);
    } else if (source == target_language_menu_button_) {
      RunMenuAt(target_language_menu_model_.get(), target_language_menu_button_,
                views::MenuItemView::TOPLEFT);
    } else {
      DCHECK_EQ(options_menu_button_, source);
      RunMenuAt(options_menu_model_.get(), options_menu_button_,
                views::MenuItemView::TOPRIGHT);
    }
  }
  
  void AfterTranslateInfoBar::GetButtons(
      views::MenuButton** first_button,
      views::MenuButton** second_button) const {
    *first_button = original_language_menu_button_;
    *second_button = target_language_menu_button_;
    if (swapped_language_buttons_ || autodetermined_source_language_)
      std::swap(*first_button, *second_button);
  }
  