Commit fb178abd authored by Leo Zhang's avatar Leo Zhang Committed by Commit Bot

Add language list and disable button in languages prefs.

Add turn on/off translate switch.
Read accept_langauges from native and show them in the languages page.
For each language item, add a fake option memu.
Screenshot: https://screenshot.googleplex.com/0HOVztouukP

Bug: 783049
Change-Id: If420d76fe12ecbff277bcd6e4ab7a3a7a3419f63
Reviewed-on: https://chromium-review.googlesource.com/762540
Commit-Queue: Leo Zhang <googleo@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarMaria Khomenko <mariakhomenko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#520715}
parent f9c5b01e
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2017 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. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:chrome="http://schemas.android.com/apk/res-auto"
android:id="@+id/language_item"
android:layout_marginStart="0dp"
style="@style/ListItemContainer">
<include layout="@layout/modern_list_item_view" />
<org.chromium.chrome.browser.widget.ListMenuButton
android:id="@+id/more"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingStart="@dimen/selectable_list_layout_row_padding"
android:paddingEnd="@dimen/selectable_list_layout_row_padding"
android:contentDescription="@string/accessibility_list_menu_button"
android:background="@null"
android:src="@drawable/ic_more_vert_black_24dp"
chrome:menuWidth="@dimen/pref_languages_item_popup_width"
chrome:chrometint="@color/dark_mode_tint" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2017 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. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/accept_language_list_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/languages_list_prefs_description" />
<android.support.v7.widget.RecyclerView
android:id="@+id/language_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</LinearLayout>
......@@ -6,7 +6,8 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:paddingStart="?android:attr/listPreferredItemPaddingLeft"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:textColor="@color/dark_mode_tint"
android:gravity="center_vertical"
android:textSize="16sp" />
......@@ -76,4 +76,9 @@
lines. -->
<attr name="singleLine" format="boolean" />
</declare-styleable>
<declare-styleable name="ListMenuButton">
<!-- Used to customize the width of the popup menu. -->
<attr name="menuWidth" format="reference|dimension" />
</declare-styleable>
</resources>
......@@ -460,6 +460,8 @@
<dimen name="pref_icon_padding">4.6dp</dimen>
<dimen name="pref_spinner_padding_end">8dp</dimen>
<dimen name="pref_languages_item_popup_width">260dp</dimen>
<!-- Dialog dimensions.
https://www.google.com/design/spec/components/dialogs.html#dialogs-simple-dialogs -->
<dimen name="dialog_width_unit">56dp</dimen> <!-- MD dialog widths are multiples of this. -->
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2017 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. -->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<org.chromium.chrome.browser.preferences.languages.LanguageListPreference
android:key="preferred_languages"
android:layout="@layout/custom_preference"
android:widgetLayout="@layout/accept_languages_list" />
<Preference
android:fragment="org.chromium.chrome.browser.preferences.languages.LanguageSelectionPreferences"
android:key="add_language"
android:title="@string/prefs_add_language" />
<org.chromium.chrome.browser.preferences.ChromeSwitchPreference
android:key="translate_switch"
android:summaryOn="@string/languages_offer_translate_switch"
android:summaryOff="@string/languages_offer_translate_switch" />
</PreferenceScreen>
......@@ -186,6 +186,11 @@ public final class PrefServiceBridge {
list.add(exception);
}
@CalledByNative
private static void copyLanguageList(List<String> list, String[] source) {
list.addAll(Arrays.asList(source));
}
/**
* Return the list of android permission strings for a given {@link ContentSettingsType}. If
* there is no permissions associated with the content setting, then an empty array is returned.
......@@ -905,6 +910,15 @@ public final class PrefServiceBridge {
nativeSetChromeHomePersonalizedOmniboxSuggestionsEnabled(enabled);
}
/**
* Return the list of preferred languages strings.
*/
public List<String> getChromeLanguageList() {
List<String> list = new ArrayList<>();
nativeGetChromeLanguageList(list);
return list;
}
private native boolean nativeIsContentSettingEnabled(int contentSettingType);
private native boolean nativeIsContentSettingManaged(int contentSettingType);
private native void nativeSetContentSettingEnabled(int contentSettingType, boolean allow);
......@@ -1075,4 +1089,5 @@ public final class PrefServiceBridge {
private native String nativeGetLatestVersionWhenClickedUpdateMenuItem();
private native void nativeSetSupervisedUserId(String supervisedUserId);
private native void nativeSetChromeHomePersonalizedOmniboxSuggestionsEnabled(boolean enabled);
private native void nativeGetChromeLanguageList(List<String> list);
}
// Copyright 2017 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.
package org.chromium.chrome.browser.preferences.languages;
import android.content.Context;
import android.preference.Preference;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.widget.ListMenuButton;
import org.chromium.chrome.browser.widget.ListMenuButton.Item;
import org.chromium.chrome.browser.widget.TintedImageView;
import java.util.List;
/**
* A preference that displays the current accept language list.
*/
public class LanguageListPreference extends Preference {
public LanguageListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
RecyclerView listView = (RecyclerView) view.findViewById(R.id.language_list);
listView.setLayoutManager(new LinearLayoutManager(getContext()));
// Get accepted language list from native.
List<String> languageList = PrefServiceBridge.getInstance().getChromeLanguageList();
listView.setAdapter(new LanguageListAdapter(languageList));
}
// TODO(crbug/783049): Pull all the inner classes below out and make the item in the list
// drag-able.
private static class LanguageListAdapter extends RecyclerView.Adapter<LanguageItemViewHolder> {
private List<String> mLanguageList;
LanguageListAdapter(List<String> languageList) {
mLanguageList = languageList;
}
@Override
public LanguageItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View languageItem = LayoutInflater.from(parent.getContext())
.inflate(R.layout.accept_languages_item, parent, false);
return new LanguageItemViewHolder(languageItem);
}
@Override
public void onBindViewHolder(LanguageItemViewHolder holder, int position) {
String code = mLanguageList.get(position);
// TODO(crbug/783049): Get language name by code and Locale from LocalizationUtils.
// displayLocale = context.getResources().getConfiguration().locale;
holder.setupUI(code);
}
@Override
public int getItemCount() {
return mLanguageList.size();
}
}
private static class LanguageItemViewHolder
extends RecyclerView.ViewHolder implements ListMenuButton.Delegate {
private static final int OFFER_TRANSLATE_POSITION = 0;
// Menu items definition.
private final Item[] mItems;
private Context mContext;
private View mRow;
private TextView mTitle;
private TintedImageView mStartIcon;
private ListMenuButton mMoreButton;
LanguageItemViewHolder(View view) {
super(view);
mContext = view.getContext();
mRow = view;
mTitle = (TextView) view.findViewById(R.id.title);
mStartIcon = (TintedImageView) view.findViewById(R.id.icon_view);
mMoreButton = (ListMenuButton) view.findViewById(R.id.more);
// TODO(crbug/783049): Set "enabled" based on whether Chrome supports to translate this
// language.
mItems = new Item[] {
new Item(mContext, R.string.languages_item_option_offer_to_translate,
R.drawable.ic_check_googblue_24dp, true),
new Item(mContext, R.string.remove, true)};
}
private void setupUI(String title) {
mTitle.setText(title);
mStartIcon.setImageResource(R.drawable.ic_drag_handle_grey600_24dp);
mMoreButton.setDelegate(this);
}
// ListMenuButton.Delegate implementation.
@Override
public Item[] getItems() {
return mItems;
}
@Override
public void onItemSelected(Item item) {
if (item.getTextId() == R.string.languages_item_option_offer_to_translate) {
// TODO(crbug/783049): Handle "offer to translate" event.
} else if (item.getTextId() == R.string.remove) {
// TODO(crbug/783049): Handle "remove" event.
}
}
}
}
// Copyright 2017 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.
package org.chromium.chrome.browser.preferences.languages;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import org.chromium.chrome.R;
/**
* Language selection fragment that lists all languages Chrome supports and allows users to
* add one of them into their preferred language list.
*/
public class LanguageSelectionPreferences extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.prefs_add_language);
}
}
......@@ -5,18 +5,60 @@
package org.chromium.chrome.browser.preferences.languages;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceFragment;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.preferences.ChromeSwitchPreference;
import org.chromium.chrome.browser.preferences.ManagedPreferenceDelegate;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.preferences.PreferenceUtils;
import org.chromium.chrome.browser.widget.TintedDrawable;
/**
* Settings fragment that displays information about Chrome languages, which allow users to
* seamlessly find and manage their languages preferences across platforms.
*/
public class LanguagesPreferences extends PreferenceFragment {
// The keys for each prefernce shown on the langauges page.
static final String ADD_LANGUAGE_KEY = "add_language";
static final String PREFERRED_LANGUAGES_KEY = "preferred_languages";
static final String TRANSLATE_SWITCH_KEY = "translate_switch";
private LanguageListPreference mLanguageListPref;
private Preference mAddLanguagePref;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.prefs_languages);
PreferenceUtils.addPreferencesFromResource(this, R.xml.languages_preferences);
mAddLanguagePref = findPreference(ADD_LANGUAGE_KEY);
mAddLanguagePref.setIcon(TintedDrawable.constructTintedDrawable(
getResources(), R.drawable.plus, R.color.pref_accent_color));
mLanguageListPref = (LanguageListPreference) findPreference(PREFERRED_LANGUAGES_KEY);
ChromeSwitchPreference translateSwitch =
(ChromeSwitchPreference) findPreference(TRANSLATE_SWITCH_KEY);
boolean isTranslateEnabled = PrefServiceBridge.getInstance().isTranslateEnabled();
translateSwitch.setChecked(isTranslateEnabled);
translateSwitch.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
PrefServiceBridge.getInstance().setTranslateEnabled((boolean) newValue);
return true;
}
});
translateSwitch.setManagedPreferenceDelegate(new ManagedPreferenceDelegate() {
@Override
public boolean isPreferenceControlledByPolicy(Preference preference) {
return PrefServiceBridge.getInstance().isTranslateManaged();
}
});
}
}
......@@ -5,13 +5,17 @@
package org.chromium.chrome.browser.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListPopupWindow;
import android.widget.TextView;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R;
/**
......@@ -20,21 +24,34 @@ import org.chromium.chrome.R;
* results.
*/
public class ListMenuButton extends TintedImageButton {
private final static int INVALID_RES_ID = 0;
/** A class that represents a single item in the popup menu. */
public static class Item {
private final String mTextString;
private final @StringRes int mTextId;
private final @DrawableRes int mEndIconId;
private final boolean mEnabled;
/**
* Creates a new {@link Item} without an end icon.
*/
public Item(Context context, @StringRes int textId, boolean enabled) {
this(context, textId, INVALID_RES_ID, enabled);
}
/**
* Creates a new {@link Item}.
* @param textId The string resource id for the text to show for this item.
* @param textId The string resource id for the text to show for this item.
* @param endIconId The optional drawable resource id to display at the end of the item.
* @param enabled Whether or not this item should be enabled.
*/
public Item(Context context, @StringRes int textId, boolean enabled) {
public Item(Context context, @StringRes int textId, @DrawableRes int endIconId,
boolean enabled) {
mTextString = context.getString(textId);
mTextId = textId;
mEnabled = enabled;
mEndIconId = endIconId;
}
@Override
......@@ -51,6 +68,10 @@ public class ListMenuButton extends TintedImageButton {
public @StringRes int getTextId() {
return mTextId;
}
public @DrawableRes int getEndIconId() {
return mEndIconId;
}
}
/** A delegate used to populate the menu and to be notified of menu selection events. */
......@@ -69,6 +90,8 @@ public class ListMenuButton extends TintedImageButton {
void onItemSelected(Item item);
}
private final int mMenuWidth;
private ListPopupWindow mPopupMenu;
private Delegate mDelegate;
......@@ -79,6 +102,10 @@ public class ListMenuButton extends TintedImageButton {
*/
public ListMenuButton(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ListMenuButton);
mMenuWidth = a.getDimensionPixelSize(R.styleable.ListMenuButton_menuWidth,
getResources().getDimensionPixelSize(R.dimen.list_menu_width));
a.recycle();
}
/**
......@@ -141,15 +168,20 @@ public class ListMenuButton extends TintedImageButton {
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
view.setEnabled(isEnabled(position));
// Set the compound drawable at the end for items with a valid endIconId,
// otherwise clear the compoud drawable if the endIconId is 0.
ApiCompatibilityUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(
(TextView) view, 0, 0, items[position].getEndIconId(), 0);
return view;
}
});
mPopupMenu.setAnchorView(this);
// This may need to be an attribute and/or parameter in the future to allow different lists
// to customize the width of the popup menu. For now relying on a constant is fine.
mPopupMenu.setWidth(getResources().getDimensionPixelSize(R.dimen.list_menu_width));
mPopupMenu.setWidth(mMenuWidth);
mPopupMenu.setVerticalOffset(-getHeight());
mPopupMenu.setModal(true);
mPopupMenu.setOnItemClickListener((parent, view, position, id) -> {
if (mDelegate != null) mDelegate.onItemSelected(items[position]);
......@@ -162,4 +194,4 @@ public class ListMenuButton extends TintedImageButton {
mPopupMenu.show();
mPopupMenu.getListView().setDivider(null);
}
}
\ No newline at end of file
}
......@@ -491,11 +491,6 @@ CHAR-LIMIT guidelines:
Unlock to view your password
</message>
<!-- Languages preferences -->
<message name="IDS_PREFS_LANGUAGES" desc="Menu item for Languages, which allows users to manage their languages preferences. [CHAR-LIMIT=32]">
Languages
</message>
<!-- Homepage preferences -->
<message name="IDS_OPTIONS_HOMEPAGE_EDIT_TITLE" desc="The title of the screen that allows users to change the URL that opens when they tap on the home page button in the omnibox.">
Edit home page
......@@ -926,6 +921,23 @@ Your Google account may have other forms of browsing history like searches and a
You have no saved website settings.
</message>
<!-- Languages preferences -->
<message name="IDS_PREFS_LANGUAGES" desc="Title for the Languages settings screen that allows users to manage their languages preferences. [CHAR-LIMIT=32]">
Languages
</message>
<message name="IDS_PREFS_ADD_LANGUAGE" desc="Title for the screen that allows users to add languages to their preferred language list. [CHAR-LIMIT=32]">
Add language
</message>
<message name="IDS_LANGUAGES_LIST_PREFS_DESCRIPTION" desc="Description on the Languages settings screen. Appears above a list of one or more languages that the user selects, to tell Chrome which languages they prefer to use to read website content.">
Websites will show text in your preferred language, when possible.
</message>
<message name="IDS_LANGUAGES_OFFER_TRANSLATE_SWITCH" desc="Appears next to the 'offer to translate' switch that controls whether or not Chrome will display the Google Translate UI on web pages that are not in the user's preferred language(s).">
Offer to translate pages in other languages
</message>
<message name="IDS_LANGUAGES_ITEM_OPTION_OFFER_TO_TRANSLATE" desc="Option in language item menu. User can click the 'Offer to translate' option to toggle whether they want Chrome to translate pages in this language. [CHAR-LIMIT=32]">
Offer to translate
</message>
<!-- Location preferences -->
<message name="IDS_WEBSITE_SETTINGS_DEVICE_LOCATION" desc="Title for Location settings, which control which websites can access your location." meaning="Geolocation">
Location
......
......@@ -959,6 +959,8 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java",
"java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionDataUseItem.java",
"java/src/org/chromium/chrome/browser/preferences/languages/LanguagesPreferences.java",
"java/src/org/chromium/chrome/browser/preferences/languages/LanguageListPreference.java",
"java/src/org/chromium/chrome/browser/preferences/languages/LanguageSelectionPreferences.java",
"java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java",
"java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java",
"java/src/org/chromium/chrome/browser/preferences/privacy/BandwidthType.java",
......
......@@ -62,6 +62,7 @@ using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;
using base::android::ToJavaArrayOfStrings;
namespace {
......@@ -1144,6 +1145,19 @@ JNI_PrefServiceBridge_SetChromeHomePersonalizedOmniboxSuggestionsEnabled(
is_enabled);
}
static void JNI_PrefServiceBridge_GetChromeLanguageList(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& list) {
std::unique_ptr<translate::TranslatePrefs> translate_prefs =
ChromeTranslateClient::CreateTranslatePrefs(GetPrefService());
std::vector<std::string> languages;
translate_prefs->GetLanguageList(&languages);
Java_PrefServiceBridge_copyLanguageList(env, list,
ToJavaArrayOfStrings(env, languages));
}
const char* PrefServiceBridge::GetPrefNameExposedToJava(int pref_index) {
DCHECK_GE(pref_index, 0);
DCHECK_LT(pref_index, Pref::PREF_NUM_PREFS);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment