blob: 29b4e1fd466606870cddd6e7cf47b055091762c1 [file] [log] [blame]
// 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.
}
}