1 // Copyright (c) 2011 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/translate_infobar_base.h"
6
7 #include "base/utf_string_conversions.h"
8 #include "chrome/browser/translate/translate_infobar_delegate.h"
9 #include "chrome/browser/ui/views/infobars/after_translate_infobar.h"
10 #include "chrome/browser/ui/views/infobars/before_translate_infobar.h"
11 #include "chrome/browser/ui/views/infobars/infobar_button_border.h"
12 #include "chrome/browser/ui/views/infobars/translate_message_infobar.h"
13 #include "grit/theme_resources.h"
14 #include "ui/base/animation/slide_animation.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/gfx/canvas_skia.h"
17 #include "views/controls/button/menu_button.h"
18 #include "views/controls/label.h"
19
20 // TranslateInfoBarDelegate ---------------------------------------------------
21
CreateInfoBar()22 InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
23 TranslateInfoBarBase* infobar = NULL;
24 switch (type_) {
25 case BEFORE_TRANSLATE:
26 infobar = new BeforeTranslateInfoBar(this);
27 break;
28 case AFTER_TRANSLATE:
29 infobar = new AfterTranslateInfoBar(this);
30 break;
31 case TRANSLATING:
32 case TRANSLATION_ERROR:
33 infobar = new TranslateMessageInfoBar(this);
34 break;
35 default:
36 NOTREACHED();
37 }
38 infobar_view_ = infobar;
39 return infobar;
40 }
41
42 // TranslateInfoBarBase -------------------------------------------------------
43
44 // static
45 const int TranslateInfoBarBase::kButtonInLabelSpacing = 5;
46
TranslateInfoBarBase(TranslateInfoBarDelegate * delegate)47 TranslateInfoBarBase::TranslateInfoBarBase(TranslateInfoBarDelegate* delegate)
48 : InfoBarView(delegate),
49 error_background_(InfoBarDelegate::WARNING_TYPE) {
50 }
51
~TranslateInfoBarBase()52 TranslateInfoBarBase::~TranslateInfoBarBase() {
53 }
54
ViewHierarchyChanged(bool is_add,View * parent,View * child)55 void TranslateInfoBarBase::ViewHierarchyChanged(bool is_add,
56 View* parent,
57 View* child) {
58 if (is_add && (child == this) && (background_color_animation_ == NULL)) {
59 background_color_animation_.reset(new ui::SlideAnimation(this));
60 background_color_animation_->SetTweenType(ui::Tween::LINEAR);
61 background_color_animation_->SetSlideDuration(500);
62 TranslateInfoBarDelegate::BackgroundAnimationType animation =
63 GetDelegate()->background_animation_type();
64 if (animation == TranslateInfoBarDelegate::NORMAL_TO_ERROR) {
65 background_color_animation_->Show();
66 } else if (animation == TranslateInfoBarDelegate::ERROR_TO_NORMAL) {
67 // Hide() runs the animation in reverse.
68 background_color_animation_->Reset(1.0);
69 background_color_animation_->Hide();
70 }
71 }
72
73 // This must happen after adding all other children so InfoBarView can ensure
74 // the close button is the last child.
75 InfoBarView::ViewHierarchyChanged(is_add, parent, child);
76 }
77
UpdateLanguageButtonText(views::MenuButton * button,LanguagesMenuModel::LanguageType language_type)78 void TranslateInfoBarBase::UpdateLanguageButtonText(
79 views::MenuButton* button,
80 LanguagesMenuModel::LanguageType language_type) {
81 TranslateInfoBarDelegate* delegate = GetDelegate();
82 button->SetText(UTF16ToWideHack(delegate->GetLanguageDisplayableNameAt(
83 (language_type == LanguagesMenuModel::ORIGINAL) ?
84 delegate->original_language_index() :
85 delegate->target_language_index())));
86 // The button may have to grow to show the new text.
87 Layout();
88 SchedulePaint();
89 }
90
GetDelegate()91 TranslateInfoBarDelegate* TranslateInfoBarBase::GetDelegate() {
92 return delegate()->AsTranslateInfoBarDelegate();
93 }
94
OnPaintBackground(gfx::Canvas * canvas)95 void TranslateInfoBarBase::OnPaintBackground(gfx::Canvas* canvas) {
96 // We need to set the separator color for |error_background_| like
97 // InfoBarView::Layout() does for the normal background.
98 const InfoBarContainer::Delegate* delegate = container_delegate();
99 if (delegate)
100 error_background_.set_separator_color(delegate->GetInfoBarSeparatorColor());
101
102 // If we're not animating, simply paint the background for the current state.
103 if (!background_color_animation_->is_animating()) {
104 GetBackground().Paint(canvas, this);
105 return;
106 }
107
108 FadeBackground(canvas, 1.0 - background_color_animation_->GetCurrentValue(),
109 *background());
110 FadeBackground(canvas, background_color_animation_->GetCurrentValue(),
111 error_background_);
112 }
113
AnimationProgressed(const ui::Animation * animation)114 void TranslateInfoBarBase::AnimationProgressed(const ui::Animation* animation) {
115 if (animation == background_color_animation_.get())
116 SchedulePaint(); // That'll trigger a PaintBackgroud.
117 else
118 InfoBarView::AnimationProgressed(animation);
119 }
120
GetBackground()121 const views::Background& TranslateInfoBarBase::GetBackground() {
122 return GetDelegate()->IsError() ? error_background_ : *background();
123 }
124
FadeBackground(gfx::Canvas * canvas,double animation_value,const views::Background & background)125 void TranslateInfoBarBase::FadeBackground(gfx::Canvas* canvas,
126 double animation_value,
127 const views::Background& background) {
128 // Draw the background into an offscreen buffer with alpha value per animation
129 // value, then blend it back into the current canvas.
130 canvas->SaveLayerAlpha(static_cast<int>(animation_value * 255));
131 canvas->AsCanvasSkia()->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
132 background.Paint(canvas, this);
133 canvas->Restore();
134 }
135