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/gtk/infobars/translate_infobar_base_gtk.h" 6 7 #include "base/strings/utf_string_conversions.h" 8 #include "chrome/browser/translate/options_menu_model.h" 9 #include "chrome/browser/translate/translate_infobar_delegate.h" 10 #include "chrome/browser/ui/gtk/gtk_util.h" 11 #include "chrome/browser/ui/gtk/infobars/after_translate_infobar_gtk.h" 12 #include "chrome/browser/ui/gtk/infobars/before_translate_infobar_gtk.h" 13 #include "chrome/browser/ui/gtk/infobars/translate_message_infobar_gtk.h" 14 #include "chrome/browser/ui/gtk/menu_gtk.h" 15 #include "grit/generated_resources.h" 16 #include "ui/base/gtk/gtk_signal_registrar.h" 17 #include "ui/base/l10n/l10n_util.h" 18 #include "ui/gfx/animation/slide_animation.h" 19 #include "ui/gfx/canvas.h" 20 21 22 // TranslateInfoBarDelegate --------------------------------------------------- 23 24 // static 25 scoped_ptr<InfoBar> TranslateInfoBarDelegate::CreateInfoBar( 26 scoped_ptr<TranslateInfoBarDelegate> delegate) { 27 if (delegate->infobar_type() == BEFORE_TRANSLATE) 28 return scoped_ptr<InfoBar>(new BeforeTranslateInfoBar(delegate.Pass())); 29 if (delegate->infobar_type() == AFTER_TRANSLATE) 30 return scoped_ptr<InfoBar>(new AfterTranslateInfoBar(delegate.Pass())); 31 return scoped_ptr<InfoBar>(new TranslateMessageInfoBar(delegate.Pass())); 32 } 33 34 35 // TranslateInfoBarBase ------------------------------------------------------- 36 37 TranslateInfoBarBase::TranslateInfoBarBase( 38 scoped_ptr<TranslateInfoBarDelegate> delegate) 39 : InfoBarGtk(delegate.PassAs<InfoBarDelegate>()), 40 background_error_percent_(0) { 41 TranslateInfoBarDelegate* translate_delegate = GetDelegate(); 42 DCHECK(translate_delegate); 43 TranslateInfoBarDelegate::BackgroundAnimationType animation = 44 translate_delegate->background_animation_type(); 45 if (animation != TranslateInfoBarDelegate::NONE) { 46 background_color_animation_.reset(new gfx::SlideAnimation(this)); 47 background_color_animation_->SetTweenType(gfx::Tween::LINEAR); 48 background_color_animation_->SetSlideDuration(500); 49 if (animation == TranslateInfoBarDelegate::NORMAL_TO_ERROR) { 50 background_color_animation_->Show(); 51 } else { 52 DCHECK_EQ(TranslateInfoBarDelegate::ERROR_TO_NORMAL, animation); 53 // Hide() runs the animation in reverse. 54 background_color_animation_->Reset(1.0); 55 background_color_animation_->Hide(); 56 } 57 } else { 58 background_error_percent_ = translate_delegate->is_error() ? 1 : 0; 59 } 60 } 61 62 TranslateInfoBarBase::~TranslateInfoBarBase() { 63 } 64 65 void TranslateInfoBarBase::AnimationProgressed( 66 const gfx::Animation* animation) { 67 DCHECK(widget()); 68 if (animation == background_color_animation_.get()) { 69 background_error_percent_ = animation->GetCurrentValue(); 70 // Queue the info bar widget for redisplay so it repaints its background. 71 gtk_widget_queue_draw(widget()); 72 } else { 73 InfoBar::AnimationProgressed(animation); 74 } 75 } 76 77 void TranslateInfoBarBase::PlatformSpecificSetOwner() { 78 InfoBarGtk::PlatformSpecificSetOwner(); 79 80 if (!ShowOptionsMenuButton()) 81 return; 82 83 // The options button sits outside the translate_box so that it can be end 84 // packed in hbox(). 85 GtkWidget* options_menu_button = CreateMenuButton( 86 l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_OPTIONS)); 87 signals()->Connect(options_menu_button, "clicked", 88 G_CALLBACK(&OnOptionsClickedThunk), this); 89 gtk_widget_show_all(options_menu_button); 90 gtk_util::CenterWidgetInHBox(hbox(), options_menu_button, true, 0); 91 } 92 93 void TranslateInfoBarBase::GetTopColor(InfoBarDelegate::Type type, 94 double* r, double* g, double* b) { 95 if (background_error_percent_ <= 0) { 96 InfoBarGtk::GetTopColor(InfoBarDelegate::PAGE_ACTION_TYPE, r, g, b); 97 } else if (background_error_percent_ >= 1) { 98 InfoBarGtk::GetTopColor(InfoBarDelegate::WARNING_TYPE, r, g, b); 99 } else { 100 double normal_r, normal_g, normal_b; 101 InfoBarGtk::GetTopColor(InfoBarDelegate::PAGE_ACTION_TYPE, 102 &normal_r, &normal_g, &normal_b); 103 104 double error_r, error_g, error_b; 105 InfoBarGtk::GetTopColor(InfoBarDelegate::WARNING_TYPE, 106 &error_r, &error_g, &error_b); 107 108 double offset_r = error_r - normal_r; 109 double offset_g = error_g - normal_g; 110 double offset_b = error_b - normal_b; 111 112 *r = normal_r + (background_error_percent_ * offset_r); 113 *g = normal_g + (background_error_percent_ * offset_g); 114 *b = normal_b + (background_error_percent_ * offset_b); 115 } 116 } 117 118 void TranslateInfoBarBase::GetBottomColor(InfoBarDelegate::Type type, 119 double* r, double* g, double* b) { 120 if (background_error_percent_ <= 0) { 121 InfoBarGtk::GetBottomColor(InfoBarDelegate::PAGE_ACTION_TYPE, r, g, b); 122 } else if (background_error_percent_ >= 1) { 123 InfoBarGtk::GetBottomColor(InfoBarDelegate::WARNING_TYPE, r, g, b); 124 } else { 125 double normal_r, normal_g, normal_b; 126 InfoBarGtk::GetBottomColor(InfoBarDelegate::PAGE_ACTION_TYPE, 127 &normal_r, &normal_g, &normal_b); 128 129 double error_r, error_g, error_b; 130 InfoBarGtk::GetBottomColor(InfoBarDelegate::WARNING_TYPE, 131 &error_r, &error_g, &error_b); 132 133 double offset_r = error_r - normal_r; 134 double offset_g = error_g - normal_g; 135 double offset_b = error_b - normal_b; 136 137 *r = normal_r + (background_error_percent_ * offset_r); 138 *g = normal_g + (background_error_percent_ * offset_g); 139 *b = normal_b + (background_error_percent_ * offset_b); 140 } 141 } 142 143 bool TranslateInfoBarBase::ShowOptionsMenuButton() const { 144 return false; 145 } 146 147 GtkWidget* TranslateInfoBarBase::CreateLanguageCombobox( 148 size_t selected_language, 149 size_t exclude_language) { 150 DCHECK(selected_language != exclude_language); 151 152 GtkListStore* model = gtk_list_store_new(LANGUAGE_COMBO_COLUMN_COUNT, 153 G_TYPE_INT, G_TYPE_STRING); 154 bool set_selection = false; 155 GtkTreeIter selected_iter; 156 TranslateInfoBarDelegate* delegate = GetDelegate(); 157 for (size_t i = 0; i < delegate->num_languages(); ++i) { 158 if (i == exclude_language) 159 continue; 160 GtkTreeIter tree_iter; 161 const base::string16& name = delegate->language_name_at(i); 162 163 gtk_list_store_append(model, &tree_iter); 164 gtk_list_store_set(model, &tree_iter, 165 LANGUAGE_COMBO_COLUMN_ID, i, 166 LANGUAGE_COMBO_COLUMN_NAME, UTF16ToUTF8(name).c_str(), 167 -1); 168 if (i == selected_language) { 169 selected_iter = tree_iter; 170 set_selection = true; 171 } 172 } 173 174 GtkWidget* combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model)); 175 if (set_selection) 176 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combobox), &selected_iter); 177 g_object_unref(model); 178 GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); 179 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE); 180 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), renderer, 181 "text", LANGUAGE_COMBO_COLUMN_NAME, 182 NULL); 183 return combobox; 184 } 185 186 // static 187 size_t TranslateInfoBarBase::GetLanguageComboboxActiveId(GtkComboBox* combo) { 188 GtkTreeIter iter; 189 if (!gtk_combo_box_get_active_iter(combo, &iter)) 190 return 0; 191 192 gint id = 0; 193 gtk_tree_model_get(gtk_combo_box_get_model(combo), &iter, 194 LANGUAGE_COMBO_COLUMN_ID, &id, 195 -1); 196 return static_cast<size_t>(id); 197 } 198 199 TranslateInfoBarDelegate* TranslateInfoBarBase::GetDelegate() { 200 return static_cast<TranslateInfoBarDelegate*>(delegate()); 201 } 202 203 void TranslateInfoBarBase::OnOptionsClicked(GtkWidget* sender) { 204 menu_model_.reset(new OptionsMenuModel(GetDelegate())); 205 ShowMenuWithModel(sender, NULL, menu_model_.get()); 206 } 207