root/ui/android/java/src/org/chromium/ui/ColorPickerAdvanced.java

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. init
  2. createAndAddNewGradient
  3. setListener
  4. getColor
  5. setColor
  6. notifyColorChanged
  7. onProgressChanged
  8. updateHueGradient
  9. updateSaturationGradient
  10. updateValueGradient
  11. refreshGradientComponents
  12. onStartTrackingTouch
  13. onStopTrackingTouch

// 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.
    }
}

/* [<][>][^][v][top][bottom][index][help] */