1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.ui;
7 import android.content.Context;
8 import android.graphics.Color;
9 import android.util.AttributeSet;
10 import android.view.LayoutInflater;
11 import android.view.View;
12 import android.view.accessibility.AccessibilityEvent;
13 import android.widget.LinearLayout;
14 import android.widget.SeekBar;
15 import android.widget.SeekBar.OnSeekBarChangeListener;
18 * Represents a more advanced way for the user to choose a color, based on selecting each of
19 * the Hue, Saturation and Value attributes.
21 public class ColorPickerAdvanced extends LinearLayout implements OnSeekBarChangeListener {
22 private static final int HUE_SEEK_BAR_MAX = 360;
24 private static final int HUE_COLOR_COUNT = 7;
26 private static final int SATURATION_SEEK_BAR_MAX = 100;
28 private static final int SATURATION_COLOR_COUNT = 2;
30 private static final int VALUE_SEEK_BAR_MAX = 100;
32 private static final int VALUE_COLOR_COUNT = 2;
34 ColorPickerAdvancedComponent mHueDetails;
36 ColorPickerAdvancedComponent mSaturationDetails;
38 ColorPickerAdvancedComponent mValueDetails;
40 private OnColorChangedListener mOnColorChangedListener;
42 private int mCurrentColor;
44 private final float[] mCurrentHsvValues = new float[3];
46 public ColorPickerAdvanced(Context context, AttributeSet attrs) {
47 super(context, attrs);
51 public ColorPickerAdvanced(Context context, AttributeSet attrs, int defStyle) {
52 super(context, attrs, defStyle);
56 public ColorPickerAdvanced(Context context) {
62 * Initializes all the views and variables in the advanced view.
65 setOrientation(LinearLayout.VERTICAL);
67 mHueDetails = createAndAddNewGradient(R.string.color_picker_hue,
68 HUE_SEEK_BAR_MAX, this);
69 mSaturationDetails = createAndAddNewGradient(R.string.color_picker_saturation,
70 SATURATION_SEEK_BAR_MAX, this);
71 mValueDetails = createAndAddNewGradient(R.string.color_picker_value,
72 VALUE_SEEK_BAR_MAX, this);
74 refreshGradientComponents();
78 * Creates a new GradientDetails object from the parameters provided, initializes it,
79 * and adds it to this advanced view.
81 * @param textResourceId The text to display for the label.
82 * @param seekBarMax The maximum value of the seek bar for the gradient.
83 * @param seekBarListener Object listening to when the user changes the seek bar.
85 * @return A new GradientDetails object initialized with the given parameters.
87 public ColorPickerAdvancedComponent createAndAddNewGradient(int textResourceId,
89 OnSeekBarChangeListener seekBarListener) {
90 LayoutInflater inflater = (LayoutInflater) getContext()
91 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
92 View newComponent = inflater.inflate(R.layout.color_picker_advanced_component, null);
93 addView(newComponent);
95 return new ColorPickerAdvancedComponent(newComponent,
102 * Sets the listener for when the user changes the color.
104 * @param onColorChangedListener The object listening for the change in color.
106 public void setListener(OnColorChangedListener onColorChangedListener) {
107 mOnColorChangedListener = onColorChangedListener;
111 * @return The color the user has currently chosen.
113 public int getColor() {
114 return mCurrentColor;
118 * Sets the color that the user has currently chosen.
120 * @param color The currently chosen color.
122 public void setColor(int color) {
123 mCurrentColor = color;
124 Color.colorToHSV(mCurrentColor, mCurrentHsvValues);
125 refreshGradientComponents();
129 * Notifies the listener, if there is one, of a change in the selected color.
131 private void notifyColorChanged() {
132 if (mOnColorChangedListener != null) {
133 mOnColorChangedListener.onColorChanged(getColor());
138 * Callback for when a slider is updated on the advanced view.
140 * @param seekBar The color slider that was updated.
141 * @param progress The new value of the color slider.
142 * @param fromUser Whether it was the user the changed the value, or whether
143 * we were setting it up.
146 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
148 mCurrentHsvValues[0] = mHueDetails.getValue();
149 mCurrentHsvValues[1] = mSaturationDetails.getValue() / 100.0f;
150 mCurrentHsvValues[2] = mValueDetails.getValue() / 100.0f;
152 mCurrentColor = Color.HSVToColor(mCurrentHsvValues);
155 updateSaturationGradient();
156 updateValueGradient();
158 notifyColorChanged();
163 * Updates only the hue gradient display with the hue value for the
164 * currently selected color.
166 private void updateHueGradient() {
167 float[] tempHsvValues = new float[3];
168 tempHsvValues[1] = mCurrentHsvValues[1];
169 tempHsvValues[2] = mCurrentHsvValues[2];
171 int[] newColors = new int[HUE_COLOR_COUNT];
173 for (int i = 0; i < HUE_COLOR_COUNT; ++i) {
174 tempHsvValues[0] = i * 60.0f;
175 newColors[i] = Color.HSVToColor(tempHsvValues);
177 mHueDetails.setGradientColors(newColors);
181 * Updates only the saturation gradient display with the saturation value
182 * for the currently selected color.
184 private void updateSaturationGradient() {
185 float[] tempHsvValues = new float[3];
186 tempHsvValues[0] = mCurrentHsvValues[0];
187 tempHsvValues[1] = 0.0f;
188 tempHsvValues[2] = mCurrentHsvValues[2];
190 int[] newColors = new int[SATURATION_COLOR_COUNT];
192 newColors[0] = Color.HSVToColor(tempHsvValues);
194 tempHsvValues[1] = 1.0f;
195 newColors[1] = Color.HSVToColor(tempHsvValues);
196 mSaturationDetails.setGradientColors(newColors);
200 * Updates only the Value gradient display with the Value amount for
201 * the currently selected color.
203 private void updateValueGradient() {
204 float[] tempHsvValues = new float[3];
205 tempHsvValues[0] = mCurrentHsvValues[0];
206 tempHsvValues[1] = mCurrentHsvValues[1];
207 tempHsvValues[2] = 0.0f;
209 int[] newColors = new int[VALUE_COLOR_COUNT];
211 newColors[0] = Color.HSVToColor(tempHsvValues);
213 tempHsvValues[2] = 1.0f;
214 newColors[1] = Color.HSVToColor(tempHsvValues);
215 mValueDetails.setGradientColors(newColors);
219 * Updates all the gradient displays to show the currently selected color.
221 private void refreshGradientComponents() {
222 // Round and bound the saturation value.
223 int saturationValue = Math.round(mCurrentHsvValues[1] * 100.0f);
224 saturationValue = Math.min(saturationValue, SATURATION_SEEK_BAR_MAX);
225 saturationValue = Math.max(saturationValue, 0);
227 // Round and bound the Value amount.
228 int valueValue = Math.round(mCurrentHsvValues[2] * 100.0f);
229 valueValue = Math.min(valueValue, VALUE_SEEK_BAR_MAX);
230 valueValue = Math.max(valueValue, 0);
232 // Don't need to round the hue value since its possible values match the seek bar
234 mHueDetails.setValue(mCurrentHsvValues[0]);
235 mSaturationDetails.setValue(saturationValue);
236 mValueDetails.setValue(valueValue);
239 updateSaturationGradient();
240 updateValueGradient();
244 public void onStartTrackingTouch(SeekBar seekBar) {
249 public void onStopTrackingTouch(SeekBar seekBar) {