| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.ui; |
| |
| import android.content.Context; |
| import android.graphics.Color; |
| import android.util.AttributeSet; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.widget.LinearLayout; |
| import android.widget.SeekBar; |
| import android.widget.SeekBar.OnSeekBarChangeListener; |
| |
| /** |
| * Represents a more advanced way for the user to choose a color, based on selecting each of |
| * the Hue, Saturation and Value attributes. |
| */ |
| public class ColorPickerAdvanced extends LinearLayout implements OnSeekBarChangeListener { |
| private static final int HUE_SEEK_BAR_MAX = 360; |
| |
| private static final int HUE_COLOR_COUNT = 7; |
| |
| private static final int SATURATION_SEEK_BAR_MAX = 100; |
| |
| private static final int SATURATION_COLOR_COUNT = 2; |
| |
| private static final int VALUE_SEEK_BAR_MAX = 100; |
| |
| private static final int VALUE_COLOR_COUNT = 2; |
| |
| ColorPickerAdvancedComponent mHueDetails; |
| |
| ColorPickerAdvancedComponent mSaturationDetails; |
| |
| ColorPickerAdvancedComponent mValueDetails; |
| |
| private OnColorChangedListener mOnColorChangedListener; |
| |
| private int mCurrentColor; |
| |
| private final float[] mCurrentHsvValues = new float[3]; |
| |
| public ColorPickerAdvanced(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| init(); |
| } |
| |
| public ColorPickerAdvanced(Context context, AttributeSet attrs, int defStyle) { |
| super(context, attrs, defStyle); |
| init(); |
| } |
| |
| public ColorPickerAdvanced(Context context) { |
| super(context); |
| init(); |
| } |
| |
| /** |
| * Initializes all the views and variables in the advanced view. |
| */ |
| private void init() { |
| setOrientation(LinearLayout.VERTICAL); |
| |
| mHueDetails = createAndAddNewGradient(R.string.color_picker_hue, |
| HUE_SEEK_BAR_MAX, this); |
| mSaturationDetails = createAndAddNewGradient(R.string.color_picker_saturation, |
| SATURATION_SEEK_BAR_MAX, this); |
| mValueDetails = createAndAddNewGradient(R.string.color_picker_value, |
| VALUE_SEEK_BAR_MAX, this); |
| refreshGradientComponents(); |
| } |
| |
| /** |
| * Creates a new GradientDetails object from the parameters provided, initializes it, |
| * and adds it to this advanced view. |
| * |
| * @param textResourceId The text to display for the label. |
| * @param seekBarMax The maximum value of the seek bar for the gradient. |
| * @param seekBarListener Object listening to when the user changes the seek bar. |
| * |
| * @return A new GradientDetails object initialized with the given parameters. |
| */ |
| public ColorPickerAdvancedComponent createAndAddNewGradient(int textResourceId, |
| int seekBarMax, |
| OnSeekBarChangeListener seekBarListener) { |
| LayoutInflater inflater = (LayoutInflater) getContext() |
| .getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
| View newComponent = inflater.inflate(R.layout.color_picker_advanced_component, null); |
| addView(newComponent); |
| |
| return new ColorPickerAdvancedComponent(newComponent, |
| textResourceId, |
| seekBarMax, |
| seekBarListener); |
| } |
| |
| /** |
| * Sets the listener for when the user changes the color. |
| * |
| * @param onColorChangedListener The object listening for the change in color. |
| */ |
| public void setListener(OnColorChangedListener onColorChangedListener) { |
| mOnColorChangedListener = onColorChangedListener; |
| } |
| |
| /** |
| * @return The color the user has currently chosen. |
| */ |
| public int getColor() { |
| return mCurrentColor; |
| } |
| |
| /** |
| * Sets the color that the user has currently chosen. |
| * |
| * @param color The currently chosen color. |
| */ |
| public void setColor(int color) { |
| mCurrentColor = color; |
| Color.colorToHSV(mCurrentColor, mCurrentHsvValues); |
| refreshGradientComponents(); |
| } |
| |
| /** |
| * Notifies the listener, if there is one, of a change in the selected color. |
| */ |
| private void notifyColorChanged() { |
| if (mOnColorChangedListener != null) { |
| mOnColorChangedListener.onColorChanged(getColor()); |
| } |
| } |
| |
| /** |
| * Callback for when a slider is updated on the advanced view. |
| * |
| * @param seekBar The color slider that was updated. |
| * @param progress The new value of the color slider. |
| * @param fromUser Whether it was the user the changed the value, or whether |
| * we were setting it up. |
| */ |
| @Override |
| public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { |
| if (fromUser) { |
| mCurrentHsvValues[0] = mHueDetails.getValue(); |
| mCurrentHsvValues[1] = mSaturationDetails.getValue() / 100.0f; |
| mCurrentHsvValues[2] = mValueDetails.getValue() / 100.0f; |
| |
| mCurrentColor = Color.HSVToColor(mCurrentHsvValues); |
| |
| updateHueGradient(); |
| updateSaturationGradient(); |
| updateValueGradient(); |
| |
| notifyColorChanged(); |
| } |
| } |
| |
| /** |
| * Updates only the hue gradient display with the hue value for the |
| * currently selected color. |
| */ |
| private void updateHueGradient() { |
| float[] tempHsvValues = new float[3]; |
| tempHsvValues[1] = mCurrentHsvValues[1]; |
| tempHsvValues[2] = mCurrentHsvValues[2]; |
| |
| int[] newColors = new int[HUE_COLOR_COUNT]; |
| |
| for (int i = 0; i < HUE_COLOR_COUNT; ++i) { |
| tempHsvValues[0] = i * 60.0f; |
| newColors[i] = Color.HSVToColor(tempHsvValues); |
| } |
| mHueDetails.setGradientColors(newColors); |
| } |
| |
| /** |
| * Updates only the saturation gradient display with the saturation value |
| * for the currently selected color. |
| */ |
| private void updateSaturationGradient() { |
| float[] tempHsvValues = new float[3]; |
| tempHsvValues[0] = mCurrentHsvValues[0]; |
| tempHsvValues[1] = 0.0f; |
| tempHsvValues[2] = mCurrentHsvValues[2]; |
| |
| int[] newColors = new int[SATURATION_COLOR_COUNT]; |
| |
| newColors[0] = Color.HSVToColor(tempHsvValues); |
| |
| tempHsvValues[1] = 1.0f; |
| newColors[1] = Color.HSVToColor(tempHsvValues); |
| mSaturationDetails.setGradientColors(newColors); |
| } |
| |
| /** |
| * Updates only the Value gradient display with the Value amount for |
| * the currently selected color. |
| */ |
| private void updateValueGradient() { |
| float[] tempHsvValues = new float[3]; |
| tempHsvValues[0] = mCurrentHsvValues[0]; |
| tempHsvValues[1] = mCurrentHsvValues[1]; |
| tempHsvValues[2] = 0.0f; |
| |
| int[] newColors = new int[VALUE_COLOR_COUNT]; |
| |
| newColors[0] = Color.HSVToColor(tempHsvValues); |
| |
| tempHsvValues[2] = 1.0f; |
| newColors[1] = Color.HSVToColor(tempHsvValues); |
| mValueDetails.setGradientColors(newColors); |
| } |
| |
| /** |
| * Updates all the gradient displays to show the currently selected color. |
| */ |
| private void refreshGradientComponents() { |
| // Round and bound the saturation value. |
| int saturationValue = Math.round(mCurrentHsvValues[1] * 100.0f); |
| saturationValue = Math.min(saturationValue, SATURATION_SEEK_BAR_MAX); |
| saturationValue = Math.max(saturationValue, 0); |
| |
| // Round and bound the Value amount. |
| int valueValue = Math.round(mCurrentHsvValues[2] * 100.0f); |
| valueValue = Math.min(valueValue, VALUE_SEEK_BAR_MAX); |
| valueValue = Math.max(valueValue, 0); |
| |
| // Don't need to round the hue value since its possible values match the seek bar |
| // range directly. |
| mHueDetails.setValue(mCurrentHsvValues[0]); |
| mSaturationDetails.setValue(saturationValue); |
| mValueDetails.setValue(valueValue); |
| |
| updateHueGradient(); |
| updateSaturationGradient(); |
| updateValueGradient(); |
| } |
| |
| @Override |
| public void onStartTrackingTouch(SeekBar seekBar) { |
| // Do nothing. |
| } |
| |
| @Override |
| public void onStopTrackingTouch(SeekBar seekBar) { |
| // Do nothing. |
| } |
| } |