/*
* * Rework from original ImageChooserPanel from Sun
* (Copyright 2006 Sun Microsystems, Inc.)
* @(#)DefaultRGBChooserPanel.java 1.31 03/01/23
*
*/
package com.mandelsoft.swing.colorchooser;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.colorchooser.AbstractColorChooserPanel;
import com.mandelsoft.swing.BufferedComponent;
import com.mandelsoft.swing.FilePanel;
import com.mandelsoft.swing.GBC;
import com.mandelsoft.swing.GBCPanel;
import com.mandelsoft.util.Utils;
/**
* The standard RGB chooser.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans<sup><font size="-2">TM</font></sup>
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*
* @version based on 1.31 01/23/03
* @author Steve Wilson
* @author Mark Davidson
* @see JColorChooser
* @see AbstractColorChooserPanel
*/
public class ImageChooserPanel extends AbstractColorChooserPanel {
private final int SCALE=4;
private final int SIZE=150;
private FilePanel file;
private JScrollPane sp;
private BufferedComponent buffer;
private ImageListener listener;
private PropertyChangeListener modellistener;
private ColorImageModel model;
public ImageChooserPanel()
{
super();
setInheritsPopupMenu(true);
modellistener=new ModelListener();
listener=new ImageListener();
setColorImageModel(new ColorImageModel());
}
public ColorImageModel getColorImageModel()
{
return model;
}
public void setColorImageModel(ColorImageModel model)
{
if (this.model!=null) {
this.model.removePropertyChangeListener(modellistener);
}
this.model=model;
this.model.addPropertyChangeListener(modellistener);
if (buffer!=null) buffer.setImage(model.getImage());
if (file!=null) file.setFilename(model.getFilename());
}
private Dimension limit(BufferedImage i, int w, int h)
{
if (w>i.getWidth()) {
w=i.getWidth();
//sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
}
else {
//sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
if (h>i.getHeight()) {
h=i.getHeight();
//sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
}
else {
//sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
}
return new Dimension(w, h);
}
public String getDisplayName()
{
return "ImageColors";
}
/**
* Provides a hint to the look and feel as to the
* <code>KeyEvent.VK</code> constant that can be used as a mnemonic to
* access the panel. A return value <= 0 indicates there is no mnemonic.
* <p>
* The return value here is a hint, it is ultimately up to the look
* and feel to honor the return value in some meaningful way.
* <p>
* This implementation looks up the value from the default
* <code>ColorChooser.rgbMnemonic</code>, or if it
* isn't available (or not an <code>Integer</code>) returns -1.
* The lookup for the default is done through the <code>UIManager</code>:
* <code>UIManager.get("ColorChooser.rgbMnemonic");</code>.
*
* @return KeyEvent.VK constant identifying the mnemonic; <= 0 for no
* mnemonic
* @see #getDisplayedMnemonicIndex
* @since 1.4
*/
public int getMnemonic()
{
return -1;
}
/**
* Provides a hint to the look and feel as to the index of the character in
* <code>getDisplayName</code> that should be visually identified as the
* mnemonic. The look and feel should only use this if
* <code>getMnemonic</code> returns a value > 0.
* <p>
* The return value here is a hint, it is ultimately up to the look
* and feel to honor the return value in some meaningful way. For example,
* a look and feel may wish to render each
* <code>AbstractColorChooserPanel</code> in a <code>JTabbedPane</code>,
* and further use this return value to underline a character in
* the <code>getDisplayName</code>.
* <p>
* This implementation looks up the value from the default
* <code>ColorChooser.rgbDisplayedMnemonicIndex</code>, or if it
* isn't available (or not an <code>Integer</code>) returns -1.
* The lookup for the default is done through the <code>UIManager</code>:
* <code>UIManager.get("ColorChooser.rgbDisplayedMnemonicIndex");</code>.
*
* @return Character index to render mnemonic for; -1 to provide no
* visual identifier for this panel.
* @see #getMnemonic
* @since 1.4
*/
public int getDisplayedMnemonicIndex()
{
return -1;
}
public Icon getSmallDisplayIcon()
{
return null;
}
public Icon getLargeDisplayIcon()
{
return null;
}
/**
* The background color, foreground color, and font are already set to the
* defaults from the defaults table before this method is called.
*/
public void installChooserPanel(JColorChooser enclosingChooser)
{
super.installChooserPanel(enclosingChooser);
}
protected void buildChooser()
{
Color color=getColorFromModel();
//setBorder(new EmptyBorder(10, 10, 10, 10));
final GBCPanel panel=new GBCPanel();
buffer=new BufferedComponent(model.getImage());
buffer.setScale(SCALE);
buffer.setScaleMode(true);
buffer.getContentPane().addMouseListener(listener);
buffer.getContentPane().addMouseMotionListener(listener);
sp=new JScrollPane(buffer);
sp.setVisible(true);
sp.setPreferredSize(new Dimension(SIZE,SIZE));
panel.add(sp, new GBC(0, 0));
String n=model.getFilename();
if (Utils.isEmpty(n)) n="C:/work/Mandelbrot.Test/src/my/mand/resources/splash.png";
file=new FilePanel("Image filename",
//"",getFrame());
n, null);
//file.setMinimumSize(new Dimension(100,10));
file.addPropertyChangeListener(FilePanel.PROP_FILENAME,modellistener);
panel.add(file, new GBC(0, 1));
JButton b=new JButton("Load");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
String n=file.getFilename();
if (Utils.isEmpty(n)) return;
File f=new File(n);
try {
BufferedImage image=ImageIO.read(f);
//System.out.println(image.getWidth());
model.setImage(image);
//ImageDialog imgd=new ImageDialog(getFrame(),image);
//imgd.setVisible(true);
}
catch (IOException ex) {
}
}
});
panel.add(b, new GBC(0, 2).setFill(GBC.NONE));
add(panel);
}
public void uninstallChooserPanel(JColorChooser enclosingChooser)
{
super.uninstallChooserPanel(enclosingChooser);
buffer.removeMouseMotionListener(listener);
buffer.removeMouseListener(listener);
buffer=null;
removeAll();
}
public void updateChooser()
{
}
private boolean adjusting=false;
private class ModelListener implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent evt)
{
if (evt.getSource()==model) {
//System.out.println("EV: "+evt.getPropertyName());
if (evt.getPropertyName().equals(ColorImageModel.PROP_IMAGE)) {
BufferedImage image=model.getImage();
sp.setVisible(true);
sp.setPreferredSize(limit(image, SIZE, SIZE));
buffer.setImage(image);
sp.revalidate();
}
else if (evt.getPropertyName().equals(ColorImageModel.PROP_FILENAME)) {
if (!adjusting) {
adjusting=true;
file.setFilename(model.getFilename());
adjusting=false;
}
}
}
else {
//System.out.println("fEV: "+evt.getPropertyName());
if (!adjusting) {
adjusting=true;
model.setFilename((String)evt.getNewValue());
adjusting=false;
}
}
}
}
private class ImageListener extends MouseAdapter {
private boolean active;
@Override
public void mouseDragged(MouseEvent e)
{
if (active) handle(e);
}
@Override
public void mouseReleased(MouseEvent e)
{
if (e.getButton()==MouseEvent.BUTTON1)
active=false;
}
@Override
public void mousePressed(MouseEvent e)
{
if (e.getButton()==MouseEvent.BUTTON1) {
active=true;
handle(e);
}
}
@Override
public void mouseClicked(MouseEvent e)
{
if (e.getButton()==MouseEvent.BUTTON1) handle(e);
}
private Color getColor(MouseEvent e)
{
int x=(int)Math.round(e.getX()/buffer.getScale());
int y=(int)Math.round(e.getY()/buffer.getScale());
BufferedImage im=buffer.getImage();
//System.out.println("color at "+x+","+y+": "+im.getRGB(x, y));
return new Color(im.getRGB(x, y));
}
private void handle(MouseEvent e)
{
int x=(int)Math.round((e.getX()-buffer.getScale()/2)/buffer.getScale());
int y=(int)Math.round((e.getY()-buffer.getScale()/2)/buffer.getScale());
BufferedImage im=buffer.getImage();
if (im==null || im.getWidth()<=x || im.getHeight()<=y) return;
//System.out.println("color at "+x+","+y+": "+im.getRGB(x, y));
getColorSelectionModel().setSelectedColor(new Color(im.getRGB(x, y)));
}
}
}