• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/gtk/infobars/translate_infobar_base_gtk.h"
6 
7 #include "base/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/l10n/l10n_util.h"
18 #include "ui/gfx/canvas.h"
19 
20 namespace {
21 
22 // To be able to map from language id <-> entry in the combo box, we
23 // store the language id in the combo box data model in addition to the
24 // displayed name.
25 enum {
26   LANGUAGE_COMBO_COLUMN_ID,
27   LANGUAGE_COMBO_COLUMN_NAME,
28   LANGUAGE_COMBO_COLUMN_COUNT
29 };
30 
31 }  // namespace
32 
TranslateInfoBarBase(TranslateInfoBarDelegate * delegate)33 TranslateInfoBarBase::TranslateInfoBarBase(TranslateInfoBarDelegate* delegate)
34     : InfoBar(delegate) {
35   TranslateInfoBarDelegate::BackgroundAnimationType animation =
36       delegate->background_animation_type();
37   if (animation != TranslateInfoBarDelegate::NONE) {
38     background_color_animation_.reset(new ui::SlideAnimation(this));
39     background_color_animation_->SetTweenType(ui::Tween::LINEAR);
40     background_color_animation_->SetSlideDuration(500);
41     if (animation == TranslateInfoBarDelegate::NORMAL_TO_ERROR) {
42       background_color_animation_->Show();
43     } else {
44       DCHECK_EQ(TranslateInfoBarDelegate::ERROR_TO_NORMAL, animation);
45       // Hide() runs the animation in reverse.
46       background_color_animation_->Reset(1.0);
47       background_color_animation_->Hide();
48     }
49   } else {
50     background_error_percent_ = delegate->IsError() ? 1 : 0;
51   }
52 }
53 
~TranslateInfoBarBase()54 TranslateInfoBarBase::~TranslateInfoBarBase() {
55 }
56 
Init()57 void TranslateInfoBarBase::Init() {
58   if (!ShowOptionsMenuButton())
59     return;
60 
61   // The options button sits outside the translate_box so that it can be end
62   // packed in hbox_.
63   GtkWidget* options_menu_button = BuildOptionsMenuButton();
64   g_signal_connect(options_menu_button, "clicked",
65                    G_CALLBACK(&OnOptionsClickedThunk), this);
66   gtk_widget_show_all(options_menu_button);
67   gtk_util::CenterWidgetInHBox(hbox_, options_menu_button, true, 0);
68 }
69 
GetTopColor(InfoBarDelegate::Type type,double * r,double * g,double * b)70 void TranslateInfoBarBase::GetTopColor(InfoBarDelegate::Type type,
71                                        double* r, double* g, double *b) {
72   if (background_error_percent_ <= 0) {
73     InfoBar::GetTopColor(InfoBarDelegate::PAGE_ACTION_TYPE, r, g, b);
74   } else if (background_error_percent_ >= 1) {
75     InfoBar::GetTopColor(InfoBarDelegate::WARNING_TYPE, r, g, b);
76   } else {
77     double normal_r, normal_g, normal_b;
78     InfoBar::GetTopColor(InfoBarDelegate::PAGE_ACTION_TYPE,
79                          &normal_r, &normal_g, &normal_b);
80 
81     double error_r, error_g, error_b;
82     InfoBar::GetTopColor(InfoBarDelegate::WARNING_TYPE,
83                          &error_r, &error_g, &error_b);
84 
85     double offset_r = error_r - normal_r;
86     double offset_g = error_g - normal_g;
87     double offset_b = error_b - normal_b;
88 
89     *r = normal_r + (background_error_percent_ * offset_r);
90     *g = normal_g + (background_error_percent_ * offset_g);
91     *b = normal_b + (background_error_percent_ * offset_b);
92   }
93 }
94 
GetBottomColor(InfoBarDelegate::Type type,double * r,double * g,double * b)95 void TranslateInfoBarBase::GetBottomColor(InfoBarDelegate::Type type,
96                                           double* r, double* g, double *b) {
97   if (background_error_percent_ <= 0) {
98     InfoBar::GetBottomColor(InfoBarDelegate::PAGE_ACTION_TYPE, r, g, b);
99   } else if (background_error_percent_ >= 1) {
100     InfoBar::GetBottomColor(InfoBarDelegate::WARNING_TYPE, r, g, b);
101   } else {
102     double normal_r, normal_g, normal_b;
103     InfoBar::GetBottomColor(InfoBarDelegate::PAGE_ACTION_TYPE,
104                             &normal_r, &normal_g, &normal_b);
105 
106     double error_r, error_g, error_b;
107     InfoBar::GetBottomColor(InfoBarDelegate::WARNING_TYPE,
108                             &error_r, &error_g, &error_b);
109 
110     double offset_r = error_r - normal_r;
111     double offset_g = error_g - normal_g;
112     double offset_b = error_b - normal_b;
113 
114     *r = normal_r + (background_error_percent_ * offset_r);
115     *g = normal_g + (background_error_percent_ * offset_g);
116     *b = normal_b + (background_error_percent_ * offset_b);
117   }
118 }
119 
AnimationProgressed(const ui::Animation * animation)120 void TranslateInfoBarBase::AnimationProgressed(const ui::Animation* animation) {
121   DCHECK(animation == background_color_animation_.get());
122   background_error_percent_ = animation->GetCurrentValue();
123   // Queue the info bar widget for redisplay so it repaints its background.
124   gtk_widget_queue_draw(widget());
125 }
126 
ShowOptionsMenuButton() const127 bool TranslateInfoBarBase::ShowOptionsMenuButton() const {
128   return false;
129 }
130 
CreateLabel(const std::string & text)131 GtkWidget* TranslateInfoBarBase::CreateLabel(const std::string& text) {
132   GtkWidget* label = gtk_label_new(text.c_str());
133   gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
134   return label;
135 }
136 
CreateLanguageCombobox(size_t selected_language,size_t exclude_language)137 GtkWidget* TranslateInfoBarBase::CreateLanguageCombobox(
138     size_t selected_language,
139     size_t exclude_language) {
140   GtkListStore* model = gtk_list_store_new(LANGUAGE_COMBO_COLUMN_COUNT,
141                                            G_TYPE_INT, G_TYPE_STRING);
142   bool set_selection = false;
143   GtkTreeIter selected_iter;
144   TranslateInfoBarDelegate* delegate = GetDelegate();
145   for (size_t i = 0; i < delegate->GetLanguageCount(); ++i) {
146     if (i == exclude_language)
147       continue;
148     GtkTreeIter tree_iter;
149     const string16& name = delegate->GetLanguageDisplayableNameAt(i);
150 
151     gtk_list_store_append(model, &tree_iter);
152     gtk_list_store_set(model, &tree_iter,
153                        LANGUAGE_COMBO_COLUMN_ID, i,
154                        LANGUAGE_COMBO_COLUMN_NAME, UTF16ToUTF8(name).c_str(),
155                        -1);
156     if (i == selected_language) {
157       selected_iter = tree_iter;
158       set_selection = true;
159     }
160   }
161 
162   GtkWidget* combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
163   if (set_selection)
164     gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combobox), &selected_iter);
165   g_object_unref(model);
166   GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
167   gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE);
168   gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), renderer,
169                                  "text", LANGUAGE_COMBO_COLUMN_NAME,
170                                  NULL);
171   return combobox;
172 }
173 
174 // static
GetLanguageComboboxActiveId(GtkComboBox * combo)175 size_t TranslateInfoBarBase::GetLanguageComboboxActiveId(GtkComboBox* combo) {
176   GtkTreeIter iter;
177   if (!gtk_combo_box_get_active_iter(combo, &iter))
178     return 0;
179 
180   gint id = 0;
181   gtk_tree_model_get(gtk_combo_box_get_model(combo), &iter,
182                      LANGUAGE_COMBO_COLUMN_ID, &id,
183                      -1);
184   return static_cast<size_t>(id);
185 }
186 
GetDelegate() const187 TranslateInfoBarDelegate* TranslateInfoBarBase::GetDelegate() const {
188   return static_cast<TranslateInfoBarDelegate*>(delegate());
189 }
190 
191 // static
BuildOptionsMenuButton()192 GtkWidget* TranslateInfoBarBase::BuildOptionsMenuButton() {
193   GtkWidget* button = gtk_button_new();
194   GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button));
195   if (former_child)
196     gtk_container_remove(GTK_CONTAINER(button), former_child);
197 
198   GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
199 
200   GtkWidget* label = gtk_label_new(
201       l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_OPTIONS).c_str());
202   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
203 
204   GtkWidget* arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
205   gtk_box_pack_start(GTK_BOX(hbox), arrow, FALSE, FALSE, 0);
206 
207   gtk_container_add(GTK_CONTAINER(button), hbox);
208 
209   return button;
210 }
211 
OnOptionsClicked(GtkWidget * sender)212 void TranslateInfoBarBase::OnOptionsClicked(GtkWidget* sender) {
213   if (!options_menu_model_.get()) {
214     options_menu_model_.reset(new OptionsMenuModel(GetDelegate()));
215     options_menu_menu_.reset(new MenuGtk(NULL, options_menu_model_.get()));
216   }
217   options_menu_menu_->PopupForWidget(sender, 1, gtk_get_current_event_time());
218 }
219 
220 // TranslateInfoBarDelegate specific method:
CreateInfoBar()221 InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
222   TranslateInfoBarBase* infobar = NULL;
223   switch (type_) {
224     case BEFORE_TRANSLATE:
225       infobar = new BeforeTranslateInfoBar(this);
226       break;
227     case AFTER_TRANSLATE:
228       infobar = new AfterTranslateInfoBar(this);
229       break;
230     case TRANSLATING:
231     case TRANSLATION_ERROR:
232       infobar = new TranslateMessageInfoBar(this);
233       break;
234     default:
235       NOTREACHED();
236   }
237   infobar->Init();
238   return infobar;
239 }
240