com.ray3k.skincomposer.dialog.DialogColorPicker.java Source code

Java tutorial

Introduction

Here is the source code for com.ray3k.skincomposer.dialog.DialogColorPicker.java

Source

/*******************************************************************************
 * MIT License
 * 
 * Copyright (c) 2017 Raymond Buckley
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 ******************************************************************************/
package com.ray3k.skincomposer.dialog;

import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Event;
import com.badlogic.gdx.scenes.scene2d.EventListener;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.ui.Container;
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Stack;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.DragListener;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.ray3k.skincomposer.CheckerDrawable;
import com.ray3k.skincomposer.GradientDrawable;
import com.ray3k.skincomposer.Main;
import com.ray3k.skincomposer.Spinner;
import com.ray3k.skincomposer.Spinner.Orientation;
import com.ray3k.skincomposer.Spinner.SpinnerStyle;
import com.ray3k.skincomposer.StackedDrawable;

public class DialogColorPicker extends Dialog {
    private Skin skin;
    private ColorListener listener;
    private Table content;
    private SpinnerStyle spinnerStyle;
    private GradientDrawable gradientS, gradientB, gradientAlpha;
    private Array<GradientDrawable> hueGradient;
    private CheckerDrawable checker;
    private StackedDrawable gradientSB;
    private StackedDrawable alphaStack;
    private static final float SIZE = 300.0f;
    private Color previousColor, selectedColor;
    private Spinner redSpinner;
    private Main main;

    public DialogColorPicker(Main main, String style, ColorListener listener, Color previousColor) {
        super("", main.getSkin(), style);

        if (previousColor == null) {
            selectedColor = new Color(Color.RED);
        } else {
            this.previousColor = new Color(previousColor);
            selectedColor = new Color(previousColor);
        }

        this.skin = main.getSkin();
        this.main = main;
        this.listener = listener;

        spinnerStyle = new Spinner.SpinnerStyle(skin.get("spinner-minus-h", Button.ButtonStyle.class),
                skin.get("spinner-plus-h", Button.ButtonStyle.class),
                skin.get("default", TextField.TextFieldStyle.class));

        gradientAlpha = new GradientDrawable(new Color(1.0f, 0, 0, 0), new Color(1.0f, 0, 0, 0), Color.RED,
                Color.RED);
        Vector3 v = rgbToHsb(selectedColor.r, selectedColor.g, selectedColor.b);
        Color temp = hsbToRgb(v.x * 360.0f, 1.0f, 1.0f);
        gradientS = new GradientDrawable(Color.WHITE, temp, temp, Color.WHITE);
        gradientB = new GradientDrawable(Color.BLACK, Color.BLACK, Color.CLEAR, Color.CLEAR);
        gradientSB = new StackedDrawable(gradientS, gradientB);

        hueGradient = new Array<>();
        hueGradient.add(new GradientDrawable(Color.MAGENTA, Color.MAGENTA, Color.RED, Color.RED));
        hueGradient.add(new GradientDrawable(Color.BLUE, Color.BLUE, Color.MAGENTA, Color.MAGENTA));
        hueGradient.add(new GradientDrawable(Color.CYAN, Color.CYAN, Color.BLUE, Color.BLUE));
        hueGradient.add(new GradientDrawable(Color.GREEN, Color.GREEN, Color.CYAN, Color.CYAN));
        hueGradient.add(new GradientDrawable(Color.YELLOW, Color.YELLOW, Color.GREEN, Color.GREEN));
        hueGradient.add(new GradientDrawable(Color.RED, Color.RED, Color.YELLOW, Color.YELLOW));

        Drawable tinted = ((TextureRegionDrawable) skin.getDrawable("white")).tint(Color.LIGHT_GRAY);
        checker = new CheckerDrawable(skin.getDrawable("white"), tinted, 10.0f, 10.0f);
        alphaStack = new StackedDrawable(checker, gradientAlpha);

        Table root = getContentTable();
        Label label = new Label("Choose a Color", skin, "title");
        label.setAlignment(Align.center);
        root.add(label).growX();

        root.row();
        content = new Table(skin);
        root.add(content);

        addListener(new InputListener() {
            @Override
            public boolean keyDown(InputEvent event, int keycode) {
                if (keycode == Keys.ESCAPE) {
                    if (listener != null) {
                        listener.handle(new ColorListener.ColorEvent(null));
                    }
                    hide();
                }
                return false;
            }
        });

        populate();
    }

    @Override
    public Dialog show(Stage stage) {
        Dialog dialog = super.show(stage);

        stage.setKeyboardFocus(redSpinner.getTextField());
        redSpinner.getTextField().selectAll();

        return dialog;
    }

    private static Vector3 tempVector;

    public static Vector3 rgbToHsb(float r, float g, float b) {
        if (tempVector == null) {
            tempVector = new Vector3();
        }
        float[] hsb = new float[3];
        java.awt.Color.RGBtoHSB((int) (255.0f * r), (int) (255.0f * g), (int) (255.0f * b), hsb);
        tempVector.x = hsb[0];
        if (MathUtils.isEqual(tempVector.x, 1.0f)) {
            tempVector.x = 0;
        }
        tempVector.y = hsb[1];
        tempVector.z = hsb[2];
        return tempVector;
    }

    public static Color hsbToRgb(float h, float s, float b) {
        Color color = new Color();

        float c = b * s;
        float hi = h / 60.0f;
        float x = c * (1.0f - Math.abs(hi % 2.0f - 1.0f));

        if (h < 0) {
            color.r = 0;
            color.g = 0;
            color.b = 0;
        } else if (h < 60) {
            color.r = c;
            color.g = x;
            color.b = 0;
        } else if (h < 120) {
            color.r = x;
            color.g = c;
            color.b = 0;
        } else if (h < 180) {
            color.r = 0;
            color.g = c;
            color.b = x;
        } else if (h < 240) {
            color.r = 0;
            color.g = x;
            color.b = c;
        } else if (h < 300) {
            color.r = x;
            color.g = 0;
            color.b = c;
        } else {
            color.r = c;
            color.g = 0;
            color.b = x;
        }

        float m = b - c;
        color.r = color.r + m;
        color.g = color.g + m;
        color.b = color.b + m;
        color.a = 1.0f;

        return color;
    }

    public static float max(float x, float y, float z) {
        float returnValue = Math.max(x, y);
        return Math.max(returnValue, z);
    }

    public static float min(float x, float y, float z) {
        float returnValue = Math.min(x, y);
        return Math.min(returnValue, z);
    }

    public void populate() {
        content.clear();
        content.defaults().padLeft(10.0f);

        Image cursor = new Image(skin.getDrawable("color-picker"));
        cursor.setTouchable(Touchable.enabled);
        Image hueKnob = new Image(skin, "color-scale");
        hueKnob.setTouchable(Touchable.enabled);
        Image hueKnob2 = new Image(skin, "color-scale-flipped");
        hueKnob2.setTouchable(Touchable.enabled);
        Image alphaKnob = new Image(skin, "color-scale");
        alphaKnob.setTouchable(Touchable.enabled);
        Image alphaKnob2 = new Image(skin, "color-scale-flipped");
        alphaKnob2.setTouchable(Touchable.enabled);

        Container selectedColorCont = new Container();
        selectedColorCont.setBackground(skin.getDrawable("white"));
        selectedColorCont.setColor(selectedColor);

        Vector3 v = rgbToHsb(selectedColor.r, selectedColor.g, selectedColor.b);

        Spinner greenSpinner, blueSpinner, alphaSpinner, hueSpinner, saturationSpinner, brightnessSpinner;

        hueSpinner = new Spinner(v.x * 359.0f, 1.0, true, Orientation.HORIZONTAL, spinnerStyle);
        hueSpinner.setMinimum(0.0);
        hueSpinner.setMaximum(359.0);
        hueSpinner.getTextField().addListener(main.getIbeamListener());
        hueSpinner.getButtonMinus().addListener(main.getHandListener());
        hueSpinner.getButtonPlus().addListener(main.getHandListener());

        saturationSpinner = new Spinner(v.y * 100.0f, 1.0, true, Orientation.HORIZONTAL, spinnerStyle);
        saturationSpinner.setMinimum(0.0);
        saturationSpinner.setMaximum(100.0);
        saturationSpinner.getTextField().addListener(main.getIbeamListener());
        saturationSpinner.getButtonMinus().addListener(main.getHandListener());
        saturationSpinner.getButtonPlus().addListener(main.getHandListener());

        brightnessSpinner = new Spinner(v.z * 100.0f, 1.0, true, Orientation.HORIZONTAL, spinnerStyle);
        brightnessSpinner.setMinimum(0.0);
        brightnessSpinner.setMaximum(100.0);
        brightnessSpinner.getTextField().addListener(main.getIbeamListener());
        brightnessSpinner.getButtonMinus().addListener(main.getHandListener());
        brightnessSpinner.getButtonPlus().addListener(main.getHandListener());

        redSpinner = new Spinner(selectedColor.r * 255.0f, 1.0, true, Orientation.HORIZONTAL, spinnerStyle);
        redSpinner.setMinimum(0.0);
        redSpinner.setMaximum(255.0);
        redSpinner.getTextField().addListener(main.getIbeamListener());
        redSpinner.getButtonMinus().addListener(main.getHandListener());
        redSpinner.getButtonPlus().addListener(main.getHandListener());

        greenSpinner = new Spinner(selectedColor.g * 255.0f, 1.0, true, Orientation.HORIZONTAL, spinnerStyle);
        greenSpinner.setMinimum(0.0);
        greenSpinner.setMaximum(255.0);
        greenSpinner.getTextField().addListener(main.getIbeamListener());
        greenSpinner.getButtonMinus().addListener(main.getHandListener());
        greenSpinner.getButtonPlus().addListener(main.getHandListener());

        blueSpinner = new Spinner(selectedColor.b * 255.0f, 1.0, true, Orientation.HORIZONTAL, spinnerStyle);
        blueSpinner.setMinimum(0.0);
        blueSpinner.setMaximum(255.0);
        blueSpinner.getTextField().addListener(main.getIbeamListener());
        blueSpinner.getButtonMinus().addListener(main.getHandListener());
        blueSpinner.getButtonPlus().addListener(main.getHandListener());

        alphaSpinner = new Spinner(selectedColor.a * 255.0f, 1.0, true, Orientation.HORIZONTAL, spinnerStyle);
        alphaSpinner.setMinimum(0.0);
        alphaSpinner.setMaximum(255.0);
        alphaSpinner.getTextField().addListener(main.getIbeamListener());
        alphaSpinner.getButtonMinus().addListener(main.getHandListener());
        alphaSpinner.getButtonPlus().addListener(main.getHandListener());

        redSpinner.setTransversalNext(greenSpinner.getTextField());
        greenSpinner.setTransversalNext(blueSpinner.getTextField());
        blueSpinner.setTransversalNext(alphaSpinner.getTextField());
        alphaSpinner.setTransversalNext(hueSpinner.getTextField());
        hueSpinner.setTransversalNext(saturationSpinner.getTextField());
        saturationSpinner.setTransversalNext(brightnessSpinner.getTextField());
        brightnessSpinner.setTransversalNext(redSpinner.getTextField());

        redSpinner.setTransversalPrevious(brightnessSpinner.getTextField());
        greenSpinner.setTransversalPrevious(redSpinner.getTextField());
        blueSpinner.setTransversalPrevious(greenSpinner.getTextField());
        alphaSpinner.setTransversalPrevious(blueSpinner.getTextField());
        hueSpinner.setTransversalPrevious(alphaSpinner.getTextField());
        saturationSpinner.setTransversalPrevious(hueSpinner.getTextField());
        brightnessSpinner.setTransversalPrevious(saturationSpinner.getTextField());

        ChangeListener rgbListener = new ChangeListener() {
            @Override
            public void changed(ChangeListener.ChangeEvent event, Actor actor) {
                selectedColor.set((float) redSpinner.getValue() / 255.0f, (float) greenSpinner.getValue() / 255.0f,
                        (float) blueSpinner.getValue() / 255.0f, (float) alphaSpinner.getValue() / 255.0f);
                Vector3 v = rgbToHsb(selectedColor.r, selectedColor.g, selectedColor.b);
                hueSpinner.setValue(v.x * 359.0f);
                saturationSpinner.setValue(v.y * 100.0f);
                brightnessSpinner.setValue(v.z * 100.0f);
                selectedColorCont.setColor(selectedColor);

                Color color = hsbToRgb((float) hueSpinner.getValue(), 1.0f, 1.0f);
                gradientS.setCol2(color);
                gradientS.setCol3(color);
                gradientAlpha.setCol3(color);
                gradientAlpha.setCol4(color);
                color = new Color(color);
                color.a = 0.0f;
                gradientAlpha.setCol1(color);
                gradientAlpha.setCol2(color);

                cursor.setX(v.y * SIZE - cursor.getWidth() / 2.0f);
                cursor.setY(v.z * SIZE - cursor.getHeight() / 2.0f);
                hueKnob.setY(v.x * SIZE - hueKnob.getHeight() / 2.0f);
                hueKnob2.setY(hueKnob.getY());
            }
        };
        redSpinner.addListener(rgbListener);
        greenSpinner.addListener(rgbListener);
        blueSpinner.addListener(rgbListener);

        ChangeListener hsbListener = new ChangeListener() {
            @Override
            public void changed(ChangeListener.ChangeEvent event, Actor actor) {
                Color color = hsbToRgb((float) hueSpinner.getValue(), (float) saturationSpinner.getValue() / 100.0f,
                        (float) brightnessSpinner.getValue() / 100.0f);
                color.a = (float) alphaSpinner.getValue() / 255.0f;
                redSpinner.setValue(color.r * 255.0f);
                greenSpinner.setValue(color.g * 255.0f);
                blueSpinner.setValue(color.b * 255.0f);
                selectedColor.set(color);
                selectedColorCont.setColor(selectedColor);

                color = hsbToRgb((float) hueSpinner.getValue(), 1.0f, 1.0f);
                gradientS.setCol2(color);
                gradientS.setCol3(color);
                gradientAlpha.setCol3(color);
                gradientAlpha.setCol4(color);
                color = new Color(color);
                color.a = 0.0f;
                gradientAlpha.setCol1(color);
                gradientAlpha.setCol2(color);

                cursor.setX((float) saturationSpinner.getValue() / 100.0f * SIZE - cursor.getWidth() / 2.0f);
                cursor.setY((float) brightnessSpinner.getValue() / 100.0f * SIZE - cursor.getHeight() / 2.0f);
                hueKnob.setY((float) hueSpinner.getValue() / 359.0f * SIZE - hueKnob.getHeight() / 2.0f);
                hueKnob2.setY(hueKnob.getY());
            }
        };
        hueSpinner.addListener(hsbListener);
        saturationSpinner.addListener(hsbListener);
        brightnessSpinner.addListener(hsbListener);

        alphaSpinner.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeListener.ChangeEvent event, Actor actor) {
                selectedColor.set((float) redSpinner.getValue() / 255.0f, (float) greenSpinner.getValue() / 255.0f,
                        (float) blueSpinner.getValue() / 255.0f, (float) alphaSpinner.getValue() / 255.0f);
                selectedColorCont.setColor(selectedColor);

                alphaKnob.setY(selectedColor.a * SIZE - alphaKnob.getHeight() / 2.0f);
                alphaKnob2.setY(alphaKnob.getY());
            }
        });

        Table panel = new Table(skin);
        panel.setBackground("color-box");
        Table t = new Table(skin);
        t.setClip(true);
        t.setBackground(gradientSB);
        t.setTouchable(Touchable.enabled);
        cursor.setPosition(v.y * SIZE - cursor.getWidth() / 2.0f, v.z * SIZE - cursor.getHeight() / 2.0f);
        t.addActor(cursor);
        DragListener dragListener = new DragListener() {
            @Override
            public void drag(InputEvent event, float x, float y, int pointer) {
                saturationSpinner.setValue(MathUtils.clamp(x / SIZE * 100.0f, 0, 100));
                brightnessSpinner.setValue(MathUtils.clamp(y / SIZE * 100.0f, 0, 100));
                saturationSpinner.fire(new ChangeListener.ChangeEvent());
            }
        };
        dragListener.setTapSquareSize(1.0f);
        t.addListener(dragListener);

        t.addListener(new InputListener() {
            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                saturationSpinner.setValue(MathUtils.clamp(x / SIZE * 100.0f, 0, 100));
                brightnessSpinner.setValue(MathUtils.clamp(y / SIZE * 100.0f, 0, 100));
                saturationSpinner.fire(new ChangeListener.ChangeEvent());

                return false;
            }
        });
        panel.add(t).size(SIZE, SIZE);
        content.add(panel);

        panel = new Table(skin);
        panel.setBackground("color-box");
        t = new Table(skin);
        t.setTouchable(Touchable.enabled);
        t.setClip(true);
        for (GradientDrawable gradient : hueGradient) {
            Container container = new Container();
            container.background(gradient);
            t.add(container).growX().height(50.0f);
            t.row();
        }
        t.addActor(hueKnob);
        t.addActor(hueKnob2);
        hueKnob.setY(v.x * SIZE - hueKnob.getHeight() / 2.0f);
        hueKnob2.setX(30.0f - hueKnob2.getWidth());
        hueKnob2.setY(v.x * SIZE - hueKnob2.getHeight() / 2.0f);
        dragListener = new DragListener() {
            @Override
            public void drag(InputEvent event, float x, float y, int pointer) {
                hueSpinner.setValue(MathUtils.clamp(y / SIZE * 359.0f, 0.0f, 359.0f));

                hueSpinner.fire(new ChangeListener.ChangeEvent());
            }
        };
        dragListener.setTapSquareSize(1.0f);
        t.addListener(dragListener);
        t.addListener(new InputListener() {
            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                hueSpinner.setValue(MathUtils.clamp(y / SIZE * 359.0f, 0.0f, 359.0f));

                hueSpinner.fire(new ChangeListener.ChangeEvent());
                return false;
            }

        });
        panel.add(t).minWidth(30.0f).height(SIZE);
        content.add(panel);

        panel = new Table(skin);
        panel.setBackground("color-box");
        t = new Table();
        t.setTouchable(Touchable.enabled);
        t.setBackground(alphaStack);
        t.setClip(true);
        t.addActor(alphaKnob);
        t.addActor(alphaKnob2);
        alphaKnob.setY(selectedColor.a * SIZE - alphaKnob.getHeight() / 2.0f);
        alphaKnob2.setX(30.0f - alphaKnob2.getWidth());
        alphaKnob2.setY(selectedColor.a * SIZE - alphaKnob2.getHeight() / 2.0f);
        dragListener = new DragListener() {
            @Override
            public void drag(InputEvent event, float x, float y, int pointer) {
                alphaSpinner.setValue(MathUtils.clamp(y / SIZE * 255.0f, 0.0f, 255.0f));

                alphaSpinner.fire(new ChangeListener.ChangeEvent());
            }
        };
        dragListener.setTapSquareSize(1.0f);
        t.addListener(dragListener);
        t.addListener(new InputListener() {
            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                alphaSpinner.setValue(MathUtils.clamp(y / SIZE * 255.0f, 0.0f, 255.0f));

                alphaSpinner.fire(new ChangeListener.ChangeEvent());
                return false;
            }

        });
        panel.add(t).minWidth(30.0f).height(SIZE);
        content.add(panel);

        t = new Table();
        t.defaults().pad(10.0f);

        Table table = new Table(skin);
        Label label = new Label("new", skin);
        label.setAlignment(Align.center);
        table.add(label).growX();
        table.row();
        Container bg = new Container();
        bg.setBackground(checker);
        Stack stack = new Stack(bg, selectedColorCont);
        panel = new Table(skin);
        panel.setBackground("color-box");
        panel.add(stack).grow();
        table.add(panel).grow();
        if (previousColor != null) {
            Container cont = new Container();
            cont.setBackground(skin.getDrawable("white"));
            cont.setColor(previousColor);
            bg = new Container();
            bg.setBackground(checker);
            stack = new Stack(bg, cont);
            panel.row();
            panel.add(stack).grow();
            table.row();
            label = new Label("current", skin);
            label.setAlignment(Align.center);
            table.add(label).growX();
            t.add(table).minWidth(80.0f).minHeight(150.0f);
        } else {
            t.add(table).minWidth(80.0f).minHeight(100.0f);
        }

        table = new Table();
        TextButton textButton = new TextButton("OK", skin);
        textButton.addListener(main.getHandListener());
        textButton.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeListener.ChangeEvent event, Actor actor) {
                if (listener != null) {
                    listener.handle(new ColorListener.ColorEvent(selectedColor));
                }
                hide();
            }
        });
        table.add(textButton).growX();
        table.row();
        textButton = new TextButton("Cancel", skin);
        textButton.addListener(main.getHandListener());
        textButton.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeListener.ChangeEvent event, Actor actor) {
                if (listener != null) {
                    listener.handle(new ColorListener.ColorEvent(null));
                }
                hide();
            }
        });
        table.add(textButton).growX().padTop(10.0f);
        t.add(table);

        t.row();
        table = new Table();
        label = new Label("R", skin, "required");
        table.add(label);
        table.add(redSpinner).padLeft(10.0f).minWidth(90.0f);
        t.add(table);

        table = new Table();
        label = new Label("H", skin, "required");
        table.add(label);
        table.add(hueSpinner).padLeft(10.0f).minWidth(90.0f);
        t.add(table);

        t.row();
        table = new Table();
        label = new Label("G", skin, "required");
        table.add(label);
        table.add(greenSpinner).padLeft(10.0f).minWidth(90.0f);
        t.add(table);

        table = new Table();
        label = new Label("S", skin, "required");
        table.add(label);
        table.add(saturationSpinner).padLeft(10.0f).minWidth(90.0f);
        t.add(table);

        t.row();
        table = new Table();
        label = new Label("B", skin, "required");
        table.add(label);
        table.add(blueSpinner).padLeft(10.0f).minWidth(90.0f);
        t.add(table);

        table = new Table();
        label = new Label("B", skin, "required");
        table.add(label);
        table.add(brightnessSpinner).padLeft(10.0f).minWidth(90.0f);
        t.add(table);

        t.row();
        table = new Table();
        label = new Label("A", skin, "required");
        table.add(label);
        t.add(table);
        table.add(alphaSpinner).padLeft(10.0f).minWidth(90.0f);
        content.add(t).growY();
    }

    public Color getSelectedColor() {
        return selectedColor;
    }

    public static abstract class ColorListener implements EventListener {

        @Override
        public boolean handle(Event event) {
            if (event instanceof ColorEvent) {
                selected(((ColorEvent) event).color);
            }
            return false;
        }

        abstract public void selected(Color color);

        public static class ColorEvent extends Event {
            Color color;

            public ColorEvent(Color color) {
                this.color = color;
            }
        }
    }
}