/*
* org.openmicroscopy.shoola.util.ui.colourpicker.ColourMenuUI
*
*------------------------------------------------------------------------------
* Copyright (C) 2006 University of Dundee. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package org.openmicroscopy.shoola.util.ui.colourpicker;
//Java imports
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
//Third-party libraries
//Application-internal dependencies
/**
* This is a UI which represents the colors as a list in the menu, currently it
* shows the color as an icon and the name of the color,
* all of which are added from the constructor. (this may change)
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @author Donald MacDonald
* <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a>
* @version 3.0
* <small>
* (<b>Internal version:</b> $Revision: $ $Date: $)
* </small>
* @since OME2.2
*/
public class ColourSwatchUI
extends JPanel
{
/** Reference to the Color model. */
private RGBControl control;
/** List of colors. */
private JList colourlist;
/** Scroll pane which contains the JList component. */
private JScrollPane scrollpane;
/** The slider representing the alpha channel. */
private ColourSlider alphaSlider;
/** Change listener for alpha slider. */
private ChangeListener alphaChangeListener;
/** Listener for the color list. */
private ListSelectionListener selectionListener;
/** The text field representing the alpha red channel. */
private JTextField alphaTextbox;
/** The JLabel representing the color alpha channel. */
private JLabel alphaLabel;
/** Action listener for alpha TextBox. */
private ActionListener alphaTextboxActionListener;
/**
* Boolean variable, true if the current component is active, this is
* controlled from the parent component. It tells the UI whether or not
* to ignore refresh events.
*/
private boolean active;
/**
* Creates the Alpha slider, and changes listener, attaching the change
* listener to the slider.
*/
private void createAlphaSlider()
{
Color s1, s;
Color e1, e;
s1 = control.getColour();
s = new Color(s1.getRed(), s1.getGreen(), s1.getBlue(), 0);
e1 = control.getColour();
e = new Color(e1.getRed(), s1.getGreen(), s1.getBlue(), 255);
alphaSlider = new ColourSlider(0, 255, s, e);
alphaSlider.setValue((int) (control.getAlpha()*255.0));
alphaChangeListener = new ChangeListener() {
public void stateChanged(ChangeEvent changeEvent)
{
ColourSlider src = (ColourSlider) changeEvent.getSource();
control.setAlpha(src.getValue()/255.0f);
}
};
alphaSlider.addChangeListener(alphaChangeListener);
}
/**
* Creates the Alpha text box, and action listener, attaching the action
* listener to the text box.
*/
private void createAlphaTextbox()
{
alphaLabel = new JLabel("Alpha");
alphaTextbox = new JTextField(""+(int) (control.getAlpha()*255));
alphaTextbox.setColumns(TabbedPaneUI.TEXTBOX_COLUMN);
alphaTextboxActionListener = new ActionListener(){
public void actionPerformed(ActionEvent actionEvent) {
JTextField src = (JTextField) actionEvent.getSource();
try {
int value = Integer.parseInt(src.getText());
if (value >=0 && value <=255)
control.setAlpha(value/255.0f);
else {
ColourPicker.invalidColorValue();
alphaTextbox.setText(""+(int) (control.getAlpha()*255));
}
} catch(NumberFormatException e) {
ColourPicker.invalidColorValue();
alphaTextbox.setText(""+(int) (control.getAlpha()*255));
}
}
};
alphaTextbox.addActionListener(alphaTextboxActionListener);
}
/**
* Returns the index of the selected color or <code>-1</code>.
*
* @return See above.
*/
private int getColorIndex(Color color)
{
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
//check if we can set the index of the color.
//red
if (r == 255 && g == 0 && b == 0) return 0;
if (r == 0 && g == 255 && b == 0) return 1;
if (r == 0 && g == 0 && b == 255) return 2;
if (r == 255 && g == 255 && b == 255) return 3;
if (r == 0 && g == 0 && b == 0) return 4;
if (r == 128 && g == 128 && b == 128) return 5;
if (r == 255 && g == 230 && b == 0) return 6;
if (r == 255 && g == 255 && b == 0) return 7;
if (r == 75 && g == 0 && b == 130) return 8;
if (r == 238 && g == 130 && b == 238) return 9;
return -1;
}
/**
* Create the colors and add the renderer {@link ColourListRenderer} to
* the JList object.
*/
private void createColours()
{
colourlist = new JList(
new Object[] {
new Object[] {Color.red, "Red"},
new Object[] {Color.green, "Green"},
new Object[] {Color.blue, "Blue"},
new Object[] {Color.white, "White"},
new Object[] {Color.black, "Black"},
new Object[] {Color.gray, "Gray"},
new Object[] {Color.orange, "Orange"},
new Object[] {Color.yellow, "Yellow"},
new Object[] {new Color(75, 0, 130), "Indigo"},
new Object[] {new Color(238, 130, 238), "Violet"},
new Object[] {Color.cyan, "Cyan"},
new Object[] {Color.magenta, "Magenta"},
});
colourlist.setCellRenderer(new ColourListRenderer());
}
/**
* Create the UI which includes adding the color list (JList) to the
* scroll pane.
*/
private void createUI()
{
createColours();
createAlphaSlider();
createAlphaTextbox();
colourlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
colourlist.setLayoutOrientation(JList.VERTICAL);
colourlist.setVisibleRowCount(-1);
int index = getColorIndex(control.getColour());
colourlist.setSelectedIndex(index);
selectionListener = new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e)
{
Object[] obj = (Object[])
colourlist.getModel().getElementAt(((JList) e.getSource()).
getLeadSelectionIndex());
control.setColour((Color) obj[0]);
}
};
colourlist.addListSelectionListener(selectionListener);
scrollpane = new JScrollPane(colourlist);
this.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 80;
gbc.weighty = 580;
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(10, 10, 10, 10);
this.add(scrollpane, gbc);
gbc.gridy = 1;
gbc.weightx = 80;
gbc.weighty = 5;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(0, 5, 0, 5);
this.add(alphaLabel, gbc);
gbc.gridy = 2;
this.add(alphaSlider, gbc);
gbc.gridx = 1;
gbc.gridy = 2;
gbc.weightx = 20;
this.add(alphaTextbox, gbc);
}
/**
* Create the UI and attach the control c.
*
* @param c Reference to the control. Mustn't be <code>null</code>.
*/
ColourSwatchUI(RGBControl c)
{
if (c == null) throw new IllegalArgumentException("No control.");
control = c;
createUI();
active = false;
}
/** Resets the selection of the color. */
void revert()
{
int index = getColorIndex(control.getColour());
colourlist.removeListSelectionListener(selectionListener);
colourlist.clearSelection();
colourlist.setSelectedIndex(index);
colourlist.addListSelectionListener(selectionListener);
}
/**
* Sets the current component Active, called from parent control letting
* this component know it should listen to refresh events.
*
* @param act Pass <code>true</code> to set the component to active,
* <code>false</code> otherwise..
*/
void setActive(boolean act) { active = act; }
/**
* Refresh method will be called by tabbedpanelUI when the model has
* changed.
*/
void refresh()
{
if (!(active)) return;
removeListeners();
updateSliders();
updateTextboxes();
revert();
addListeners();
repaint();
}
/**
* Adds change listeners to the components. Used in conjunction with
* {@link #removeListeners()} to get round spurious event
* triggers when updating components.
*/
void addListeners()
{
alphaSlider.addChangeListener(alphaChangeListener);
alphaTextbox.addActionListener(alphaTextboxActionListener);
}
/**
* Removes change listeners to the components. Used in conjunction with
* {@link #addListeners()} to get round spurious event
* triggers when updating components.
*/
void removeListeners()
{
alphaSlider.removeChangeListener(alphaChangeListener);
alphaTextbox.removeActionListener(alphaTextboxActionListener);
}
/**
* Updates the alpha slider of the UI, including changing the color
* gradient of the slider tracks.
*/
void updateAlphaSlider()
{
Color s, s1, e;
alphaSlider.setValue((int) (control.getAlpha()*255));
s1 = control.getColour();
s = new Color(s1.getRed(), s1.getGreen(), s1.getBlue(), 0);
e = new Color(s1.getRed(), s1.getGreen(), s1.getBlue(), 255);
alphaSlider.setRGBStart(s);
alphaSlider.setRGBEnd(e);
}
/**
* Updates the sliders of the UI, including changing the color gradient
* of the different slider tracks.
*/
void updateSliders() { updateAlphaSlider(); }
/** Updates the text boxes of the UI. */
void updateTextboxes()
{
alphaTextbox.setText(""+(int) (control.getAlpha()*255));
}
}