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