/* Copyright (C) 2006-2007 Julien Pauty
*
* This file is part of Nomad.
*
* Nomad 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.
*
* Nomad 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 Nomad; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.sf.nmedit.patchmodifier.mutator;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.TransferHandler;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Variation extends JComponent implements ChangeListener{
/**
*
*/
private static final long serialVersionUID = -3543257101198489340L;
private VariationState state = null;
private static final Border VarBorder = BorderFactory.createLineBorder(Color.GRAY);
// render to buffer - improves rendering performance of component
private BufferedImage renderedImage = null;
private boolean modifiedFlag = true;
public Variation(){
setBackground(Color.BLACK);
setBorder(VarBorder);
setTransferHandler(new VariationTransferHandler());
VariationListener listener = new VariationListener();
addMouseListener(listener);
addMouseMotionListener(listener);
setPreferredSize(new Dimension(50,50));
setMaximumSize(new Dimension(50,50));
setMinimumSize(new Dimension(50,50));
}
public void addVariationSelectionListener(VariationSelectionListener l) {
listenerList.add(VariationSelectionListener.class, l);
}
public void removeVariationSelectionListener(VariationSelectionListener l) {
listenerList.remove(VariationSelectionListener.class, l);
}
protected transient ChangeEvent changeEvent; // this is source
protected void fireSelectionChanged() {
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==VariationSelectionListener.class) {
// Lazily create the event:
// if (changeEvent == null)
// changeEvent = new ChangeEvent(this);
((VariationSelectionListener)listeners[i+1]).variationSelectionChanged(this);
}
}
}
private void setModifiedFlag()
{
modifiedFlag = true;
repaint();
}
public Color colorValue(int hue){
//return Color.getHSBColor(hue/128f, hue/128f, hue/128f);
//return Color.getHSBColor(hue/128f, hue/128f,.8f);
//return Color.getHSBColor(hue/128f, 0f, hue/128f);
return Color.getHSBColor(.2f*hue/128f,1f-hue/128f,.8f); // ok variation rouge
//return Color.getHSBColor(.3f*hue/128f,.5f+.5f*hue/128f,.8f);
}
private Polygon poly = null;
// private Polygon getPolygon()
// {
// //if (poly==null){
// if (values == null) return null;
//
// poly = new Polygon();
//
// Dimension dd = getSizeWithoutInsets();
//
// int w = dd.width/8;
// int h = dd.height/8;
//
//
// poly.addPoint(w/2,h/2);
//
// int prevX = w/2;
// int prevY = h/2;
// double prevAngle = 0;
// for (int i = 0; i < values.size() ; i += 2)
// {
// double angle = 2*Math.PI* values.get(i)/512f+prevAngle;
// double amplitude = values.get(i+1)/2;// shouldn't it be /2d ?
// int x = (int)(prevX+amplitude*Math.cos(angle));
// int y = (int)(prevY+amplitude*Math.sin(angle));
// poly.addPoint(x,y);
// prevX = x;
// prevY = y;
// prevAngle = angle;
// }
//
// Rectangle bound = poly.getBounds();
//
// // translate the poly to 0,0
// if (bound.x < 0) poly.translate(-bound.x, 0);
// if (bound.y < 0) poly.translate(0,-bound.y);
//
// // scale it
// double scaleX = bound.width/((double)getWidth()-10d);
// double scaleY = bound.height/((double)getHeight()-10d);
//
// //System.out.println(scaleX+" "+scaleY);
// for (int i=0; i < poly.xpoints.length; i++)
// {
// poly.xpoints[i] /= scaleX;
// poly.xpoints[i] += 5;
// }
// for (int i=0; i < poly.ypoints.length; i++)
// {
// poly.ypoints[i] /= scaleY;
// poly.ypoints[i] += 5;
// }
// //System.out.println(p.getBounds());
// //}
// return poly;
//
// }
private Dimension getSizeWithoutInsets()
{
Insets insets = getInsets();
int ww = getWidth()-insets.left-insets.right;
int hh = getHeight()-insets.top-insets.bottom;
return new Dimension(ww,hh);
}
double angles[] = new double[64];
private Polygon getPolygon2()
{
// 4 param means no modules added by the user
if (state.getValues() == null || state.getValues().size() == 0)
return null;
poly = new Polygon();
Dimension dd = getSizeWithoutInsets();
int w = dd.width/8;
int h = dd.height/8;
poly.addPoint(w/2,h/2);
int prevX = w/2;
int prevY = h/2;
double prevAngle = 0;
for (int i = 0; i < state.getValues().size()-1 ; i += 2)
{
double angle = 2*Math.PI* state.getValues().get(i)/512d+prevAngle;
angles[i] = 2*Math.PI* state.getValues().get(i)/512d;
double amplitude = state.getValues().get(i+1)/2d;// shouldn't it be /2d ?
int x = (int)(prevX+amplitude*Math.cos(angle));
int y = (int)(prevY+amplitude*Math.sin(angle));
poly.addPoint(x,y);
prevX = x;
prevY = y;
prevAngle = angle;
}
Rectangle bound = poly.getBounds();
// translate the poly to 0,0
if (bound.x < 0) poly.translate(-bound.x, 0);
if (bound.y < 0) poly.translate(0,-bound.y);
// scale it
//System.out.println(bound.width+ " " +bound.height+" " + bound.x+ " "+ bound.y);
double scaleX = bound.width/((double)getWidth()-10d);
double scaleY = bound.height/((double)getHeight()-10d);
//System.out.println(scaleX+" "+scaleY);
for (int i=0; i < poly.xpoints.length; i++)
{
poly.xpoints[i] /= scaleX;
poly.xpoints[i] += 5;
}
for (int i=0; i < poly.ypoints.length; i++)
{
poly.ypoints[i] /= scaleY;
poly.ypoints[i] += 5;
}
return poly;
}
public void setBorder(Border b)
{
super.setBorder(b);
setModifiedFlag();
}
public void setBackground(Color bg)
{
super.setBackground(bg);
setModifiedFlag();
}
public void paintComponent(Graphics g)
{
// not necessary super.paintComponent(g);
BufferedImage image = getRenderedImage();
g.drawImage(image, 0, 0, null);
}
private BufferedImage getRenderedImage()
{
BufferedImage image = renderedImage;
boolean recreate = image == null || (image.getWidth()!=getWidth()) && image.getHeight()!=getHeight();
if ((!recreate) && (!modifiedFlag)) return image;
if (recreate)
{
if (image != null) image.flush(); // free resources
image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
renderedImage = image;
}
Graphics2D g2 = image.createGraphics();
try
{
renderVariation(g2);
}
finally
{
g2.dispose();
}
return image;
}
private void renderVariation(Graphics2D g2)
{
//g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
// if (values != null){
// for (int x = 0 ; x < 8 ; x++)
// {
// for (int y = 0 ; y < 8 ; y++)
// {
// int w = getWidth()/8;
// int h = getHeight()/8;
// //Color c = mutator.getPalette()[mutator.getColors()[series][x+y*8]];
// Color c = colorValue(getValues()[x+y*8]);
// g2.setColor(c);
// g2.fillRect(x*w,y*h,w,h);
//
// //g.fillRect(0,0,getWidth(),getHeight());
// }
// }
// }
Insets insets = getInsets();
int w = getWidth()-insets.left-insets.right;
int h = getHeight()-insets.top - insets.bottom;
g2.setColor(getBackground());
Border border = getBorder();
if (border == null || border.isBorderOpaque())
g2.fillRect(0, 0, getWidth(), getHeight());
else
g2.fillRect(insets.left, insets.top,w,h);
if (state != null && state.getValues() != null){
if (state.isSelected()) {
g2.setColor(Color.RED);
g2.drawRect(insets.left, insets.top,w-1,h-1);
/*if (border == null || border.isBorderOpaque()) {
g2.drawRect(1, 1, getWidth()-3, getHeight()-2);
//System.out.println(0+" "+ 0+ " "+ getWidth()+ " "+ getHeight());
}
else {
g2.drawRect(insets.left, insets.top,w,h);
//System.out.println(insets.left+" "+ insets.top+ " "+w+" " +h);
}*/
}
Polygon p = getPolygon2();
if (p!= null)
for (int i = 0 ; i < p.xpoints.length-1 ; i ++){
if (i%2 == 0){
g2.setColor(colorValue((int )(angles[i]*256/Math.PI)));
//g2.setStroke(new StrokeWidthManager());
//System.out.println(angles[i]*256/Math.PI + " a ");
}
g2.drawLine(p.xpoints[i],p.ypoints[i],p.xpoints[i+1],p.ypoints[i+1]);
}
}
}
// public void setParameters(Vector<PParameter> parameters) {
// this.parameters = parameters;
// }
//
// public void setValues(Vector<Integer> values) {
// this.values = values;
// setModifiedFlag();
// }
//
// public void updateValues(Vector<Integer> values) {
// this.values.clear();
//
// for (Integer integer : values) {
// this.values.add(integer);
// }
//
// setModifiedFlag();
// }
public class VariationListener implements MouseMotionListener, MouseListener{
private MouseEvent firstMouseEvent = null;
public void mouseDragged(MouseEvent e) {
if (firstMouseEvent != null){
// If they are holding down the control key, COPY rather than MOVE
int ctrlMask = InputEvent.CTRL_DOWN_MASK;
int action = ((e.getModifiersEx() & ctrlMask) == ctrlMask) ?
TransferHandler.COPY : TransferHandler.MOVE;
int dx = Math.abs(e.getX() - firstMouseEvent.getX());
int dy = Math.abs(e.getY() - firstMouseEvent.getY());
//Arbitrarily define a 5-pixel shift as the
//official beginning of a drag.
if (dx > 2 || dy > 2) {
//System.out.println("drag");
//This is a drag, not a click.
JComponent c = (JComponent)e.getSource();
TransferHandler handler = c.getTransferHandler();
//Tell the transfer handler to initiate the drag.
handler.exportAsDrag(c, firstMouseEvent, action);
firstMouseEvent = null;
}
}
}
public void mouseMoved(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
// Variation v = (Variation) (e.getSource());
fireSelectionChanged();
}
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent e) {
firstMouseEvent = e;
e.consume();
}
public void mouseReleased(MouseEvent arg0) {
firstMouseEvent = null;
}
}
public void stateChanged(ChangeEvent e) {
setModifiedFlag();
}
public VariationState getState() {
return state;
}
public void setState(VariationState state) {
if (this.state != null) {
this.state.removeChangeListener(this);
}
this.state = state;
if (this.state != null) {
this.state.addChangeListener(this);
}
setModifiedFlag();
}
}