diff options
18 files changed, 1535 insertions, 89 deletions
diff --git a/chrome/app/chrome_dll_resource.h b/chrome/app/chrome_dll_resource.h index 6d1090b..5302f1f 100644 --- a/chrome/app/chrome_dll_resource.h +++ b/chrome/app/chrome_dll_resource.h @@ -230,13 +230,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 3584702..135c3da 100644 --- a/chrome/app/resources/locale_settings.grd +++ b/chrome/app/resources/locale_settings.grd @@ -586,6 +586,11 @@ <message name="IDS_AUTOFILL_DIALOG_HEIGHT_LINES" use_name_for_id="true"> 35 </message> + + <!-- The URL for About Google Translate. --> + <message name="IDS_ABOUT_GOOGLE_TRANSLATE_URL" translateable="false"> + http://translate.google.com/support/?hl=[GRITLANGCODE] + </message> </messages> </release> </grit> diff --git a/chrome/browser/tab_contents/infobar_delegate.h b/chrome/browser/tab_contents/infobar_delegate.h index d6a1899..1ec6506 100644 --- a/chrome/browser/tab_contents/infobar_delegate.h +++ b/chrome/browser/tab_contents/infobar_delegate.h @@ -13,6 +13,7 @@ class AlertInfoBarDelegate; class ConfirmInfoBarDelegate; +class TranslateInfoBarDelegate; class InfoBar; class LinkInfoBarDelegate; class SkBitmap; @@ -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..3f26d58 --- /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( + menus::SimpleMenuModel::Delegate* menu_delegate, + TranslateInfoBarDelegate* translate_delegate, + bool original_language) + : menus::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, ASCIIToUTF16(*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..00780e9 --- /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 "app/menus/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 menus::SimpleMenuModel { + public: + explicit LanguagesMenuModel(menus::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..4dfd631 --- /dev/null +++ b/chrome/browser/translate/options_menu_model.cc @@ -0,0 +1,37 @@ +// 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(menus::SimpleMenuModel::Delegate* delegate, + TranslateInfoBarDelegate* translate_delegate, bool before_translate) + : menus::SimpleMenuModel(delegate) { + string16 original_language = + ASCIIToUTF16(translate_delegate->original_language()); + 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 { + AddCheckItem(IDC_TRANSLATE_OPTIONS_ALWAYS, + l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS_ALWAYS, + original_language, + ASCIIToUTF16(translate_delegate->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..e335059 --- /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 "app/menus/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 menus::SimpleMenuModel { + public: + explicit OptionsMenuModel(menus::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..a80506f --- /dev/null +++ b/chrome/browser/translate/translate_infobars_delegates.cc @@ -0,0 +1,214 @@ +// 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/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( + const std::string& original_language) { + original_language_ = original_language; + // TODO(kuan): Send stats to Google Translate that original language has been + // modified. +} + +void TranslateInfoBarDelegate::ModifyTargetLanguage( + const std::string& target_language) { + NOTREACHED() << "Subclass should override"; +} + +void TranslateInfoBarDelegate::GetAvailableOriginalLanguages( + std::vector<std::string>* languages) { + // TODO(kuan): Call backend when it's ready; hardcode a list for now. + languages->push_back("Arabic"); + languages->push_back("Bengali"); + languages->push_back("Bulgarian"); + languages->push_back("Chinese (Simplified Han)"); + languages->push_back("Chinese (Traditional Han)"); + languages->push_back("Croatian"); + languages->push_back("Czech"); + languages->push_back("Danish"); + languages->push_back("Dutch"); + languages->push_back("English"); + languages->push_back("Estonian"); + languages->push_back("Filipino"); + languages->push_back("Finnish"); + languages->push_back("French"); + languages->push_back("German"); + languages->push_back("Greek"); + languages->push_back("Hebrew"); + languages->push_back("Hindi"); + languages->push_back("Hungarian"); + languages->push_back("Indonesian"); + languages->push_back("Italian"); + languages->push_back("Japanese"); + languages->push_back("Korean"); + languages->push_back("Latvian"); + languages->push_back("Lithuanian"); + languages->push_back("Norwegian"); + languages->push_back("Polish"); + languages->push_back("Portuguese"); + languages->push_back("Romanian"); + languages->push_back("Russian"); + languages->push_back("Serbian"); + languages->push_back("Slovak"); + languages->push_back("Slovenian"); + languages->push_back("Spanish"); + languages->push_back("Swedish"); + languages->push_back("Tamil"); + languages->push_back("Thai"); + languages->push_back("Turkish"); + languages->push_back("Ukrainian"); + languages->push_back("Vietnamese"); +} + +void TranslateInfoBarDelegate::GetAvailableTargetLanguages( + std::vector<std::string>* languages) { + NOTREACHED() << "Subclass should override"; +} + +void TranslateInfoBarDelegate::Translate() { + // TODO(kuan): Call actual Translate method. +/* + Translate(WideToUTF8(original_language()), WideToUTF8(target_language())); +*/ +} + +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: protected: ---------------------------------------- + +TranslateInfoBarDelegate::TranslateInfoBarDelegate(TabContents* tab_contents, + PrefService* user_prefs, const std::string& original_language, + const std::string& target_language) + : InfoBarDelegate(tab_contents), + tab_contents_(tab_contents), + original_language_(original_language), + target_language_(target_language), + prefs_(user_prefs) { +} + +// BeforeTranslateInfoBarDelegate: public: ------------------------------------- + +BeforeTranslateInfoBarDelegate::BeforeTranslateInfoBarDelegate( + TabContents* tab_contents, PrefService* user_prefs, const GURL& url, + const std::string& original_language, const std::string& target_language) + : TranslateInfoBarDelegate(tab_contents, user_prefs, original_language, + target_language), + site_(url.HostNoBrackets()), + never_translate_language_(false), + never_translate_site_(false) { +} + +bool BeforeTranslateInfoBarDelegate::IsLanguageBlacklisted() { + never_translate_language_ = + prefs_.IsLanguageBlacklisted(original_language()); + return never_translate_language_; +} + +void BeforeTranslateInfoBarDelegate::ToggleLanguageBlacklist() { + never_translate_language_ = !never_translate_language_; + if (never_translate_language_) + prefs_.BlacklistLanguage(original_language()); + else + prefs_.RemoveLanguageFromBlacklist(original_language()); +} + +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_); +} + +// AfterTranslateInfoBarDelegate: public: -------------------------------------- + +AfterTranslateInfoBarDelegate::AfterTranslateInfoBarDelegate( + TabContents* tab_contents, PrefService* user_prefs, + const std::string& original_language, const std::string& target_language) + : TranslateInfoBarDelegate(tab_contents, user_prefs, original_language, + target_language), + always_translate_(false) { +} + +void AfterTranslateInfoBarDelegate::GetAvailableTargetLanguages( + std::vector<std::string>* languages) { + // TODO(kuan): Call backend when it's ready; hardcode a list for now. + GetAvailableOriginalLanguages(languages); +} + +void AfterTranslateInfoBarDelegate::ModifyTargetLanguage( + const std::string& target_language) { + target_language_ = target_language; +} + +bool AfterTranslateInfoBarDelegate::ShouldAlwaysTranslate() { + always_translate_ = prefs_.IsLanguagePairWhitelisted(original_language(), + target_language()); + return always_translate_; +} + +void AfterTranslateInfoBarDelegate::ToggleAlwaysTranslate() { + always_translate_ = !always_translate_; + if (always_translate_) + prefs_.WhitelistLanguagePair(original_language(), target_language()); + else + prefs_.RemoveLanguagePairFromWhitelist(original_language(), + target_language()); +} diff --git a/chrome/browser/translate/translate_infobars_delegates.h b/chrome/browser/translate/translate_infobars_delegates.h new file mode 100644 index 0000000..80bada0 --- /dev/null +++ b/chrome/browser/translate/translate_infobars_delegates.h @@ -0,0 +1,108 @@ +// 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(const std::string& original_language); + virtual void ModifyTargetLanguage(const std::string& target_language); + virtual void Translate(); + virtual bool IsLanguageBlacklisted(); + virtual void ToggleLanguageBlacklist(); + virtual bool IsSiteBlacklisted(); + virtual void ToggleSiteBlacklist(); + virtual bool ShouldAlwaysTranslate(); + virtual void ToggleAlwaysTranslate(); + + const std::string& original_language() const { + return original_language_; + } + const std::string& target_language() const { + return target_language_; + } + 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(); + + protected: + TranslateInfoBarDelegate(TabContents* contents, PrefService* user_prefs, + const std::string& original_language, const std::string& target_language); + + TabContents* tab_contents_; // Weak. + std::string original_language_; + std::string target_language_; + TranslatePrefs prefs_; + + 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(const std::string& target_language); + 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..3b8df24 100644 --- a/chrome/browser/views/infobars/infobars.cc +++ b/chrome/browser/views/infobars/infobars.cc @@ -23,11 +23,9 @@ // 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 int InfoBar::kHorizontalPadding = 3; +const int InfoBar::kIconLabelSpacing = 5; +const int InfoBar::kButtonSpacing = 5; static const SkColor kInfoBackgroundColorTop = SkColorSetRGB(170, 214, 112); static const SkColor kInfoBackgroundColorBottom = SkColorSetRGB(146, 205, 114); @@ -40,25 +38,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 +65,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; @@ -195,6 +184,16 @@ 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) { diff --git a/chrome/browser/views/infobars/infobars.h b/chrome/browser/views/infobars/infobars.h index 9870ad4..aff4928 100644 --- a/chrome/browser/views/infobars/infobars.h +++ b/chrome/browser/views/infobars/infobars.h @@ -56,6 +56,10 @@ class InfoBar : public views::View, // is (due to animation). static const double kTargetHeight; + static const int kHorizontalPadding; + static const int kIconLabelSpacing; + static const int kButtonSpacing; + // Overridden from views::View: virtual gfx::Size GetPreferredSize(); virtual void Layout(); @@ -74,6 +78,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..ed1034c --- /dev/null +++ b/chrome/browser/views/infobars/translate_infobars.cc @@ -0,0 +1,582 @@ +// 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; + } + + original_language_menu_button_ = CreateMenuButton(kMenuIDOriginalLanguage, + ASCIIToWide(GetDelegate()->original_language())); + 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::kButtonSpacing, + OffsetY(this, button1_ps), button1_ps.width(), button1_ps.height()); + + // Place label_2 after first language menu button. + label_2_->SetBounds(button1->bounds().right() + InfoBar::kButtonSpacing, + 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::kButtonSpacing, + 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::kButtonSpacing, + InfoBar::OffsetY(this, label3_ps), text3_width, label3_ps.height()); + } + } +} + +// TranslateInfoBar, InfoBar overrides: ---------------------------------------- + +int TranslateInfoBar::GetAvailableWidth() const { + gfx::Size icon_ps = icon_->GetPreferredSize(); + gfx::Size language_ps = original_language_menu_button_->GetPreferredSize(); + gfx::Size options_ps = options_menu_button_->GetPreferredSize(); + return (InfoBar::GetAvailableWidth() - options_ps.width() - + language_ps.width() - (InfoBar::kButtonSpacing * 3) - + icon_ps.width() - 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, menus::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, + menus::Accelerator* accelerator) { + return false; +} + +void TranslateInfoBar::ExecuteCommand(int command_id) { + if (command_id >= IDC_TRANSLATE_ORIGINAL_LANGUAGE_BASE) { + string16 new_language = original_language_menu_model_->GetLabelAt( + command_id - IDC_TRANSLATE_ORIGINAL_LANGUAGE_BASE); + OnLanguageModified(original_language_menu_button_, new_language); + } 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::kButtonSpacing); +} + +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, + const string16& new_language) { + // Only proceed if a different language has been selected. + if (new_language == WideToUTF16(menu_button->text())) + return; + std::string ascii_lang(UTF16ToUTF8(new_language)); + if (menu_button == original_language_menu_button_) + GetDelegate()->ModifyOriginalLanguage(ascii_lang); + else + GetDelegate()->ModifyTargetLanguage(ascii_lang); + menu_button->SetText(UTF16ToWide(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() - + deny_ps.width() - (InfoBar::kButtonSpacing * 2)); +} + +// 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() + InfoBar::kButtonSpacing, + 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::kButtonSpacing, + 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) { + target_language_menu_button_ = CreateMenuButton(kMenuIDTargetLanguage, + ASCIIToWide(GetDelegate()->target_language())); + 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::kButtonSpacing); +} + +// 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, menus::SimpleMenuModel::Delegate implementation: ----- + +void AfterTranslateInfoBar::ExecuteCommand(int command_id) { + if (command_id >= IDC_TRANSLATE_TARGET_LANGUAGE_BASE) { + string16 new_language = target_language_menu_model_->GetLabelAt( + command_id - IDC_TRANSLATE_TARGET_LANGUAGE_BASE); + OnLanguageModified(target_language_menu_button_, new_language); + } 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..ae2d512 --- /dev/null +++ b/chrome/browser/views/infobars/translate_infobars.h @@ -0,0 +1,137 @@ +// 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 "app/menus/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 menus::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 menus::SimpleMenuModel::Delegate: + virtual bool IsCommandIdChecked(int command_id) const; + virtual bool IsCommandIdEnabled(int command_id) const; + virtual bool GetAcceleratorForCommandId(int command_id, + menus::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, + const string16& new_language); + 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() { + return NULL; + } + + 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); + + // 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 menus::SimpleMenuModel::Delegate: + virtual void ExecuteCommand(int command_id); + + protected: + // Overridden from InfoBar: + virtual int GetAvailableWidth() const; + + virtual views::MenuButton* target_language_menu_button() { + 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_browser.gypi b/chrome/chrome_browser.gypi index d89aca1..2f2819b 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1624,6 +1624,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', @@ -1779,6 +1787,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', diff --git a/views/controls/button/text_button.cc b/views/controls/button/text_button.cc index 0df9578c..042f9d2 100644 --- a/views/controls/button/text_button.cc +++ b/views/controls/button/text_button.cc @@ -68,9 +68,10 @@ TextButtonBorder::TextButtonBorder() { TextButtonBorder::~TextButtonBorder() { } + //////////////////////////////////////////////////////////////////////////////// // -// TextButtonBackground - painting +// TextButtonBorder - painting // //////////////////////////////////////////////////////////////////////////////// @@ -84,71 +85,76 @@ void TextButtonBorder::Paint(const View& view, gfx::Canvas* canvas) const { set = &pushed_set_; if (set) { - gfx::Rect bounds = view.bounds(); - - // Draw the top left image - canvas->DrawBitmapInt(*set->top_left, 0, 0); - - // Tile the top image - canvas->TileImageInt( - *set->top, - set->top_left->width(), - 0, - bounds.width() - set->top_right->width() - set->top_left->width(), - set->top->height()); - - // Draw the top right image - canvas->DrawBitmapInt(*set->top_right, - bounds.width() - set->top_right->width(), 0); - - // Tile the left image - canvas->TileImageInt( - *set->left, - 0, - set->top_left->height(), - set->top_left->width(), - bounds.height() - set->top->height() - set->bottom_left->height()); - - // Tile the center image - canvas->TileImageInt( - *set->center, - set->left->width(), - set->top->height(), - bounds.width() - set->right->width() - set->left->width(), - bounds.height() - set->bottom->height() - set->top->height()); - - // Tile the right image - canvas->TileImageInt( - *set->right, - bounds.width() - set->right->width(), - set->top_right->height(), - bounds.width(), - bounds.height() - set->bottom_right->height() - - set->top_right->height()); - - // Draw the bottom left image - canvas->DrawBitmapInt(*set->bottom_left, - 0, - bounds.height() - set->bottom_left->height()); - - // Tile the bottom image - canvas->TileImageInt( - *set->bottom, - set->bottom_left->width(), - bounds.height() - set->bottom->height(), - bounds.width() - set->bottom_right->width() - - set->bottom_left->width(), - set->bottom->height()); - - // Draw the bottom right image - canvas->DrawBitmapInt(*set->bottom_right, - bounds.width() - set->bottom_right->width(), - bounds.height() - set->bottom_right->height()); + Paint(view, canvas, *set); } else { // Do nothing } } +void TextButtonBorder::Paint(const View& view, gfx::Canvas* canvas, + const MBBImageSet& set) const { + gfx::Rect bounds = view.bounds(); + + // Draw the top left image + canvas->DrawBitmapInt(*set.top_left, 0, 0); + + // Tile the top image + canvas->TileImageInt( + *set.top, + set.top_left->width(), + 0, + bounds.width() - set.top_right->width() - set.top_left->width(), + set.top->height()); + + // Draw the top right image + canvas->DrawBitmapInt(*set.top_right, + bounds.width() - set.top_right->width(), 0); + + // Tile the left image + canvas->TileImageInt( + *set.left, + 0, + set.top_left->height(), + set.top_left->width(), + bounds.height() - set.top->height() - set.bottom_left->height()); + + // Tile the center image + canvas->TileImageInt( + *set.center, + set.left->width(), + set.top->height(), + bounds.width() - set.right->width() - set.left->width(), + bounds.height() - set.bottom->height() - set.top->height()); + + // Tile the right image + canvas->TileImageInt( + *set.right, + bounds.width() - set.right->width(), + set.top_right->height(), + bounds.width(), + bounds.height() - set.bottom_right->height() - + set.top_right->height()); + + // Draw the bottom left image + canvas->DrawBitmapInt(*set.bottom_left, + 0, + bounds.height() - set.bottom_left->height()); + + // Tile the bottom image + canvas->TileImageInt( + *set.bottom, + set.bottom_left->width(), + bounds.height() - set.bottom->height(), + bounds.width() - set.bottom_right->width() - + set.bottom_left->width(), + set.bottom->height()); + + // Draw the bottom right image + canvas->DrawBitmapInt(*set.bottom_right, + bounds.width() - set.bottom_right->width(), + bounds.height() - set.bottom_right->height()); +} + void TextButtonBorder::GetInsets(gfx::Insets* insets) const { insets->Set(kPreferredPaddingVertical, kPreferredPaddingHorizontal, kPreferredPaddingVertical, kPreferredPaddingHorizontal); @@ -169,7 +175,8 @@ TextButton::TextButton(ButtonListener* listener, const std::wstring& text) color_highlight_(kHighlightColor), color_hover_(kHoverColor), has_hover_icon_(false), - max_width_(0) { + max_width_(0), + normal_has_border_(false) { SetText(text); set_border(new TextButtonBorder); SetAnimationDuration(kHoverAnimationDurationMs); @@ -222,6 +229,10 @@ void TextButton::ClearMaxTextSize() { max_text_size_ = text_size_; } +void TextButton::SetNormalHasBorder(bool normal_has_border) { + normal_has_border_ = normal_has_border; +} + void TextButton::Paint(gfx::Canvas* canvas, bool for_drag) { if (!for_drag) { PaintBackground(canvas); @@ -235,7 +246,8 @@ void TextButton::Paint(gfx::Canvas* canvas, bool for_drag) { canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); PaintBorder(canvas); canvas->restore(); - } else if (state_ == BS_HOT || state_ == BS_PUSHED) { + } else if (state_ == BS_HOT || state_ == BS_PUSHED || + (state_ == BS_NORMAL && normal_has_border_)) { PaintBorder(canvas); } diff --git a/views/controls/button/text_button.h b/views/controls/button/text_button.h index d895a6e..b6bd739 100644 --- a/views/controls/button/text_button.h +++ b/views/controls/button/text_button.h @@ -36,7 +36,7 @@ class TextButtonBorder : public Border { // Returns the insets for the border. virtual void GetInsets(gfx::Insets* insets) const; - private: + protected: // Images struct MBBImageSet { SkBitmap* top_left; @@ -52,6 +52,10 @@ class TextButtonBorder : public Border { MBBImageSet hot_set_; MBBImageSet pushed_set_; + virtual void Paint(const View& view, gfx::Canvas* canvas, + const MBBImageSet& set) const; + + private: DISALLOW_COPY_AND_ASSIGN(TextButtonBorder); }; @@ -112,6 +116,7 @@ class TextButton : public CustomButton { void SetDisabledColor(SkColor color); void SetHighlightColor(SkColor color); void SetHoverColor(SkColor color); + void SetNormalHasBorder(bool normal_has_border); // Paint the button into the specified canvas. If |for_drag| is true, the // function paints a drag image representation into the canvas. @@ -176,6 +181,9 @@ class TextButton : public CustomButton { // indicates the width is not constrained. int max_width_; + // This is true if normal state has a border frame; default is false. + bool normal_has_border_; + DISALLOW_COPY_AND_ASSIGN(TextButton); }; |