Launcher3: add simple setting to switch grid size

until we know if we bring back ThemePicker grid handling

Change-Id: I5aef73e653226e819ba9c89bfe571ec36d82e080

Launcher3: filter possible grid option for settings

Change-Id: I54e309a989675e3a041ac7e9f583824980d10249

Launcher3: Adapt grid option for a14

Change-Id: If934e0cc82448204b0e442cb61c836824cd76c26
diff --git a/res/values-v33/style.xml b/res/values-v33/style.xml
index 1261b23..3e9fa95 100644
--- a/res/values-v33/style.xml
+++ b/res/values-v33/style.xml
@@ -29,6 +29,7 @@
         <item name="android:windowNoTitle">true</item>
         <item name="preferenceTheme">@style/HomeSettings.PreferenceTheme</item>
         <item name="android:windowAnimationStyle">@style/Animation.SharedBackground</item>
+        <item name="alertDialogTheme">@style/AlertDialogTheme</item>
     </style>
 
     <style name="Animation.SharedBackground" parent="@android:style/Animation.Activity">
@@ -37,4 +38,15 @@
         <item name="android:activityCloseEnterAnimation">@anim/shared_x_axis_activity_close_enter</item>
         <item name="android:activityCloseExitAnimation">@anim/shared_x_axis_activity_close_exit</item>
     </style>
+
+    <style name="AlertDialogTheme" parent="@style/Theme.AppCompat.DayNight.Dialog.Alert">
+        <item name="colorAccent">@color/home_settings_header_accent</item>
+        <item name="android:colorBackground">@color/home_settings_header_expanded</item>
+
+        <item name="android:windowSoftInputMode">adjustResize</item>
+        <item name="android:clipToPadding">true</item>
+        <item name="android:clipChildren">true</item>
+
+        <item name="dialogCornerRadius">8dp</item>
+    </style>
 </resources>
\ No newline at end of file
diff --git a/res/values/custom_strings.xml b/res/values/custom_strings.xml
new file mode 100644
index 0000000..d68edfd
--- /dev/null
+++ b/res/values/custom_strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  Copyright (C) 2018 The OmniROM Project
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <string name="state_loading">Applying\u2026</string>
+    <string name="pref_qsb_show_summary"></string>
+    <string name="pref_qsb_show_title">Show search widget</string>
+    <string name="pref_grid_title">Grid size</string>
+
+</resources>
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 284ab9e..410cc35 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -50,4 +50,9 @@
         launcher:logIdOn="615"
         launcher:logIdOff="616" />
 
+    <ListPreference
+        android:key="pref_grid"
+        android:title="@string/pref_grid_title"
+        android:persistent="false"/>
+
 </androidx.preference.PreferenceScreen>
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 52ce4e8..4cdc4eb 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -27,9 +27,12 @@
 import android.app.Activity;
 import android.content.Intent;
 import android.net.Uri;
+import android.content.res.XmlResourceParser;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.Log;
+import android.util.Xml;
 import android.view.MenuItem;
 import android.view.View;
 
@@ -40,6 +43,7 @@
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 import androidx.fragment.app.FragmentManager;
+import androidx.preference.ListPreference;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback;
@@ -49,22 +53,34 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.launcher3.BuildConfig;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile.GridOption;
 import com.android.launcher3.LauncherFiles;
 import com.android.launcher3.R;
 import com.android.launcher3.states.RotationHelper;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.SettingsCache;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * Settings activity for Launcher. Currently implements the following setting: Allow rotation
  */
 public class SettingsActivity extends FragmentActivity
         implements OnPreferenceStartFragmentCallback, OnPreferenceStartScreenCallback {
+    private static final String TAG = "SettingsActivity";
 
     @VisibleForTesting
     static final String DEVELOPER_OPTIONS_KEY = "pref_developer_options";
 
     private static final String NOTIFICATION_DOTS_PREFERENCE_KEY = "pref_icon_badging";
+    private static final String GRID_SIZE_PREFERENCE_KEY = "pref_grid";
 
     public static final String EXTRA_FRAGMENT_ARGS = ":settings:fragment_args";
 
@@ -201,6 +217,48 @@
             if (getActivity() != null && !TextUtils.isEmpty(getPreferenceScreen().getTitle())) {
                 getActivity().setTitle(getPreferenceScreen().getTitle());
             }
+
+            final ListPreference grid = (ListPreference) findPreference(GRID_SIZE_PREFERENCE_KEY);
+            InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(getContext());
+            ArrayList<String> entries = new ArrayList<>();
+            ArrayList<String> values = new ArrayList<>();
+            for (GridOption gridOption : parseAllGridOptions(idp.deviceType)) {
+                values.add(gridOption.name);
+                entries.add(gridOption.numColumns + " x " + gridOption.numRows);
+            }
+
+            grid.setEntries(entries.toArray(new String[entries.size()]));
+            grid.setEntryValues(values.toArray(new String[values.size()]));
+
+            String currentGrid = idp.getCurrentGridName(getContext());
+            int valueIndex = grid.findIndexOfValue(currentGrid);
+            grid.setValueIndex(valueIndex >= 0 ? valueIndex : 0);
+            grid.setSummary(grid.getEntry());
+
+            grid.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+                public boolean onPreferenceChange(Preference preference, Object newValue) {
+                    // Verify that this is a valid grid option
+                    String gridName = (String) newValue;
+                    GridOption match = null;
+                    for (GridOption option : parseAllGridOptions(idp.deviceType)) {
+                        if (option.name.equals(gridName)) {
+                            match = option;
+                            break;
+                        }
+                    }
+                    if (match == null) {
+                        return false;
+                    }
+
+                    InvariantDeviceProfile.INSTANCE.get(getContext())
+                            .setCurrentGrid(getContext(), gridName);
+
+                    int valueIndex = grid.findIndexOfValue(gridName);
+                    grid.setValueIndex(valueIndex >= 0 ? valueIndex : 0);
+                    grid.setSummary(grid.getEntries()[valueIndex]);
+                    return true;
+                }
+            });
         }
 
         @Override
@@ -324,5 +382,27 @@
                     list, position, screen.findPreference(mHighLightKey))
                     : null;
         }
+
+        private List<GridOption> parseAllGridOptions(int deviceType) {
+            List<GridOption> result = new ArrayList<>();
+            try (XmlResourceParser parser = getContext().getResources().getXml(R.xml.device_profiles)) {
+                final int depth = parser.getDepth();
+                int type;
+                while (((type = parser.next()) != XmlPullParser.END_TAG ||
+                        parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+                    if ((type == XmlPullParser.START_TAG)
+                            && GridOption.TAG_NAME.equals(parser.getName())) {
+                        GridOption gridOption = new GridOption(getContext(), Xml.asAttributeSet(parser));
+                        if (gridOption.isEnabled(deviceType)) {
+                            result.add(gridOption);
+                        }
+                    }
+                }
+            } catch (IOException | XmlPullParserException e) {
+                Log.e(TAG, "Error parsing device profile", e);
+                return Collections.emptyList();
+            }
+            return result;
+        }
     }
 }