// Copyright (c) 2011 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/translate_infobar_base.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/translate/translate_infobar_delegate.h"
#include "chrome/browser/ui/views/infobars/after_translate_infobar.h"
#include "chrome/browser/ui/views/infobars/before_translate_infobar.h"
#include "chrome/browser/ui/views/infobars/infobar_button_border.h"
#include "chrome/browser/ui/views/infobars/translate_message_infobar.h"
#include "grit/theme_resources.h"
#include "ui/base/animation/slide_animation.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas_skia.h"
#include "views/controls/button/menu_button.h"
#include "views/controls/label.h"
// TranslateInfoBarDelegate ---------------------------------------------------
InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
TranslateInfoBarBase* infobar = NULL;
switch (type_) {
case BEFORE_TRANSLATE:
infobar = new BeforeTranslateInfoBar(this);
break;
case AFTER_TRANSLATE:
infobar = new AfterTranslateInfoBar(this);
break;
case TRANSLATING:
case TRANSLATION_ERROR:
infobar = new TranslateMessageInfoBar(this);
break;
default:
NOTREACHED();
}
infobar_view_ = infobar;
return infobar;
}
// TranslateInfoBarBase -------------------------------------------------------
// static
const int TranslateInfoBarBase::kButtonInLabelSpacing = 5;
TranslateInfoBarBase::TranslateInfoBarBase(TranslateInfoBarDelegate* delegate)
: InfoBarView(delegate),
error_background_(InfoBarDelegate::WARNING_TYPE) {
}
TranslateInfoBarBase::~TranslateInfoBarBase() {
}
void TranslateInfoBarBase::ViewHierarchyChanged(bool is_add,
View* parent,
View* child) {
if (is_add && (child == this) && (background_color_animation_ == NULL)) {
background_color_animation_.reset(new ui::SlideAnimation(this));
background_color_animation_->SetTweenType(ui::Tween::LINEAR);
background_color_animation_->SetSlideDuration(500);
TranslateInfoBarDelegate::BackgroundAnimationType animation =
GetDelegate()->background_animation_type();
if (animation == TranslateInfoBarDelegate::NORMAL_TO_ERROR) {
background_color_animation_->Show();
} else if (animation == TranslateInfoBarDelegate::ERROR_TO_NORMAL) {
// Hide() runs the animation in reverse.
background_color_animation_->Reset(1.0);
background_color_animation_->Hide();
}
}
// This must happen after adding all other children so InfoBarView can ensure
// the close button is the last child.
InfoBarView::ViewHierarchyChanged(is_add, parent, child);
}
void TranslateInfoBarBase::UpdateLanguageButtonText(
views::MenuButton* button,
LanguagesMenuModel::LanguageType language_type) {
TranslateInfoBarDelegate* delegate = GetDelegate();
button->SetText(UTF16ToWideHack(delegate->GetLanguageDisplayableNameAt(
(language_type == LanguagesMenuModel::ORIGINAL) ?
delegate->original_language_index() :
delegate->target_language_index())));
// The button may have to grow to show the new text.
Layout();
SchedulePaint();
}
TranslateInfoBarDelegate* TranslateInfoBarBase::GetDelegate() {
return delegate()->AsTranslateInfoBarDelegate();
}
void TranslateInfoBarBase::OnPaintBackground(gfx::Canvas* canvas) {
// We need to set the separator color for |error_background_| like
// InfoBarView::Layout() does for the normal background.
const InfoBarContainer::Delegate* delegate = container_delegate();
if (delegate)
error_background_.set_separator_color(delegate->GetInfoBarSeparatorColor());
// If we're not animating, simply paint the background for the current state.
if (!background_color_animation_->is_animating()) {
GetBackground().Paint(canvas, this);
return;
}
FadeBackground(canvas, 1.0 - background_color_animation_->GetCurrentValue(),
*background());
FadeBackground(canvas, background_color_animation_->GetCurrentValue(),
error_background_);
}
void TranslateInfoBarBase::AnimationProgressed(const ui::Animation* animation) {
if (animation == background_color_animation_.get())
SchedulePaint(); // That'll trigger a PaintBackgroud.
else
InfoBarView::AnimationProgressed(animation);
}
const views::Background& TranslateInfoBarBase::GetBackground() {
return GetDelegate()->IsError() ? error_background_ : *background();
}
void TranslateInfoBarBase::FadeBackground(gfx::Canvas* canvas,
double animation_value,
const views::Background& background) {
// Draw the background into an offscreen buffer with alpha value per animation
// value, then blend it back into the current canvas.
canvas->SaveLayerAlpha(static_cast<int>(animation_value * 255));
canvas->AsCanvasSkia()->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
background.Paint(canvas, this);
canvas->Restore();
}