cmparts: Add LiveDisplay settings
* Welcome to CMParts, have a nice day!
Change-Id: Ie89830c6315ed583942cb62c3d03e9f3137bf168
diff --git a/res/drawable/color_temperature_preview.xml b/res/drawable/color_temperature_preview.xml
new file mode 100644
index 0000000..0a358f6
--- /dev/null
+++ b/res/drawable/color_temperature_preview.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <gradient
+ android:angle="0"
+ android:startColor="#ff3800"
+ android:endColor="#bfd3ff" />
+</shape>
diff --git a/res/drawable/color_tuning_preview.xml b/res/drawable/color_tuning_preview.xml
new file mode 100644
index 0000000..589237a
--- /dev/null
+++ b/res/drawable/color_tuning_preview.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <gradient
+ android:angle="0"
+ android:startColor="#000000"
+ android:endColor="#FFFFFF" />
+</shape>
diff --git a/res/layout/display_color_calibration.xml b/res/layout/display_color_calibration.xml
new file mode 100644
index 0000000..bc1b001
--- /dev/null
+++ b/res/layout/display_color_calibration.xml
@@ -0,0 +1,102 @@
+<?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:cm="http://schemas.android.com/apk/res/org.cyanogenmod.cmparts"
+ 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/color_red_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/color_red_title"
+ android:paddingTop="10dip" />
+ <TextView android:id="@+id/color_red_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:paddingTop="10dip" />
+ <org.cyanogenmod.cmparts.IntervalSeekBar android:id="@+id/color_red_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_red_text"
+ android:paddingTop="2dip"
+ cm:min="0.20"
+ cm:max="1.00"
+ cm:defaultValue="1.00"
+ cm:digits="4" />
+
+ <TextView android:id="@+id/color_green_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_red_seekbar"
+ android:text="@string/color_green_title"
+ android:paddingTop="10dip" />
+ <TextView android:id="@+id/color_green_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_red_seekbar"
+ android:layout_alignParentRight="true"
+ android:paddingTop="10dip" />
+ <org.cyanogenmod.cmparts.IntervalSeekBar android:id="@+id/color_green_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_green_text"
+ android:paddingTop="2dip"
+ cm:min="0.20"
+ cm:max="1.00"
+ cm:defaultValue="1.00"
+ cm:digits="4" />
+
+ <TextView android:id="@+id/color_blue_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_green_seekbar"
+ android:text="@string/color_blue_title"
+ android:paddingTop="10dip" />
+ <TextView android:id="@+id/color_blue_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_green_seekbar"
+ android:layout_alignParentRight="true"
+ android:paddingTop="10dip" />
+ <org.cyanogenmod.cmparts.IntervalSeekBar android:id="@+id/color_blue_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_blue_text"
+ android:paddingTop="2dip"
+ cm:min="0.20"
+ cm:max="1.00"
+ cm:defaultValue="1.00"
+ cm:digits="4" />
+
+ <ImageView android:id="@+id/black_scale_picture_color"
+ android:src="@drawable/color_tuning_preview"
+ android:layout_width="match_parent"
+ android:layout_height="40dip"
+ android:layout_below="@id/color_blue_seekbar"
+ android:paddingTop="20dip" />
+
+ </RelativeLayout>
+</ScrollView>
diff --git a/res/layout/display_picture_adjustment.xml b/res/layout/display_picture_adjustment.xml
new file mode 100644
index 0000000..ebbcb59
--- /dev/null
+++ b/res/layout/display_picture_adjustment.xml
@@ -0,0 +1,124 @@
+<?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:cm="http://schemas.android.com/apk/res/org.cyanogenmod.cmparts"
+ 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" />
+ <org.cyanogenmod.cmparts.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"
+ cm:min="0.20"
+ cm:max="1.00"
+ cm:defaultValue="1.00"
+ cm: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" />
+ <org.cyanogenmod.cmparts.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"
+ cm:min="0.20"
+ cm:max="1.00"
+ cm:defaultValue="1.00"
+ cm: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" />
+ <org.cyanogenmod.cmparts.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"
+ cm:min="0.20"
+ cm:max="1.00"
+ cm:defaultValue="1.00"
+ cm: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" />
+ <org.cyanogenmod.cmparts.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"
+ cm:min="0.20"
+ cm:max="1.00"
+ cm:defaultValue="1.00"
+ cm: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>
diff --git a/res/layout/display_temperature.xml b/res/layout/display_temperature.xml
new file mode 100644
index 0000000..c10f7c4
--- /dev/null
+++ b/res/layout/display_temperature.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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"
+ 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/day_temperature_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/live_display_day"
+ android:paddingTop="10dip" />
+ <TextView android:id="@+id/day_temperature_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:paddingTop="10dip" />
+ <SeekBar android:id="@+id/day_temperature_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/day_temperature_text"
+ android:paddingTop="2dip" />
+
+ <TextView android:id="@+id/night_temperature_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/day_temperature_seekbar"
+ android:text="@string/live_display_night"
+ android:paddingTop="10dip" />
+ <TextView android:id="@+id/night_temperature_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/day_temperature_seekbar"
+ android:layout_alignParentRight="true"
+ android:paddingTop="10dip" />
+ <SeekBar android:id="@+id/night_temperature_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/night_temperature_text"
+ android:paddingTop="2dip" />
+
+ <ImageView android:id="@+id/black_scale_picture_color"
+ android:src="@drawable/color_temperature_preview"
+ android:layout_width="match_parent"
+ android:layout_height="40dip"
+ android:layout_below="@id/night_temperature_seekbar"
+ android:paddingTop="20dip" />
+
+ </RelativeLayout>
+</ScrollView>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index eb01190..e871ff3 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -16,4 +16,11 @@
<resources>
<attr name="preferenceBackgroundColor" format="color" />
+
+ <declare-styleable name="IntervalSeekBar">
+ <attr name="min" format="float" />
+ <attr name="max" format="float" />
+ <attr name="defaultValue" />
+ <attr name="digits" format="integer" />
+ </declare-styleable>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bf1c733..0158414 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -21,8 +21,8 @@
<string name="dlg_ok">OK</string>
<string name="cancel">Cancel</string>
<string name="add">Add</string>
- <string name="choose_app">Choose app</string>
- <string name="reset">Reset</string>
+ <string name="choose_app">Choose app</string>
+ <string name="reset">Reset</string>
<string name="advanced">Advanced</string>
<!-- Privacy Settings Header item -->
@@ -96,5 +96,52 @@
<string name="led_notification_text">LED light enabled by settings</string>
<string name="notification_light_no_apps_summary">To add per app control, activate \'%1$s\' and press \'\u002b\' on the menu bar</string>
+ <!-- LiveDisplay -->
+ <string name="live_display_summary">Optimize your screen based on time of day and ambient conditions to improve readability and reduce eyestrain</string>
+ <string name="live_display_mode">Display mode</string>
+ <string name="live_display_color_temperature_title">Color temperature</string>
+ <string name="live_display_color_temperature_summary">Day: <xliff:g id="day_temperature">%1$d</xliff:g>K Night: <xliff:g id="night_temperature">%2$d</xliff:g>K</string>
+ <string name="live_display_color_temperature_label"><xliff:g id="degrees">%1$d</xliff:g>K</string>
+ <string name="live_display_day">Day</string>
+ <string name="live_display_night">Night</string>
+ <string name="live_display_outdoor_mode_title">Automatic outdoor mode</string>
+ <string name="live_display_outdoor_mode_summary">Increase brightness and saturation automatically under bright sunlight</string>
+ <string name="live_display_low_power_title">Reduce power consumption</string>
+ <string name="live_display_low_power_summary">Adjust display for lowest power consumption without degradation</string>
+ <string name="live_display_enhance_color_title">Enhance colors</string>
+ <string name="live_display_enhance_color_summary">Improve color vibrance of flesh tones, scenery, and other images</string>
+ <string name="live_display_color_profile_title">Color profile</string>
+ <string name="live_display_color_profile_standard_title">Standard</string>
+ <string name="live_display_color_profile_standard_summary">Accurate colors and bright whites</string>
+ <string name="live_display_color_profile_natural_title">Natural</string>
+ <string name="live_display_color_profile_natural_summary">Realistic colors and flesh tones</string>
+ <string name="live_display_color_profile_dynamic_title">Dynamic</string>
+ <string name="live_display_color_profile_dynamic_summary">Enhanced colors and bright whites</string>
+ <string name="live_display_color_profile_cinema_title">Cinema</string>
+ <string name="live_display_color_profile_cinema_summary">Perfect color reproduction for video</string>
+ <string name="live_display_color_profile_astronomy_title">Astronomy</string>
+ <string name="live_display_color_profile_astronomy_summary">Deep red for preserving night vision</string>
+ <string name="live_display_color_profile_photography_title">Photography</string>
+ <string name="live_display_color_profile_photography_summary">Perfect color reproduction for photos</string>
+ <string name="live_display_color_profile_basic_title">Basic</string>
+ <string name="live_display_color_profile_basic_summary">Use the display uncalibrated</string>
+ <string name="live_display_color_profile_adaptive_title">Adaptive</string>
+ <string name="live_display_color_profile_adaptive_summary">Colors adapt to ambient conditions</string>
+ <string name="color_calibration_title">Color calibration</string>
+ <string name="color_calibration_summary">Calibrate on-screen colors</string>
+ <string name="color_red_title">Red</string>
+ <string name="color_green_title">Green</string>
+ <string name="color_blue_title">Blue</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>
+
</resources>
+
diff --git a/res/xml/livedisplay.xml b/res/xml/livedisplay.xml
new file mode 100644
index 0000000..ef1d9bd
--- /dev/null
+++ b/res/xml/livedisplay.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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.
+-->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <PreferenceCategory
+ android:key="live_display_options"
+ android:title="@*cyanogenmod.platform:string/live_display_title">
+
+ <!-- Color profile -->
+ <ListPreference
+ android:key="live_display_color_profile"
+ android:title="@string/live_display_color_profile_title"
+ android:persistent="false" />
+
+ <ListPreference
+ android:key="live_display"
+ android:title="@string/live_display_mode"
+ android:persistent="false" />
+
+ <!-- Manual temperature selection -->
+ <org.cyanogenmod.cmparts.livedisplay.DisplayTemperature
+ android:key="live_display_color_temperature"
+ android:title="@string/live_display_color_temperature_title"
+ android:dialogTitle="@*cyanogenmod.platform:string/live_display_title"
+ android:persistent="false" />
+
+ <!-- Outdoor mode / SRE -->
+ <cyanogenmod.preference.CMSystemSettingSwitchPreference
+ android:key="display_auto_outdoor_mode"
+ android:title="@string/live_display_outdoor_mode_title"
+ android:summary="@string/live_display_outdoor_mode_summary"
+ android:defaultValue="@*cyanogenmod.platform:bool/config_defaultAutoOutdoorMode" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="advanced"
+ android:title="@string/advanced">
+
+ <!-- RGB display color adjustments -->
+ <org.cyanogenmod.cmparts.livedisplay.DisplayColor
+ android:key="color_calibration"
+ android:title="@string/color_calibration_title"
+ android:dialogTitle="@string/color_calibration_title"
+ android:summary="@string/color_calibration_summary"
+ android:persistent="false"/>
+
+ <!-- HSIC display color adjustments -->
+ <org.cyanogenmod.cmparts.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 -->
+ <cyanogenmod.preference.CMSystemSettingSwitchPreference
+ android:key="display_low_power"
+ android:title="@string/live_display_low_power_title"
+ android:summary="@string/live_display_low_power_summary"
+ android:defaultValue="@*cyanogenmod.platform:bool/config_defaultCABC" />
+
+ <!-- Color enhancement -->
+ <cyanogenmod.preference.CMSystemSettingSwitchPreference
+ android:key="display_color_enhance"
+ android:title="@string/live_display_enhance_color_title"
+ android:summary="@string/live_display_enhance_color_summary"
+ android:defaultValue="@*cyanogenmod.platform:bool/config_defaultColorEnhancement" />
+
+ </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/src/org/cyanogenmod/cmparts/CustomDialogPreference.java b/src/org/cyanogenmod/cmparts/CustomDialogPreference.java
index 8e8ab92..5fa9175 100644
--- a/src/org/cyanogenmod/cmparts/CustomDialogPreference.java
+++ b/src/org/cyanogenmod/cmparts/CustomDialogPreference.java
@@ -26,7 +26,7 @@
import android.util.AttributeSet;
import android.view.View;
-public class CustomDialogPreference<T extends Dialog> extends DialogPreference {
+public class CustomDialogPreference<T extends DialogInterface> extends DialogPreference {
private CustomPreferenceDialogFragment mFragment;
@@ -48,7 +48,7 @@
}
public boolean isDialogOpen() {
- return getDialog() != null && getDialog().isShowing();
+ return getDialog() != null && getDialog() instanceof Dialog && ((Dialog)getDialog()).isShowing();
}
public T getDialog() {
@@ -62,7 +62,7 @@
protected void onDialogClosed(boolean positiveResult) {
}
- protected void onClick(DialogInterface dialog, int which) {
+ protected void onClick(T dialog, int which) {
}
protected void onBindDialogView(View view) {
@@ -80,6 +80,10 @@
mFragment = fragment;
}
+ protected boolean onDismissDialog(T dialog, int which) {
+ return true;
+ }
+
public static class CustomPreferenceDialogFragment extends PreferenceDialogFragment {
public static CustomPreferenceDialogFragment newInstance(String key) {
@@ -94,6 +98,43 @@
return (CustomDialogPreference) getPreference();
}
+ private class OnDismissListener implements View.OnClickListener {
+ private final int mWhich;
+ private final DialogInterface mDialog;
+
+ public OnDismissListener(DialogInterface dialog, int which) {
+ mWhich = which;
+ mDialog = dialog;
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (getCustomizablePreference().onDismissDialog(mDialog, mWhich)) {
+ mDialog.dismiss();
+ }
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (getDialog() instanceof AlertDialog) {
+ AlertDialog a = (AlertDialog)getDialog();
+ if (a.getButton(Dialog.BUTTON_NEUTRAL) != null) {
+ a.getButton(Dialog.BUTTON_NEUTRAL).setOnClickListener(
+ new OnDismissListener(a, Dialog.BUTTON_NEUTRAL));
+ }
+ if (a.getButton(Dialog.BUTTON_POSITIVE) != null) {
+ a.getButton(Dialog.BUTTON_POSITIVE).setOnClickListener(
+ new OnDismissListener(a, Dialog.BUTTON_POSITIVE));
+ }
+ if (a.getButton(Dialog.BUTTON_NEGATIVE) != null) {
+ a.getButton(Dialog.BUTTON_NEGATIVE).setOnClickListener(
+ new OnDismissListener(a, Dialog.BUTTON_NEGATIVE));
+ }
+ }
+ }
+
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
diff --git a/src/org/cyanogenmod/cmparts/IntervalSeekBar.java b/src/org/cyanogenmod/cmparts/IntervalSeekBar.java
new file mode 100644
index 0000000..995d34d
--- /dev/null
+++ b/src/org/cyanogenmod/cmparts/IntervalSeekBar.java
@@ -0,0 +1,102 @@
+/*
+ * 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 org.cyanogenmod.cmparts;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.SeekBar;
+
+/**
+ * Custom SeekBar that allows setting both a minimum and maximum value.
+ * This also handles floating point values (to 2 decimal places) through
+ * integer conversions.
+ */
+public class IntervalSeekBar extends SeekBar {
+ private float mMin;
+ private float mMax;
+ private float mDefault;
+ private float mMultiplier;
+
+ public IntervalSeekBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ TypedArray seekBarType = context.obtainStyledAttributes(attrs,
+ R.styleable.IntervalSeekBar, 0, 0);
+
+ mMax = seekBarType.getFloat(R.styleable.IntervalSeekBar_max, 1.5f);
+ mMin = seekBarType.getFloat(R.styleable.IntervalSeekBar_min, 0.5f);
+ mDefault = seekBarType.getFloat(R.styleable.IntervalSeekBar_defaultValue, 1.0f);
+
+ int digits = seekBarType.getInt(R.styleable.IntervalSeekBar_digits, 0);
+ mMultiplier = (float) Math.pow(10, digits);
+
+ if (mMin > mMax) {
+ float temp = mMax;
+ mMax = mMin;
+ mMin = temp;
+ }
+
+ setMax(convertFloatToProgress(mMax));
+ setProgressFloat(mDefault);
+
+ seekBarType.recycle();
+ }
+
+ /*
+ * Converts from SeekBar units (which the SeekBar uses), to scale units
+ * (which are saved).
+ * This operation is the inverse of setFontScaling.
+ */
+ public float getProgressFloat() {
+ return (getProgress() / mMultiplier) + mMin;
+ }
+
+ /*
+ * Converts from scale units (which are saved), to SeekBar units
+ * (which the SeekBar uses). This also sets the SeekBar progress.
+ * This operation is the inverse of getProgressFloat.
+ */
+ public void setProgressFloat(float progress) {
+ setProgress(convertFloatToProgress(progress));
+ }
+
+ private int convertFloatToProgress(float value) {
+ return Math.round((value - mMin) * mMultiplier);
+ }
+
+ public float getMinimum() {
+ return mMin;
+ }
+
+ public float getMaximum() {
+ return mMax;
+ }
+
+ public float getDefault() {
+ return mDefault;
+ }
+
+ public void setMaximum(float max) {
+ mMax = max;
+ setMax(convertFloatToProgress(mMax));
+ }
+
+ public void setMinimum(float min) {
+ mMin = min;
+ }
+}
diff --git a/src/org/cyanogenmod/cmparts/PartsActivity.java b/src/org/cyanogenmod/cmparts/PartsActivity.java
index b463b9a..65dbd01 100644
--- a/src/org/cyanogenmod/cmparts/PartsActivity.java
+++ b/src/org/cyanogenmod/cmparts/PartsActivity.java
@@ -20,19 +20,24 @@
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.preference.PreferenceActivity;
+import android.util.Log;
+import org.cyanogenmod.cmparts.livedisplay.LiveDisplay;
import org.cyanogenmod.cmparts.notificationlight.BatteryLightSettings;
import org.cyanogenmod.cmparts.notificationlight.NotificationLightSettings;
public class PartsActivity extends PreferenceActivity {
+ public static final String TAG = "PartsActivity";
+
public static final String EXTRA_PART = "part";
public static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
public static final String FRAGMENT_PREFIX = "cmparts:";
- public static final String FRAGMENT_NOTIFICATION_LIGHTS = "notification_lights";
public static final String FRAGMENT_BATTERY_LIGHTS = "battery_lights";
+ public static final String FRAGMENT_NOTIFICATION_LIGHTS = "notification_lights";
+ public static final String FRAGMENT_LIVEDISPLAY = "livedisplay";
private ActionBar mActionBar;
@@ -47,11 +52,17 @@
return;
}
String part = keys[1];
+ Log.d(TAG, "Launching fragment: " + partExtra);
+
SettingsPreferenceFragment fragment = null;
if (part.equals(FRAGMENT_NOTIFICATION_LIGHTS)) {
fragment = new NotificationLightSettings();
} else if (part.equals(FRAGMENT_BATTERY_LIGHTS)) {
fragment = new BatteryLightSettings();
+ } else if (part.equals(FRAGMENT_LIVEDISPLAY)) {
+ fragment = new LiveDisplay();
+ } else {
+ Log.d(TAG, "Unknown fragment: " + part);
}
mActionBar = getActionBar();
diff --git a/src/org/cyanogenmod/cmparts/livedisplay/DisplayColor.java b/src/org/cyanogenmod/cmparts/livedisplay/DisplayColor.java
new file mode 100644
index 0000000..d112131
--- /dev/null
+++ b/src/org/cyanogenmod/cmparts/livedisplay/DisplayColor.java
@@ -0,0 +1,235 @@
+/*
+ * 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.
+ */
+
+package org.cyanogenmod.cmparts.livedisplay;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import org.cyanogenmod.cmparts.CustomDialogPreference;
+import org.cyanogenmod.cmparts.IntervalSeekBar;
+import org.cyanogenmod.cmparts.R;
+
+import cyanogenmod.hardware.LiveDisplayManager;
+
+/**
+ * Special preference type that allows configuration of Color settings
+ */
+public class DisplayColor extends CustomDialogPreference<AlertDialog> {
+ private static final String TAG = "ColorCalibration";
+
+ private final Context mContext;
+ private final LiveDisplayManager mLiveDisplay;
+
+ // These arrays must all match in length and order
+ private static final int[] SEEKBAR_ID = new int[] {
+ R.id.color_red_seekbar,
+ R.id.color_green_seekbar,
+ R.id.color_blue_seekbar
+ };
+
+ private static final int[] SEEKBAR_VALUE_ID = new int[] {
+ R.id.color_red_value,
+ R.id.color_green_value,
+ R.id.color_blue_value
+ };
+
+ private ColorSeekBar[] mSeekBars = new ColorSeekBar[SEEKBAR_ID.length];
+
+ private final float[] mCurrentColors = new float[3];
+ private final float[] mOriginalColors = new float[3];
+
+ public DisplayColor(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mContext = context;
+ mLiveDisplay = LiveDisplayManager.getInstance(mContext);
+
+ setDialogLayoutResource(R.layout.display_color_calibration);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder, DialogInterface.OnClickListener listener) {
+ super.onPrepareDialogBuilder(builder, listener);
+
+ builder.setNeutralButton(R.string.reset,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ System.arraycopy(mLiveDisplay.getColorAdjustment(), 0, mOriginalColors, 0, 3);
+ System.arraycopy(mOriginalColors, 0, mCurrentColors, 0, 3);
+
+ 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]);
+ mSeekBars[i] = new ColorSeekBar(seekBar, value, i);
+ mSeekBars[i].mSeekBar.setMinimum(0.1f);
+ mSeekBars[i].mSeekBar.setMaximum(1.0f);
+
+ mSeekBars[i].mSeekBar.setProgressFloat(mCurrentColors[i]);
+ int percent = Math.round(100F * mCurrentColors[i]);
+ value.setText(String.format("%d%%", percent));
+ }
+ }
+
+ @Override
+ protected boolean onDismissDialog(AlertDialog dialog, int which) {
+ // Can't use onPrepareDialogBuilder for this as we want the dialog
+ // to be kept open on click
+ if (which == DialogInterface.BUTTON_NEUTRAL) {
+ for (int i = 0; i < mSeekBars.length; i++) {
+ mSeekBars[i].mSeekBar.setProgressFloat(1.0f);
+ mCurrentColors[i] = 1.0f;
+ }
+ updateColors(mCurrentColors);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+ updateColors(positiveResult ? mCurrentColors : mOriginalColors);
+ }
+
+ @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.currentColors = mCurrentColors;
+ myState.originalColors = mOriginalColors;
+
+ // Restore the old state when the activity or dialog is being paused
+ updateColors(mOriginalColors);
+
+ 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.originalColors, 0, mOriginalColors, 0, 3);
+ System.arraycopy(myState.currentColors, 0, mCurrentColors, 0, 3);
+ for (int i = 0; i < mSeekBars.length; i++) {
+ mSeekBars[i].mSeekBar.setProgressFloat(mCurrentColors[i]);
+ }
+ updateColors(mCurrentColors);
+ }
+
+ private static class SavedState extends BaseSavedState {
+ float[] originalColors;
+ float[] currentColors;
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public SavedState(Parcel source) {
+ super(source);
+ originalColors = source.createFloatArray();
+ currentColors = source.createFloatArray();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeFloatArray(originalColors);
+ dest.writeFloatArray(currentColors);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ private void updateColors(float[] colors) {
+ mLiveDisplay.setColorAdjustment(colors);
+ }
+
+ private class ColorSeekBar implements SeekBar.OnSeekBarChangeListener {
+ private int mIndex;
+ private final IntervalSeekBar mSeekBar;
+ private TextView mValue;
+
+ public ColorSeekBar(IntervalSeekBar seekBar, TextView value, int index) {
+ mSeekBar = seekBar;
+ mValue = value;
+ mIndex = index;
+
+ mSeekBar.setOnSeekBarChangeListener(this);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ IntervalSeekBar isb = (IntervalSeekBar)seekBar;
+ float fp = isb.getProgressFloat();
+ if (fromUser) {
+ mCurrentColors[mIndex] = fp > 1.0f ? 1.0f : fp;
+ updateColors(mCurrentColors);
+ }
+
+ int percent = Math.round(100F * fp);
+ mValue.setText(String.format("%d%%", percent));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+ }
+}
diff --git a/src/org/cyanogenmod/cmparts/livedisplay/DisplayTemperature.java b/src/org/cyanogenmod/cmparts/livedisplay/DisplayTemperature.java
new file mode 100644
index 0000000..e272bb0
--- /dev/null
+++ b/src/org/cyanogenmod/cmparts/livedisplay/DisplayTemperature.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package org.cyanogenmod.cmparts.livedisplay;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import org.cyanogenmod.cmparts.CustomDialogPreference;
+import org.cyanogenmod.cmparts.R;
+import org.cyanogenmod.internal.util.MathUtils;
+
+import cyanogenmod.hardware.LiveDisplayConfig;
+import cyanogenmod.hardware.LiveDisplayManager;
+
+/**
+ * Preference for selection of color temperature range for LiveDisplay
+ */
+public class DisplayTemperature extends CustomDialogPreference<AlertDialog> {
+ private static final String TAG = "DisplayTemperature";
+
+ private final Context mContext;
+
+ private ColorTemperatureSeekBar mDayTemperature;
+ private ColorTemperatureSeekBar mNightTemperature;
+
+ private int mOriginalDayTemperature;
+ private int mOriginalNightTemperature;
+
+ private final LiveDisplayManager mLiveDisplay;
+ private final LiveDisplayConfig mConfig;
+
+ private static final int STEP = 100;
+
+ public DisplayTemperature(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+ mLiveDisplay = LiveDisplayManager.getInstance(mContext);
+ mConfig = mLiveDisplay.getConfig();
+
+ setDialogLayoutResource(R.layout.display_temperature);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder, DialogInterface.OnClickListener listener) {
+ super.onPrepareDialogBuilder(builder, listener);
+
+ builder.setNeutralButton(R.string.reset,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ mOriginalDayTemperature = mLiveDisplay.getDayColorTemperature();
+ mOriginalNightTemperature = mLiveDisplay.getNightColorTemperature();
+
+ SeekBar day = (SeekBar) view.findViewById(R.id.day_temperature_seekbar);
+ TextView dayText = (TextView) view.findViewById(R.id.day_temperature_value);
+ mDayTemperature = new ColorTemperatureSeekBar(day, dayText);
+
+ SeekBar night = (SeekBar) view.findViewById(R.id.night_temperature_seekbar);
+ TextView nightText = (TextView) view.findViewById(R.id.night_temperature_value);
+ mNightTemperature = new ColorTemperatureSeekBar(night, nightText);
+
+ mDayTemperature.setTemperature(mOriginalDayTemperature);
+ mNightTemperature.setTemperature(mOriginalNightTemperature);
+ }
+
+
+ @Override
+ protected boolean onDismissDialog(AlertDialog dialog, int which) {
+ // Can't use onPrepareDialogBuilder for this as we want the dialog
+ // to be kept open on click
+ if (which == DialogInterface.BUTTON_NEUTRAL) {
+ mDayTemperature.setTemperature(mConfig.getDefaultDayTemperature());
+ mNightTemperature.setTemperature(mConfig.getDefaultNightTemperature());
+ updateTemperature(true);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+ updateTemperature(positiveResult);
+ }
+
+ @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.originalDayTemperature = mOriginalDayTemperature;
+ myState.originalNightTemperature = mOriginalNightTemperature;
+ myState.currentDayTemperature = mDayTemperature.getTemperature();
+ myState.currentNightTemperature = mNightTemperature.getTemperature();
+
+ // Restore the old state when the activity or dialog is being paused
+ updateTemperature(false);
+
+ 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());
+
+ mOriginalDayTemperature = myState.originalDayTemperature;
+ mOriginalNightTemperature = myState.originalNightTemperature;
+ mDayTemperature.setTemperature(myState.currentDayTemperature);
+ mNightTemperature.setTemperature(myState.currentNightTemperature);;
+
+ updateTemperature(true);
+ }
+
+ private static class SavedState extends BaseSavedState {
+ int originalDayTemperature;
+ int originalNightTemperature;
+ int currentDayTemperature;
+ int currentNightTemperature;
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public SavedState(Parcel source) {
+ super(source);
+ originalDayTemperature = source.readInt();
+ originalNightTemperature = source.readInt();
+ currentDayTemperature = source.readInt();
+ currentNightTemperature = source.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(originalDayTemperature);
+ dest.writeInt(originalNightTemperature);
+ dest.writeInt(currentDayTemperature);
+ dest.writeInt(currentNightTemperature);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ private void updateTemperature(boolean accept) {
+ int day = accept ? mDayTemperature.getTemperature() : mOriginalDayTemperature;
+ int night = accept ? mNightTemperature.getTemperature() : mOriginalNightTemperature;
+ callChangeListener(new Integer[] { day, night });
+
+ mLiveDisplay.setDayColorTemperature(day);
+ mLiveDisplay.setNightColorTemperature(night);
+ }
+
+ int roundUp(int value) {
+ return ((value + STEP / 2) / STEP) * STEP;
+ }
+
+ private class ColorTemperatureSeekBar implements SeekBar.OnSeekBarChangeListener {
+ private final SeekBar mSeekBar;
+ private final TextView mValue;
+
+ private final int mMin;
+ private final int mMax;
+
+ private final int mBalanceMin;
+ private final int mBalanceMax;
+
+ private final int mBarMax;
+
+ private final boolean mUseBalance;
+ private final double[] mBalanceCurve;
+
+ public ColorTemperatureSeekBar(SeekBar seekBar, TextView value) {
+ mSeekBar = seekBar;
+ mValue = value;
+ mMin = mConfig.getColorTemperatureRange().getLower();
+ mMax = mConfig.getColorTemperatureRange().getUpper();
+ mBalanceMin = mConfig.getColorBalanceRange().getLower();
+ mBalanceMax = mConfig.getColorBalanceRange().getUpper();
+ mUseBalance = mConfig.hasFeature(LiveDisplayManager.FEATURE_COLOR_BALANCE) &&
+ ((mBalanceMin != 0) || (mBalanceMax != 0));
+
+ if (mUseBalance) {
+ mBalanceCurve = MathUtils.powerCurve(mMin, mConfig.getDefaultDayTemperature(), mMax);
+ mBarMax = mBalanceMax - mBalanceMin;
+ } else {
+ mBalanceCurve = null;
+ mBarMax = (mMax - mMin) / STEP;
+ }
+ mSeekBar.setMax(mBarMax);
+ mSeekBar.setOnSeekBarChangeListener(this);
+
+ // init text value
+ int p = mSeekBar.getProgress();
+ onProgressChanged(mSeekBar, p, false);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (fromUser) {
+ updateTemperature(true);
+ }
+
+ int displayValue;
+ if (mUseBalance) {
+ displayValue = roundUp(Math.round((float)MathUtils.linearToPowerCurve(
+ mBalanceCurve, (double)progress / (double)mBarMax)));
+ } else {
+ displayValue = progress * STEP + mMin;
+ }
+ Log.d(TAG, "onProgressChanged: progress=" + progress + " displayValue=" + displayValue);
+
+ mValue.setText(mContext.getResources().getString(
+ R.string.live_display_color_temperature_label, displayValue));
+ }
+
+ public void setTemperature(int temperature) {
+ if (mUseBalance) {
+ double z = MathUtils.powerCurveToLinear(mBalanceCurve, (double)temperature);
+ mSeekBar.setProgress(Math.round((float)(z * (double)mBarMax)));
+ return;
+ }
+ int p = Math.max(temperature, mMin) - mMin;
+ mSeekBar.setProgress(Math.round((float) p / STEP));
+ }
+
+ public int getTemperature() {
+ if (mUseBalance) {
+ return Math.round((float)MathUtils.linearToPowerCurve(
+ mBalanceCurve, (double)mSeekBar.getProgress() / (double)mBarMax));
+ }
+ return mSeekBar.getProgress() * STEP + mMin;
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+ }
+}
diff --git a/src/org/cyanogenmod/cmparts/livedisplay/LiveDisplay.java b/src/org/cyanogenmod/cmparts/livedisplay/LiveDisplay.java
new file mode 100644
index 0000000..8e0d536
--- /dev/null
+++ b/src/org/cyanogenmod/cmparts/livedisplay/LiveDisplay.java
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 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.
+ */
+package org.cyanogenmod.cmparts.livedisplay;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v14.preference.SwitchPreference;
+import android.provider.SearchIndexableResource;
+import android.util.Log;
+
+import com.android.internal.util.ArrayUtils;
+
+import org.cyanogenmod.cmparts.R;
+import org.cyanogenmod.cmparts.SettingsPreferenceFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import cyanogenmod.hardware.CMHardwareManager;
+import cyanogenmod.hardware.DisplayMode;
+import cyanogenmod.hardware.LiveDisplayConfig;
+import cyanogenmod.hardware.LiveDisplayManager;
+import cyanogenmod.providers.CMSettings;
+
+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;
+
+public class LiveDisplay extends SettingsPreferenceFragment implements
+ Preference.OnPreferenceChangeListener {
+
+ private static final String TAG = "LiveDisplay";
+
+ private static final String KEY_CATEGORY_LIVE_DISPLAY = "live_display_options";
+ private static final String KEY_CATEGORY_ADVANCED = "advanced";
+
+ private static final String KEY_LIVE_DISPLAY = "live_display";
+ private static final String KEY_LIVE_DISPLAY_AUTO_OUTDOOR_MODE =
+ "display_auto_outdoor_mode";
+ private static final String KEY_LIVE_DISPLAY_LOW_POWER = "display_low_power";
+ private static final String KEY_LIVE_DISPLAY_COLOR_ENHANCE = "display_color_enhance";
+ 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_PICTURE_ADJUSTMENT = "picture_adjustment";
+
+ private static final String KEY_LIVE_DISPLAY_COLOR_PROFILE = "live_display_color_profile";
+
+ private final Handler mHandler = new Handler();
+ private final SettingsObserver mObserver = new SettingsObserver();
+
+ private ListPreference mLiveDisplay;
+
+ private SwitchPreference mColorEnhancement;
+ private SwitchPreference mLowPower;
+ private SwitchPreference mOutdoorMode;
+
+ private PictureAdjustment mPictureAdjustment;
+ private DisplayTemperature mDisplayTemperature;
+ private DisplayColor mDisplayColor;
+
+ private ListPreference mColorProfile;
+ private String[] mColorProfileSummaries;
+
+ private String[] mModeEntries;
+ private String[] mModeValues;
+ private String[] mModeSummaries;
+
+ private boolean mHasDisplayModes = false;
+
+ private LiveDisplayManager mLiveDisplayManager;
+ private LiveDisplayConfig mConfig;
+
+ private CMHardwareManager mHardware;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Resources res = getResources();
+
+ mHardware = CMHardwareManager.getInstance(getActivity());
+ mLiveDisplayManager = LiveDisplayManager.getInstance(getActivity());
+ mConfig = mLiveDisplayManager.getConfig();
+
+ addPreferencesFromResource(R.xml.livedisplay);
+
+ PreferenceCategory liveDisplayPrefs = (PreferenceCategory)
+ findPreference(KEY_CATEGORY_LIVE_DISPLAY);
+ PreferenceCategory advancedPrefs = (PreferenceCategory)
+ findPreference(KEY_CATEGORY_ADVANCED);
+
+ int adaptiveMode = mLiveDisplayManager.getMode();
+
+ mLiveDisplay = (ListPreference) findPreference(KEY_LIVE_DISPLAY);
+ mLiveDisplay.setValue(String.valueOf(adaptiveMode));
+
+ mModeEntries = res.getStringArray(
+ org.cyanogenmod.platform.internal.R.array.live_display_entries);
+ mModeValues = res.getStringArray(
+ org.cyanogenmod.platform.internal.R.array.live_display_values);
+ mModeSummaries = res.getStringArray(
+ org.cyanogenmod.platform.internal.R.array.live_display_summaries);
+
+ // Remove outdoor mode from lists if there is no support
+ if (!mConfig.hasFeature(LiveDisplayManager.MODE_OUTDOOR)) {
+ int idx = ArrayUtils.indexOf(mModeValues, String.valueOf(MODE_OUTDOOR));
+ String[] entriesTemp = new String[mModeEntries.length - 1];
+ String[] valuesTemp = new String[mModeValues.length - 1];
+ String[] summariesTemp = new String[mModeSummaries.length - 1];
+ int j = 0;
+ for (int i = 0; i < mModeEntries.length; i++) {
+ if (i == idx) {
+ continue;
+ }
+ entriesTemp[j] = mModeEntries[i];
+ valuesTemp[j] = mModeValues[i];
+ summariesTemp[j] = mModeSummaries[i];
+ j++;
+ }
+ mModeEntries = entriesTemp;
+ mModeValues = valuesTemp;
+ mModeSummaries = summariesTemp;
+ }
+
+ mLiveDisplay.setEntries(mModeEntries);
+ mLiveDisplay.setEntryValues(mModeValues);
+ mLiveDisplay.setOnPreferenceChangeListener(this);
+
+ mDisplayTemperature = (DisplayTemperature) findPreference(KEY_LIVE_DISPLAY_TEMPERATURE);
+
+ mColorProfile = (ListPreference) findPreference(KEY_LIVE_DISPLAY_COLOR_PROFILE);
+ if (liveDisplayPrefs != null && mColorProfile != null
+ && (!mConfig.hasFeature(FEATURE_DISPLAY_MODES) || !updateDisplayModes())) {
+ liveDisplayPrefs.removePreference(mColorProfile);
+ } else {
+ mHasDisplayModes = true;
+ mColorProfile.setOnPreferenceChangeListener(this);
+ }
+
+ mOutdoorMode = (SwitchPreference) findPreference(KEY_LIVE_DISPLAY_AUTO_OUTDOOR_MODE);
+ if (liveDisplayPrefs != null && mOutdoorMode != null
+ && !mConfig.hasFeature(MODE_OUTDOOR)) {
+ liveDisplayPrefs.removePreference(mOutdoorMode);
+ mOutdoorMode = null;
+ }
+
+ mLowPower = (SwitchPreference) findPreference(KEY_LIVE_DISPLAY_LOW_POWER);
+ if (advancedPrefs != null && mLowPower != null
+ && !mConfig.hasFeature(FEATURE_CABC)) {
+ advancedPrefs.removePreference(mLowPower);
+ mLowPower = null;
+ }
+
+ mColorEnhancement = (SwitchPreference) findPreference(KEY_LIVE_DISPLAY_COLOR_ENHANCE);
+ if (advancedPrefs != null && mColorEnhancement != null
+ && !mConfig.hasFeature(FEATURE_COLOR_ENHANCEMENT)) {
+ advancedPrefs.removePreference(mColorEnhancement);
+ mColorEnhancement = null;
+ }
+
+ 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;
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateModeSummary();
+ updateTemperatureSummary();
+ updateColorProfileSummary(null);
+ mObserver.register(true);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mObserver.register(false);
+ }
+
+ private String getStringForResourceName(String resourceName, String defaultValue) {
+ Resources res = getResources();
+ int resId = res.getIdentifier(resourceName, "string", "org.cyanogenmod.livedisplay");
+ if (resId <= 0) {
+ Log.e(TAG, "No resource found for " + resourceName);
+ return defaultValue;
+ } else {
+ return res.getString(resId);
+ }
+ }
+
+ private boolean updateDisplayModes() {
+ final DisplayMode[] modes = mHardware.getDisplayModes();
+ if (modes == null || modes.length == 0) {
+ return false;
+ }
+
+ final DisplayMode cur = mHardware.getCurrentDisplayMode() != null
+ ? mHardware.getCurrentDisplayMode() : mHardware.getDefaultDisplayMode();
+ int curId = -1;
+ String[] entries = new String[modes.length];
+ String[] values = new String[modes.length];
+ mColorProfileSummaries = new String[modes.length];
+ for (int i = 0; i < modes.length; i++) {
+ values[i] = String.valueOf(modes[i].id);
+ String name = modes[i].name.toLowerCase().replace(" ", "_");
+ String nameRes = String.format("live_display_color_profile_%s_title", name);
+ entries[i] = getStringForResourceName(nameRes, modes[i].name);
+
+ // Populate summary
+ String summaryRes = String.format("live_display_color_profile_%s_summary", name);
+ String summary = getStringForResourceName(summaryRes, null);
+ if (summary != null) {
+ summary = String.format("%s - %s", entries[i], summary);
+ }
+ mColorProfileSummaries[i] = summary;
+
+ if (cur != null && modes[i].id == cur.id) {
+ curId = cur.id;
+ }
+ }
+ mColorProfile.setEntries(entries);
+ mColorProfile.setEntryValues(values);
+ if (curId >= 0) {
+ mColorProfile.setValue(String.valueOf(curId));
+ }
+
+ return true;
+ }
+
+ private void updateColorProfileSummary(String value) {
+ if (!mHasDisplayModes) {
+ return;
+ }
+
+ if (value == null) {
+ DisplayMode cur = mHardware.getCurrentDisplayMode() != null
+ ? mHardware.getCurrentDisplayMode() : mHardware.getDefaultDisplayMode();
+ if (cur != null && cur.id >= 0) {
+ value = String.valueOf(cur.id);
+ }
+ }
+
+ int idx = mColorProfile.findIndexOfValue(value);
+ if (idx < 0) {
+ Log.e(TAG, "No summary resource found for profile " + value);
+ mColorProfile.setSummary(null);
+ return;
+ }
+
+ mColorProfile.setValue(value);
+ mColorProfile.setSummary(mColorProfileSummaries[idx]);
+ }
+
+ private void updateModeSummary() {
+ int mode = mLiveDisplayManager.getMode();
+
+ int index = ArrayUtils.indexOf(mModeValues, String.valueOf(mode));
+ if (index < 0) {
+ index = ArrayUtils.indexOf(mModeValues, String.valueOf(MODE_OFF));
+ }
+
+ mLiveDisplay.setSummary(mModeSummaries[index]);
+ mLiveDisplay.setValue(String.valueOf(mode));
+
+ if (mDisplayTemperature != null) {
+ mDisplayTemperature.setEnabled(mode != MODE_OFF);
+ }
+ if (mOutdoorMode != null) {
+ mOutdoorMode.setEnabled(mode != MODE_OFF);
+ }
+ }
+
+ private void updateTemperatureSummary() {
+ int day = mLiveDisplayManager.getDayColorTemperature();
+ int night = mLiveDisplayManager.getNightColorTemperature();
+
+ mDisplayTemperature.setSummary(getResources().getString(
+ R.string.live_display_color_temperature_summary,
+ mDisplayTemperature.roundUp(day),
+ mDisplayTemperature.roundUp(night)));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object objValue) {
+ if (preference == mLiveDisplay) {
+ mLiveDisplayManager.setMode(Integer.valueOf((String)objValue));
+ } else if (preference == mColorProfile) {
+ int id = Integer.valueOf((String)objValue);
+ Log.i("LiveDisplay", "Setting mode: " + id);
+ for (DisplayMode mode : mHardware.getDisplayModes()) {
+ if (mode.id == id) {
+ mHardware.setDisplayMode(mode, true);
+ updateColorProfileSummary((String)objValue);
+ break;
+ }
+ }
+ }
+ return true;
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ private final Uri DISPLAY_TEMPERATURE_DAY_URI =
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_DAY);
+ private final Uri DISPLAY_TEMPERATURE_NIGHT_URI =
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_NIGHT);
+ private final Uri DISPLAY_TEMPERATURE_MODE_URI =
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_MODE);
+
+ public SettingsObserver() {
+ super(mHandler);
+ }
+
+ public void register(boolean register) {
+ final ContentResolver cr = getContentResolver();
+ if (register) {
+ cr.registerContentObserver(DISPLAY_TEMPERATURE_DAY_URI, false, this, UserHandle.USER_ALL);
+ cr.registerContentObserver(DISPLAY_TEMPERATURE_NIGHT_URI, false, this, UserHandle.USER_ALL);
+ cr.registerContentObserver(DISPLAY_TEMPERATURE_MODE_URI, false, this, UserHandle.USER_ALL);
+ } else {
+ cr.unregisterContentObserver(this);
+ }
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ updateModeSummary();
+ updateTemperatureSummary();
+ }
+ }
+
+ /*
+ * Disabled until search query is implemented
+ *
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ ArrayList<SearchIndexableResource> result =
+ new ArrayList<SearchIndexableResource>();
+
+ SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.livedisplay;
+ result.add(sir);
+
+ return result;
+ }
+
+ @Override
+ public List<String> getNonIndexableKeys(Context context) {
+ final CMHardwareManager hardware = CMHardwareManager.getInstance(context);
+ final LiveDisplayConfig config = LiveDisplayManager.getInstance(context).getConfig();
+
+ ArrayList<String> result = new ArrayList<String>();
+ if (!hardware.isSupported(FEATURE_DISPLAY_MODES)) {
+ result.add(KEY_LIVE_DISPLAY_COLOR_PROFILE);
+ }
+ if (!config.hasFeature(MODE_OUTDOOR)) {
+ result.add(KEY_LIVE_DISPLAY_AUTO_OUTDOOR_MODE);
+ }
+ if (!config.hasFeature(FEATURE_COLOR_ENHANCEMENT)) {
+ result.add(KEY_LIVE_DISPLAY_COLOR_ENHANCE);
+ }
+ if (!config.hasFeature(FEATURE_CABC)) {
+ result.add(KEY_LIVE_DISPLAY_LOW_POWER);
+ }
+ 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/org/cyanogenmod/cmparts/livedisplay/PictureAdjustment.java b/src/org/cyanogenmod/cmparts/livedisplay/PictureAdjustment.java
new file mode 100644
index 0000000..cb79840
--- /dev/null
+++ b/src/org/cyanogenmod/cmparts/livedisplay/PictureAdjustment.java
@@ -0,0 +1,257 @@
+/*
+ * 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 org.cyanogenmod.cmparts.livedisplay;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Range;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import org.cyanogenmod.cmparts.CustomDialogPreference;
+import org.cyanogenmod.cmparts.IntervalSeekBar;
+import org.cyanogenmod.cmparts.R;
+
+import java.util.List;
+
+import cyanogenmod.hardware.HSIC;
+import cyanogenmod.hardware.LiveDisplayManager;
+
+/**
+ * Special preference type that allows configuration of Color settings
+ */
+public class PictureAdjustment extends CustomDialogPreference<AlertDialog> {
+ 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, DialogInterface.OnClickListener listener) {
+ super.onPrepareDialogBuilder(builder, listener);
+
+ builder.setNeutralButton(R.string.reset,
+ 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 boolean onDismissDialog(AlertDialog dialog, int which) {
+ // Can't use onPrepareDialogBuilder for this as we want the dialog
+ // to be kept open on click
+ if (which == DialogInterface.BUTTON_NEUTRAL) {
+ System.arraycopy(mLiveDisplay.getDefaultPictureAdjustment().toFloatArray(),
+ 0, mCurrentAdj, 0, 5);
+ updateBars();
+ updateAdjustment(mCurrentAdj);
+ return false;
+ }
+ return true;
+ }
+
+ @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));
+ }
+ }
+}