OSDN Git Service

livedisplay: Add picture adjustment settings
authorSteve Kondik <steve@cyngn.com>
Fri, 22 Jul 2016 06:43:51 +0000 (23:43 -0700)
committerSteve Kondik <steve@cyngn.com>
Sat, 6 Aug 2016 00:49:54 +0000 (17:49 -0700)
 * Allow user setting of hue, saturation, intensity, and contrast
 * These controls are associated by the current display mode

Change-Id: I5de24a0b5c2972f115920167fa97afa3a136b80d

res/layout/display_picture_adjustment.xml [new file with mode: 0644]
res/values/cm_strings.xml
res/xml/livedisplay.xml
src/com/android/settings/livedisplay/LiveDisplay.java
src/com/android/settings/livedisplay/PictureAdjustment.java [new file with mode: 0644]

diff --git a/res/layout/display_picture_adjustment.xml b/res/layout/display_picture_adjustment.xml
new file mode 100644 (file)
index 0000000..e1d9da9
--- /dev/null
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013-2015 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center_horizontal"
+            android:paddingStart="20dip"
+            android:paddingEnd="20dip"
+            android:paddingBottom="20dip">
+
+        <TextView android:id="@+id/adj_hue_text"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/adj_hue_title"
+                android:paddingTop="10dip" />
+        <TextView android:id="@+id/adj_hue_value"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:paddingTop="10dip" />
+        <com.android.settings.IntervalSeekBar android:id="@+id/adj_hue_seekbar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/adj_hue_text"
+                android:paddingTop="2dip"
+                settings:min="0.20"
+                settings:max="1.00"
+                settings:defaultValue="1.00"
+                settings:digits="4" />
+
+        <TextView android:id="@+id/adj_saturation_text"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/adj_hue_seekbar"
+                android:text="@string/adj_saturation_title"
+                android:paddingTop="10dip" />
+        <TextView android:id="@+id/adj_saturation_value"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/adj_hue_seekbar"
+                android:layout_alignParentRight="true"
+                android:paddingTop="10dip" />
+        <com.android.settings.IntervalSeekBar android:id="@+id/adj_saturation_seekbar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/adj_saturation_text"
+                android:paddingTop="2dip"
+                settings:min="0.20"
+                settings:max="1.00"
+                settings:defaultValue="1.00"
+                settings:digits="4" />
+
+        <TextView android:id="@+id/adj_intensity_text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/adj_saturation_seekbar"
+                android:text="@string/adj_intensity_title"
+                android:paddingTop="10dip" />
+        <TextView android:id="@+id/adj_intensity_value"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/adj_saturation_seekbar"
+                android:layout_alignParentRight="true"
+                android:paddingTop="10dip" />
+        <com.android.settings.IntervalSeekBar android:id="@+id/adj_intensity_seekbar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/adj_intensity_text"
+                android:paddingTop="2dip"
+                settings:min="0.20"
+                settings:max="1.00"
+                settings:defaultValue="1.00"
+                settings:digits="4" />
+
+        <TextView android:id="@+id/adj_contrast_text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/adj_intensity_seekbar"
+                android:text="@string/adj_contrast_title"
+                android:paddingTop="10dip" />
+        <TextView android:id="@+id/adj_contrast_value"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/adj_intensity_seekbar"
+                android:layout_alignParentRight="true"
+                android:paddingTop="10dip" />
+        <com.android.settings.IntervalSeekBar android:id="@+id/adj_contrast_seekbar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/adj_contrast_text"
+                android:paddingTop="2dip"
+                settings:min="0.20"
+                settings:max="1.00"
+                settings:defaultValue="1.00"
+                settings:digits="4" />
+
+
+        <ImageView android:id="@+id/black_scale_picture_adjustment"
+                android:src="@drawable/color_tuning_preview"
+                android:layout_width="match_parent"
+                android:layout_height="40dip"
+                android:layout_below="@id/adj_contrast_seekbar"
+                android:paddingTop="20dip" />
+
+    </RelativeLayout>
+</ScrollView>
index 3f5113d..3e8c02a 100644 (file)
     <string name="live_display_color_profile_adaptive_title">Adaptive</string>
     <string name="live_display_color_profile_adaptive_summary">Colors adapt to ambient conditions</string>
 
+    <!-- LiveDisplay : Picture Adjustment -->
+    <string name="picture_adjustment_title">Picture adjustment</string>
+    <string name="picture_adjustment_summary">Adjust hue, saturation, intensity, and contrast</string>
+    <string name="adj_hue_title">Hue</string>
+    <string name="adj_saturation_title">Saturation</string>
+    <string name="adj_intensity_title">Intensity</string>
+       <string name="adj_contrast_title">Contrast</string>
+
     <!-- Whether to display IME switcher notifcation -->
     <string name="ime_switcher_notify">Selector icon</string>
     <string name="ime_switcher_notify_summary">Display input method selector icon</string>
index fa93a19..3f0af3a 100644 (file)
             android:key="advanced"
             android:title="@string/advanced">
 
-        <!-- screen color -->
-        <PreferenceScreen
-                android:persistent="false"
-                android:key="screencolor_settings"
-                android:title="@string/screencolor"
-                android:summary="@string/screencolor_summary">
-            <intent
-                    android:action="com.qualcomm.display.PPService"
-                    android:targetPackage="com.android.settings"
-                    android:targetClass="com.android.settings.ScreenColorSettings" />
-        </PreferenceScreen>
-
+        <!-- RGB display color adjustments -->
         <com.android.settings.livedisplay.DisplayColor
                 android:key="color_calibration"
                 android:title="@string/color_calibration_title"
                 android:summary="@string/color_calibration_summary"
                 android:persistent="false"/>
 
+        <!-- HSIC display color adjustments -->
+        <com.android.settings.livedisplay.PictureAdjustment
+                android:key="picture_adjustment"
+                android:title="@string/picture_adjustment_title"
+                android:dialogTitle="@string/picture_adjustment_title"
+                android:summary="@string/picture_adjustment_summary"
+                android:persistent="false"/>
+
         <!-- Adaptive backlight -->
         <com.android.settings.cyanogenmod.CMSystemSettingSwitchPreference
                 android:key="display_low_power"
index 51a295d..a3f4636 100644 (file)
 package com.android.settings.livedisplay;
 
 import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_CABC;
+import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_COLOR_ADJUSTMENT;
 import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_COLOR_ENHANCEMENT;
 import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_DISPLAY_MODES;
+import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_PICTURE_ADJUSTMENT;
 import static cyanogenmod.hardware.LiveDisplayManager.MODE_OFF;
 import static cyanogenmod.hardware.LiveDisplayManager.MODE_OUTDOOR;
 
@@ -71,7 +73,7 @@ public class LiveDisplay extends SettingsPreferenceFragment implements
     private static final String KEY_LIVE_DISPLAY_TEMPERATURE = "live_display_color_temperature";
 
     private static final String KEY_DISPLAY_COLOR = "color_calibration";
-    private static final String KEY_SCREEN_COLOR_SETTINGS = "screencolor_settings";
+    private static final String KEY_PICTURE_ADJUSTMENT = "picture_adjustment";
 
     private static final String KEY_LIVE_DISPLAY_COLOR_PROFILE = "live_display_color_profile";
 
@@ -84,8 +86,9 @@ public class LiveDisplay extends SettingsPreferenceFragment implements
     private SwitchPreference mLowPower;
     private SwitchPreference mOutdoorMode;
 
-    private PreferenceScreen mScreenColorSettings;
+    private PictureAdjustment mPictureAdjustment;
     private DisplayTemperature mDisplayTemperature;
+    private DisplayColor mDisplayColor;
 
     private ListPreference mColorProfile;
     private String[] mColorProfileSummaries;
@@ -186,12 +189,18 @@ public class LiveDisplay extends SettingsPreferenceFragment implements
             mColorEnhancement = null;
         }
 
-        mScreenColorSettings = (PreferenceScreen) findPreference(KEY_SCREEN_COLOR_SETTINGS);
-        if (advancedPrefs != null) {
-            if (mScreenColorSettings != null &&
-                    (mHasDisplayModes ||!isPostProcessingSupported(getActivity()))) {
-                advancedPrefs.removePreference(mScreenColorSettings);
-            }
+        mPictureAdjustment = (PictureAdjustment) findPreference(KEY_PICTURE_ADJUSTMENT);
+        if (advancedPrefs != null && mPictureAdjustment != null &&
+                    !mConfig.hasFeature(LiveDisplayManager.FEATURE_PICTURE_ADJUSTMENT)) {
+            advancedPrefs.removePreference(mPictureAdjustment);
+            mPictureAdjustment = null;
+        }
+
+        mDisplayColor = (DisplayColor) findPreference(KEY_DISPLAY_COLOR);
+        if (advancedPrefs != null && mDisplayColor != null &&
+                !mConfig.hasFeature(LiveDisplayManager.FEATURE_COLOR_ADJUSTMENT)) {
+            advancedPrefs.removePreference(mDisplayColor);
+            mDisplayColor = null;
         }
     }
 
@@ -405,11 +414,12 @@ public class LiveDisplay extends SettingsPreferenceFragment implements
             if (!config.hasFeature(FEATURE_CABC)) {
                 result.add(KEY_LIVE_DISPLAY_LOW_POWER);
             }
-            if (!isPostProcessingSupported(context)) {
-                result.add(KEY_SCREEN_COLOR_SETTINGS);
-            } else {
+            if (!config.hasFeature(FEATURE_COLOR_ADJUSTMENT)) {
                 result.add(KEY_DISPLAY_COLOR);
             }
+            if (!config.hasFeature(FEATURE_PICTURE_ADJUSTMENT)) {
+                result.add(KEY_PICTURE_ADJUSTMENT);
+            }
             return result;
         }
     };
diff --git a/src/com/android/settings/livedisplay/PictureAdjustment.java b/src/com/android/settings/livedisplay/PictureAdjustment.java
new file mode 100644 (file)
index 0000000..657d7d4
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.livedisplay;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.util.AttributeSet;
+import android.util.Range;
+import android.view.View;
+import android.widget.Button;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.android.settings.IntervalSeekBar;
+import com.android.settings.R;
+
+import cyanogenmod.hardware.HSIC;
+import cyanogenmod.hardware.LiveDisplayManager;
+
+import java.util.List;
+
+/**
+ * Special preference type that allows configuration of Color settings
+ */
+public class PictureAdjustment extends DialogPreference {
+    private static final String TAG = "PictureAdjustment";
+
+    private final Context mContext;
+    private final LiveDisplayManager mLiveDisplay;
+    private final List<Range<Float>> mRanges;
+
+    // These arrays must all match in length and order
+    private static final int[] SEEKBAR_ID = new int[] {
+        R.id.adj_hue_seekbar,
+        R.id.adj_saturation_seekbar,
+        R.id.adj_intensity_seekbar,
+        R.id.adj_contrast_seekbar
+    };
+
+    private static final int[] SEEKBAR_VALUE_ID = new int[] {
+        R.id.adj_hue_value,
+        R.id.adj_saturation_value,
+        R.id.adj_intensity_value,
+        R.id.adj_contrast_value
+    };
+
+    private ColorSeekBar[] mSeekBars = new ColorSeekBar[SEEKBAR_ID.length];
+
+    private final float[] mCurrentAdj = new float[5];
+    private final float[] mOriginalAdj = new float[5];
+
+    public PictureAdjustment(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mContext = context;
+        mLiveDisplay = LiveDisplayManager.getInstance(mContext);
+        mRanges = mLiveDisplay.getConfig().getPictureAdjustmentRanges();
+
+        setDialogLayoutResource(R.layout.display_picture_adjustment);
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+        builder.setNeutralButton(R.string.settings_reset_button,
+                new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+            }
+        });
+    }
+
+    private void updateBars() {
+        for (int i = 0; i < SEEKBAR_ID.length; i++) {
+            mSeekBars[i].setValue(mCurrentAdj[i]);
+        }
+    }
+
+    @Override
+    protected void onBindDialogView(View view) {
+        super.onBindDialogView(view);
+
+        System.arraycopy(mLiveDisplay.getPictureAdjustment().toFloatArray(), 0, mOriginalAdj, 0, 5);
+        System.arraycopy(mOriginalAdj, 0, mCurrentAdj, 0, 5);
+
+        for (int i = 0; i < SEEKBAR_ID.length; i++) {
+            IntervalSeekBar seekBar = (IntervalSeekBar) view.findViewById(SEEKBAR_ID[i]);
+            TextView value = (TextView) view.findViewById(SEEKBAR_VALUE_ID[i]);
+            final Range<Float> range = mRanges.get(i);
+            mSeekBars[i] = new ColorSeekBar(seekBar, range, value, i);
+        }
+        updateBars();
+    }
+
+    @Override
+    protected void showDialog(Bundle state) {
+        super.showDialog(state);
+
+        // Can't use onPrepareDialogBuilder for this as we want the dialog
+        // to be kept open on click
+        AlertDialog d = (AlertDialog) getDialog();
+        Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL);
+        defaultsButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                System.arraycopy(mLiveDisplay.getDefaultPictureAdjustment().toFloatArray(),
+                        0, mCurrentAdj, 0, 5);
+                updateBars();
+                updateAdjustment(mCurrentAdj);
+            }
+        });
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        super.onDialogClosed(positiveResult);
+        updateAdjustment(positiveResult ? mCurrentAdj : mOriginalAdj);
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        if (getDialog() == null || !getDialog().isShowing()) {
+            return superState;
+        }
+
+        // Save the dialog state
+        final SavedState myState = new SavedState(superState);
+        myState.currentAdj = mCurrentAdj;
+        myState.originalAdj = mOriginalAdj;
+
+        // Restore the old state when the activity or dialog is being paused
+        updateAdjustment(mOriginalAdj);
+
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+
+        System.arraycopy(myState.originalAdj, 0, mOriginalAdj, 0, 5);
+        System.arraycopy(myState.currentAdj, 0, mCurrentAdj, 0, 5);
+
+        updateBars();
+        updateAdjustment(mCurrentAdj);
+    }
+
+    private static class SavedState extends BaseSavedState {
+        float[] originalAdj;
+        float[] currentAdj;
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public SavedState(Parcel source) {
+            super(source);
+            originalAdj = source.createFloatArray();
+            currentAdj = source.createFloatArray();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeFloatArray(originalAdj);
+            dest.writeFloatArray(currentAdj);
+        }
+
+        public static final Creator<SavedState> CREATOR =
+                new Creator<PictureAdjustment.SavedState>() {
+
+            public PictureAdjustment.SavedState createFromParcel(Parcel in) {
+                return new PictureAdjustment.SavedState(in);
+            }
+
+            public PictureAdjustment.SavedState[] newArray(int size) {
+                return new PictureAdjustment.SavedState[size];
+            }
+        };
+    }
+
+    private void updateAdjustment(final float[] adjustment) {
+        mLiveDisplay.setPictureAdjustment(HSIC.fromFloatArray(adjustment));
+    }
+
+    private class ColorSeekBar implements SeekBar.OnSeekBarChangeListener {
+        private int mIndex;
+        private final IntervalSeekBar mSeekBar;
+        private TextView mValue;
+        private Range<Float> mRange;
+
+        public ColorSeekBar(IntervalSeekBar seekBar, Range<Float> range, TextView value, int index) {
+            mSeekBar = seekBar;
+            mValue = value;
+            mIndex = index;
+            mRange = range;
+            mSeekBar.setMinimum(range.getLower());
+            mSeekBar.setMaximum(range.getUpper());
+
+            mSeekBar.setOnSeekBarChangeListener(this);
+        }
+
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+            IntervalSeekBar isb = (IntervalSeekBar)seekBar;
+            float fp = isb.getProgressFloat();
+            if (fromUser) {
+                mCurrentAdj[mIndex] = mRanges.get(mIndex).clamp(fp);
+                updateAdjustment(mCurrentAdj);
+            }
+            mValue.setText(getLabel(mCurrentAdj[mIndex]));
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+            // Do nothing here
+        }
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+            // Do nothing here
+        }
+
+        private String getLabel(float value) {
+            if (mRange.getUpper() == 1.0f) {
+                return String.format("%d%%", Math.round(100F * value));
+            }
+            return String.format("%d", Math.round(value));
+        }
+
+        public void setValue(float value) {
+            mSeekBar.setProgressFloat(value);
+            mValue.setText(getLabel(value));
+        }
+    }
+}