Bug 1029646 - Update layout direction of configuration and DecorView, r=ahunt
authormaliu <max@mxli.us>
Tue, 03 Jan 2017 15:14:59 +0800
changeset 329538 4e763552b6cf1e3401d1da1e70409e8f3753d944
parent 329537 ba7efd1b9af97c00698451583bf41ddd2ca8bcaa
child 329539 ff279eed787191b2b4dc874d6699c51eba9c1ac8
push id31213
push usercbook@mozilla.com
push dateMon, 16 Jan 2017 15:34:36 +0000
treeherdermozilla-central@aeda115ca5c3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahunt
bugs1029646
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1029646 - Update layout direction of configuration and DecorView, r=ahunt MozReview-Commit-ID: FiDwoX45yV9
mobile/android/base/java/org/mozilla/gecko/BrowserLocaleManager.java
mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
mobile/android/base/java/org/mozilla/gecko/toolbar/BrowserToolbar.java
mobile/android/base/java/org/mozilla/gecko/toolbar/BrowserToolbarTabletBase.java
mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserLocaleManager.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserLocaleManager.java
@@ -21,16 +21,17 @@ import org.mozilla.gecko.util.GeckoJarRe
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.os.Build;
 import android.util.Log;
 
 /**
  * This class manages persistence, application, and otherwise handling of
  * user-specified locales.
  *
  * Of note:
  *
@@ -290,16 +291,21 @@ public class BrowserLocaleManager implem
     @Override
     public void updateConfiguration(Context context, Locale locale) {
         Resources res = context.getResources();
         Configuration config = res.getConfiguration();
 
         // We should use setLocale, but it's unexpectedly missing
         // on real devices.
         config.locale = locale;
+        //  LayoutDirection is also updated in setLocale, do this manually.
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            config.setLayoutDirection(locale);
+        }
+
         res.updateConfiguration(config, null);
     }
 
     private SharedPreferences getSharedPreferences(Context context) {
         return GeckoSharedPrefs.forApp(context);
     }
 
     /**
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -106,16 +106,17 @@ import android.widget.ListView;
 import android.widget.RelativeLayout;
 import android.widget.SimpleAdapter;
 import android.widget.TextView;
 import android.widget.Toast;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.mozilla.gecko.util.ViewUtil;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
 import java.net.URL;
 import java.util.ArrayList;
@@ -1497,16 +1498,19 @@ public abstract class GeckoApp
         if (!ThreadUtils.isOnUiThread()) {
             throw new RuntimeException("onLocaleReady must always be called from the UI thread.");
         }
 
         final Locale loc = Locales.parseLocaleCode(locale);
         if (loc.equals(mLastLocale)) {
             Log.d(LOGTAG, "New locale same as old; onLocaleReady has nothing to do.");
         }
+        BrowserLocaleManager.getInstance().updateConfiguration(GeckoApp.this, loc);
+        ViewUtil.setLayoutDirection(getWindow().getDecorView(), loc);
+        refreshChrome();
 
         // The URL bar hint needs to be populated.
         TextView urlBar = (TextView) findViewById(R.id.url_bar_title);
         if (urlBar != null) {
             final String hint = getResources().getString(R.string.url_bar_default_text);
             urlBar.setHint(hint);
         } else {
             Log.d(LOGTAG, "No URL bar in GeckoApp. Not loading localized hint string.");
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
+++ b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
@@ -45,16 +45,17 @@ import org.mozilla.gecko.updater.UpdateS
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.ContextUtils;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.HardwareUtils;
 import org.mozilla.gecko.util.InputOptionsUtils;
 import org.mozilla.gecko.util.NativeJSObject;
 import org.mozilla.gecko.util.ThreadUtils;
+import org.mozilla.gecko.util.ViewUtil;
 
 import android.annotation.TargetApi;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.NotificationManager;
 import android.content.ContentResolver;
@@ -75,22 +76,26 @@ import android.preference.Preference.OnP
 import android.preference.Preference.OnPreferenceClickListener;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceGroup;
 import android.preference.SwitchPreference;
 import android.preference.TwoStatePreference;
 import android.support.design.widget.Snackbar;
 import android.support.design.widget.TextInputLayout;
 import android.support.v4.content.LocalBroadcastManager;
+import android.support.v4.content.res.ResourcesCompat;
+import android.support.v4.text.TextUtilsCompat;
+import android.support.v4.view.ViewCompat;
 import android.support.v7.app.ActionBar;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.Log;
+import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.AdapterView;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.ListAdapter;
 import android.widget.ListView;
 
@@ -257,16 +262,24 @@ public class GeckoPreferences
             setTitle(title);
         }
     }
 
     private void onLocaleChanged(Locale newLocale) {
         Log.d(LOGTAG, "onLocaleChanged: " + newLocale);
 
         BrowserLocaleManager.getInstance().updateConfiguration(getApplicationContext(), newLocale);
+        //  If activity is not recreated, also update locale to current activity configuration
+        BrowserLocaleManager.getInstance().updateConfiguration(GeckoPreferences.this, newLocale);
+        ViewUtil.setLayoutDirection(getWindow().getDecorView(), newLocale);
+
+        //  Force update navigate up icon by current layout direction
+        final ActionBar actionBar = getSupportActionBar();
+        actionBar.setHomeAsUpIndicator(android.support.v7.appcompat.R.drawable.abc_ic_ab_back_mtrl_am_alpha);
+
         this.lastLocale = newLocale;
 
         if (isMultiPane()) {
             // This takes care of the left pane.
             invalidateHeaders();
 
             // Detach and reattach the current prefs pane so that it
             // reflects the new locale.
--- a/mobile/android/base/java/org/mozilla/gecko/toolbar/BrowserToolbar.java
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/BrowserToolbar.java
@@ -354,16 +354,17 @@ public abstract class BrowserToolbar ext
         this.progressBar = progressBar;
     }
 
     public void setTabHistoryController(TabHistoryController tabHistoryController) {
         this.tabHistoryController = tabHistoryController;
     }
 
     public void refresh() {
+        progressBar.setImageDrawable(getResources().getDrawable(R.drawable.progress));
         urlDisplayLayout.dismissSiteIdentityPopup();
     }
 
     public boolean onBackPressed() {
         // If we exit editing mode during the animation,
         // we're put into an inconsistent state (bug 1017276).
         if (isEditing() && !isAnimating()) {
             Telemetry.sendUIEvent(TelemetryContract.Event.CANCEL,
--- a/mobile/android/base/java/org/mozilla/gecko/toolbar/BrowserToolbarTabletBase.java
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/BrowserToolbarTabletBase.java
@@ -123,16 +123,23 @@ abstract class BrowserToolbarTabletBase 
     @Override
     protected void updateNavigationButtons(final Tab tab) {
         backButton.setEnabled(canDoBack(tab));
         animateForwardButton(
                 canDoForward(tab) ? ForwardButtonAnimation.SHOW : ForwardButtonAnimation.HIDE);
     }
 
     @Override
+    public void refresh() {
+        super.refresh();
+        forwardButton.setImageDrawable(getResources().getDrawable(R.drawable.ic_menu_forward));
+        backButton.setImageDrawable(getResources().getDrawable(R.drawable.ic_menu_back));
+    }
+
+    @Override
     public void setNextFocusDownId(int nextId) {
         super.setNextFocusDownId(nextId);
         backButton.setNextFocusDownId(nextId);
         forwardButton.setNextFocusDownId(nextId);
     }
 
     @Override
     public void setPrivateMode(final boolean isPrivate) {
--- a/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java
+++ b/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java
@@ -1,23 +1,27 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 package org.mozilla.gecko.util;
 
 import android.content.res.TypedArray;
 import android.os.Build;
+import android.support.v4.text.TextUtilsCompat;
 import android.support.v4.view.MarginLayoutParamsCompat;
+import android.support.v4.view.ViewCompat;
 import android.view.View;
 import android.view.ViewGroup;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.R;
 
+import java.util.Locale;
+
 public class ViewUtil {
 
     /**
      * Enable a circular touch ripple for a given view. This is intended for borderless views,
      * such as (3-dot) menu buttons.
      *
      * Because of platform limitations a square ripple is used on Android 4.
      */
@@ -46,9 +50,26 @@ public class ViewUtil {
                 layoutParams.rightMargin = marginStart;
             } else {
                 layoutParams.leftMargin = marginStart;
             }
         } else {
             MarginLayoutParamsCompat.setMarginStart(layoutParams, marginStart);
         }
     }
+
+    /**
+     * Force set layout direction to RTL or LTR by Locale.
+     * @param view
+     * @param locale
+     */
+    public static void setLayoutDirection(View view, Locale locale) {
+        switch (TextUtilsCompat.getLayoutDirectionFromLocale(locale)) {
+            case ViewCompat.LAYOUT_DIRECTION_RTL:
+                ViewCompat.setLayoutDirection(view, ViewCompat.LAYOUT_DIRECTION_RTL);
+                break;
+            case ViewCompat.LAYOUT_DIRECTION_LTR:
+            default:
+                ViewCompat.setLayoutDirection(view, ViewCompat.LAYOUT_DIRECTION_LTR);
+                break;
+        }
+    }
 }