Newer
Older
MagnetRON / src / org / ntlab / deltaViewer / DeltaAnimation.java
package org.ntlab.deltaViewer;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.swing.SwingUtilities;

import com.mxgraph.canvas.mxGraphics2DCanvas;
import com.mxgraph.model.mxICell;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.util.mxPoint;

/**
 * Generate delta animation for MagnetRON.
 * 
 * @author Nitta Lab.
 */
public class DeltaAnimation {

	private DeltaGraphAdapter mxgraph;
	private mxGraphComponent mxgraphComponent;
	
	private Graphics2D graphics2D;
	private Timer timer;
	private static int FINAL_STEP_COUNT = 10;

	private mxICell sourceCell;
	
	GeneralPath p = new GeneralPath();

	// X, Y
	private mxPoint sourcePoint;
	private mxPoint targetPoint;
	private mxPoint curPoint;
	private mxPoint updatePoint = new mxPoint();
	
	// Width, Height
	private Dimension targetDimension;
	private Dimension curDimension = new Dimension();
	private Dimension updateDimension = new Dimension();

	private double scale = 1;
	
	/**
	 * @param mxgraph
	 * @param mxgraphComponent
	 */
	public DeltaAnimation(DeltaGraphAdapter mxgraph, mxGraphComponent mxgraphComponent) {
		this.mxgraph = mxgraph;
		this.mxgraphComponent = mxgraphComponent;
		graphics2D = (Graphics2D)mxgraphComponent.getGraphics();
	}

	/**
	 * @param zoomLevel	Zoom level of MagnetRON view.
	 */
	public void setScale(double zoomLevel) {
		this.scale = zoomLevel;
	}

	/**
	 * Set to move animation sourcell vertex to targetPoint.
	 * 
	 * @param sourceCell	Vertex.
	 * @param targetPoint XY coordinates.
	 */
	public void setVertexAnimation(mxICell sourceCell, mxPoint targetPoint) {
		this.sourceCell = sourceCell;
		this.targetPoint = targetPoint;
		curPoint = new mxPoint(sourceCell.getGeometry().getX(), sourceCell.getGeometry().getY());
//		System.out.println("sourcePoint : " + sourceCell.getGeometry().getPoint());
//		System.out.println("targetPoint : " + targetPoint);
		calculateResizeLineModel();
	}
	
	/**
	 * Set stretch(expand) animation of edge from sourcePoint to targetPoint.
	 * 
	 * @param sourcePoint	Edge sourcePoint.
	 * @param targetPoint	Edge targetPoint.
	 */
	public void setExpandEdgeAnimation(mxPoint sourcePoint, mxPoint targetPoint) {
		this.sourcePoint = new mxPoint(sourcePoint.getX() * scale + 1, sourcePoint.getY() * scale + 1);
		this.targetPoint = new mxPoint(targetPoint.getX() * scale, targetPoint.getY() * scale);
		curPoint = this.sourcePoint;
//		System.out.println("sourcePoint : " + sourcePoint);
//		System.out.println("targetPoint : " + targetPoint);
		
		graphics2D = (Graphics2D)mxgraphComponent.getGraphics();
		graphics2D.setColor(Color.decode("#008000"));

		float width = (float) (1 * scale);
		Stroke dashed = new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[]{(float) (3.0f * scale * width), (float) (3.0f * scale * width)}, 0.0f);
		graphics2D.setStroke(dashed);
		calculateResizeLineModel();
	}

	/**
	 * Set to move animation sourcell vertex clone to targetPoint, reduce edge length.
	 * 
	 * @param sourceCell Remove sourceCell vertex clone.
	 * @param targetPoint
	 */
	public void setReductionEdgeAnimation(mxICell sourceCell, mxPoint targetPoint) {
		this.sourceCell = sourceCell;
		this.targetPoint = targetPoint;
		curPoint = new mxPoint(sourceCell.getGeometry().getX(), sourceCell.getGeometry().getY());
//		System.out.println("sourcePoint : " + sourceCell.getGeometry().getPoint());
//		System.out.println("targetPoint : " + targetPoint);
		calculateResizeLineModel();
	}

	/**
	 * Set animation resize vertex.
	 * 
	 * @param sourceCell
	 * @param targetDimension Vertex (Width, Height)
	 */
	public void setResizeVertexAnimation(mxICell sourceCell, Dimension targetDimension) {
		this.sourceCell = sourceCell;
		this.targetDimension = targetDimension;
		curDimension.setSize(sourceCell.getGeometry().getWidth(), sourceCell.getGeometry().getHeight());
		calculateResizeVertexModel();
	}

	/**
	 * Calculate updatePoint every second from curPoint and targetPoint.
	 */
	public void calculateResizeLineModel() {
		mxPoint distancePoint = new mxPoint();
		distancePoint.setX(targetPoint.getX() - curPoint.getX()); 
		distancePoint.setY(targetPoint.getY() - curPoint.getY()); 
		updatePoint.setX(distancePoint.getX() / FINAL_STEP_COUNT);
		updatePoint.setY(distancePoint.getY() / FINAL_STEP_COUNT);
	}
	
	/**
	 * Calculate updateDimension every second from curPoint and targetPoint.
	 */
	public void calculateResizeVertexModel() {
		Dimension distanceDimension = new Dimension();
		distanceDimension.setSize(targetDimension.getWidth() - curDimension.getWidth(), targetDimension.getHeight() - curDimension.getWidth());
		updateDimension.setSize(distanceDimension.getWidth() / FINAL_STEP_COUNT, distanceDimension.getHeight() / FINAL_STEP_COUNT);
	}

	/**
	 * Start animation to move sourcell vertex to targetPoint for 10 sec.
	 */
	public void startVertexAnimation() {
		timer = new Timer();
		timer.schedule(new TimerTask() {
			int stepCount = 0;
			
			@Override
			public void run() {
				if(stepCount < FINAL_STEP_COUNT) {
					updateVertexAnimation();
					stepCount++;
					if(stepCount >= FINAL_STEP_COUNT){
						timer.cancel();
					}
				}
			}
		}, 0, 100);
		try {
			Thread.sleep(1001);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Start stretch(expand) animation of edge from sourcePoint to targetPoint for 10 sec.
	*/
	public void startExpandEdgeAnimation() {
		timer = new Timer();
		timer.schedule(new TimerTask() {
			int stepCount = 0;
			
			@Override
			public void run() {
				if(stepCount < FINAL_STEP_COUNT) {
					updateExpandEdgeAnimation();
			    	stepCount++;
					if(stepCount >= FINAL_STEP_COUNT){
						timer.cancel();
					}
				} 
			}
		}, 0, 100);
		try {
			Thread.sleep(1001);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Start move animation sourcell vertex clone to targetPoint, reduce edge length for 10 sec.
	 */
	public void startReductionEdgeAnimation() {
//		timer = new Timer();
//		timer.schedule(new TimerTask() {
//			int stepCount = 0;
//			
//			@Override
//			public void run() {
//				if(stepCount < FINAL_STEP_COUNT) {
//					updateReductionEdgeAnimation();
//			    	stepCount++;
//					if(stepCount >= FINAL_STEP_COUNT){
//						timer.cancel();
//					}
//				} 
//			}
//		}, 0, 100);
//		try {
//			Thread.sleep(1001);
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
		 ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
         scheduledThreadPoolExecutor.scheduleWithFixedDelay(new TimerTask() {
 			int stepCount = 0;
			
 			@Override
 			public void run() {
 				if(stepCount < FINAL_STEP_COUNT) {
					updateReductionEdgeAnimation();
 					System.out.println(stepCount + ": " + curPoint.getX());
 					stepCount++;
 					if(stepCount >= FINAL_STEP_COUNT){
 						timer.cancel();
 					}
 				}
 			}
 		}, 0, 100, TimeUnit.MILLISECONDS);
		try {
			System.out.println("Thread.sleep()");
			Thread.sleep(1001);
			System.out.println("Thread.start()");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Start animation resize vertex for 10 sec.
	 */
	public void startResizeVertexAnimation() {
//		timer = new Timer();
//		timer.schedule(new TimerTask() {
//			int stepCount = 0;
//			
//			@Override
//			public void run() {
//				if(stepCount < FINAL_STEP_COUNT) {
//					updateResizeVertexAnimation();
//					stepCount++;
//					if(stepCount >= FINAL_STEP_COUNT){
//						timer.cancel();
//					}
//				}
//			}
//		}, 0, 100);
//		try {
//			Thread.sleep(1000);
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
		
		 ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
         scheduledThreadPoolExecutor.scheduleWithFixedDelay(new TimerTask() {
 			int stepCount = 0;
			
 			@Override
 			public void run() {
 				if(stepCount < FINAL_STEP_COUNT) {
 					updateResizeVertexAnimation();
 					System.out.println(stepCount + ": " + curDimension.width);
 					stepCount++;
 					if(stepCount >= FINAL_STEP_COUNT){
 						timer.cancel();
 					}
 				}
 			}
 		}, 0, 100, TimeUnit.MILLISECONDS);
		try {
			System.out.println("Thread.sleep()");
			Thread.sleep(1001);
			System.out.println("Thread.start()");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Update animation to move sourcell vertex to targetPoint every second.
	 */
	private void updateVertexAnimation() {
		// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
		mxgraph.getModel().beginUpdate();
		try {
			curPoint.setX(sourceCell.getGeometry().getX());
			curPoint.setY(sourceCell.getGeometry().getY());
			sourceCell.getGeometry().setX(curPoint.getX() + updatePoint.getX());
			sourceCell.getGeometry().setY(curPoint.getY() + updatePoint.getY());
//			System.out.println(sourceCell.getGeometry().getPoint());
		} finally {
			  mxgraph.getModel().endUpdate();
		}
    	mxgraphComponent.refresh();
	}

	/**
	 * Update stretch(expand) animation of edge length updatePoint every second.
	 */
	private void updateExpandEdgeAnimation() {
		Runnable r = new Runnable() {
			public void run() {
				p.reset();
				p.moveTo((float)curPoint.getX(), (float)curPoint.getY());
				curPoint.setX(curPoint.getX() + updatePoint.getX());
				curPoint.setY(curPoint.getY() + updatePoint.getY());
//					   System.out.println("curPoint : " + curPoint);
				 p.lineTo((float)curPoint.getX(), (float)curPoint.getY());
				 graphics2D.draw(p);
				 }
			};	
			
			// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
			if (!SwingUtilities.isEventDispatchThread()) {
				SwingUtilities.invokeLater(r);
				} else {
					r.run();
				}
	}
		
	/**
	 * Update move animation sourcell vertex clone to targetPoint, reduce edge length updatePoint every second.
	 */
	private void updateReductionEdgeAnimation() {
			// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
			mxgraph.getModel().beginUpdate();
			try {
				curPoint.setX(sourceCell.getGeometry().getX());
				curPoint.setY(sourceCell.getGeometry().getY());
				sourceCell.getGeometry().setX(curPoint.getX() + updatePoint.getX());
				sourceCell.getGeometry().setY(curPoint.getY() + updatePoint.getY());
	//			System.out.println(sourceCell.getGeometry().getPoint());
			} finally {
				  mxgraph.getModel().endUpdate();
			}
	    	mxgraphComponent.refresh();
		}

	/**
	 * Update animation resize vertex every second.
	 */
	private void updateResizeVertexAnimation() {
		// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.	
		mxgraph.getModel().beginUpdate();
		try {
			double preCenterX = sourceCell.getGeometry().getCenterX();
		    double preCenterY = sourceCell.getGeometry().getCenterY();

			curDimension.setSize(sourceCell.getGeometry().getWidth(), sourceCell.getGeometry().getHeight());
			sourceCell.getGeometry().setWidth(curDimension.getWidth() + updateDimension.getWidth());
			sourceCell.getGeometry().setHeight(curDimension.getHeight() + updateDimension.getHeight());

	    	double curCenterX = sourceCell.getGeometry().getCenterX();
	    	double curCenterY = sourceCell.getGeometry().getCenterY();
	    	double distanceX = (curCenterX - preCenterX);
	    	double distanceY = (curCenterY - preCenterY);
	    	double curX = sourceCell.getGeometry().getX();
	    	double curY = sourceCell.getGeometry().getY();
	    	
	    	sourceCell.getGeometry().setX(curX - distanceX);
	    	sourceCell.getGeometry().setY(curY - distanceY);

	    	for (int i = 0; i < sourceCell.getChildCount(); i++) {
	    		mxICell childCell = sourceCell.getChildAt(i);
//	    		System.out.println("child" + childCell);
		    	curX = childCell.getGeometry().getX();
		    	curY = childCell.getGeometry().getY();
		    	childCell.getGeometry().setX(curX + distanceX);
		    	childCell.getGeometry().setY(curY + distanceY);
	    	}
		} finally {
			  mxgraph.getModel().endUpdate();
		}
    	mxgraphComponent.refresh();
	}
}