summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorerg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-11 22:50:31 +0000
committererg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-11 22:50:31 +0000
commitd3ad7359b7bb6b279d71c2b9e2f0937a3413f0fb (patch)
tree3ff462c0bbcb18a7efee05cf7677d3a670784601 /chrome/browser
parent9913ab8cc18beafd08427e3fd9d4786836e69949 (diff)
downloadchromium_src-d3ad7359b7bb6b279d71c2b9e2f0937a3413f0fb.zip
chromium_src-d3ad7359b7bb6b279d71c2b9e2f0937a3413f0fb.tar.gz
chromium_src-d3ad7359b7bb6b279d71c2b9e2f0937a3413f0fb.tar.bz2
GTK: Implement translate toolbar. Tested on spiegel.de, www.lemonde.fr and mainichi.jp (from an English profile).
BUG=36714,37528 TEST=Open up a page that's not in your current language. You should be presented with a toolbar offering to apply Google Translate to the page. Review URL: http://codereview.chromium.org/830005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41332 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser_main.cc4
-rw-r--r--chrome/browser/gtk/gtk_util.cc6
-rw-r--r--chrome/browser/gtk/gtk_util.h7
-rw-r--r--chrome/browser/gtk/infobar_gtk.cc4
-rw-r--r--chrome/browser/gtk/options/advanced_contents_gtk.cc85
-rw-r--r--chrome/browser/gtk/options/advanced_contents_gtk.h2
-rw-r--r--chrome/browser/gtk/translate_infobars.cc370
-rw-r--r--chrome/browser/gtk/translate_infobars.h99
-rw-r--r--chrome/browser/translate/translate_infobars_delegates.cc9
-rw-r--r--chrome/browser/views/infobars/translate_infobars.h4
10 files changed, 568 insertions, 22 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index 8cadec5..ccba43d 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -844,12 +844,8 @@ int BrowserMain(const MainFunctionParams& parameters) {
process_singleton.Create();
-#if !defined(OS_LINUX)
// Create the TranslateManager singleton.
- // TODO(jcampan): enable on Linux when the info-bars are implemented.
- // http://crbug.com/36714
Singleton<TranslateManager>::get();
-#endif // !OS_LINUX
// Show the First Run UI if this is the first time Chrome has been run on
// this computer, or we're being compelled to do so by a command line flag.
diff --git a/chrome/browser/gtk/gtk_util.cc b/chrome/browser/gtk/gtk_util.cc
index 88b60fb..c9512b2 100644
--- a/chrome/browser/gtk/gtk_util.cc
+++ b/chrome/browser/gtk/gtk_util.cc
@@ -424,14 +424,16 @@ void InitRCStyles() {
gtk_rc_parse_string(kRCText);
}
-void CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget, bool pack_at_end,
- int padding) {
+GtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget,
+ bool pack_at_end, int padding) {
GtkWidget* centering_vbox = gtk_vbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(centering_vbox), widget, TRUE, FALSE, 0);
if (pack_at_end)
gtk_box_pack_end(GTK_BOX(hbox), centering_vbox, FALSE, FALSE, padding);
else
gtk_box_pack_start(GTK_BOX(hbox), centering_vbox, FALSE, FALSE, padding);
+
+ return centering_vbox;
}
std::string ConvertAcceleratorsFromWindowsStyle(const std::string& label) {
diff --git a/chrome/browser/gtk/gtk_util.h b/chrome/browser/gtk/gtk_util.h
index dad4d6b..d2fca75 100644
--- a/chrome/browser/gtk/gtk_util.h
+++ b/chrome/browser/gtk/gtk_util.h
@@ -126,9 +126,10 @@ void InitRCStyles();
// Stick the widget in the given hbox without expanding vertically. The widget
// is packed at the start of the hbox. This is useful for widgets that would
-// otherwise expand to fill the vertical space of the hbox (e.g. buttons).
-void CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget, bool pack_at_end,
- int padding);
+// otherwise expand to fill the vertical space of the hbox
+// (e.g. buttons). Returns the vbox that widget was packed in.
+GtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget,
+ bool pack_at_end, int padding);
// Change windows accelerator style to GTK style. (GTK uses _ for
// accelerators. Windows uses & with && as an escape for &.)
diff --git a/chrome/browser/gtk/infobar_gtk.cc b/chrome/browser/gtk/infobar_gtk.cc
index 79c3290..60d618c 100644
--- a/chrome/browser/gtk/infobar_gtk.cc
+++ b/chrome/browser/gtk/infobar_gtk.cc
@@ -162,8 +162,8 @@ void InfoBar::SetThemeProvider(GtkThemeProvider* theme_provider) {
}
void InfoBar::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
+ const NotificationSource& source,
+ const NotificationDetails& details) {
UpdateBorderColor();
}
diff --git a/chrome/browser/gtk/options/advanced_contents_gtk.cc b/chrome/browser/gtk/options/advanced_contents_gtk.cc
index 665da0e..edb9256 100644
--- a/chrome/browser/gtk/options/advanced_contents_gtk.cc
+++ b/chrome/browser/gtk/options/advanced_contents_gtk.cc
@@ -33,6 +33,7 @@
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/common/chrome_paths.h"
+#include "chrome/common/gtk_signal.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/process_watcher.h"
#include "grit/chromium_strings.h"
@@ -473,6 +474,85 @@ void NetworkSection::StartProxyConfigUtil(const ProxyConfigCommand& command) {
}
///////////////////////////////////////////////////////////////////////////////
+// TranslateSection
+
+class TranslateSection : public OptionsPageBase {
+ public:
+ explicit TranslateSection(Profile* profile);
+ virtual ~TranslateSection() {}
+
+ GtkWidget* get_page_widget() const {
+ return page_;
+ }
+
+ private:
+ // Overridden from OptionsPageBase.
+ virtual void NotifyPrefChanged(const std::wstring* pref_name);
+
+ CHROMEGTK_CALLBACK_0(TranslateSection, void, OnTranslateClicked);
+
+ // Preferences for this section:
+ BooleanPrefMember enable_translate_;
+
+ // The widget containing the options for this section.
+ GtkWidget* page_;
+
+ // The checkbox.
+ GtkWidget* translate_checkbox_;
+
+ // Flag to ignore gtk callbacks while we are loading prefs, to avoid
+ // then turning around and saving them again.
+ bool pref_changing_;
+
+ scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(TranslateSection);
+};
+
+TranslateSection::TranslateSection(Profile* profile)
+ : OptionsPageBase(profile),
+ pref_changing_(true) {
+ page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+ accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+ page_, profile));
+
+ translate_checkbox_ = CreateCheckButtonWithWrappedLabel(
+ IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE);
+ gtk_box_pack_start(GTK_BOX(page_), translate_checkbox_,
+ FALSE, FALSE, 0);
+ g_signal_connect(translate_checkbox_, "clicked",
+ G_CALLBACK(OnTranslateClickedThunk), this);
+ accessible_widget_helper_->SetWidgetName(
+ translate_checkbox_,
+ IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE);
+
+ // Init member prefs so we can update the controls if prefs change.
+ enable_translate_.Init(prefs::kEnableTranslate, profile->GetPrefs(), this);
+
+ NotifyPrefChanged(NULL);
+}
+
+void TranslateSection::NotifyPrefChanged(const std::wstring* pref_name) {
+ pref_changing_ = true;
+ if (!pref_name || *pref_name == prefs::kAlternateErrorPagesEnabled) {
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(translate_checkbox_), enable_translate_.GetValue());
+ }
+ pref_changing_ = false;
+}
+
+void TranslateSection::OnTranslateClicked(GtkWidget* widget) {
+ if (pref_changing_)
+ return;
+ bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+ UserMetricsRecordAction(
+ enabled ? "Options_Translate_Enable" : "Options_Translate_Disable",
+ profile()->GetPrefs());
+ enable_translate_.SetValue(enabled);
+}
+
+///////////////////////////////////////////////////////////////////////////////
// PrivacySection
class PrivacySection : public OptionsPageBase {
@@ -1102,6 +1182,11 @@ void AdvancedContentsGtk::Init() {
l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_NETWORK),
network_section_->get_page_widget(), false);
+ translate_section_.reset(new TranslateSection(profile_));
+ options_builder.AddOptionGroup(
+ l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_TRANSLATE),
+ translate_section_->get_page_widget(), false);
+
download_section_.reset(new DownloadSection(profile_));
options_builder.AddOptionGroup(
l10n_util::GetStringUTF8(IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME),
diff --git a/chrome/browser/gtk/options/advanced_contents_gtk.h b/chrome/browser/gtk/options/advanced_contents_gtk.h
index befd3c5..40a04b62 100644
--- a/chrome/browser/gtk/options/advanced_contents_gtk.h
+++ b/chrome/browser/gtk/options/advanced_contents_gtk.h
@@ -15,6 +15,7 @@ class DownloadSection;
class NetworkSection;
class PrivacySection;
class SecuritySection;
+class TranslateSection;
class WebContentSection;
class AdvancedContentsGtk {
@@ -35,6 +36,7 @@ class AdvancedContentsGtk {
// The sections of the page.
scoped_ptr<DownloadSection> download_section_;
scoped_ptr<NetworkSection> network_section_;
+ scoped_ptr<TranslateSection> translate_section_;
scoped_ptr<PrivacySection> privacy_section_;
scoped_ptr<SecuritySection> security_section_;
scoped_ptr<WebContentSection> web_content_section_;
diff --git a/chrome/browser/gtk/translate_infobars.cc b/chrome/browser/gtk/translate_infobars.cc
new file mode 100644
index 0000000..63ea67d
--- /dev/null
+++ b/chrome/browser/gtk/translate_infobars.cc
@@ -0,0 +1,370 @@
+// Copyright (c) 2010 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/gtk/translate_infobars.h"
+
+#include "app/l10n_util.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/gtk/menu_gtk.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/translate/translate_infobars_delegates.h"
+#include "chrome/browser/translate/options_menu_model.h"
+#include "chrome/common/notification_service.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "grit/theme_resources.h"
+
+namespace {
+
+// Reorders the widgets in the NULL terminated array |widgets| that are all
+// children of |box|.
+void ReorderWidgetsTo(GtkWidget* box, GtkWidget** widgets) {
+ for (int count = 0; *widgets != NULL; widgets++) {
+ gtk_box_reorder_child(GTK_BOX(box), *widgets, count++);
+ gtk_widget_show_all(*widgets);
+ }
+}
+
+// Creates a combobox set up to display text from a list of language codes
+// (translating the codes into the display string).
+GtkWidget* BuildLanguageComboboxFrom(
+ const std::vector<std::string>& languages) {
+ GtkListStore* model = gtk_list_store_new(1, G_TYPE_STRING);
+ for (std::vector<std::string>::const_iterator iter = languages.begin();
+ iter != languages.end(); ++iter) {
+ GtkTreeIter tree_iter;
+ std::string name = UTF16ToUTF8(
+ TranslateInfoBarDelegate::GetDisplayNameForLocale(*iter));
+ gtk_list_store_append(model, &tree_iter);
+ gtk_list_store_set(model, &tree_iter, 0, name.c_str(), -1);
+ }
+
+ GtkWidget* combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
+ g_object_unref(model);
+ GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE);
+ gtk_cell_layout_set_attributes(
+ GTK_CELL_LAYOUT(combobox), renderer, "text", 0, NULL);
+
+ return combobox;
+}
+
+// Builds a button with an arrow in it to emulate the menu-button style from
+// the windows version.
+GtkWidget* BuildOptionsMenuButton() {
+ GtkWidget* button = gtk_button_new();
+ GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button));
+ if (former_child)
+ gtk_container_remove(GTK_CONTAINER(button), former_child);
+
+ GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
+
+ GtkWidget* label = gtk_label_new(
+ l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_OPTIONS).c_str());
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ GtkWidget* arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+ gtk_box_pack_start(GTK_BOX(hbox), arrow, FALSE, FALSE, 0);
+
+ gtk_container_add(GTK_CONTAINER(button), hbox);
+
+ return button;
+}
+
+} // namespace
+
+TranslateInfoBar::TranslateInfoBar(TranslateInfoBarDelegate* delegate)
+ : InfoBar(delegate),
+ swapped_language_placeholders_(false) {
+ BuildWidgets();
+
+ // Register for PAGE_TRANSLATED notification.
+ notification_registrar_.Add(this, NotificationType::PAGE_TRANSLATED,
+ Source<TabContents>(GetDelegate()->tab_contents()));
+}
+
+TranslateInfoBar::~TranslateInfoBar() {
+}
+
+void TranslateInfoBar::Observe(NotificationType type,
+ const NotificationSource& source, const NotificationDetails& details) {
+ if (type.value == NotificationType::PAGE_TRANSLATED) {
+ TabContents* tab = Source<TabContents>(source).ptr();
+ if (tab != GetDelegate()->tab_contents())
+ return;
+
+ UpdateState(TranslateInfoBarDelegate::kAfterTranslate);
+ } else {
+ InfoBar::Observe(type, source, details);
+ }
+}
+
+bool TranslateInfoBar::IsCommandIdChecked(int command_id) const {
+ TranslateInfoBarDelegate* translate_delegate = GetDelegate();
+ switch (command_id) {
+ case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_LANG :
+ return translate_delegate->IsLanguageBlacklisted();
+
+ case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_SITE :
+ return translate_delegate->IsSiteBlacklisted();
+
+ case IDC_TRANSLATE_OPTIONS_ALWAYS :
+ return translate_delegate->ShouldAlwaysTranslate();
+
+ default:
+ NOTREACHED() << "Invalid command_id from menu";
+ break;
+ }
+ return false;
+}
+
+bool TranslateInfoBar::IsCommandIdEnabled(int command_id) const {
+ return true;
+}
+
+bool TranslateInfoBar::GetAcceleratorForCommandId(int command_id,
+ menus::Accelerator* accelerator) {
+ return false;
+}
+
+void TranslateInfoBar::ExecuteCommand(int command_id) {
+ switch (command_id) {
+ case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_LANG:
+ GetDelegate()->ToggleLanguageBlacklist();
+ break;
+
+ case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_SITE:
+ GetDelegate()->ToggleSiteBlacklist();
+ break;
+
+ case IDC_TRANSLATE_OPTIONS_ALWAYS:
+ GetDelegate()->ToggleAlwaysTranslate();
+ break;
+
+ case IDC_TRANSLATE_OPTIONS_ABOUT: {
+ TabContents* tab_contents = GetDelegate()->tab_contents();
+ if (tab_contents) {
+ string16 url = l10n_util::GetStringUTF16(
+ IDS_ABOUT_GOOGLE_TRANSLATE_URL);
+ tab_contents->OpenURL(GURL(url), GURL(), NEW_FOREGROUND_TAB,
+ PageTransition::LINK);
+ }
+ break;
+ }
+
+ default:
+ NOTREACHED() << "Invalid command id from menu.";
+ break;
+ }
+}
+
+void TranslateInfoBar::BuildWidgets() {
+ translate_box_ = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+ gtk_widget_set_no_show_all(translate_box_, TRUE);
+
+ // Add all labels to the translate_box_. Unlike views or cocoa, there's no
+ // concept of manual layout in GTK, so we'll manually reorder these widgets
+ // inside |translate_box_| and selectively show and hide them.
+ label_1_ = gtk_label_new(NULL);
+ gtk_box_pack_start(GTK_BOX(translate_box_), label_1_, FALSE, FALSE, 0);
+
+ label_2_ = gtk_label_new(NULL);
+ gtk_box_pack_start(GTK_BOX(translate_box_), label_2_, FALSE, FALSE, 0);
+
+ label_3_ = gtk_label_new(NULL);
+ gtk_box_pack_start(GTK_BOX(translate_box_), label_3_, FALSE, FALSE, 0);
+
+ translating_label_ = gtk_label_new(
+ l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_TRANSLATING).c_str());
+ gtk_box_pack_start(GTK_BOX(translate_box_), translating_label_,
+ FALSE, FALSE, 0);
+
+ accept_button_ = gtk_button_new_with_label(
+ l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_ACCEPT).c_str());
+ g_signal_connect(accept_button_, "clicked",
+ G_CALLBACK(&OnAcceptPressedThunk), this);
+ accept_button_vbox_ = gtk_util::CenterWidgetInHBox(
+ translate_box_, accept_button_, false, 0);
+
+ deny_button_ = gtk_button_new_with_label(
+ l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_DENY).c_str());
+ g_signal_connect(deny_button_, "clicked",
+ G_CALLBACK(&OnDenyPressedThunk), this);
+ deny_button_vbox_ = gtk_util::CenterWidgetInHBox(
+ translate_box_, deny_button_, false, 0);
+
+ std::vector<std::string> orig_languages;
+ GetDelegate()->GetAvailableOriginalLanguages(&orig_languages);
+ original_language_combobox_ = BuildLanguageComboboxFrom(orig_languages);
+ g_signal_connect(original_language_combobox_, "changed",
+ G_CALLBACK(&OnOriginalModifiedThunk), this);
+ original_language_combobox_vbox_ = gtk_util::CenterWidgetInHBox(
+ translate_box_, original_language_combobox_, false, 0);
+
+ std::vector<std::string> target_languages;
+ GetDelegate()->GetAvailableTargetLanguages(&target_languages);
+ target_language_combobox_ = BuildLanguageComboboxFrom(target_languages);
+ g_signal_connect(target_language_combobox_, "changed",
+ G_CALLBACK(&OnTargetModifiedThunk), this);
+ target_language_combobox_vbox_ = gtk_util::CenterWidgetInHBox(
+ translate_box_, target_language_combobox_, false, 0);
+
+ gtk_box_pack_start(GTK_BOX(hbox_), translate_box_, FALSE, FALSE, 0);
+
+ // The options button sits outside the translate_box so that it can be end
+ // packed in hbox_.
+ options_menu_button_ = BuildOptionsMenuButton();
+ g_signal_connect(options_menu_button_, "clicked",
+ G_CALLBACK(&OnOptionsClickedThunk), this);
+ gtk_widget_show_all(options_menu_button_);
+ gtk_util::CenterWidgetInHBox(
+ hbox_, options_menu_button_, true, 0);
+
+ UpdateState(GetDelegate()->state());
+
+ gtk_widget_show_all(border_bin_.get());
+}
+
+void TranslateInfoBar::UpdateState(
+ TranslateInfoBarDelegate::TranslateState new_state) {
+ // Show the box...
+ gtk_widget_show(translate_box_);
+ // ...but hide all children of the translate box. They will be selectively
+ // unhidden and reordered based on the current translate state.
+ gtk_container_foreach(
+ GTK_CONTAINER(translate_box_),
+ reinterpret_cast<void (*)(GtkWidget*, void*)>(gtk_widget_hide_all), NULL);
+
+ switch (new_state) {
+ case TranslateInfoBarDelegate::kBeforeTranslate: {
+ SetLabels();
+
+ GtkWidget* before_state[] = {
+ label_1_,
+ original_language_combobox_vbox_,
+ label_2_,
+ accept_button_vbox_,
+ deny_button_vbox_,
+ NULL
+ };
+ ReorderWidgetsTo(translate_box_, before_state);
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(original_language_combobox_),
+ GetDelegate()->original_lang_index());
+ break;
+ }
+ case TranslateInfoBarDelegate::kTranslating: {
+ gtk_widget_show(translating_label_);
+ break;
+ }
+ case TranslateInfoBarDelegate::kAfterTranslate: {
+ SetLabels();
+ GtkWidget* first_button_box =
+ swapped_language_placeholders_ ?
+ target_language_combobox_vbox_ : original_language_combobox_vbox_;
+ GtkWidget* second_button_box =
+ swapped_language_placeholders_ ?
+ original_language_combobox_vbox_ : target_language_combobox_vbox_;
+
+ GtkWidget* after_state[] = {
+ label_1_,
+ first_button_box,
+ label_2_,
+ second_button_box,
+ label_3_,
+ NULL
+ };
+ ReorderWidgetsTo(translate_box_, after_state);
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(original_language_combobox_),
+ GetDelegate()->original_lang_index());
+ gtk_combo_box_set_active(GTK_COMBO_BOX(target_language_combobox_),
+ GetDelegate()->target_lang_index());
+ break;
+ }
+ default: {
+ NOTIMPLEMENTED() << "Received state " << new_state;
+ }
+ }
+
+ // Clear options menu model so that it'll be created for new state.
+ options_menu_model_.reset();
+}
+
+void TranslateInfoBar::SetLabels() {
+ std::vector<size_t> offsets;
+ string16 message_text_utf16;
+ GetDelegate()->GetMessageText(&message_text_utf16, &offsets,
+ &swapped_language_placeholders_);
+
+ string16 text = message_text_utf16.substr(0, offsets[0]);
+ gtk_label_set_text(GTK_LABEL(label_1_), UTF16ToUTF8(text).c_str());
+
+ text = message_text_utf16.substr(offsets[0], offsets[1] - offsets[0]);
+ gtk_label_set_text(GTK_LABEL(label_2_), UTF16ToUTF8(text).c_str());
+
+ if (offsets.size() == 3) {
+ text = message_text_utf16.substr(offsets[1], offsets[2] - offsets[1]);
+ gtk_label_set_text(GTK_LABEL(label_3_), UTF16ToUTF8(text).c_str());
+ }
+}
+
+TranslateInfoBarDelegate* TranslateInfoBar::GetDelegate() const {
+ return static_cast<TranslateInfoBarDelegate*>(delegate());
+}
+
+void TranslateInfoBar::LanguageModified() {
+ options_menu_model_.reset();
+
+ // Selecting an item from the "from language" menu in the before translate
+ // phase shouldn't trigger translation - http://crbug.com/36666
+ if (GetDelegate()->state() == TranslateInfoBarDelegate::kAfterTranslate)
+ GetDelegate()->Translate();
+}
+
+void TranslateInfoBar::OnOriginalModified(GtkWidget* sender) {
+ int index = gtk_combo_box_get_active(GTK_COMBO_BOX(sender));
+ if (index == GetDelegate()->original_lang_index())
+ return;
+
+ GetDelegate()->ModifyOriginalLanguage(index);
+
+ LanguageModified();
+}
+
+void TranslateInfoBar::OnTargetModified(GtkWidget* sender) {
+ int index = gtk_combo_box_get_active(GTK_COMBO_BOX(sender));
+ if (index == GetDelegate()->target_lang_index())
+ return;
+
+ GetDelegate()->ModifyTargetLanguage(index);
+
+ LanguageModified();
+}
+
+void TranslateInfoBar::OnAcceptPressed(GtkWidget* sender) {
+ GetDelegate()->Translate();
+ UpdateState(GetDelegate()->state());
+}
+
+void TranslateInfoBar::OnDenyPressed(GtkWidget* sender) {
+ GetDelegate()->TranslationDeclined();
+ RemoveInfoBar();
+}
+
+void TranslateInfoBar::OnOptionsClicked(GtkWidget* sender) {
+ if (!options_menu_model_.get()) {
+ options_menu_model_.reset(new OptionsMenuModel(this, GetDelegate()));
+ options_menu_menu_.reset(new MenuGtk(this, options_menu_model_.get()));
+ }
+ options_menu_menu_->Popup(sender, 1, gtk_get_current_event_time());
+}
+
+// TranslateInfoBarDelegate, InfoBarDelegate overrides: ------------------
+
+InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
+ return new TranslateInfoBar(this);
+}
diff --git a/chrome/browser/gtk/translate_infobars.h b/chrome/browser/gtk/translate_infobars.h
new file mode 100644
index 0000000..56f69c2
--- /dev/null
+++ b/chrome/browser/gtk/translate_infobars.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_BROWSER_GTK_TRANSLATE_INFOBARS_H_
+#define CHROME_BROWSER_GTK_TRANSLATE_INFOBARS_H_
+
+#include <gtk/gtk.h>
+
+#include "app/menus/simple_menu_model.h"
+#include "chrome/browser/gtk/infobar_gtk.h"
+#include "chrome/browser/gtk/menu_gtk.h"
+#include "chrome/browser/translate/translate_infobars_delegates.h"
+#include "chrome/common/gtk_signal.h"
+#include "chrome/common/notification_registrar.h"
+
+class OptionsMenuModel;
+
+// InfoBar that asks user if they want to translate a page that isn't in the
+// user's language to their language. Bar changes during and after translation.
+class TranslateInfoBar : public InfoBar,
+ public menus::SimpleMenuModel::Delegate,
+ public MenuGtk::Delegate {
+ public:
+ explicit TranslateInfoBar(TranslateInfoBarDelegate* delegate);
+ virtual ~TranslateInfoBar();
+
+ // Overridden from NotificationObserver (through InfoBar):
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source, const NotificationDetails& details);
+
+ // Overridden for both menus::SimpleMenuModel::Delegate and MenuGtk::Delegate:
+ virtual bool IsCommandIdChecked(int command_id) const;
+ virtual bool IsCommandIdEnabled(int command_id) const;
+
+ // Overridden from menus::SimpleMenuModel::Delegate:
+ virtual bool GetAcceleratorForCommandId(int command_id,
+ menus::Accelerator* accelerator);
+ virtual void ExecuteCommand(int command_id);
+
+ // Overridden from MenuGtk::Delegate:
+ virtual void ExecuteCommandById(int command_id) {
+ ExecuteCommand(command_id);
+ }
+
+ private:
+ // Builds all the widgets and sets the initial view of the dialog.
+ void BuildWidgets();
+
+ // Changes the layout of the info bar, displaying the correct widgets in the
+ // correct order for |new_state|.
+ void UpdateState(TranslateInfoBarDelegate::TranslateState new_state);
+
+ // Sets the text in the three labels for the current state.
+ void SetLabels();
+
+ // Casts delegate() to the only possible subclass.
+ TranslateInfoBarDelegate* GetDelegate() const;
+
+ // Called after OnOriginalModified or OnTargetModified.
+ void LanguageModified();
+
+ CHROMEGTK_CALLBACK_0(TranslateInfoBar, void, OnOriginalModified);
+ CHROMEGTK_CALLBACK_0(TranslateInfoBar, void, OnTargetModified);
+ CHROMEGTK_CALLBACK_0(TranslateInfoBar, void, OnAcceptPressed);
+ CHROMEGTK_CALLBACK_0(TranslateInfoBar, void, OnDenyPressed);
+ CHROMEGTK_CALLBACK_0(TranslateInfoBar, void, OnOptionsClicked);
+
+ GtkWidget* translate_box_;
+ GtkWidget* label_1_;
+ GtkWidget* label_2_;
+ GtkWidget* label_3_;
+ GtkWidget* translating_label_;
+
+ GtkWidget* accept_button_;
+ GtkWidget* accept_button_vbox_;
+
+ GtkWidget* deny_button_;
+ GtkWidget* deny_button_vbox_;
+
+ GtkWidget* original_language_combobox_;
+ GtkWidget* original_language_combobox_vbox_;
+
+ GtkWidget* target_language_combobox_;
+ GtkWidget* target_language_combobox_vbox_;
+
+ GtkWidget* options_menu_button_;
+ scoped_ptr<MenuGtk> options_menu_menu_;
+ scoped_ptr<OptionsMenuModel> options_menu_model_;
+
+ // This is true if language placeholders in label have been swapped.
+ bool swapped_language_placeholders_;
+
+ NotificationRegistrar notification_registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(TranslateInfoBar);
+};
+
+#endif // CHROME_BROWSER_GTK_TRANSLATE_INFOBARS_H_
diff --git a/chrome/browser/translate/translate_infobars_delegates.cc b/chrome/browser/translate/translate_infobars_delegates.cc
index db03c5c..948e337 100644
--- a/chrome/browser/translate/translate_infobars_delegates.cc
+++ b/chrome/browser/translate/translate_infobars_delegates.cc
@@ -215,15 +215,6 @@ string16 TranslateInfoBarDelegate::GetDisplayNameForLocale(
language_code, g_browser_process->GetApplicationLocale(), true);
}
-#if !defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
-// TranslateInfoBarDelegate: InfoBarDelegate overrides: ------------------------
-
-InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
- NOTIMPLEMENTED();
- return NULL;
-}
-#endif // !TOOLKIT_VIEWS
-
// TranslateInfoBarDelegate: private: ------------------------------------------
TranslateInfoBarDelegate::TranslateInfoBarDelegate(TabContents* tab_contents,
diff --git a/chrome/browser/views/infobars/translate_infobars.h b/chrome/browser/views/infobars/translate_infobars.h
index 4cc7703..c343eb0 100644
--- a/chrome/browser/views/infobars/translate_infobars.h
+++ b/chrome/browser/views/infobars/translate_infobars.h
@@ -6,11 +6,11 @@
#define CHROME_BROWSER_VIEWS_INFOBARS_TRANSLATE_INFOBARS_H_
#include "app/menus/simple_menu_model.h"
-#include "chrome/common/notification_registrar.h"
#include "chrome/browser/translate/translate_infobars_delegates.h"
#include "chrome/browser/views/infobars/infobars.h"
-#include "views/controls/menu/view_menu_delegate.h"
+#include "chrome/common/notification_registrar.h"
#include "views/controls/menu/menu_2.h"
+#include "views/controls/menu/view_menu_delegate.h"
namespace views {
class ImageButton;