/*
* Copyright 2011 Uwe Krueger.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mandelsoft.mand.cm;
import java.awt.Color;
/**
*
* @author Uwe Krüger
*/
public final class InterpolationPoint extends EventSourceSupport {
public static boolean debug=false;
private int index;
private InterpolationPoint next;
private InterpolationPoint prev;
private boolean fixed;
private ColormapModel model;
private Color color;
protected InterpolationPoint(int index, ColormapModel colormap)
{
this.model=colormap;
this.index=index;
this.color=model.getColor(index);
}
public ColormapModel getModel()
{ return model;
}
public Color getColor()
{
return color;
}
public boolean isFixed()
{
return fixed;
}
public int getIndex()
{
return index;
}
public double getRelativePosition()
{
if (getPrev()==null || getNext()==null) return -1;
int p=getPrev().getIndex();
int n=getNext().getIndex();
double position=(getIndex()-p-1)/(double)(n-p-2);
return position;
}
public void setRelativePosition(double position)
{
int p=getPrev().getIndex();
int n=getNext().getIndex();
int i=(int)(position*(double)(n-p-2)+p+1);
setIndex(i, false);
}
public InterpolationPoint getPrev()
{
return prev;
}
public InterpolationPoint getNext()
{
return next;
}
public void setFixed(boolean fixed)
{
if (fixed!=this.fixed) {
this.fixed=fixed;
fireInterpolationPointEvent(InterpolationPointEvent.IPE_CHANGED);
}
}
public void setColor(Color c)
{
if (c!=getColor()) setColor(c,true);
}
public void delete()
{
if (next==null||prev==null) return;
if (!isFixed()) {
model.setAdjusting(true);
try {
model.getColormap().startModification();
if (debug) System.out.println("remove "+index+" prev="+prev.getIndex()+" next="+next.
getIndex());
next.setPrev(prev);
prev.setNext(next);
next.interpolateL(null);
if (getPrev()!=null) getPrev().setPosition();
if (getNext()!=null) getNext().setPosition();
next=prev=null;
model.getColormap().endModification();
}
finally {
model.setAdjusting(false);
}
cleanup();
}
}
////////////////////////////////////////////////////////////////////////////
// interaction with colormap model
////////////////////////////////////////////////////////////////////////////
protected void cleanup()
{
fireInterpolationPointEvent(InterpolationPointEvent.IPE_DELETED);
}
protected void setPosition()
{
fireInterpolationPointEvent(InterpolationPointEvent.IPE_NEIGHBOR_CHANGED);
}
public void setIndex(int index, boolean adjust)
{
if (index!=this.index) {
_prepareSetIndex(index);
_finishSetIndex(adjust);
}
}
protected void _prepareSetIndex(int index)
{
this.index=index;
}
protected void _finishSetIndex(boolean adjust)
{
if (getPrev()!=null) getPrev().setPosition();
if (adjust) setPosition();
if (getNext()!=null) getNext().setPosition();
setColor(null,false);
fireInterpolationPointEvent(InterpolationPointEvent.IPE_MOVED);
}
protected void setColor(Color c, boolean adjusted)
{ Color old=getColor();
boolean locked=model.isAdjusting();
model.setAdjusting(true);
try {
if (!locked) model.getColormap().startModification();
interpolateR(c);
interpolateL(c);
if (!locked) model.getColormap().endModification();
}
finally {
model.setAdjusting(locked);
}
if (adjusted && getColor()!=old) {
fireInterpolationPointEvent(InterpolationPointEvent.IPE_COLOR_CHANGED);
}
}
private void setNext(InterpolationPoint next)
{
this.next=next;
}
private void setPrev(InterpolationPoint prev)
{
this.prev=prev;
}
protected void add(InterpolationPoint ip)
{
if (ip.getIndex()<=index) throw new IllegalArgumentException("ip is lower");
if (next!=null&&ip.getIndex()>=next.getIndex())
throw new IllegalArgumentException("ip is too high");
ip.setNext(next);
ip.setPrev(this);
if (next!=null) ip.next.setPrev(ip);
next=ip;
ip.fireInterpolationPointEvent(InterpolationPointEvent.IPE_ADDED);
if (ip.getPrev()!=null) ip.getPrev().setPosition();
if (ip.getNext()!=null) ip.getNext().setPosition();
}
protected void fireInterpolationPointEvent(int id)
{
fireInterpolationPointEvent(this, id);
getModel().fireInterpolationPointEvent(this,id);
}
////////////////////////////////////////////////////////////////////////////
// interpolation
////////////////////////////////////////////////////////////////////////////
private void interpolateL(Color n)
{
interpolate(n, prev);
}
private void interpolateR(Color n)
{
interpolate(n, next);
}
private void interpolate(Color n, InterpolationPoint ip)
{
if (ip==null) {
if (n!=null) {
model.getColormap().setColor(index, n);
color=n;
}
}
else {
if (n==null) n=getColor();
color=n;
if (debug) System.out.println("interpolate "+index+" to "+ip.getIndex()+": "+
color+"-"+ip.getColor());
int rx=ip.getIndex()-index;
int dx=Integer.signum(rx);
Color start=n;
Color end=ip.getColor();
//System.out.println("rx="+rx+", dx="+dx);
double sred=start.getRed();
double sgreen=start.getGreen();
double sblue=start.getBlue();
double dred=end.getRed()-sred;
double dgreen=end.getGreen()-sgreen;
double dblue=end.getBlue()-sblue;
//System.out.println("sred="+sred+", "+sgreen+", "+sblue);
//System.out.println("dred="+dred+", "+dgreen+", "+dblue);
/*
*/
for (int i=0; i!=rx;
i+=dx) {
int cur=i+getIndex();
/*
System.out.println(" set "+cur+" ("+(int)(sred+i*dred/rx)+","+
(int)(sgreen+i*dgreen/rx)+","+
(int)(sblue+i*dblue/rx)+")");
*/
model.getColormap().setColor(cur,
new Color((int)(sred+i*dred/rx),
(int)(sgreen+i*dgreen/rx),
(int)(sblue+i*dblue/rx)));
}
}
}
}