diff options
author | kuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-04 21:37:53 +0000 |
---|---|---|
committer | kuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-04 21:37:53 +0000 |
commit | 5fd00714eb3eed6f6cc8dcc8d310dbc18f42059f (patch) | |
tree | ec79e4150383891307895bc6ee7f240e3102a979 /chrome | |
parent | 5638498ac845b895d35158a4e703949d83497744 (diff) | |
download | chromium_src-5fd00714eb3eed6f6cc8dcc8d310dbc18f42059f.zip chromium_src-5fd00714eb3eed6f6cc8dcc8d310dbc18f42059f.tar.gz chromium_src-5fd00714eb3eed6f6cc8dcc8d310dbc18f42059f.tar.bz2 |
merge translate infobars from trunk to branch 249
- merge is completely manual with quite some changes to code; practically a new changelist is created based on changelists committed on trunk.
- code that calls backend is currently blocked with TODO for jay to unblock when he merges the backend.
BUG=31297
TEST=none for now.
Review URL: http://codereview.chromium.org/563026
git-svn-id: svn://svn.chromium.org/chrome/branches/249/src@38134 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/chrome_dll_resource.h | 11 | ||||
-rw-r--r-- | chrome/app/resources/locale_settings.grd | 5 | ||||
-rw-r--r-- | chrome/browser/tab_contents/infobar_delegate.h | 10 | ||||
-rw-r--r-- | chrome/browser/translate/languages_menu_model.cc | 33 | ||||
-rw-r--r-- | chrome/browser/translate/languages_menu_model.h | 24 | ||||
-rw-r--r-- | chrome/browser/translate/options_menu_model.cc | 40 | ||||
-rw-r--r-- | chrome/browser/translate/options_menu_model.h | 24 | ||||
-rw-r--r-- | chrome/browser/translate/translate_infobars_delegates.cc | 212 | ||||
-rw-r--r-- | chrome/browser/translate/translate_infobars_delegates.h | 122 | ||||
-rw-r--r-- | chrome/browser/translate/translate_prefs.cc | 171 | ||||
-rw-r--r-- | chrome/browser/translate/translate_prefs.h | 51 | ||||
-rw-r--r-- | chrome/browser/views/infobars/infobars.cc | 60 | ||||
-rw-r--r-- | chrome/browser/views/infobars/infobars.h | 17 | ||||
-rw-r--r-- | chrome/browser/views/infobars/translate_infobars.cc | 606 | ||||
-rw-r--r-- | chrome/browser/views/infobars/translate_infobars.h | 146 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 10 |
16 files changed, 1511 insertions, 31 deletions
diff --git a/chrome/app/chrome_dll_resource.h b/chrome/app/chrome_dll_resource.h index be95402..84be54a 100644 --- a/chrome/app/chrome_dll_resource.h +++ b/chrome/app/chrome_dll_resource.h @@ -223,13 +223,22 @@ #define IDC_CHECK_SPELLING_OF_THIS_FIELD 41107 #define IDC_SYNC_BOOKMARKS 41108 #define IDC_SPELLPANEL_TOGGLE 41109 + +// Translate +#define IDC_TRANSLATE_OPTIONS_ALWAYS 42000 +#define IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_LANG 42001 +#define IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_SITE 42002 +#define IDC_TRANSLATE_OPTIONS_ABOUT 42003 +#define IDC_TRANSLATE_ORIGINAL_LANGUAGE_BASE 42100 +#define IDC_TRANSLATE_TARGET_LANGUAGE_BASE 42400 + // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 3001 -#define _APS_NEXT_COMMAND_VALUE 42000 +#define _APS_NEXT_COMMAND_VALUE 43000 #define _APS_NEXT_CONTROL_VALUE 4017 #define _APS_NEXT_SYMED_VALUE 1001 #endif diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd index db478fa..b778b0d 100644 --- a/chrome/app/resources/locale_settings.grd +++ b/chrome/app/resources/locale_settings.grd @@ -735,6 +735,11 @@ 4 </message> + <!-- The URL for About Google Translate. --> + <message name="IDS_ABOUT_GOOGLE_TRANSLATE_URL" translateable="false"> + http://www.google.com/support/chrome/bin/answer.py?answer=173424&hl=[GRITLANGCODE] + </message> + <!-- The width and height of the Content Settings Exceptions dialog box in --> <!-- characters and lines (See above). --> <message name="IDS_CONTENT_EXCEPTION_DIALOG_WIDTH_CHARS" use_name_for_id="true"> diff --git a/chrome/browser/tab_contents/infobar_delegate.h b/chrome/browser/tab_contents/infobar_delegate.h index d6a1899..4e37848 100644 --- a/chrome/browser/tab_contents/infobar_delegate.h +++ b/chrome/browser/tab_contents/infobar_delegate.h @@ -15,6 +15,7 @@ class AlertInfoBarDelegate; class ConfirmInfoBarDelegate; class InfoBar; class LinkInfoBarDelegate; +class TranslateInfoBarDelegate; class SkBitmap; class ThemeInstalledInfoBarDelegate; @@ -47,7 +48,8 @@ class InfoBarDelegate { enum Type { INFO_TYPE, WARNING_TYPE, - ERROR_TYPE + ERROR_TYPE, + PAGE_ACTION_TYPE }; // Returns true if the supplied |delegate| is equal to this one. Equality is @@ -102,6 +104,12 @@ class InfoBarDelegate { return NULL; } + // Returns a pointer to the TranslateInfoBarDelegate interface, if + // implemented. + virtual TranslateInfoBarDelegate* AsTranslateInfoBarDelegate() { + return NULL; + } + // Returns the type of the infobar. The type determines the appearance (such // as background color) of the infobar. virtual Type GetInfoBarType() { diff --git a/chrome/browser/translate/languages_menu_model.cc b/chrome/browser/translate/languages_menu_model.cc new file mode 100644 index 0000000..f05292b --- /dev/null +++ b/chrome/browser/translate/languages_menu_model.cc @@ -0,0 +1,33 @@ +// 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/translate/languages_menu_model.h" + +#include "base/string_util.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/translate/translate_infobars_delegates.h" + +LanguagesMenuModel::LanguagesMenuModel( + views::SimpleMenuModel::Delegate* menu_delegate, + TranslateInfoBarDelegate* translate_delegate, + bool original_language) + : views::SimpleMenuModel(menu_delegate) { + std::vector<std::string> languages; + int base_command_id = 0; + if (original_language) { + base_command_id = IDC_TRANSLATE_ORIGINAL_LANGUAGE_BASE; + translate_delegate->GetAvailableOriginalLanguages(&languages); + } else { + base_command_id = IDC_TRANSLATE_TARGET_LANGUAGE_BASE; + translate_delegate->GetAvailableTargetLanguages(&languages); + } + std::vector<std::string>::const_iterator iter = languages.begin(); + for (int i = base_command_id; iter != languages.end(); ++i, ++iter) { + AddItem(i, TranslateInfoBarDelegate::GetDisplayNameForLocale(*iter)); + } +} + +LanguagesMenuModel::~LanguagesMenuModel() { +} + diff --git a/chrome/browser/translate/languages_menu_model.h b/chrome/browser/translate/languages_menu_model.h new file mode 100644 index 0000000..1434aa3 --- /dev/null +++ b/chrome/browser/translate/languages_menu_model.h @@ -0,0 +1,24 @@ +// 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_TRANSLATE_LANGUAGES_MENU_MODEL_H_ +#define CHROME_BROWSER_TRANSLATE_LANGUAGES_MENU_MODEL_H_ + +#include "views/controls/menu/simple_menu_model.h" + +class TranslateInfoBarDelegate; + +// A menu model that builds the contents of the language menus in the translate +// infobar, i.e. the original and target languages. +class LanguagesMenuModel : public views::SimpleMenuModel { + public: + explicit LanguagesMenuModel(views::SimpleMenuModel::Delegate* menu_delegate, + TranslateInfoBarDelegate* translate_delegate, bool original_language); + virtual ~LanguagesMenuModel(); + + private: + DISALLOW_COPY_AND_ASSIGN(LanguagesMenuModel); +}; + +#endif // CHROME_BROWSER_TRANSLATE_LANGUAGES_MENU_MODEL_H_ diff --git a/chrome/browser/translate/options_menu_model.cc b/chrome/browser/translate/options_menu_model.cc new file mode 100644 index 0000000..4a663f8 --- /dev/null +++ b/chrome/browser/translate/options_menu_model.cc @@ -0,0 +1,40 @@ +// 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/translate/options_menu_model.h" + +#include "app/l10n_util.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/translate/translate_infobars_delegates.h" +#include "grit/generated_resources.h" + +OptionsMenuModel::OptionsMenuModel(views::SimpleMenuModel::Delegate* delegate, + TranslateInfoBarDelegate* translate_delegate, bool before_translate) + : views::SimpleMenuModel(delegate) { + string16 original_language = + TranslateInfoBarDelegate::GetDisplayNameForLocale( + translate_delegate->original_lang_code()); + if (before_translate) { + AddCheckItem(IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_LANG, + l10n_util::GetStringFUTF16( + IDS_TRANSLATE_INFOBAR_OPTIONS_NEVER_TRANSLATE_LANG, + original_language)); + AddCheckItem(IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_SITE, + l10n_util::GetStringUTF16( + IDS_TRANSLATE_INFOBAR_OPTIONS_NEVER_TRANSLATE_SITE)); + } else { + string16 target_language = + TranslateInfoBarDelegate::GetDisplayNameForLocale( + translate_delegate->target_lang_code()); + AddCheckItem(IDC_TRANSLATE_OPTIONS_ALWAYS, + l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS_ALWAYS, + original_language, target_language)); + } + AddItemWithStringId(IDC_TRANSLATE_OPTIONS_ABOUT, + IDS_TRANSLATE_INFOBAR_OPTIONS_ABOUT); +} + +OptionsMenuModel::~OptionsMenuModel() { +} + diff --git a/chrome/browser/translate/options_menu_model.h b/chrome/browser/translate/options_menu_model.h new file mode 100644 index 0000000..c43eb25 --- /dev/null +++ b/chrome/browser/translate/options_menu_model.h @@ -0,0 +1,24 @@ +// Copyright (c) 2009 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_TRANSLATE_OPTIONS_MENU_MODEL_H_ +#define CHROME_BROWSER_TRANSLATE_OPTIONS_MENU_MODEL_H_ + +#include "views/controls/menu/simple_menu_model.h" + +class TranslateInfoBarDelegate; + +// A menu model that builds the contents of the options menu in the translate +// infobar. This menu has only one level (no submenus). +class OptionsMenuModel : public views::SimpleMenuModel { + public: + explicit OptionsMenuModel(views::SimpleMenuModel::Delegate* menu_delegate, + TranslateInfoBarDelegate* translate_delegate, bool before_translate); + virtual ~OptionsMenuModel(); + + private: + DISALLOW_COPY_AND_ASSIGN(OptionsMenuModel); +}; + +#endif // CHROME_BROWSER_TRANSLATE_OPTIONS_MENU_MODEL_H_ diff --git a/chrome/browser/translate/translate_infobars_delegates.cc b/chrome/browser/translate/translate_infobars_delegates.cc new file mode 100644 index 0000000..9a457b1 --- /dev/null +++ b/chrome/browser/translate/translate_infobars_delegates.cc @@ -0,0 +1,212 @@ +// 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/translate/translate_infobars_delegates.h" + +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "chrome/browser/browser_process.h" +// TODO(jcampan): unblock when backend is merged in. +// #include "chrome/browser/renderer_host/translation_service.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" + +// TranslateInfoBarDelegate: InfoBarDelegate overrides: ------------------------ + +SkBitmap* TranslateInfoBarDelegate::GetIcon() const { + return ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_INFOBAR_TRANSLATE); +} + +bool TranslateInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const { + TranslateInfoBarDelegate* translate_delegate = + delegate->AsTranslateInfoBarDelegate(); + // There can be only 1 translate infobar at any one time. + return (!!translate_delegate); +} + +void TranslateInfoBarDelegate::InfoBarClosed() { + delete this; +} + +// TranslateInfoBarDelegate: public: ------------------------------------------- + +void TranslateInfoBarDelegate::ModifyOriginalLanguage(int lang_index) { + original_lang_index_ = lang_index; + // TODO(kuan): Send stats to Google Translate that original language has been + // modified. +} + +void TranslateInfoBarDelegate::ModifyTargetLanguage(int lang_index) { + NOTREACHED() << "Subclass should override"; +} + +void TranslateInfoBarDelegate::GetAvailableOriginalLanguages( + std::vector<std::string>* languages) { + // TODO(jcampan): unblock when backend is merged in. + // TranslationService::GetSupportedLanguages(languages); +} + +void TranslateInfoBarDelegate::GetAvailableTargetLanguages( + std::vector<std::string>* languages) { + NOTREACHED() << "Subclass should override"; +} + +void TranslateInfoBarDelegate::Translate() { + // TODO(jcampan): unblock when backend is merged in. + /* + if (original_lang_index_ != target_lang_index_) + tab_contents_->TranslatePage(original_lang_code(), target_lang_code()); + */ +} + +bool TranslateInfoBarDelegate::IsLanguageBlacklisted() { + NOTREACHED() << "Subclass should override"; + return false; +} + +bool TranslateInfoBarDelegate::IsSiteBlacklisted() { + NOTREACHED() << "Subclass should override"; + return false; +} + +bool TranslateInfoBarDelegate::ShouldAlwaysTranslate() { + NOTREACHED() << "Subclass should override"; + return false; +} + +void TranslateInfoBarDelegate::ToggleLanguageBlacklist() { + NOTREACHED() << "Subclass should override"; +} + +void TranslateInfoBarDelegate::ToggleSiteBlacklist() { + NOTREACHED() << "Subclass should override"; +} + +void TranslateInfoBarDelegate::ToggleAlwaysTranslate() { + NOTREACHED() << "Subclass should override"; +} + +// TranslateInfoBarDelegate: static: ------------------------------------------- + +string16 TranslateInfoBarDelegate::GetDisplayNameForLocale( + const std::string& language_code) { + return l10n_util::GetDisplayNameForLocale( + language_code, g_browser_process->GetApplicationLocale(), true); +} + +// TranslateInfoBarDelegate: protected: ---------------------------------------- + +TranslateInfoBarDelegate::TranslateInfoBarDelegate(TabContents* tab_contents, + PrefService* user_prefs, const std::string& original_lang_code, + const std::string& target_lang_code) + : InfoBarDelegate(tab_contents), + tab_contents_(tab_contents), + original_lang_index_(0), + target_lang_index_(0), + prefs_(user_prefs) { + // TODO(jcampan): unblock when backend is merged in. + // TranslationService::GetSupportedLanguages(&supported_languages_); + for (size_t i = 0; i < supported_languages_.size(); ++i) { + if (original_lang_code == supported_languages_[i]) { + original_lang_index_ = i; + break; + } + } + for (size_t i = 0; i < supported_languages_.size(); ++i) { + if (target_lang_code == supported_languages_[i]) { + target_lang_index_ = i; + break; + } + } +} + +// BeforeTranslateInfoBarDelegate: public: ------------------------------------- + +BeforeTranslateInfoBarDelegate::BeforeTranslateInfoBarDelegate( + TabContents* tab_contents, PrefService* user_prefs, const GURL& url, + const std::string& original_lang_code, const std::string& target_lang_code) + : TranslateInfoBarDelegate(tab_contents, user_prefs, original_lang_code, + target_lang_code), + site_(url.HostNoBrackets()), + never_translate_language_(false), + never_translate_site_(false) { +} + +bool BeforeTranslateInfoBarDelegate::IsLanguageBlacklisted() { + never_translate_language_ = + prefs_.IsLanguageBlacklisted(original_lang_code()); + return never_translate_language_; +} + +void BeforeTranslateInfoBarDelegate::ToggleLanguageBlacklist() { + never_translate_language_ = !never_translate_language_; + if (never_translate_language_) + prefs_.BlacklistLanguage(original_lang_code()); + else + prefs_.RemoveLanguageFromBlacklist(original_lang_code()); +} + +bool BeforeTranslateInfoBarDelegate::IsSiteBlacklisted() { + never_translate_site_ = prefs_.IsSiteBlacklisted(site_); + return never_translate_site_; +} + +void BeforeTranslateInfoBarDelegate::ToggleSiteBlacklist() { + never_translate_site_ = !never_translate_site_; + if (never_translate_site_) + prefs_.BlacklistSite(site_); + else + prefs_.RemoveSiteFromBlacklist(site_); +} + +#if !defined(TOOLKIT_VIEWS) +InfoBar* BeforeTranslateInfoBarDelegate::CreateInfoBar() { + NOTIMPLEMENTED(); + return NULL; +} +#endif // !TOOLKIT_VIEWS + +// AfterTranslateInfoBarDelegate: public: -------------------------------------- + +AfterTranslateInfoBarDelegate::AfterTranslateInfoBarDelegate( + TabContents* tab_contents, PrefService* user_prefs, + const std::string& original_lang_code, const std::string& target_lang_code) + : TranslateInfoBarDelegate(tab_contents, user_prefs, original_lang_code, + target_lang_code), + always_translate_(false) { +} + +void AfterTranslateInfoBarDelegate::GetAvailableTargetLanguages( + std::vector<std::string>* languages) { + // TODO(jcampan): unblock when backend is merged in. + // TranslationService::GetSupportedLanguages(languages); +} + +void AfterTranslateInfoBarDelegate::ModifyTargetLanguage(int lang_index) { + target_lang_index_ = lang_index; +} + +bool AfterTranslateInfoBarDelegate::ShouldAlwaysTranslate() { + always_translate_ = prefs_.IsLanguagePairWhitelisted(original_lang_code(), + target_lang_code()); + return always_translate_; +} + +void AfterTranslateInfoBarDelegate::ToggleAlwaysTranslate() { + always_translate_ = !always_translate_; + if (always_translate_) + prefs_.WhitelistLanguagePair(original_lang_code(), target_lang_code()); + else + prefs_.RemoveLanguagePairFromWhitelist(original_lang_code(), + target_lang_code()); +} + +#if !defined(TOOLKIT_VIEWS) +InfoBar* AfterTranslateInfoBarDelegate::CreateInfoBar() { + NOTIMPLEMENTED(); + return NULL; +} +#endif // !TOOLKIT_VIEWS diff --git a/chrome/browser/translate/translate_infobars_delegates.h b/chrome/browser/translate/translate_infobars_delegates.h new file mode 100644 index 0000000..5b10f3f --- /dev/null +++ b/chrome/browser/translate/translate_infobars_delegates.h @@ -0,0 +1,122 @@ +// 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_TRANSLATE_TRANSLATE_INFOBARS_DELEGATES_H_ +#define CHROME_BROWSER_TRANSLATE_TRANSLATE_INFOBARS_DELEGATES_H_ + +#include "chrome/browser/tab_contents/infobar_delegate.h" +#include "chrome/browser/translate/translate_prefs.h" + +class SkBitmap; + +// An interface derived from InfoBarDelegate to form the base interface for +// translate infobars. +class TranslateInfoBarDelegate : public InfoBarDelegate { + public: + virtual void GetAvailableOriginalLanguages( + std::vector<std::string>* languages); + virtual void GetAvailableTargetLanguages( + std::vector<std::string>* languages); + virtual void ModifyOriginalLanguage(int lang_index); + virtual void ModifyTargetLanguage(int lang_index); + virtual void Translate(); + virtual bool IsLanguageBlacklisted(); + virtual void ToggleLanguageBlacklist(); + virtual bool IsSiteBlacklisted(); + virtual void ToggleSiteBlacklist(); + virtual bool ShouldAlwaysTranslate(); + virtual void ToggleAlwaysTranslate(); + + int original_lang_index() const { + return original_lang_index_; + } + int target_lang_index() const { + return target_lang_index_; + } + const std::string& original_lang_code() const { + return supported_languages_[original_lang_index_]; + } + const std::string& target_lang_code() const { + return supported_languages_[target_lang_index_]; + } + const std::string& GetLocaleFromIndex(int lang_index) const { + return supported_languages_[lang_index]; + } + TabContents* tab_contents() const { + return tab_contents_; + } + + // Overridden from InfoBarDelegate. + virtual Type GetInfoBarType() { + return PAGE_ACTION_TYPE; + } + virtual SkBitmap* GetIcon() const; + virtual bool EqualsDelegate(InfoBarDelegate* delegate) const; + virtual TranslateInfoBarDelegate* AsTranslateInfoBarDelegate() { + return this; + } + virtual void InfoBarClosed(); + + // Returns the printable version of the language code |language_code|. + static string16 GetDisplayNameForLocale(const std::string& language_code); + + protected: + TranslateInfoBarDelegate(TabContents* contents, PrefService* user_prefs, + const std::string& original_language, const std::string& target_language); + + TabContents* tab_contents_; // Weak. + int original_lang_index_; + int target_lang_index_; + TranslatePrefs prefs_; + // The list of languages supported. + std::vector<std::string> supported_languages_; + + DISALLOW_COPY_AND_ASSIGN(TranslateInfoBarDelegate); +}; + +class BeforeTranslateInfoBarDelegate : public TranslateInfoBarDelegate { + public: + BeforeTranslateInfoBarDelegate(TabContents* contents, PrefService* user_prefs, + const GURL& url, const std::string& original_language, + const std::string& target_language); + + // Overriden from TranslateInfoBarDelegate: + virtual bool IsLanguageBlacklisted(); + virtual void ToggleLanguageBlacklist(); + virtual bool IsSiteBlacklisted(); + virtual void ToggleSiteBlacklist(); + + // Overridden from InfoBarDelegate: + virtual InfoBar* CreateInfoBar(); + + private: + std::string site_; + bool never_translate_language_; + bool never_translate_site_; + + DISALLOW_COPY_AND_ASSIGN(BeforeTranslateInfoBarDelegate); +}; + +class AfterTranslateInfoBarDelegate : public TranslateInfoBarDelegate { + public: + AfterTranslateInfoBarDelegate(TabContents* contents, PrefService* user_prefs, + const std::string& original_language, const std::string& target_language); + + // Overriden from TranslateInfoBar: + virtual void GetAvailableTargetLanguages( + std::vector<std::string>* languages); + virtual void ModifyTargetLanguage(int lang_index); + virtual bool ShouldAlwaysTranslate(); + virtual void ToggleAlwaysTranslate(); + + // Overridden from InfoBarDelegate: + virtual InfoBar* CreateInfoBar(); + + private: + bool always_translate_; + + DISALLOW_COPY_AND_ASSIGN(AfterTranslateInfoBarDelegate); +}; + +#endif // CHROME_BROWSER_TRANSLATE_TRANSLATE_INFOBARS_DELEGATES_H_ diff --git a/chrome/browser/translate/translate_prefs.cc b/chrome/browser/translate/translate_prefs.cc new file mode 100644 index 0000000..ab69058 --- /dev/null +++ b/chrome/browser/translate/translate_prefs.cc @@ -0,0 +1,171 @@ +// 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/translate/translate_prefs.h" + +#include "base/string_util.h" +#include "chrome/common/pref_service.h" + +static const wchar_t kPrefTranslateLanguageBlacklist[] = + L"translate_language_blacklist"; +static const wchar_t kPrefTranslateSiteBlacklist[] = + L"translate_site_blacklist"; +static const wchar_t kPrefTranslateWhitelists[] = L"translate_whitelists"; + +// TranslatePrefs: public: ----------------------------------------------------- + +TranslatePrefs::TranslatePrefs(PrefService* user_prefs) + : prefs_(user_prefs) { + Register(); +} + +bool TranslatePrefs::IsLanguageBlacklisted( + const std::string& original_language) { + return IsValueBlacklisted(kPrefTranslateLanguageBlacklist, original_language); +} + +void TranslatePrefs::BlacklistLanguage(const std::string& original_language) { + BlacklistValue(kPrefTranslateLanguageBlacklist, original_language); +} + +void TranslatePrefs::RemoveLanguageFromBlacklist( + const std::string& original_language) { + RemoveValueFromBlacklist(kPrefTranslateLanguageBlacklist, original_language); +} + +bool TranslatePrefs::IsSiteBlacklisted(const std::string& site) { + return IsValueBlacklisted(kPrefTranslateSiteBlacklist, site); +} + +void TranslatePrefs::BlacklistSite(const std::string& site) { + BlacklistValue(kPrefTranslateSiteBlacklist, site); +} + +void TranslatePrefs::RemoveSiteFromBlacklist(const std::string& site) { + RemoveValueFromBlacklist(kPrefTranslateSiteBlacklist, site); +} + +bool TranslatePrefs::IsLanguagePairWhitelisted( + const std::string& original_language, + const std::string& target_language) { + const DictionaryValue* dict = prefs_->GetDictionary(kPrefTranslateWhitelists); + if (dict && !dict->empty()) { + ListValue* whitelist = NULL; + if (dict->GetList(ASCIIToWide(original_language), &whitelist) && + whitelist && !whitelist->empty() && + IsValueInList(whitelist, target_language)) + return true; + } + return false; +} + +void TranslatePrefs::WhitelistLanguagePair( + const std::string& original_language, + const std::string& target_language) { + DictionaryValue* dict = prefs_->GetMutableDictionary( + kPrefTranslateWhitelists); + if (!dict) { + NOTREACHED() << "Unregistered translate whitelist pref"; + return; + } + std::wstring wide_original(ASCIIToWide(original_language)); + StringValue* language = new StringValue(target_language); + ListValue* whitelist = NULL; + if (dict->GetList(wide_original, &whitelist) && whitelist) { + whitelist->Append(language); + } else { + ListValue new_whitelist; + new_whitelist.Append(language); + dict->Set(wide_original, new_whitelist.DeepCopy()); + } + prefs_->ScheduleSavePersistentPrefs(); +} + +void TranslatePrefs::RemoveLanguagePairFromWhitelist( + const std::string& original_language, + const std::string& target_language) { + DictionaryValue* dict = prefs_->GetMutableDictionary( + kPrefTranslateWhitelists); + if (!dict) { + NOTREACHED() << "Unregistered translate whitelist pref"; + return; + } + ListValue* whitelist = NULL; + std::wstring wide_original(ASCIIToWide(original_language)); + if (dict->GetList(wide_original, &whitelist) && whitelist) { + StringValue language(target_language); + if (whitelist->Remove(language) != -1) { + if (whitelist->empty()) // If list is empty, remove key from dict. + dict->Remove(wide_original, NULL); + prefs_->ScheduleSavePersistentPrefs(); + } + } +} + +// TranslatePrefs: static: ----------------------------------------------------- + +bool TranslatePrefs::CanTranslate(PrefService* user_prefs, + const std::string& original_language, const GURL& url) { + TranslatePrefs prefs(user_prefs); + if (prefs.IsSiteBlacklisted(url.HostNoBrackets())) + return false; + return (!prefs.IsLanguageBlacklisted(original_language)); +} + +bool TranslatePrefs::ShouldAutoTranslate(PrefService* user_prefs, + const std::string& original_language, + const std::string& target_language) { + TranslatePrefs prefs(user_prefs); + return prefs.IsLanguagePairWhitelisted(original_language, target_language); +} + +// TranslatePrefs: private: ---------------------------------------------------- + +void TranslatePrefs::Register() { + if (!prefs_->FindPreference(kPrefTranslateLanguageBlacklist)) + prefs_->RegisterListPref(kPrefTranslateLanguageBlacklist); + if (!prefs_->FindPreference(kPrefTranslateSiteBlacklist)) + prefs_->RegisterListPref(kPrefTranslateSiteBlacklist); + if (!prefs_->FindPreference(kPrefTranslateWhitelists)) + prefs_->RegisterDictionaryPref(kPrefTranslateWhitelists); +} + +bool TranslatePrefs::IsValueInList(const ListValue* list, + const std::string& in_value) { + for (size_t i = 0; i < list->GetSize(); ++i) { + std::string value; + if (list->GetString(i, &value) && value == in_value) + return true; + } + return false; +} + +bool TranslatePrefs::IsValueBlacklisted(const wchar_t* pref_id, + const std::string& value) { + const ListValue* blacklist = prefs_->GetList(pref_id); + return (blacklist && !blacklist->empty() && IsValueInList(blacklist, value)); +} + +void TranslatePrefs::BlacklistValue(const wchar_t* pref_id, + const std::string& value) { + ListValue* blacklist = prefs_->GetMutableList(pref_id); + if (!blacklist) { + NOTREACHED() << "Unregistered translate blacklist pref"; + return; + } + blacklist->Append(new StringValue(value)); + prefs_->ScheduleSavePersistentPrefs(); +} + +void TranslatePrefs::RemoveValueFromBlacklist(const wchar_t* pref_id, + const std::string& value) { + ListValue* blacklist = prefs_->GetMutableList(pref_id); + if (!blacklist) { + NOTREACHED() << "Unregistered translate blacklist pref"; + return; + } + StringValue string_value(value); + if (blacklist->Remove(string_value) != -1) + prefs_->ScheduleSavePersistentPrefs(); +} diff --git a/chrome/browser/translate/translate_prefs.h b/chrome/browser/translate/translate_prefs.h new file mode 100644 index 0000000..542dacc --- /dev/null +++ b/chrome/browser/translate/translate_prefs.h @@ -0,0 +1,51 @@ +// 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_TRANSLATE_TRANSLATE_PREFS_H_ +#define CHROME_BROWSER_TRANSLATE_TRANSLATE_PREFS_H_ + +#include <vector> + +#include "googleurl/src/gurl.h" + +class ListValue; +class PrefService; + +class TranslatePrefs { + public: + explicit TranslatePrefs(PrefService* user_prefs); + + bool IsLanguageBlacklisted(const std::string& original_language); + void BlacklistLanguage(const std::string& original_language); + void RemoveLanguageFromBlacklist(const std::string& original_language); + + bool IsSiteBlacklisted(const std::string& site); + void BlacklistSite(const std::string& site); + void RemoveSiteFromBlacklist(const std::string& site); + + bool IsLanguagePairWhitelisted(const std::string& original_language, + const std::string& target_language); + void WhitelistLanguagePair(const std::string& original_language, + const std::string& target_language); + void RemoveLanguagePairFromWhitelist(const std::string& original_language, + const std::string& target_language); + + static bool CanTranslate(PrefService* user_prefs, + const std::string& original_language, const GURL& url); + static bool ShouldAutoTranslate(PrefService* user_prefs, + const std::string& original_language, + const std::string& target_language); + + private: + void Register(); + bool IsValueBlacklisted(const wchar_t* pref_id, const std::string& value); + void BlacklistValue(const wchar_t* pref_id, const std::string& value); + void RemoveValueFromBlacklist(const wchar_t* pref_id, + const std::string& value); + bool IsValueInList(const ListValue* list, const std::string& value); + + PrefService* prefs_; // Weak. +}; + +#endif // CHROME_BROWSER_TRANSLATE_TRANSLATE_PREFS_H_ diff --git a/chrome/browser/views/infobars/infobars.cc b/chrome/browser/views/infobars/infobars.cc index 1cba466..fd6437b7 100644 --- a/chrome/browser/views/infobars/infobars.cc +++ b/chrome/browser/views/infobars/infobars.cc @@ -22,12 +22,13 @@ #include "views/widget/widget.h" // static -const double InfoBar::kTargetHeight = 37.0; - -static const int kVerticalPadding = 3; -static const int kHorizontalPadding = 3; -static const int kIconLabelSpacing = 5; -static const int kButtonSpacing = 5; +const double InfoBar::kTargetHeight = 36.0; +const int InfoBar::kHorizontalPadding = 6; +const int InfoBar::kIconLabelSpacing = 6; +const int InfoBar::kButtonButtonSpacing = 10; +const int InfoBar::kEndOfLabelSpacing = 16; +const int InfoBar::kCloseButtonSpacing = 12; +const int InfoBar::kButtonInLabelSpacing = 5; static const SkColor kInfoBackgroundColorTop = SkColorSetRGB(170, 214, 112); static const SkColor kInfoBackgroundColorBottom = SkColorSetRGB(146, 205, 114); @@ -40,25 +41,12 @@ static const SkColor kErrorBackgroundColorTop = kWarningBackgroundColorTop; static const SkColor kErrorBackgroundColorBottom = kWarningBackgroundColorBottom; -static const int kSeparatorLineHeight = 1; - -namespace { -// Returns a centered y-position of a control of height specified in |prefsize| -// within the standard InfoBar height. Stable during an animation. -int CenterY(const gfx::Size prefsize) { - return std::max((static_cast<int>(InfoBar::kTargetHeight) - - prefsize.height()) / 2, 0); -} +static const SkColor kPageActionBackgroundColorTop = + SkColorSetRGB(209, 222, 245); +static const SkColor kPageActionBackgroundColorBottom = + SkColorSetRGB(178, 201, 239); -// Returns a centered y-position of a control of height specified in |prefsize| -// within the standard InfoBar height, adjusted according to the current amount -// of animation offset the |parent| InfoBar currently has. Changes during an -// animation. -int OffsetY(views::View* parent, const gfx::Size prefsize) { - return CenterY(prefsize) - - (static_cast<int>(InfoBar::kTargetHeight) - parent->height()); -} -} +static const int kSeparatorLineHeight = 1; // InfoBarBackground ----------------------------------------------------------- @@ -80,6 +68,10 @@ class InfoBarBackground : public views::Background { top_color = kErrorBackgroundColorTop; bottom_color = kErrorBackgroundColorBottom; break; + case InfoBarDelegate::PAGE_ACTION_TYPE: + top_color = kPageActionBackgroundColorTop; + bottom_color = kPageActionBackgroundColorBottom; + break; default: NOTREACHED(); break; @@ -169,7 +161,7 @@ gfx::Size InfoBar::GetPreferredSize() { void InfoBar::Layout() { gfx::Size button_ps = close_button_->GetPreferredSize(); - close_button_->SetBounds(width() - kButtonSpacing - button_ps.width(), + close_button_->SetBounds(width() - kHorizontalPadding - button_ps.width(), OffsetY(this, button_ps), button_ps.width(), button_ps.height()); } @@ -188,13 +180,23 @@ void InfoBar::ViewHierarchyChanged(bool is_add, views::View* parent, // InfoBar, protected: --------------------------------------------------------- int InfoBar::GetAvailableWidth() const { - return close_button_->x() - kButtonSpacing; + return close_button_->x() - kCloseButtonSpacing; } void InfoBar::RemoveInfoBar() const { container_->RemoveDelegate(delegate()); } +int InfoBar::CenterY(const gfx::Size prefsize) { + return std::max((static_cast<int>(InfoBar::kTargetHeight) - + prefsize.height()) / 2, 0); +} + +int InfoBar::OffsetY(views::View* parent, const gfx::Size prefsize) { + return CenterY(prefsize) - + (static_cast<int>(InfoBar::kTargetHeight) - parent->height()); +} + // InfoBar, views::ButtonListener implementation: ------------------ void InfoBar::ButtonPressed(views::Button* sender, const views::Event& event) { @@ -453,7 +455,7 @@ void ConfirmInfoBar::Layout() { cancel_button_->SetBounds(available_width - cancel_button_width, OffsetY(this, cancel_ps), cancel_ps.width(), cancel_ps.height()); - int spacing = cancel_button_width > 0 ? kButtonSpacing : 0; + int spacing = cancel_button_width > 0 ? kButtonButtonSpacing : 0; ok_button_->SetBounds(cancel_button_->x() - spacing - ok_button_width, OffsetY(this, ok_ps), ok_ps.width(), ok_ps.height()); AlertInfoBar::Layout(); @@ -487,9 +489,9 @@ void ConfirmInfoBar::ButtonPressed( int ConfirmInfoBar::GetAvailableWidth() const { if (ok_button_) - return ok_button_->x() - kButtonSpacing; + return ok_button_->x() - kEndOfLabelSpacing; if (cancel_button_) - return cancel_button_->x() - kButtonSpacing; + return cancel_button_->x() - kEndOfLabelSpacing; return InfoBar::GetAvailableWidth(); } diff --git a/chrome/browser/views/infobars/infobars.h b/chrome/browser/views/infobars/infobars.h index 9870ad4..970b1ab 100644 --- a/chrome/browser/views/infobars/infobars.h +++ b/chrome/browser/views/infobars/infobars.h @@ -56,6 +56,13 @@ class InfoBar : public views::View, // is (due to animation). static const double kTargetHeight; + static const int kHorizontalPadding; + static const int kIconLabelSpacing; + static const int kButtonButtonSpacing; + static const int kEndOfLabelSpacing; + static const int kCloseButtonSpacing; + static const int kButtonInLabelSpacing; + // Overridden from views::View: virtual gfx::Size GetPreferredSize(); virtual void Layout(); @@ -74,6 +81,16 @@ class InfoBar : public views::View, // (Will lead to this InfoBar being closed). void RemoveInfoBar() const; + // Returns a centered y-position of a control of height specified in + // |prefsize| within the standard InfoBar height. Stable during an animation. + int CenterY(const gfx::Size prefsize); + + // Returns a centered y-position of a control of height specified in + // |prefsize| within the standard InfoBar height, adjusted according to the + // current amount of animation offset the |parent| InfoBar currently has. + // Changes during an animation. + int OffsetY(views::View* parent, const gfx::Size prefsize); + // Overridden from views::ButtonListener: virtual void ButtonPressed(views::Button* sender, const views::Event& event); diff --git a/chrome/browser/views/infobars/translate_infobars.cc b/chrome/browser/views/infobars/translate_infobars.cc new file mode 100644 index 0000000..c1850df --- /dev/null +++ b/chrome/browser/views/infobars/translate_infobars.cc @@ -0,0 +1,606 @@ +// 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/views/infobars/translate_infobars.h" + +#include "app/gfx/canvas.h" +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/utf_string_conversions.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/translate/languages_menu_model.h" +#include "chrome/browser/translate/options_menu_model.h" +#include "grit/app_resources.h" +#include "grit/generated_resources.h" +#include "grit/locale_settings.h" +#include "grit/theme_resources.h" +#include "views/controls/button/image_button.h" +#include "views/controls/button/menu_button.h" +#include "views/controls/button/text_button.h" +#include "views/controls/image_view.h" +#include "views/controls/label.h" +#include "views/controls/message_box_view.h" + +// IDs for various menus. +static const int kMenuIDOptions = 1000; +static const int kMenuIDOriginalLanguage = 1001; +static const int kMenuIDTargetLanguage = 1002; + +//////////////////////////////////////////////////////////////////////////////// +// +// TranslateButtonBorder +// +// A TextButtonBorder subclass that adds to also paint button frame in normal +// state, and changes the images used. +// +//////////////////////////////////////////////////////////////////////////////// + +class TranslateButtonBorder : public views::TextButtonBorder { + public: + TranslateButtonBorder(); + virtual ~TranslateButtonBorder(); + + // Overriden from Border + virtual void Paint(const views::View& view, gfx::Canvas* canvas) const; + + private: + MBBImageSet normal_set_; + + private: + DISALLOW_COPY_AND_ASSIGN(TranslateButtonBorder); +}; + +// TranslateButtonBorder, public: ---------------------------------------------- + +TranslateButtonBorder::TranslateButtonBorder() { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + + normal_set_.top_left = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_LEFT_N); + normal_set_.top = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_N); + normal_set_.top_right = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_RIGHT_N); + normal_set_.left = rb.GetBitmapNamed(IDR_INFOBARBUTTON_LEFT_N); + normal_set_.center = rb.GetBitmapNamed(IDR_INFOBARBUTTON_CENTER_N); + normal_set_.right = rb.GetBitmapNamed(IDR_INFOBARBUTTON_RIGHT_N); + normal_set_.bottom_left = rb.GetBitmapNamed(IDR_INFOBARBUTTON_BOTTOM_LEFT_N); + normal_set_.bottom = rb.GetBitmapNamed(IDR_INFOBARBUTTON_BOTTOM_N); + normal_set_.bottom_right = rb.GetBitmapNamed( + IDR_INFOBARBUTTON_BOTTOM_RIGHT_N); + + hot_set_.top_left = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_LEFT_H); + hot_set_.top = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_H); + hot_set_.top_right = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_RIGHT_H); + hot_set_.left = rb.GetBitmapNamed(IDR_INFOBARBUTTON_LEFT_H); + hot_set_.center = rb.GetBitmapNamed(IDR_INFOBARBUTTON_CENTER_H); + hot_set_.right = rb.GetBitmapNamed(IDR_INFOBARBUTTON_RIGHT_H); + hot_set_.bottom_left = rb.GetBitmapNamed(IDR_INFOBARBUTTON_BOTTOM_LEFT_H); + hot_set_.bottom = rb.GetBitmapNamed(IDR_INFOBARBUTTON_BOTTOM_H); + hot_set_.bottom_right = rb.GetBitmapNamed(IDR_INFOBARBUTTON_BOTTOM_RIGHT_H); + + pushed_set_.top_left = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_LEFT_P); + pushed_set_.top = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_P); + pushed_set_.top_right = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_RIGHT_P); + pushed_set_.left = rb.GetBitmapNamed(IDR_INFOBARBUTTON_LEFT_P); + pushed_set_.center = rb.GetBitmapNamed(IDR_INFOBARBUTTON_CENTER_P); + pushed_set_.right = rb.GetBitmapNamed(IDR_INFOBARBUTTON_RIGHT_P); + pushed_set_.bottom_left = rb.GetBitmapNamed(IDR_INFOBARBUTTON_BOTTOM_LEFT_P); + pushed_set_.bottom = rb.GetBitmapNamed(IDR_INFOBARBUTTON_BOTTOM_P); + pushed_set_.bottom_right = rb.GetBitmapNamed( + IDR_INFOBARBUTTON_BOTTOM_RIGHT_P); +} + +TranslateButtonBorder::~TranslateButtonBorder() { +} + +// TranslateButtonBorder, Border overrides: ------------------------------------ + +void TranslateButtonBorder::Paint(const views::View& view, gfx::Canvas* canvas) + const { + const views::TextButton* mb = static_cast<const views::TextButton*>(&view); + int state = mb->state(); + + // TextButton takes care of deciding when to call Paint. + const MBBImageSet* set = &normal_set_; + if (state == views::TextButton::BS_HOT) + set = &hot_set_; + else if (state == views::TextButton::BS_PUSHED) + set = &pushed_set_; + + TextButtonBorder::Paint(view, canvas, *set); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// TranslateTextButton +// +// A TextButton subclass that overrides OnMousePressed to default to +// CustomButton so as to create pressed state effect. +// +//////////////////////////////////////////////////////////////////////////////// + +class TranslateTextButton : public views::TextButton { + public: + TranslateTextButton(views::ButtonListener* listener, int label_id); + virtual ~TranslateTextButton(); + + protected: + // Overriden from TextButton: + virtual bool OnMousePressed(const views::MouseEvent& e); + + private: + DISALLOW_COPY_AND_ASSIGN(TranslateTextButton); +}; + +// TranslateButtonBorder, public: ---------------------------------------------- + +TranslateTextButton::TranslateTextButton(views::ButtonListener* listener, + int label_id) + : TextButton(listener, l10n_util::GetString(label_id)) { + set_border(new TranslateButtonBorder); + SetNormalHasBorder(true); // Normal button state has border. + SetAnimationDuration(0); // Disable animation during state change. +} + +TranslateTextButton::~TranslateTextButton() { +} + +// TranslateButtonBorder, protected:-------------------------------------------- +bool TranslateTextButton::OnMousePressed(const views::MouseEvent& e) { + return views::CustomButton::OnMousePressed(e); +} + +// TranslateInfoBar, public: --------------------------------------------------- + +TranslateInfoBar::TranslateInfoBar(TranslateInfoBarDelegate* delegate, + bool before_translate, int label_id) + : InfoBar(delegate), + before_translate_(before_translate), + swapped_language_placeholders_(false) { + icon_ = new views::ImageView; + SkBitmap* image = delegate->GetIcon(); + if (image) + icon_->SetImage(image); + AddChildView(icon_); + + // Set up the labels. + std::vector<size_t> offsets; + std::wstring message_text = l10n_util::GetStringF(label_id, std::wstring(), + std::wstring(), &offsets); + if (!offsets.empty() && offsets.size() <= 2) { + // Sort the offsets if necessary. + if (offsets.size() == 2 && offsets[0] > offsets[1]) { + size_t offset0 = offsets[0]; + offsets[0] = offsets[1]; + offsets[1] = offset0; + swapped_language_placeholders_ = true; + } + if (offsets[offsets.size() - 1] != message_text.length()) + offsets.push_back(message_text.length()); + } else { + NOTREACHED() << "Invalid no. of placeholders in label."; + } + + const gfx::Font& font = ResourceBundle::GetSharedInstance().GetFont( + ResourceBundle::MediumFont); + label_1_ = new views::Label(message_text.substr(0, offsets[0]), font); + label_1_->SetColor(SK_ColorBLACK); + label_1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + AddChildView(label_1_); + + label_2_ = new views::Label( + message_text.substr(offsets[0], offsets[1] - offsets[0]), font); + label_2_->SetColor(SK_ColorBLACK); + label_2_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + AddChildView(label_2_); + + if (offsets.size() == 3) { + label_3_ = new views::Label( + message_text.substr(offsets[1], offsets[2] - offsets[1]), font); + label_3_->SetColor(SK_ColorBLACK); + label_3_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + AddChildView(label_3_); + } else { + label_3_ = NULL; + } + + string16 language_name = TranslateInfoBarDelegate::GetDisplayNameForLocale( + GetDelegate()->original_lang_code()); + original_language_menu_button_ = CreateMenuButton(kMenuIDOriginalLanguage, + UTF16ToWideHack(language_name)); + AddChildView(original_language_menu_button_); + + options_menu_button_ = CreateMenuButton(kMenuIDOptions, + l10n_util::GetString(IDS_TRANSLATE_INFOBAR_OPTIONS)); + AddChildView(options_menu_button_); +} + +TranslateInfoBar::~TranslateInfoBar() { +} + +// TranslateInfoBar, views::View overrides: ------------------------------------ + +void TranslateInfoBar::Layout() { + // Layout the close button. + InfoBar::Layout(); + + // Layout the icon on left of bar. + gfx::Size icon_ps = icon_->GetPreferredSize(); + icon_->SetBounds(InfoBar::kHorizontalPadding, InfoBar::OffsetY(this, icon_ps), + icon_ps.width(), icon_ps.height()); + + // Layout the options menu button on right of bar. + int available_width = InfoBar::GetAvailableWidth(); + gfx::Size options_ps = options_menu_button_->GetPreferredSize(); + options_menu_button_->SetBounds(available_width - options_ps.width(), + OffsetY(this, options_ps), options_ps.width(), options_ps.height()); + + // Layout the controls between icon and options i.e. labels, original language + // menu button, and if available, target language menu button. + // We layout target language menu button here (as opposed to in + // AfterTranslateInfoBar) because the 2 language menu buttons could be swapped + // for different locales. + views::MenuButton* button1 = original_language_menu_button_; + views::MenuButton* button2 = target_language_menu_button(); + if (button2 && swapped_language_placeholders_) { + button1 = button2; + button2 = original_language_menu_button_; + } + gfx::Size button1_ps = button1->GetPreferredSize(); + int available_text_width = std::max(GetAvailableWidth(), 0); + gfx::Size label1_ps = label_1_->GetPreferredSize(); + gfx::Size label2_ps = label_2_->GetPreferredSize(); + gfx::Size label3_ps; + if (label_3_) + label3_ps = label_3_->GetPreferredSize(); + int text1_width = label1_ps.width(); + int text2_width = label2_ps.width(); + int text3_width = label3_ps.width(); + int total_text_width = text1_width + text2_width + text3_width; + if (total_text_width > available_text_width) { + double ratio = static_cast<double>(available_text_width) / + static_cast<double>(total_text_width); + text1_width = static_cast<int>(text1_width * ratio); + text2_width = static_cast<int>(text2_width * ratio); + text3_width = static_cast<int>(text3_width * ratio); + } + label_1_->SetBounds(icon_->bounds().right() + InfoBar::kIconLabelSpacing, + InfoBar::OffsetY(this, label1_ps), text1_width, label1_ps.height()); + + // Place first language menu button after label_1. + button1->SetBounds(label_1_->bounds().right() + + InfoBar::kButtonInLabelSpacing, OffsetY(this, button1_ps), + button1_ps.width(), button1_ps.height()); + + // Place label_2 after first language menu button. + label_2_->SetBounds(button1->bounds().right() + + GetSpacingAfterFirstLanguageButton(), InfoBar::OffsetY(this, label2_ps), + text2_width, label2_ps.height()); + + // If second language menu button is available, place it after label_2. + if (button2) { + gfx::Size button2_ps = button2->GetPreferredSize(); + button2->SetBounds(label_2_->bounds().right() + + InfoBar::kButtonInLabelSpacing, OffsetY(this, button2_ps), + button2_ps.width(), button2_ps.height()); + + if (label_3_) { + gfx::Size label3_ps = label_3_->GetPreferredSize(); + // Place label_3 after first language menu button. + label_3_->SetBounds(button2->bounds().right() + + InfoBar::kButtonInLabelSpacing, InfoBar::OffsetY(this, label3_ps), + text3_width, label3_ps.height()); + } + } +} + +// TranslateInfoBar, InfoBar overrides: ---------------------------------------- + +int TranslateInfoBar::GetAvailableWidth() const { + gfx::Size icon_ps = icon_->GetPreferredSize(); + // For language button, reserve spacing before and after it. + gfx::Size language_ps = original_language_menu_button_->GetPreferredSize(); + int language_spacing = InfoBar::kButtonInLabelSpacing + + GetSpacingAfterFirstLanguageButton(); + // Options button could come after different types of controls, so we reserve + // different spacings for each: + // - after label_3 (i.e. this label follows the second language button): + // spacing after second language button and for end of sentence + // - after second language button (i.e. there's no label_3): spacing for end + // of sentence + // - all other cases, regular button spacing before options button + gfx::Size options_ps = options_menu_button_->GetPreferredSize(); + int options_spacing = + (label_3_ ? InfoBar::kButtonInLabelSpacing + InfoBar::kEndOfLabelSpacing : + (target_language_menu_button() ? InfoBar::kEndOfLabelSpacing : + InfoBar::kButtonButtonSpacing)); + return (InfoBar::GetAvailableWidth() - options_ps.width() - options_spacing - + language_ps.width() - language_spacing - + icon_->bounds().right() - InfoBar::kIconLabelSpacing); +} + +// TranslateInfoBar, views::ViewMenuDelegate implementation: ------------------- + +void TranslateInfoBar::RunMenu(views::View* source, const gfx::Point& pt) { + int menu_id = source->GetID(); + if (menu_id == kMenuIDOptions) { + if (!options_menu_model_.get()) { + options_menu_model_.reset(new OptionsMenuModel(this, GetDelegate(), + before_translate_)); + options_menu_menu_.reset(new views::Menu2(options_menu_model_.get())); + } + options_menu_menu_->RunMenuAt(pt, + (UILayoutIsRightToLeft() ? views::Menu2::ALIGN_TOPLEFT : + views::Menu2::ALIGN_TOPRIGHT)); + } else if (menu_id == kMenuIDOriginalLanguage) { + if (!original_language_menu_model_.get()) { + original_language_menu_model_.reset( + new LanguagesMenuModel(this, GetDelegate(), true)); + original_language_menu_menu_.reset( + new views::Menu2(original_language_menu_model_.get())); + } + views::Menu2::Alignment alignment; + gfx::Point menu_position = DetermineMenuPositionAndAlignment( + original_language_menu_button_, &alignment); + original_language_menu_menu_->RunMenuAt(menu_position, alignment); + } else { + NOTREACHED() << "Invalid source menu."; + } +} + +// TranslateInfoBar, views::SimpleMenuModel::Delegate implementation: ---------- + +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, + views::Accelerator* accelerator) { + return false; +} + +void TranslateInfoBar::ExecuteCommand(int command_id) { + if (command_id >= IDC_TRANSLATE_ORIGINAL_LANGUAGE_BASE) { + OnLanguageModified(original_language_menu_button_, + command_id - IDC_TRANSLATE_ORIGINAL_LANGUAGE_BASE); + } else { + 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; + } + } +} + +// TranslateInfoBar, protected: ------------------------------------------------ + +views::MenuButton* TranslateInfoBar::CreateMenuButton(int menu_id, + const std::wstring& label) { + views::MenuButton* menu_button = + new views::MenuButton(NULL, label, this, true); + menu_button->SetID(menu_id); + menu_button->set_border(new TranslateButtonBorder); + menu_button->SetNormalHasBorder(true); + menu_button->SetAnimationDuration(0); + return menu_button; +} + +int TranslateInfoBar::GetAvailableX() const { + return ((label_3_ ? label_3_->bounds().right() : label_2_->bounds().right()) + + InfoBar::kEndOfLabelSpacing); +} + +gfx::Point TranslateInfoBar::DetermineMenuPositionAndAlignment( + views::MenuButton* menu_button, views::Menu2::Alignment* alignment) { + gfx::Rect lb = menu_button->GetLocalBounds(true); + gfx::Point menu_position(lb.origin()); + menu_position.Offset(2, lb.height() - 3); + if (UILayoutIsRightToLeft()) { + menu_position.Offset(lb.width() - 4, 0); + *alignment = views::Menu2::ALIGN_TOPRIGHT; + } else { + *alignment = views::Menu2::ALIGN_TOPLEFT; + } + View::ConvertPointToScreen(menu_button, &menu_position); +#if defined(OS_WIN) + int left_bound = GetSystemMetrics(SM_XVIRTUALSCREEN); + if (menu_position.x() < left_bound) + menu_position.set_x(left_bound); +#endif + return menu_position; +} + +void TranslateInfoBar::OnLanguageModified(views::MenuButton* menu_button, + int new_language_index) { + // Only proceed if a different language has been selected. + if (menu_button == original_language_menu_button_) { + if (new_language_index == GetDelegate()->original_lang_index()) + return; + GetDelegate()->ModifyOriginalLanguage(new_language_index); + } else { + if (new_language_index == GetDelegate()->target_lang_index()) + return; + GetDelegate()->ModifyTargetLanguage(new_language_index); + } + + string16 new_language = TranslateInfoBarDelegate::GetDisplayNameForLocale( + GetDelegate()->GetLocaleFromIndex(new_language_index)); + menu_button->SetText(UTF16ToWideHack(new_language)); + menu_button->ClearMaxTextSize(); + menu_button->SizeToPreferredSize(); + Layout(); + SchedulePaint(); + // Clear options menu model so that it'll be created with new language. + options_menu_model_.reset(); + if (!before_translate_) + GetDelegate()->Translate(); +} + +TranslateInfoBarDelegate* TranslateInfoBar::GetDelegate() const { + return static_cast<TranslateInfoBarDelegate*>(delegate()); +} + +// BeforeTranslateInfoBar, public: --------------------------------------------- + +BeforeTranslateInfoBar::BeforeTranslateInfoBar( + BeforeTranslateInfoBarDelegate* delegate) + : TranslateInfoBar(delegate, true, IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE) { + accept_button_ = new TranslateTextButton(this, IDS_TRANSLATE_INFOBAR_ACCEPT); + AddChildView(accept_button_); + + deny_button_ = new TranslateTextButton(this, IDS_TRANSLATE_INFOBAR_DENY); + AddChildView(deny_button_); +} + +BeforeTranslateInfoBar::~BeforeTranslateInfoBar() { +} + +// BeforeTranslateInfoBar, InfoBar overrides: ---------------------------------- + +int BeforeTranslateInfoBar::GetAvailableWidth() const { + gfx::Size accept_ps = accept_button_->GetPreferredSize(); + gfx::Size deny_ps = deny_button_->GetPreferredSize(); + return (TranslateInfoBar::GetAvailableWidth() - + accept_ps.width() - InfoBar::kEndOfLabelSpacing - + deny_ps.width() - InfoBar::kButtonButtonSpacing); +} + +// BeforeTranslateInfoBar, views::View overrides: ------------------------------ + +void BeforeTranslateInfoBar::Layout() { + // Layout the icon, options menu, language menu and close buttons. + TranslateInfoBar::Layout(); + + // Layout accept button. + gfx::Size accept_ps = accept_button_->GetPreferredSize(); + accept_button_->SetBounds(TranslateInfoBar::GetAvailableX(), + OffsetY(this, accept_ps), accept_ps.width(), accept_ps.height()); + + // Layout deny button. + gfx::Size deny_ps = deny_button_->GetPreferredSize(); + deny_button_->SetBounds( + accept_button_->bounds().right() + InfoBar::kButtonButtonSpacing, + OffsetY(this, deny_ps), deny_ps.width(), deny_ps.height()); +} + +// BeforeTranslateInfoBar, views::ButtonListener overrides: -------------------- + +void BeforeTranslateInfoBar::ButtonPressed( + views::Button* sender, const views::Event& event) { + if (sender == accept_button_) { + // TODO(kuan): If privacy warning box is needed (awaiting PM/UX decision), + // implement it. + GetDelegate()->Translate(); + } else if (sender != deny_button_) { // Let base InfoBar handle close button. + InfoBar::ButtonPressed(sender, event); + } + RemoveInfoBar(); +} + +// AfterTranslateInfoBar, public: ---------------------------------------------- + +AfterTranslateInfoBar::AfterTranslateInfoBar( + AfterTranslateInfoBarDelegate* delegate) + : TranslateInfoBar(delegate, false, IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE) { + string16 language_name = TranslateInfoBarDelegate::GetDisplayNameForLocale( + GetDelegate()->target_lang_code()); + target_language_menu_button_ = CreateMenuButton(kMenuIDTargetLanguage, + UTF16ToWideHack(language_name)); + AddChildView(target_language_menu_button_); +} + +AfterTranslateInfoBar::~AfterTranslateInfoBar() { +} + +// AfterTranslateInfoBar, InfoBar overrides: ---------------------------------- + +int AfterTranslateInfoBar::GetAvailableWidth() const { + gfx::Size target_ps = target_language_menu_button_->GetPreferredSize(); + return (TranslateInfoBar::GetAvailableWidth() - target_ps.width() - + InfoBar::kButtonInLabelSpacing); +} + +// AfterTranslateInfoBar, views::ViewMenuDelegate implementation: -------------- + +void AfterTranslateInfoBar::RunMenu(views::View* source, const gfx::Point& pt) { + if (source->GetID() == kMenuIDTargetLanguage) { + if (!target_language_menu_model_.get()) { + target_language_menu_model_.reset( + new LanguagesMenuModel(this, GetDelegate(), false)); + target_language_menu_menu_.reset( + new views::Menu2(target_language_menu_model_.get())); + } + views::Menu2::Alignment alignment; + gfx::Point menu_position = DetermineMenuPositionAndAlignment( + target_language_menu_button_, &alignment); + target_language_menu_menu_->RunMenuAt(menu_position, alignment); + } else { + TranslateInfoBar::RunMenu(source, pt); + } +} + +// AfterTranslateInfoBar, views::SimpleMenuModel::Delegate implementation: ----- + +void AfterTranslateInfoBar::ExecuteCommand(int command_id) { + if (command_id >= IDC_TRANSLATE_TARGET_LANGUAGE_BASE) { + OnLanguageModified(target_language_menu_button_, + command_id - IDC_TRANSLATE_TARGET_LANGUAGE_BASE); + } else { + TranslateInfoBar::ExecuteCommand(command_id); + } +} + +// BeforeTranslateInfoBarDelegate, InfoBarDelegate overrides: ------------------ + +InfoBar* BeforeTranslateInfoBarDelegate::CreateInfoBar() { + return new BeforeTranslateInfoBar(this); +} + +// AfterTranslateInfoBarDelegate, InfoBarDelegate overrides: ------------------ + +InfoBar* AfterTranslateInfoBarDelegate::CreateInfoBar() { + return new AfterTranslateInfoBar(this); +} + diff --git a/chrome/browser/views/infobars/translate_infobars.h b/chrome/browser/views/infobars/translate_infobars.h new file mode 100644 index 0000000..a571a7e --- /dev/null +++ b/chrome/browser/views/infobars/translate_infobars.h @@ -0,0 +1,146 @@ +// 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_VIEWS_INFOBARS_TRANSLATE_INFOBARS_H_ +#define CHROME_BROWSER_VIEWS_INFOBARS_TRANSLATE_INFOBARS_H_ + +#include "views/controls/menu/simple_menu_model.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 "views/controls/menu/menu_2.h" + +namespace views { +class ImageButton; +class ImageView; +class Label; +class MenuButton; +} +class LanguagesMenuModel; +class OptionsMenuModel; +class TranslateTextButton; + +// This file contains implementations for infobars for the Translate feature. + +class TranslateInfoBar : public InfoBar, + public views::ViewMenuDelegate, + public views::SimpleMenuModel::Delegate { + public: + TranslateInfoBar(TranslateInfoBarDelegate* delegate, bool before_translate, + int label_id); + virtual ~TranslateInfoBar(); + + // Overridden from views::View: + virtual void Layout(); + + // Overridden from views::MenuDelegate: + virtual void RunMenu(views::View* source, const gfx::Point& pt); + + // Overridden from views::SimpleMenuModel::Delegate: + virtual bool IsCommandIdChecked(int command_id) const; + virtual bool IsCommandIdEnabled(int command_id) const; + virtual bool GetAcceleratorForCommandId(int command_id, + views::Accelerator* accelerator); + virtual void ExecuteCommand(int command_id); + + protected: + views::MenuButton* CreateMenuButton(int menu_id, const std::wstring& label); + gfx::Point DetermineMenuPositionAndAlignment(views::MenuButton* menu_button, + views::Menu2::Alignment* alignment); + void OnLanguageModified(views::MenuButton* menu_button, + int new_language_index); + TranslateInfoBarDelegate* GetDelegate() const; + + // Overridden from InfoBar: + virtual int GetAvailableWidth() const; + + // Returns the leftmost position that subclasses can position their controls. + virtual int GetAvailableX() const; + + virtual views::MenuButton* target_language_menu_button() const { + return NULL; + } + + virtual int GetSpacingAfterFirstLanguageButton() const { + return InfoBar::kButtonInLabelSpacing; + } + + private: + bool before_translate_; + views::ImageView* icon_; + views::Label* label_1_; + views::Label* label_2_; + views::Label* label_3_; + views::MenuButton* original_language_menu_button_; + views::MenuButton* options_menu_button_; + + scoped_ptr<LanguagesMenuModel> original_language_menu_model_; + scoped_ptr<OptionsMenuModel> options_menu_model_; + + scoped_ptr<views::Menu2> original_language_menu_menu_; + scoped_ptr<views::Menu2> options_menu_menu_; + + // This is true if language placeholders in label have been swapped. + bool swapped_language_placeholders_; + + DISALLOW_COPY_AND_ASSIGN(TranslateInfoBar); +}; + +class BeforeTranslateInfoBar : public TranslateInfoBar { + public: + explicit BeforeTranslateInfoBar(BeforeTranslateInfoBarDelegate* delegate); + virtual ~BeforeTranslateInfoBar(); + + // Overridden from views::View: + virtual void Layout(); + + protected: + // Overridden from views::ButtonListener: + virtual void ButtonPressed(views::Button* sender, const views::Event& event); + + // Overriden from TranslateInfoBar: + virtual int GetSpacingAfterFirstLanguageButton() const { + return 10; + } + + // Overridden from InfoBar: + virtual int GetAvailableWidth() const; + + private: + TranslateTextButton* accept_button_; + TranslateTextButton* deny_button_; + + DISALLOW_COPY_AND_ASSIGN(BeforeTranslateInfoBar); +}; + +class AfterTranslateInfoBar : public TranslateInfoBar { + public: + explicit AfterTranslateInfoBar(AfterTranslateInfoBarDelegate* delegate); + virtual ~AfterTranslateInfoBar(); + + // Overridden from views::MenuDelegate: + virtual void RunMenu(views::View* source, const gfx::Point& pt); + + // Overridden from views::SimpleMenuModel::Delegate: + virtual void ExecuteCommand(int command_id); + + protected: + // Overridden from InfoBar: + virtual int GetAvailableWidth() const; + + virtual views::MenuButton* target_language_menu_button() const { + return target_language_menu_button_; + } + + private: + views::MenuButton* target_language_menu_button_; + + scoped_ptr<LanguagesMenuModel> target_language_menu_model_; + + scoped_ptr<views::Menu2> target_language_menu_menu_; + + DISALLOW_COPY_AND_ASSIGN(AfterTranslateInfoBar); +}; + +#endif // CHROME_BROWSER_VIEWS_INFOBARS_TRANSLATE_INFOBARS_H_ diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 6da2208e..a7ec0e2 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -2262,6 +2262,14 @@ 'browser/thumbnail_store.h', 'browser/toolbar_model.cc', 'browser/toolbar_model.h', + 'browser/translate/languages_menu_model.cc', + 'browser/translate/languages_menu_model.h', + 'browser/translate/options_menu_model.cc', + 'browser/translate/options_menu_model.h', + 'browser/translate/translate_infobars_delegates.cc', + 'browser/translate/translate_infobars_delegates.h', + 'browser/translate/translate_prefs.cc', + 'browser/translate/translate_prefs.h', 'browser/user_data_manager.cc', 'browser/user_data_manager.h', 'browser/utility_process_host.cc', @@ -2406,6 +2414,8 @@ 'browser/views/infobars/infobar_container.h', 'browser/views/infobars/infobars.cc', 'browser/views/infobars/infobars.h', + 'browser/views/infobars/translate_infobars.cc', + 'browser/views/infobars/translate_infobars.h', 'browser/views/jsmessage_box_dialog.cc', 'browser/views/jsmessage_box_dialog.h', 'browser/views/keyword_editor_view.cc', |