diff --git a/src/org/ntlab/animations/MagnetRONAnimation.java b/src/org/ntlab/animations/MagnetRONAnimation.java new file mode 100644 index 0000000..52e1200 --- /dev/null +++ b/src/org/ntlab/animations/MagnetRONAnimation.java @@ -0,0 +1,472 @@ +package org.ntlab.animations; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.Dimension2D; +import java.awt.geom.Point2D; +import java.util.TimerTask; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.ntlab.deltaViewer.DeltaGraphAdapter; +import org.ntlab.deltaViewer.MagnetRONScheduledThreadPoolExecutor; + +import com.mxgraph.model.mxICell; +import com.mxgraph.swing.mxGraphComponent; +/** + * + * + * @author Nitta Lab. + */ +public abstract class MagnetRONAnimation { + + // Test code (will be deleted) + private static final String TAG = MagnetRONAnimation.class.getSimpleName(); + + protected DeltaGraphAdapter mxgraph; + protected mxGraphComponent mxgraphComponent; + + protected ThreadPoolExecutor threadPoolExecutor; + protected ScheduledFuture scheduledFuture; + /** + * Initial delays the start of an animation. + * + * Cannot be negative. Setting to a negative number will result in {@link IllegalArgumentException}. + * + * @defaultValue 0ms + */ + private long initialDelay; + private static final long DEFAULT_INITIAL_DELAY = 0L; + /** + * Delays the interval between repeating an animation. + * + * Cannot be negative. Setting to a negative number will result in {@link IllegalArgumentException}. + * + * @defaultValue 0ms + */ + private long delay; + private static final long DEFAULT_DELAY = 0L; + + /** + * Defines the direction/speed at which the {@code MagnetRONAnimation} is expected to + * be played. + *

+ * The absolute value of {@code rate} indicates the speed which the + * {@code Animation} is to be played, while the sign of {@code rate} + * indicates the direction. A positive value of {@code rate} indicates + * forward play, a negative value indicates backward play and {@code 0.0} to + * stop a running {@code MagnetRONAnimation}. + *

+ * Rate {@code 1.0} is normal play, {@code 2.0} is 2 time normal, + * {@code -1.0} is backwards, etc... + * + *

+ * Inverting the rate of a running {@code MagnetRONAnimation} will cause the + * {@code MagnetRONAnimation} to reverse direction in place and play back over the + * portion of the {@code MagnetRONAnimation} that has already elapsed. + * + * @defaultValue 1.0 + */ + private double rate; + private static final double DEFAULT_RATE = 1.0; + + /** + * Read-only variable to indicate current direction/speed at which the + * {@code MagnetRONAnimation} is being played. + *

+ * {@code currentRate} is not necessary equal to {@code rate}. + * {@code currentRate} is set to {@code 0.0} when animation is paused or + * stopped. {@code currentRate} may also point to different direction during + * reverse cycles when {@code reverse} is {@code true} + * + * @defaultValue 0.0 + */ + private double currentRate; + private static final double DEFAULT_CURRENT_RATE = 0.0; + + /** + * Defines the number of cycles in this animation. The {@code totalCycleCount} + * may be {@code INDEFINITE} for animations that repeat indefinitely, but + * must otherwise be > 0. + *

+ * It is not possible to change the {@code totalCycleCount} of a running + * {@code MagnetRONAnimation}. If the value of {@code totalCycleCount} is changed for a + * running {@code MagnetRONAnimation}, the animation has to be stopped and started again to pick + * up the new value. + * + * @defaultValue 1 + * + */ + private int totalCycleCount; + private static final int DEFAULT_TOTAL_CYCLE_COUNT = 1; + /** + * The current number of cycles in this animation. + * + * @defaultValu 0 + */ + private int currentCycleCount = 0; + + /** + * Used to specify an animation that repeats indefinitely, until the + * {@code stop()} method is called. + */ + private static final int INDEFINITE = -1; + + /** + * The status of the {@code MagnetRONAnimation}. + * + * In {@code MagnetRONAnimation} can be in one of three states: + * {@link Status#STOPPED}, {@link Status#PAUSED} or {@link Status#RUNNING}. + */ + private Status currentStatus; + private static final Status DEFAULT_STATUS = Status.STOPPED; + + /** + * The action to be executed at the conclusion of this {@code MagnetRONAnimation}. + */ + private ActionListener onFinished; + + /** + * Defines whether this + * {@code MagnetRONAnimation} reverses direction on alternating cycles. If + * {@code true}, the + * {@code MagnetRONAnimation} will proceed reverses on the cycle. + * Otherwise, animation will loop such that each cycle proceeds forward from the start. + * + * It is not possible to change the {@code reverse} flag of a running + * {@code MagnetRONAnimation}. If the value of {@code reverse} is changed for a + * running {@code MagnetRONAnimation}, the animation has to be stopped and started again to pick + * up the new value. + * + * @defaultValue false + */ + private boolean reverse; + private static final boolean DEFAULT_REVERSE = false; + + /** + * The object to animate. + */ + private mxICell sourceCell; + + /** + * The initial point of sourceCell. + */ + private Point2D sourceInitPoint; + + /** + * The initial size of sourceCell. + */ + private Dimension2D sourceInitDimension; + + /** + * The possible state for MagnetRONAnimation. + */ + protected static enum Status { + /** + * The paused state. + */ + PAUSED, + /** + * The running state. + */ + RUNNING, + /** + * The stopped state. + */ + STOPPED + } + + private static int animationCount = 0; + + /** + * The constructor of {@code MagnetRONAnimation}. + * + * @param mxgraph: visualization model + * @param mxgraphComponent: visualization model group + */ + protected MagnetRONAnimation(DeltaGraphAdapter mxgraph, mxGraphComponent mxgraphComponent) { + this.mxgraph = mxgraph; + this.mxgraphComponent = mxgraphComponent; + } + + protected void setThreadPoolExecutor(ThreadPoolExecutor threadPoolExecutor) { + this.threadPoolExecutor = threadPoolExecutor; + } + + public void setInitialDelay(long initialDelay) { + this.initialDelay = initialDelay; + } + + public void setDelay(long delay) { + this.delay = delay; + } + + protected void setRate(double rate) { + this.rate = rate; + } + + protected void setCurrentRate(double currentRate) { + this.currentRate = currentRate; + } + + public void setTotalCycleCount(int totalCycleCount) { + this.totalCycleCount = totalCycleCount; + } + + protected void setCurrentCycleCount(int currentCycleCount) { + this.currentCycleCount = currentCycleCount; + } + + protected void setCurrentStatus(Status currentStatus) { + this.currentStatus = currentStatus; + } + + public void setOnFinished(ActionListener onFinished) { + this.onFinished = onFinished; + } + + public void setReverse(boolean reverse) { + this.reverse = reverse; + } + + protected void setSourceCell(mxICell sourceCell) { + this.sourceCell = sourceCell; + } + + protected void setSourceInitialPoint(Point2D sourceInitPoint) { + this.sourceInitPoint = sourceInitPoint; + } + + protected void setSourceInitialDimension(Dimension2D sourceInitDimension) { + this.sourceInitDimension = sourceInitDimension; + } + + protected void setScheduledFuture(ScheduledFuture scheduledFuture) { + this.scheduledFuture = scheduledFuture; + } + + protected abstract void setDestination(double x, double y); + + protected abstract void setVelocity(double x, double y); + + protected ThreadPoolExecutor getThreadPoolExecutor() { + return threadPoolExecutor; + } + + public long getInitialDelay() { + if (initialDelay == 0L) return DEFAULT_INITIAL_DELAY; + return initialDelay; + } + + public long getDelay() { + if (delay == 0L) return DEFAULT_DELAY; + return delay; + } + + protected double getRate() { + if (rate == 0.0) return DEFAULT_RATE; + return rate; + } + + protected double getCurrentRate() { + if (currentRate == 0.0) return DEFAULT_CURRENT_RATE; + return currentRate; + } + + public int getTotalCycleCount() { + if (totalCycleCount == 0) return DEFAULT_TOTAL_CYCLE_COUNT; + return totalCycleCount; + } + + protected int getCurrentCycleCount() { + return currentCycleCount; + } + + protected Status getCurrentStatus() { + if (currentStatus == null) return DEFAULT_STATUS; + return currentStatus; + } + + public ActionListener getOnFinished() { + return onFinished; + } + + public boolean getReverse() { + if (!reverse) return DEFAULT_REVERSE; + return reverse; + } + + protected mxICell getSourceCell() { + return sourceCell; + } + + protected Point2D getSourceInitialPoint() { + return sourceInitPoint; + } + + protected Dimension2D getSourceInitialDimension() { + return sourceInitDimension; + } + + protected ScheduledFuture getScheduledFuture() { + return scheduledFuture; + } + + /** + * Set expand or reduction animation of edge to targetPoint. + * Must be call {@code MagnetRONAnimation#init(mxICell, mxPoint, ThreadPoolExecutor)} before calling {@code MagnetRONAnimation#play()}. + * + * @param sourceCell: edge object + * @param destinationPoint + */ + public void init(mxICell sourceCell, double destinationX, double destinationY, ThreadPoolExecutor threadPoolExecutor) { + setSourceCell(sourceCell); + setDestination(destinationX, destinationY); + setThreadPoolExecutor(threadPoolExecutor); + setSourceInitialPoint(getSourceCell().getGeometry().getPoint()); + setSourceInitialDimension( + new Dimension((int) getSourceCell().getGeometry().getWidth(), + (int) getSourceCell().getGeometry().getHeight())); + setCurrentCycleCount(0); + } + + public void updateCurrentCycle() { + if (!getReverse()) { // Animation direction is forward. + setCurrentCycleCount((int) (currentCycleCount + Math.signum(getTotalCycleCount()))); + } else { + setCurrentCycleCount((int) (currentCycleCount - Math.signum(getTotalCycleCount()))); + } + } + + public void interpolate(double cycleCount) { + + } + + public void playFrom() { + + } + + public void play() { + switch (getCurrentStatus()) { + case STOPPED: + if (getThreadPoolExecutor() != null & getThreadPoolExecutor() instanceof ScheduledThreadPoolExecutor) { + ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = (ScheduledThreadPoolExecutor) getThreadPoolExecutor(); + setThreadPoolExecutor(scheduledThreadPoolExecutor); + ScheduledFuture scheduledFuture = scheduledThreadPoolExecutor.scheduleWithFixedDelay(new TimerTask() { + @Override + public void run() { + if(Math.abs(getCurrentCycleCount()) < Math.abs(getTotalCycleCount())) { + // Test code (will be deleted) + System.out.println(TAG + ": Run task " + getSourceCell().getId() + " " + MagnetRONAnimation.this.getClass().getSimpleName() + "-" + getCurrentCycleCount() + ". ThreadId=" + Thread.currentThread().getId()); + updateCurrentCycle(); + jumpTo(getCurrentCycleCount()); + } else if(Math.abs(getCurrentCycleCount()) >= Math.abs(getTotalCycleCount())){ + animationCount = 0; + onFinished(); + } + } + }, getInitialDelay(), getDelay(), TimeUnit.MILLISECONDS); + setScheduledFuture(scheduledFuture); + setCurrentStatus(Status.RUNNING); + animationCount = 1; + }; + break; + case PAUSED: + if (getThreadPoolExecutor() != null & getThreadPoolExecutor() instanceof MagnetRONScheduledThreadPoolExecutor) { + MagnetRONScheduledThreadPoolExecutor scheduledThreadPoolExecutor = (MagnetRONScheduledThreadPoolExecutor) getThreadPoolExecutor(); + scheduledThreadPoolExecutor.resume(); + setCurrentStatus(Status.RUNNING); + } + break; + default: + break; + }; + } + + /** + * Sleep main thread and wait for {@link MagnetRONAnimation#play()} to finish running. + */ + public static void waitAnimationEnd() { + while (animationCount > 0) { + try { + Thread.sleep(1L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + // Buffer for another waiting animation. + try { + Thread.sleep(30L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * Play animation in sync with main thread. + */ + public void syncPlay() { + if (getCurrentStatus() == Status.STOPPED) { + try { + Thread.sleep(getInitialDelay()); + while (true) { + while (getCurrentStatus() == Status.PAUSED) { + Thread.sleep(1L); + } + if(Math.abs(getCurrentCycleCount()) < Math.abs(getTotalCycleCount())) { + // Test code (will be deleted) + System.out.println(TAG + ": Run task " + getSourceCell().getId() + " " + MagnetRONAnimation.this.getClass().getSimpleName() + "-" + getCurrentCycleCount() + ". ThreadId=" + Thread.currentThread().getId()); + updateCurrentCycle(); + jumpTo(getCurrentCycleCount()); + } else if(Math.abs(getCurrentCycleCount()) >= Math.abs(getTotalCycleCount())){ + onFinished(); + break; + } + Thread.sleep(getDelay()); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void playFormStart() { + + } + + public void stop() { + if (getCurrentStatus() == Status.RUNNING) { + getScheduledFuture().cancel(true); + } + setCurrentStatus(Status.STOPPED); + setCurrentRate(0.0); + } + + public void pause() { + if (getCurrentStatus() == Status.RUNNING) { + if (getThreadPoolExecutor() != null && getThreadPoolExecutor() instanceof MagnetRONScheduledThreadPoolExecutor) { + MagnetRONScheduledThreadPoolExecutor scheduledThreadPoolExecutor = (MagnetRONScheduledThreadPoolExecutor) getThreadPoolExecutor(); + scheduledThreadPoolExecutor.pause(); + setCurrentStatus(Status.PAUSED); + } + } + + } + + private final void onFinished() { + stop(); + final ActionListener listener = getOnFinished(); + if (listener != null) { + try { + listener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null)); + } catch (Exception e) { + Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); + } + } + } + + protected abstract void jumpTo(int currentCycleCount); +} diff --git a/src/org/ntlab/animations/TranslateAnimation.java b/src/org/ntlab/animations/TranslateAnimation.java new file mode 100644 index 0000000..723e4d0 --- /dev/null +++ b/src/org/ntlab/animations/TranslateAnimation.java @@ -0,0 +1,108 @@ +package org.ntlab.animations; + +import java.awt.Point; +import java.awt.geom.Point2D; +import java.util.concurrent.ThreadPoolExecutor; + +import org.ntlab.deltaViewer.DeltaGraphAdapter; + +import com.mxgraph.model.mxICell; +import com.mxgraph.swing.mxGraphComponent; + +/** + * Animation of edge stretching and shrinking, vertex translating. + * + * @author Nitta Lab. + */ +public class TranslateAnimation extends MagnetRONAnimation { + + // Test code (will be deleted) + private static final String TAG = TranslateAnimation.class.getSimpleName(); + + /** + * The destination point where the sourceCell animates. + */ + private Point2D destinationPoint; + /** + * The point to update for each cycle count. + */ + private Point2D velocity; + + /** + * The constructor of {@code TranslateAnimation}. + * + * @param mxgraph + * @param mxgraphComponent + */ + public TranslateAnimation(DeltaGraphAdapter mxgraph, mxGraphComponent mxgraphComponent) { + super(mxgraph, mxgraphComponent); + } + + @Override + protected void setDestination(double x, double y) { + setDestinationPoint(new Point2D.Double(x, y)); + } + + private void setDestinationPoint(Point2D destinationPoint) { + this.destinationPoint = destinationPoint; + } + + @Override + protected void setVelocity(double x, double y) { + setVelocity(new Point2D.Double(x, y)); + } + + private void setVelocity(Point2D velocity) { + this.velocity = velocity; + } + + private Point2D getDestinationPoint() { + return destinationPoint; + } + + private Point2D getVelocity() { + return velocity; + } + + public void init(mxICell sourceCell, Point2D destinationPoint, ThreadPoolExecutor threadPoolExecutor) { + init(sourceCell, destinationPoint.getX(), destinationPoint.getY(), threadPoolExecutor); + } + + /** + * See {@code MagnetRONAnimation#init(mxICell, double, double, ThreadPoolExecutor)} + * + * @param sourceCell + * @param destinationPoint + * @param threadPoolExecutor + */ + @Override + public void init(mxICell sourceCell, double x, double y, ThreadPoolExecutor threadPoolExecutor) { + super.init(sourceCell, x, y, threadPoolExecutor); + + Point2D curPt = new Point(sourceCell.getGeometry().getPoint()); + + // Calculate resize line model + Point2D distancePoint = new Point(); + distancePoint.setLocation(destinationPoint.getX() - curPt.getX(), + destinationPoint.getY() - curPt.getY()); + Point2D velocity = new Point2D.Double(); + velocity.setLocation(distancePoint.getX() / getTotalCycleCount(), distancePoint.getY() / getTotalCycleCount()); + setVelocity(velocity); + } + + @Override + protected void jumpTo(int currentCycleCount) { + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized(mxgraph.getModel()) { + try { + getSourceCell().getGeometry().setX(getSourceInitialPoint().getX() + getVelocity().getX() * currentCycleCount); + getSourceCell().getGeometry().setY(getSourceInitialPoint().getY() + getVelocity().getY() * currentCycleCount); + } finally { + mxgraph.getModel().endUpdate(); + } + mxgraphComponent.refresh(); + } + } + +} diff --git a/src/org/ntlab/animations/VertexResizeAnimation.java b/src/org/ntlab/animations/VertexResizeAnimation.java new file mode 100644 index 0000000..4c020a3 --- /dev/null +++ b/src/org/ntlab/animations/VertexResizeAnimation.java @@ -0,0 +1,109 @@ +package org.ntlab.animations; + +import java.awt.Dimension; +import java.awt.geom.Dimension2D; +import java.util.concurrent.ThreadPoolExecutor; + +import org.ntlab.deltaViewer.DeltaGraphAdapter; + +import com.mxgraph.model.mxICell; +import com.mxgraph.swing.mxGraphComponent; + +/** + * Animation to resize vertex. + * + * @author Nitta Lab. + */ +public class VertexResizeAnimation extends MagnetRONAnimation { + + // Test code (will be deleted) + private static final String TAG = VertexResizeAnimation.class.getSimpleName(); + + /** + * The destination dimension where the sourceCell animates. + */ + private Dimension2D destinationDimension; + /** + * The dimension to update for each cycle count. + */ + private Dimension2D velocity; + + /** + * The constructor of {@code VertexResizeAnimation}. + * + * @param mxgraph + * @param mxgraphComponent + */ + public VertexResizeAnimation(DeltaGraphAdapter mxgraph, mxGraphComponent mxgraphComponent) { + super(mxgraph, mxgraphComponent); + } + + @Override + protected void setDestination(double x, double y) { + setDestinationDimension(new Dimension((int) x, (int) y)); + } + + private void setDestinationDimension(Dimension2D destinationDimension) { + this.destinationDimension = destinationDimension; + } + + @Override + protected void setVelocity(double x, double y) { + setVelocity(new Dimension((int) x, (int) y)); + } + + private void setVelocity(Dimension2D velocity) { + this.velocity = velocity; + } + + private Dimension2D getDestinationDimension() { + return destinationDimension; + } + + private Dimension2D getVelocity() { + return velocity; + } + + public void init(mxICell sourceCell, Dimension2D destinationDimension, ThreadPoolExecutor threadPoolExecutor) { + init(sourceCell, destinationDimension.getWidth(), destinationDimension.getHeight(), threadPoolExecutor); + } + + /** + * See {@code MagnetRONAnimation#init(mxICell, double, double, ThreadPoolExecutor)} + * + * @param sourceCell + * @param destinationDimension + * @param threadPoolExecutor + */ + @Override + public void init(mxICell sourceCell, double width, double height, ThreadPoolExecutor threadPoolExecutor) { + super.init(sourceCell, width, height, threadPoolExecutor); + + Dimension2D curDim = new Dimension(); + curDim.setSize(sourceCell.getGeometry().getWidth(), sourceCell.getGeometry().getHeight()); + + // Calculate resize dimension model + Dimension2D distanceDimension = new Dimension(); + distanceDimension.setSize(destinationDimension.getWidth() - curDim.getWidth(), + destinationDimension.getHeight() - curDim.getHeight()); + Dimension2D velocity = new Dimension(); + velocity.setSize(distanceDimension.getWidth() / getTotalCycleCount(), distanceDimension.getHeight() / getTotalCycleCount()); + setVelocity(velocity); + } + + @Override + protected void jumpTo(int currentCycleCount) { + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized(mxgraph.getModel()) { + try { + getSourceCell().getGeometry().setWidth(getSourceInitialDimension().getWidth() + getVelocity().getWidth() * currentCycleCount); + getSourceCell().getGeometry().setHeight(getSourceInitialDimension().getHeight() + getVelocity().getHeight() * currentCycleCount); + } finally { + mxgraph.getModel().endUpdate(); + } + mxgraphComponent.refresh(); + } + } + +} diff --git a/src/org/ntlab/deltaViewer/CollaborationViewer.java b/src/org/ntlab/deltaViewer/CollaborationViewer.java index 19f68a0..6cbb48d 100644 --- a/src/org/ntlab/deltaViewer/CollaborationViewer.java +++ b/src/org/ntlab/deltaViewer/CollaborationViewer.java @@ -1,13 +1,13 @@ package org.ntlab.deltaViewer; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Point; +import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import org.ntlab.animations.MagnetRONAnimation; +import org.ntlab.animations.TranslateAnimation; import org.ntlab.deltaExtractor.Alias; import org.ntlab.deltaExtractor.IAliasCollector; import org.ntlab.deltaExtractor.Alias.AliasType; @@ -22,10 +22,15 @@ import org.ntlab.trace.TracePoint; import com.mxgraph.model.mxICell; -import com.mxgraph.util.mxPoint; import com.mxgraph.view.mxGraphView; public class CollaborationViewer extends MagnetRONViewer { + + private static final long serialVersionUID = 9123813231037494846L; + + // Test code (will be deleted) + private static final String TAG = CollaborationViewer.class.getSimpleName(); + private IObjectCallGraph objectCallGraph; private double scale = 1; @@ -69,7 +74,7 @@ System.out.println(", " + scale); // scale = 1.5; view.setScale(scale); - deltaAnimation.setScale(scale); +// deltaAnimation.setScale(scale); update(); } @@ -92,9 +97,9 @@ * @param numFrame Current animation frame. */ public void stepToAnimation(int numFrame) { - // TODO Implement doLastAnimation to support plural Delta. - // TOD curFrame debug. - System.out.println("Frame: " + curFrame + "->" + numFrame); + // TODO: Implement doLastAnimation to support plural Delta. + // TODO: curFrame debug. + System.out.println(TAG + ": Frame=" + curFrame + "->" + numFrame); // if (numFrame - curFrame == 1) { List relatedPoints = objectCallGraph.getRelatedPoints(); List aliasList = aliasCollector.getAliasList(); @@ -105,7 +110,7 @@ if (curFrameAlias != null) { for (TracePoint rp: relatedPoints) { if (curFrameAlias.getTimeStamp() < rp.getStatement().getTimeStamp() && rp.getStatement().getTimeStamp() < numFrameAlias.getTimeStamp()) { - System.out.println("\r\nLast Animation."); + System.out.println("\r\n" + TAG + ": Last Animation."); doLastAnimation(numFrame, rp); return; } @@ -113,19 +118,18 @@ } doAnimation(curFrame, numFrame); } else if (curFrameAlias != null && numFrameAlias == null) { - System.out.println("\r\nLast Animation."); + System.out.println("\r\n" + TAG + ": Last Animation."); doLastAnimation(numFrame, relatedPoints.get(relatedPoints.size() - 1)); } else { - System.out.println("ERROR : Not exist alias."); + System.out.println(TAG + ": ERROR Not exist alias."); } // } else { - // TODO Considering fast-forwarding animations. + // TODO: Considering fast-forwarding animations. // } } private void doLastAnimation(int numFrame, TracePoint relatedPoint) { - // TODO Implement doLastAnimation to support plural Delta. - outputLog(); + // TODO: Implement doLastAnimation to support plural Delta. curFrame = numFrame; List aliasList = aliasCollector.getAliasList(); Alias prevAlias = aliasList.get(numFrame - 1); @@ -171,8 +175,8 @@ String tgtObjId = null; //Array��List�̂Ƃ��������x����t����i�m���ɕ������Ă�����̂Ƃ�)getSignature->contains("List.get(") || "Map.get(") <�z���C�g���X�g> -// if (methodExec.getSignature().contains("List.add(") || -// methodExec.getSignature().contains("Map.put(")) { +// if (methodExec.getSignature().contains("List.add(") || +// methodExec.getSignature().contains("Map.put(")) { if (calledMethodExec.isCollectionType() && (methodSignature.contains("add(") || methodSignature.contains("set(") @@ -261,82 +265,119 @@ // updateObjectVertices(); // } - // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. - mxgraph.getModel().beginUpdate(); - try { - List meList = new ArrayList<>(methodExecToVertexMap.keySet()); - Collections.reverse(meList); - System.out.println(meList.size()); - for(int i = 0; i < meList.size(); i++) { - String objectId = meList.get(i).getThisObjId(); - ObjectVertex sourceVertexObject = objectToVertexMap.get(objectId); // sourceVertex - MethodExecution me = meList.get(i); - if (nextAlias != null && me.getSignature().equals(nextAlias.getMethodSignature())) break; - if (i != meList.size()-1) { - for(Statement st: me.getStatements()) { - if(st instanceof MethodInvocation) { - MethodExecution calledMethodExec = ((MethodInvocation) st).getCalledMethodExecution(); - String calledObjectId = calledMethodExec.getThisObjId(); - System.out.println(calledObjectId); - if(objectToVertexMap.containsKey(calledObjectId)) { - mxICell calledCell = (mxICell)objectToVertexMap.get(calledObjectId).getCell(); - Point absolutePointCalledCell = getAbsolutePointforCell(calledCell); - System.out.println(objectId + ", " + me.getSignature()); -// objectToVertexMap.get(calledObjectId).resetCellPosition(); -// if (methodExecToVertexMap.get(methodExec).getArguments().contains(objectToVertexMap.get(calledObjectId)) || methodExecToVertexMap.get(methodExec).getLocals().contains(objectToVertexMap.get(calledObjectId))) { -// calledCell.getParent().remove(calledCell); -// calledCell.setParent(mxDefaultParent); -// calledCell.getGeometry().setX(absolutePointCalledCell.getX()); -// calledCell.getGeometry().setY(absolutePointCalledCell.getY()); -// deltaAnimation.setVertexAnimation(calledCell, new mxPoint(objectToVertexMap.get(calledObjectId).getInitialX(), objectToVertexMap.get(calledObjectId).getInitialY())); -// deltaAnimation.startVertexAnimation(); -// } - removeCalledMethodExecutionVertex(sourceVertexObject, me.getCallerMethodExecution(), me); - updateObjectVertices(); -// removeVertexMethodExecution(sourceVertexObject, methodExec); -// update(); - break; + List meList = new ArrayList<>(methodExecToVertexMap.keySet()); + Collections.reverse(meList); + System.out.println(meList.size()); + for(int i = 0; i < meList.size(); i++) { + String objectId = meList.get(i).getThisObjId(); + ObjectVertex sourceVertexObject = objectToVertexMap.get(objectId); // sourceVertex + MethodExecution me = meList.get(i); + if (nextAlias != null && me.getSignature().equals(nextAlias.getMethodSignature())) break; + if (i != meList.size()-1) { + for(Statement st: me.getStatements()) { + if(st instanceof MethodInvocation) { + MethodExecution calledMethodExec = ((MethodInvocation) st).getCalledMethodExecution(); + String calledObjectId = calledMethodExec.getThisObjId(); + System.out.println(calledObjectId); + if(objectToVertexMap.containsKey(calledObjectId)) { + mxICell calledCell = (mxICell)objectToVertexMap.get(calledObjectId).getCell(); + Point2D absolutePointCalledCell = getAbsolutePointforCell(calledCell); + System.out.println(objectId + ", " + me.getSignature()); +// objectToVertexMap.get(calledObjectId).resetCellPosition(); +// if (methodExecToVertexMap.get(methodExec).getArguments().contains(objectToVertexMap.get(calledObjectId)) || methodExecToVertexMap.get(methodExec).getLocals().contains(objectToVertexMap.get(calledObjectId))) { +// calledCell.getParent().remove(calledCell); +// calledCell.setParent(mxDefaultParent); +// calledCell.getGeometry().setX(absolutePointCalledCell.getX()); +// calledCell.getGeometry().setY(absolutePointCalledCell.getY()); +// deltaAnimation.setVertexAnimation(calledCell, new mxPoint(objectToVertexMap.get(calledObjectId).getInitialX(), objectToVertexMap.get(calledObjectId).getInitialY())); +// deltaAnimation.startVertexAnimation(); +// } + removeCalledMethodExecutionVertex(sourceVertexObject, me.getCallerMethodExecution(), me); + updateObjectVertices(); +// removeVertexMethodExecution(sourceVertexObject, methodExec); +// update(); + break; + } + } + } + } else { + outputLog(); + + // Change! + List arguments = new ArrayList<>(methodExecToVertexMap.get(me).getArguments()); + List locals = new ArrayList<>(methodExecToVertexMap.get(me).getLocals()); + if (arguments.size() != 0) { + for (ObjectVertex vo: arguments) { + mxICell cell = (mxICell)vo.getCell(); + Point2D absolutePointCell = getAbsolutePointforCell(cell); + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { +// cell.getParent().remove(cell); +// cell.setParent(mxDefaultParent); + if (!cell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + cell.getParent().remove(cell); + cell.setParent(getMxDefaultParent()); + } + cell.getGeometry().setX(absolutePointCell.getX()); + cell.getGeometry().setY(absolutePointCell.getY()); + } finally { + mxgraph.getModel().endUpdate(); } } - } - } else { - outputLog(); - // Change! - List arguments = new ArrayList<>(methodExecToVertexMap.get(me).getArguments()); - List locals = new ArrayList<>(methodExecToVertexMap.get(me).getLocals()); - if (arguments.size() != 0) { - for (ObjectVertex vo: arguments) { - mxICell cell = (mxICell)vo.getCell(); - Point absolutePointCell = getAbsolutePointforCell(cell); - cell.getParent().remove(cell); - cell.setParent(mxDefaultParent); - cell.getGeometry().setX(absolutePointCell.getX()); - cell.getGeometry().setY(absolutePointCell.getY()); - deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); - deltaAnimation.startVertexAnimation(); - methodExecToVertexMap.get(me).getArguments().remove(vo); - } - }else if (locals.size() != 0) { - for (ObjectVertex vo: locals) { - mxICell cell = (mxICell)vo.getCell(); - Point absolutePointCell = getAbsolutePointforCell(cell); - cell.getParent().remove(cell); - cell.setParent(mxDefaultParent); - cell.getGeometry().setX(absolutePointCell.getX()); - cell.getGeometry().setY(absolutePointCell.getY()); - deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); - deltaAnimation.startVertexAnimation(); - methodExecToVertexMap.get(me).getLocals().remove(vo); - } +// deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); +// deltaAnimation.startVertexAnimation(); +// deltaAnimation.sleepThread(DEFAULT_THREAD_SLEEP_MILLIS); + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(cell, vo.getInitialX(), vo.getInitialY(), threadPoolExecutor); +// vertexAnim.play(); +// sleepMainThread(DEFAULT_THREAD_SLEEP_MILLIS); + vertexAnim.syncPlay(); + methodExecToVertexMap.get(me).getArguments().remove(vo); } - updateObjectVertices(); + }else if (locals.size() != 0) { + for (ObjectVertex vo: locals) { + mxICell cell = (mxICell)vo.getCell(); + Point2D absolutePointCell = getAbsolutePointforCell(cell); + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { +// cell.getParent().remove(cell); +// cell.setParent(mxDefaultParent); + if (!cell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + cell.getParent().remove(cell); + cell.setParent(getMxDefaultParent()); + } + cell.getGeometry().setX(absolutePointCell.getX()); + cell.getGeometry().setY(absolutePointCell.getY()); + } finally { + mxgraph.getModel().endUpdate(); + } + } +// deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); +// deltaAnimation.startVertexAnimation(); +// deltaAnimation.sleepThread(DEFAULT_THREAD_SLEEP_MILLIS); + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(cell, vo.getInitialX(), vo.getInitialY(), threadPoolExecutor); +// vertexAnim.play(); +// sleepMainThread(DEFAULT_THREAD_SLEEP_MILLIS); + vertexAnim.syncPlay(); + methodExecToVertexMap.get(me).getLocals().remove(vo); + } } + updateObjectVertices(); } - } finally { - mxgraph.getModel().endUpdate(); } - update(); + update(); } /** @@ -350,14 +391,14 @@ // Create vertices(mxGraph) and objectVertices. List refList = objectCallGraph.getReferences(); int ocgSize = refList.size(); - double vertexObjWidth = VERTEX_OBJECT_SIZE.getWidth(); - double vertexObjHeight = VERTEX_OBJECT_SIZE.getHeight(); + double vertexObjWidth = DEFAULT_OBJECT_VERTEX_SIZE.getWidth(); + double vertexObjHeight = DEFAULT_OBJECT_VERTEX_SIZE.getHeight(); { MethodExecution coordinator = objectCallGraph.getStartPoints().get(0); String coordinatorObjId = coordinator.getThisObjId(); String coordinatorClassName = coordinator.getThisClassName(); - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, coordinatorObjId, coordinatorClassName, 0, 0, VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), coordinatorObjId, coordinatorClassName, 0, 0, DEFAULT_OBJECT_VERTEX_SIZE.getWidth(), DEFAULT_OBJECT_VERTEX_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. objectToVertexMap.put(coordinatorObjId, new ObjectVertex(coordinatorClassName, vertex, 0, 0)); } @@ -371,7 +412,7 @@ if (srcClassName.contains("[L")) { srcClassName = formatArrayName(srcClassName); } - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), ref.getSrcObjectId(), srcClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, 0, 0)); } // dstSide @@ -381,7 +422,7 @@ if (dstClassName.contains("[L")) { dstClassName = formatArrayName(dstClassName); } - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getDstObjectId(), dstClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), ref.getDstObjectId(), dstClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), vertex, 0, 0)); } } else { @@ -390,7 +431,7 @@ if (srcClassName.contains("[L")) { srcClassName = formatArrayName(srcClassName); } - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), ref.getSrcObjectId(), srcClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, 0, 0)); } if (!objectToVertexMap.containsKey(ref.getDstObjectId())) { @@ -498,9 +539,9 @@ if (srcCell != null && dstCell != null) { // isCreation() System.out.println("makeEdgeObject: " + fieldName + ", " + srcClassName + " (" + srcCell.hashCode() + "), " + " (" + dstCell.hashCode() + ")"/* + ", " + dstClassName*/); // BUG:NullPointerException - Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldName, fieldName, srcCell, dstCell); - Point absPtSrcCell = getAbsolutePointforCell((mxICell)srcCell); - Point absPtDstCell = getAbsolutePointforCell((mxICell)dstCell); + Object edge = mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldName, fieldName, srcCell, dstCell); + Point2D absPtSrcCell = getAbsolutePointforCell((mxICell)srcCell); + Point2D absPtDstCell = getAbsolutePointforCell((mxICell)dstCell); setEdgePoint((mxICell)edge, absPtSrcCell, absPtDstCell); edgeMap.put(srcClassName + "." + fieldName, new Edge(fieldName, TypeName.Reference, edge)); } diff --git a/src/org/ntlab/deltaViewer/DeltaAnimation.java b/src/org/ntlab/deltaViewer/DeltaAnimation.java index 76d9c25..0439c30 100644 --- a/src/org/ntlab/deltaViewer/DeltaAnimation.java +++ b/src/org/ntlab/deltaViewer/DeltaAnimation.java @@ -1,27 +1,18 @@ 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. + * Delta animation for MagnetRON. * * @author Nitta Lab. */ @@ -31,7 +22,6 @@ private mxGraphComponent mxgraphComponent; private Graphics2D graphics2D; - private Timer timer; private static int FINAL_STEP_COUNT = 10; private mxICell sourceCell; @@ -50,7 +40,7 @@ private Dimension updateDimension = new Dimension(); private double scale = 1; - + /** * @param mxgraph * @param mxgraphComponent @@ -67,9 +57,9 @@ public void setScale(double zoomLevel) { this.scale = zoomLevel; } - + /** - * Set to move animation sourcell vertex to targetPoint. + * Set to move animation source cell vertex to targetPoint. * * @param sourceCell Vertex. * @param targetPoint XY coordinates. @@ -78,8 +68,6 @@ 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(); } @@ -99,7 +87,7 @@ } /** - * Set to move animation sourcell vertex clone to targetPoint, reduce edge length. + * Set to move animation source cell vertex clone to targetPoint, reduce edge length. * * @param sourceCell Remove sourceCell vertex clone. * @param targetPoint @@ -148,82 +136,65 @@ } /** - * Start animation to move sourcell vertex to targetPoint for 10 sec. + * Start animation to move source cell vertex to targetPoint for 10sec. */ public void startVertexAnimation() { - timer = new Timer(); - timer.schedule(new TimerTask() { + ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); + scheduledThreadPoolExecutor.scheduleWithFixedDelay(new TimerTask() { int stepCount = 0; @Override public void run() { if(stepCount < FINAL_STEP_COUNT) { updateVertexAnimation(); + System.out.println("updateVertexAnimation: " + stepCount + " " + curPoint.getX()); stepCount++; if(stepCount >= FINAL_STEP_COUNT){ - timer.cancel(); + scheduledThreadPoolExecutor.shutdown(); } } } - }, 0, 100); - try { - Thread.sleep(1001); - } catch (InterruptedException e) { - e.printStackTrace(); - } + }, 0, 100, TimeUnit.MILLISECONDS); +// sleepThread(doThreadSleep); +// try { +// Thread.sleep(1001); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } } /** - * Start stretch(expand) animation of edge from sourcePoint to targetPoint for 10 sec. + * Start stretch(expand) animation of edge from sourcePoint to targetPoint for 10sec. */ public void startExpandEdgeAnimation() { - timer = new Timer(); - timer.schedule(new TimerTask() { + ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); + scheduledThreadPoolExecutor.scheduleWithFixedDelay(new TimerTask() { int stepCount = 0; @Override public void run() { if(stepCount < FINAL_STEP_COUNT) { updateExpandEdgeAnimation(); - System.out.println(stepCount + ": " + curPoint.getX()); + System.out.println("updateExpandEdgeAnimation: " + stepCount + " " + curPoint.getX()); stepCount++; if(stepCount >= FINAL_STEP_COUNT){ - timer.cancel(); + scheduledThreadPoolExecutor.shutdown(); } - } + } } - }, 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); + }, 0, 100, TimeUnit.MILLISECONDS); +// sleepThread(doThreadSleep); // try { // Thread.sleep(1001); // } catch (InterruptedException e) { // e.printStackTrace(); // } + } + + /** + * Start move animation source cell vertex clone to targetPoint, reduce edge length for 10sec. + */ + public void startReductionEdgeAnimation() { ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); scheduledThreadPoolExecutor.scheduleWithFixedDelay(new TimerTask() { int stepCount = 0; @@ -235,46 +206,25 @@ System.out.println(stepCount + ": " + curPoint.getX()); stepCount++; if(stepCount >= FINAL_STEP_COUNT){ - timer.cancel(); scheduledThreadPoolExecutor.shutdown(); } } } }, 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); +// sleepThread(doThreadSleep); // try { -// Thread.sleep(1000); +// System.out.println("Thread.sleep()"); +// Thread.sleep(1001); +// System.out.println("Thread.start()"); // } catch (InterruptedException e) { // e.printStackTrace(); // } + } + /** + * Start animation resize vertex for 10sec. + */ + public void startResizeVertexAnimation() { ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); scheduledThreadPoolExecutor.scheduleWithFixedDelay(new TimerTask() { int stepCount = 0; @@ -286,23 +236,23 @@ System.out.println(stepCount + ": " + curDimension.width); stepCount++; if(stepCount >= FINAL_STEP_COUNT){ - timer.cancel(); scheduledThreadPoolExecutor.shutdown(); } } } }, 0, 100, TimeUnit.MILLISECONDS); - try { - System.out.println("Thread.sleep()"); - Thread.sleep(1001); - System.out.println("Thread.start()"); - } catch (InterruptedException e) { - e.printStackTrace(); - } +// sleepThread(doThreadSleep); +// 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. + * Update animation to move source cell 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. @@ -382,7 +332,6 @@ 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); @@ -393,4 +342,13 @@ } mxgraphComponent.refresh(); } + + public void sleepThread(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } diff --git a/src/org/ntlab/deltaViewer/DeltaGraphAdapter.java b/src/org/ntlab/deltaViewer/DeltaGraphAdapter.java index 86046c3..ae7841d 100644 --- a/src/org/ntlab/deltaViewer/DeltaGraphAdapter.java +++ b/src/org/ntlab/deltaViewer/DeltaGraphAdapter.java @@ -1,17 +1,14 @@ package org.ntlab.deltaViewer; -import java.util.AbstractMap.SimpleEntry; -import java.util.HashMap; -import java.util.Map.Entry; import org.jgrapht.Graph; import org.jgrapht.ext.JGraphXAdapter; -import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.DirectedWeightedPseudograph; import com.mxgraph.model.mxCell; import com.mxgraph.model.mxGeometry; import com.mxgraph.model.mxICell; +import com.mxgraph.model.mxIGraphModel; import com.mxgraph.util.mxConstants; /** @@ -21,10 +18,14 @@ */ public class DeltaGraphAdapter extends JGraphXAdapter { protected Graph graphT; - + private DeltaGraphModel deltaGraphModel; + +// private long refreshedTime = 0L; + public DeltaGraphAdapter(DirectedWeightedPseudograph graphT) { super(graphT); this.graphT = graphT; + this.deltaGraphModel = new DeltaGraphModel(super.getModel()); } /** @@ -161,8 +162,209 @@ } return cell; } + + @Override + public void refresh() { +// long curTime = System.currentTimeMillis(); +// if (curTime - refreshedTime > 5L) { +// super.refresh(); +// refreshedTime = curTime; +// } +// if (((DeltaGraphModel) getModel()).getCount() <= 1) { +// view.reload(); +// repaint(); +// } + super.refresh(); + } public Graph getGraph() { return graphT; } + + @Override + public mxIGraphModel getModel() { + if (deltaGraphModel == null) return super.getModel(); + return deltaGraphModel; + } + + public class DeltaGraphModel implements mxIGraphModel { + + private mxIGraphModel model; + private int count = 0; + + public DeltaGraphModel(mxIGraphModel model) { + this.model = model; + } + + public int getCount() { + return count; + } + + @Override + public Object getRoot() { + return model.getRoot(); + } + + @Override + public Object setRoot(Object root) { + return model.setRoot(root); + } + + @Override + public Object[] cloneCells(Object[] cells, boolean includeChildren) { + return model.cloneCells(cells, includeChildren); + } + + @Override + public boolean isAncestor(Object parent, Object child) { + return model.isAncestor(parent, child); + } + + @Override + public boolean contains(Object cell) { + return model.contains(cell); + } + + @Override + public Object getParent(Object child) { + return model.getParent(child); + } + + @Override + public Object add(Object parent, Object child, int index) { + return model.add(parent, child, index); + } + + @Override + public Object remove(Object cell) { + return model.remove(cell); + } + + @Override + public int getChildCount(Object cell) { + return model.getChildCount(cell); + } + + @Override + public Object getChildAt(Object parent, int index) { + return model.getChildAt(parent, index); + } + + @Override + public Object getTerminal(Object edge, boolean isSource) { + return model.getTerminal(edge, isSource); + } + + @Override + public Object setTerminal(Object edge, Object terminal, boolean isSource) { + return model.setTerminal(edge, terminal, isSource); + } + + @Override + public int getEdgeCount(Object cell) { + return model.getEdgeCount(cell); + } + + @Override + public Object getEdgeAt(Object cell, int index) { + return model.getEdgeAt(cell, index); + } + + @Override + public boolean isVertex(Object cell) { + return model.isVertex(cell); + } + + @Override + public boolean isEdge(Object cell) { + return model.isEdge(cell); + } + + @Override + public boolean isConnectable(Object cell) { + return model.isConnectable(cell); + } + + @Override + public Object getValue(Object cell) { + return model.getValue(cell); + } + + @Override + public Object setValue(Object cell, Object value) { + return model.setValue(cell, value); + } + + @Override + public mxGeometry getGeometry(Object cell) { + return model.getGeometry(cell); + } + + @Override + public mxGeometry setGeometry(Object cell, mxGeometry geometry) { + return model.setGeometry(cell, geometry); + } + + @Override + public String getStyle(Object cell) { + return model.getStyle(cell); + } + + @Override + public String setStyle(Object cell, String style) { + return model.setStyle(cell, style); + } + + @Override + public boolean isCollapsed(Object cell) { + return model.isCollapsed(cell); + } + + @Override + public boolean setCollapsed(Object cell, boolean collapsed) { + return model.setCollapsed(cell, collapsed); + } + + @Override + public boolean isVisible(Object cell) { + return model.isVisible(cell); + } + + @Override + public boolean setVisible(Object cell, boolean visible) { + return model.setVisible(cell, visible); + } + + @Override + public void beginUpdate() { + if (count == 0) { + model.beginUpdate(); + } + count++; + } + + @Override + public void endUpdate() { + count--; + if (count == 0) { + model.endUpdate(); + } + } + + @Override + public void addListener(String eventName, mxIEventListener listener) { + model.addListener(eventName, listener); + } + + @Override + public void removeListener(mxIEventListener listener) { + model.removeListener(listener); + } + + @Override + public void removeListener(mxIEventListener listener, String eventName) { + model.removeListener(listener, eventName); + } + + } } diff --git a/src/org/ntlab/deltaViewer/DeltaViewer.java b/src/org/ntlab/deltaViewer/DeltaViewer.java index 9e218f1..6bbc6de 100644 --- a/src/org/ntlab/deltaViewer/DeltaViewer.java +++ b/src/org/ntlab/deltaViewer/DeltaViewer.java @@ -1,12 +1,12 @@ package org.ntlab.deltaViewer; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Point; +import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.ntlab.animations.MagnetRONAnimation; +import org.ntlab.animations.TranslateAnimation; import org.ntlab.deltaExtractor.Alias; import org.ntlab.deltaExtractor.Delta; import org.ntlab.deltaExtractor.ExtractedStructure; @@ -79,7 +79,7 @@ System.out.println(", " + scale); // scale = 1.5; view.setScale(scale); - deltaAnimation.setScale(scale); +// deltaAnimation.setScale(scale); update(); } @@ -259,7 +259,7 @@ System.out.println(calledObjectId); if(objectToVertexMap.containsKey(calledObjectId)) { mxICell calledCell = (mxICell)objectToVertexMap.get(calledObjectId).getCell(); - Point absolutePointCalledCell = getAbsolutePointforCell(calledCell); + Point2D absolutePointCalledCell = getAbsolutePointforCell(calledCell); System.out.println(objectId + ", " + methodExec.getSignature()); // objectToVertexMap.get(calledObjectId).resetCellPosition(); // if (methodExecToVertexMap.get(methodExec).getArguments().contains(objectToVertexMap.get(calledObjectId)) || methodExecToVertexMap.get(methodExec).getLocals().contains(objectToVertexMap.get(calledObjectId))) { @@ -287,25 +287,35 @@ if (arguments.size() != 0) { for (ObjectVertex vo: arguments) { mxICell cell = (mxICell)vo.getCell(); - Point absolutePointCell = getAbsolutePointforCell(cell); + Point2D absolutePointCell = getAbsolutePointforCell(cell); cell.getParent().remove(cell); - cell.setParent(mxDefaultParent); + cell.setParent(getMxDefaultParent()); cell.getGeometry().setX(absolutePointCell.getX()); cell.getGeometry().setY(absolutePointCell.getY()); - deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); - deltaAnimation.startVertexAnimation(); +// deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); +// deltaAnimation.startVertexAnimation(); + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(cell, vo.getInitialX(), vo.getInitialY(), threadPoolExecutor); + vertexAnim.play(); methodExecToVertexMap.get(methodExec).getArguments().remove(vo); } }else if (locals.size() != 0) { for (ObjectVertex vo: locals) { mxICell cell = (mxICell)vo.getCell(); - Point absolutePointCell = getAbsolutePointforCell(cell); + Point2D absolutePointCell = getAbsolutePointforCell(cell); cell.getParent().remove(cell); - cell.setParent(mxDefaultParent); + cell.setParent(getMxDefaultParent()); cell.getGeometry().setX(absolutePointCell.getX()); cell.getGeometry().setY(absolutePointCell.getY()); - deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); - deltaAnimation.startVertexAnimation(); +// deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); +// deltaAnimation.startVertexAnimation(); + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(cell, vo.getInitialX(), vo.getInitialY(), threadPoolExecutor); + vertexAnim.play(); methodExecToVertexMap.get(methodExec).getLocals().remove(vo); } } @@ -347,7 +357,7 @@ System.out.println("coordinator: " + coordinatorClassName + ", " + coordinatorObjId); coordinatorPoint.setX(coordinatorPoint.getX() + time * 2); xCor += time * 2; - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, coordinatorObjId, coordinatorClassName, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), coordinatorObjId, coordinatorClassName, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)), DEFAULT_OBJECT_VERTEX_SIZE.getWidth(), DEFAULT_OBJECT_VERTEX_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. objectToVertexMap.put(coordinatorObjId, new ObjectVertex(coordinatorClassName, vertex, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)))); srcSideSize++; } @@ -358,7 +368,7 @@ if (srcClassName.contains("[L")) { srcClassName = formatArrayName(srcClassName); } - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), ref.getSrcObjectId(), srcClassName, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)), DEFAULT_OBJECT_VERTEX_SIZE.getWidth(), DEFAULT_OBJECT_VERTEX_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)))); } if (!objectToVertexMap.containsKey(ref.getDstObjectId())) { @@ -367,7 +377,7 @@ if (dstClassName.contains("[L")) { dstClassName = formatArrayName(dstClassName); } - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getDstObjectId(), dstClassName, xCor + (time * (srcSideSize - i)), yCor + (time * (srcSideSize - i)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), ref.getDstObjectId(), dstClassName, xCor + (time * (srcSideSize - i)), yCor + (time * (srcSideSize - i)), DEFAULT_OBJECT_VERTEX_SIZE.getWidth(), DEFAULT_OBJECT_VERTEX_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), vertex, xCor + (time * (srcSideSize - i)), yCor + (time * (srcSideSize - i)))); } } else { @@ -375,7 +385,7 @@ if (srcClassName.contains("[L")) { srcClassName = formatArrayName(srcClassName); } - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), ref.getSrcObjectId(), srcClassName, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)), DEFAULT_OBJECT_VERTEX_SIZE.getWidth(), DEFAULT_OBJECT_VERTEX_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)))); objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), null, xCor + (time * (srcSideSize - i)), yCor + (time * (srcSideSize - i)))); } @@ -391,7 +401,7 @@ coordinatorPoint.setX(coordinatorPoint.getX() + time * 2); xCor += time * 2; System.out.println(coordinatorPoint.getX() + ", " + xCor); - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, coordinatorObjId, coordinatorClassName, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), coordinatorObjId, coordinatorClassName, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)), DEFAULT_OBJECT_VERTEX_SIZE.getWidth(), DEFAULT_OBJECT_VERTEX_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. objectToVertexMap.put(coordinatorObjId, new ObjectVertex(coordinatorClassName, vertex, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)))); dstSideSize++; } @@ -402,7 +412,7 @@ if (srcClassName.contains("[L")) { srcClassName = formatArrayName(srcClassName); } - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), ref.getSrcObjectId(), srcClassName, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)), DEFAULT_OBJECT_VERTEX_SIZE.getWidth(), DEFAULT_OBJECT_VERTEX_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)))); cnt++; } @@ -411,7 +421,7 @@ if (dstClassName.contains("[L")) { dstClassName = formatArrayName(dstClassName); } - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getDstObjectId(), dstClassName, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. + Object vertex = mxgraph.insertDeltaVertex(getMxDefaultParent(), ref.getDstObjectId(), dstClassName, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)), DEFAULT_OBJECT_VERTEX_SIZE.getWidth(), DEFAULT_OBJECT_VERTEX_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), vertex, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)))); } } else { @@ -567,9 +577,9 @@ if (srcCell != null && dstCell != null) { // isCreation() System.out.println("makeEdgeObject: " + fieldName + ", " + srcClassName + " (" + srcCell.hashCode() + "), " + " (" + dstCell.hashCode() + ")"/* + ", " + dstClassName*/); // BUG:NullPointerException - Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldName, fieldName, srcCell, dstCell); - Point absPtSrcCell = getAbsolutePointforCell((mxICell)srcCell); - Point absPtDstCell = getAbsolutePointforCell((mxICell)dstCell); + Object edge = mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldName, fieldName, srcCell, dstCell); + Point2D absPtSrcCell = getAbsolutePointforCell((mxICell)srcCell); + Point2D absPtDstCell = getAbsolutePointforCell((mxICell)dstCell); setEdgePoint((mxICell)edge, absPtSrcCell, absPtDstCell); edgeMap.put(srcClassName + "." + fieldName, new Edge(fieldName, TypeName.Reference, edge)); } diff --git a/src/org/ntlab/deltaViewer/MagnetRONScheduledThreadPoolExecutor.java b/src/org/ntlab/deltaViewer/MagnetRONScheduledThreadPoolExecutor.java new file mode 100644 index 0000000..9768f62 --- /dev/null +++ b/src/org/ntlab/deltaViewer/MagnetRONScheduledThreadPoolExecutor.java @@ -0,0 +1,57 @@ +package org.ntlab.deltaViewer; + +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +/** + * + * + * @author Nitta Lab. + */ +public class MagnetRONScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor { + + private boolean isPaused; + private ReentrantLock pauseLock = new ReentrantLock(); + private Condition unpaused = pauseLock.newCondition(); + + public MagnetRONScheduledThreadPoolExecutor(int corePoolSize) { + super(corePoolSize); + } + + protected void beforeExecute(Thread t, Runnable r) { + super.beforeExecute(t, r); + pauseLock.lock(); + try { + while (isPaused) unpaused.await(); + } catch (InterruptedException ie) { + t.interrupt(); + } finally { + pauseLock.unlock(); + } + } + + public void stop() { + super.shutdown(); + } + + public void pause() { + pauseLock.lock(); + try { + isPaused = true; + } finally { + pauseLock.unlock(); + } + } + + public void resume() { + pauseLock.lock(); + try { + isPaused = false; + unpaused.signalAll(); + } finally { + pauseLock.unlock(); + } + } + +} diff --git a/src/org/ntlab/deltaViewer/MagnetRONViewer.java b/src/org/ntlab/deltaViewer/MagnetRONViewer.java index 287aefa..560da96 100644 --- a/src/org/ntlab/deltaViewer/MagnetRONViewer.java +++ b/src/org/ntlab/deltaViewer/MagnetRONViewer.java @@ -3,8 +3,11 @@ import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.Point; +import java.awt.event.ActionListener; +import java.awt.geom.Dimension2D; import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.awt.geom.Point2D.Double; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collections; @@ -13,11 +16,15 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.ThreadPoolExecutor; import javax.swing.JPanel; import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.DirectedWeightedPseudograph; +import org.ntlab.animations.MagnetRONAnimation; +import org.ntlab.animations.TranslateAnimation; +import org.ntlab.animations.VertexResizeAnimation; import org.ntlab.deltaExtractor.Alias; import org.ntlab.deltaExtractor.IAliasCollector; import org.ntlab.deltaExtractor.Alias.AliasType; @@ -42,13 +49,26 @@ import com.mxgraph.util.mxUtils; import com.mxgraph.view.mxCellState; -abstract public class MagnetRONViewer extends JPanel { +/** - protected static Dimension DEFAULT_SIZE = new Dimension(1300, 700); + * + * @author Nitta Lab. + */ +public abstract class MagnetRONViewer extends JPanel { + + private static final long serialVersionUID = -6828987937804142956L; + + // Test code (will be deleted) + private static final String TAG = MagnetRONViewer.class.getSimpleName(); + + protected static Dimension DEFAULT_WINDOW_SIZE = new Dimension(1300, 700); protected static String WINDOW_TITLE = "Delta Viewer"; - protected static Dimension VERTEX_OBJECT_SIZE = new Dimension(70, 70); - protected static Dimension VERTEX_METHOD_EXECUTION_SIZE = new Dimension(55, 20); + protected static Dimension DEFAULT_OBJECT_VERTEX_SIZE = new Dimension(70, 70); + protected static Dimension DEFAULT_METHOD_EXECUTION_VERTEX_SIZE = new Dimension(55, 20); + + protected static long DEFAULT_THREAD_SLEEP_MILLIS = 1100L; + protected static long POSTPONE_ANIMATION_MILLIS = 250L; protected IAliasCollector aliasCollector; @@ -61,9 +81,10 @@ protected mxICell mxDefaultParent; protected mxGraphComponent mxgraphComponent; + protected ThreadPoolExecutor threadPoolExecutor; protected DeltaAnimation deltaAnimation; protected int curFrame = 0; - + public MagnetRONViewer() { mxgraph = new DeltaGraphAdapter(new DirectedWeightedPseudograph(DefaultEdge.class)); mxDefaultParent = (mxCell)mxgraph.getDefaultParent(); @@ -72,43 +93,45 @@ return new CurvedCanvas(this); } }; - deltaAnimation = new DeltaAnimation(mxgraph, mxgraphComponent); - mxgraphComponent.setPreferredSize(DEFAULT_SIZE); + + deltaAnimation = new DeltaAnimation(mxgraph, getGraphComponent()); + threadPoolExecutor = new MagnetRONScheduledThreadPoolExecutor(2); + getGraphComponent().setPreferredSize(DEFAULT_WINDOW_SIZE); setLayout(new BorderLayout()); - add(mxgraphComponent, BorderLayout.CENTER); + add(getGraphComponent(), BorderLayout.CENTER); } + public mxICell getMxDefaultParent() { + return mxDefaultParent; + } + public mxGraphComponent getGraphComponent() { return mxgraphComponent; } public void clear() { mxgraph.getModel().beginUpdate(); - try { - System.out.println("Clear: "); - for (ObjectVertex ov: objectToVertexMap.values()) { - mxICell ovCell = (mxICell)ov.getCell(); - if (ovCell != null) { - if (!ovCell.getParent().equals(mxDefaultParent)) { - // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. - ovCell.getParent().remove(ovCell); - ovCell.setParent(mxDefaultParent); + synchronized (mxgraph.getModel()) { + try { + for (ObjectVertex ov: objectToVertexMap.values()) { + mxICell ovCell = (mxICell)ov.getCell(); + if (ovCell != null) { + if (!ovCell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + ovCell.getParent().remove(ovCell); + ovCell.setParent(getMxDefaultParent()); + } } } + mxgraph.removeCells(mxgraph.getChildVertices(getMxDefaultParent())); + } finally { + mxgraph.getModel().endUpdate(); } - } finally { - mxgraph.getModel().endUpdate(); } + curFrame = 0; objectToVertexMap.clear(); methodExecToVertexMap.clear(); edgeMap.clear(); - curFrame = 0; - mxgraph.getModel().beginUpdate(); - try { - mxgraph.removeCells(mxgraph.getChildVertices(mxDefaultParent)); - } finally { - mxgraph.getModel().endUpdate(); - } } abstract public void initAnimation(); @@ -116,14 +139,14 @@ /** * Step to animation of specified alias. * - * @param alias Alias type and occurrence point etc. + * @param alias: alias type and occurrence point etc. */ abstract public void stepToAnimation(Alias alias); /** * Parent : Step to animation of specified numFrame. * - * @param numFrame Current animation frame. + * @param numFrame: current animation frame */ abstract public void stepToAnimation(int numFrame); @@ -137,8 +160,8 @@ for (int i = fromFrame; i <= toFrame; i++) { List aliasList = new ArrayList<>(aliasCollector.getAliasList()); Alias alias = aliasList.get(i); - System.out.println("\r\n" + i + ": " + alias.getAliasType().toString()); - System.out.println(alias.getObjectId() + ", " + alias.getMethodSignature() + " l." + alias.getLineNo()); + // Test code (will be deleted) + System.out.println("\r\n" + TAG + ": Frame=" + i + ", aliasType=" + alias.getAliasType().toString() + ", objectId=" + alias.getObjectId() + ", methodSignature=" + alias.getMethodSignature() + ", l." + alias.getLineNo()); switch(alias.getAliasType()) { case RETURN_VALUE: moveObjectVertex(alias); @@ -150,7 +173,7 @@ update(); break; case CONSTRACTOR_INVOCATION: - // TODO When called after RECEIVER. + // TODO: Confirm the program behavior when called after RECEIVER. createObjectVertexOnConstractor(alias); createMethodExecutionVertex(alias.getObjectId(), ((MethodInvocation)alias.getOccurrencePoint().getStatement()).getCallerSideMethodName(), ((MethodInvocation)alias.getOccurrencePoint().getStatement()).getCalledMethodExecution()); update(); @@ -172,7 +195,7 @@ } break; case RECEIVER: - // Make VertexMethodExecution of called method execution. + // Make {@code MethodExecutionVertex} of called method execution. MethodExecution calledMethodExec = ((MethodInvocation) alias.getOccurrencePoint().getStatement()).getCalledMethodExecution(); if (!methodExecToVertexMap.containsKey(calledMethodExec)) { MethodExecution methodExec = alias.getMethodExecution(); @@ -189,47 +212,62 @@ break; } curFrame = i + 1; - outputLog(); } } /** - * Create ObjectVertex when CONSTRACTOR_INVOCATION. + * Create {@code ObjectVertex} when CONSTRACTOR_INVOCATION. + * * @param alias */ protected void createObjectVertexOnConstractor(Alias alias) { ObjectVertex objectVertex = objectToVertexMap.get(alias.getObjectId()); - String sourceObjId = alias.getMethodExecution().getThisObjId(); - mxICell sourceCell = (mxICell)objectToVertexMap.get(sourceObjId).getCell(); - double sourceWidth = sourceCell.getGeometry().getWidth(); - double sourceHeight = sourceCell.getGeometry().getHeight(); - double overlapWidth = sourceWidth * Math.sqrt(2) * 0.1; - double overlapHeight = sourceHeight - (sourceHeight * Math.sqrt(2) * 0.1); - MethodInvocation methodInvocation; + MethodExecution methodExec = alias.getMethodExecution(); + String srcObjId = alias.getMethodExecution().getThisObjId(); + mxICell srcCell = (mxICell)objectToVertexMap.get(srcObjId).getCell(); + double srcWidth = srcCell.getGeometry().getWidth(); + double srcHeight = srcCell.getGeometry().getHeight(); + double overlapWidth = srcWidth * Math.sqrt(2) * 0.1; + double overlapHeight = srcHeight - (srcHeight * Math.sqrt(2) * 0.1); + Point2D srcCellAbsPt = getAbsolutePointforCell(srcCell); + MethodInvocation methodInv; String fieldName = null; - if (!alias.getMethodExecution().isCollectionType() && alias.getOccurrencePoint().getStatement() != null) { - methodInvocation = (MethodInvocation)alias.getOccurrencePoint().getStatement(); - fieldName = methodInvocation.getCallerSideMethodName(); + if (!methodExec.isCollectionType() + && alias.getOccurrencePoint().getStatement() != null) { + methodInv = (MethodInvocation)alias.getOccurrencePoint().getStatement(); + fieldName = methodInv.getCallerSideMethodName(); } - Point absPtSrcCell = getAbsolutePointforCell(sourceCell); + mxICell ovCell; + MagnetRONAnimation.waitAnimationEnd(); mxgraph.getModel().beginUpdate(); - try { - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, alias.getObjectId(), objectVertex.getLabel(), absPtSrcCell.getX() + overlapWidth, absPtSrcCell.getY() + overlapHeight, VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. -// Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, objectVertex.getLabel(), objectVertex.getLabel(), absPtSrcCell.getX() + overlapWidth, absPtSrcCell.getY() + overlapHeight, VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. - objectVertex.setCell(vertex); - Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldName, null, sourceCell, vertex); - setEdgePoint((mxCell)edge, absPtSrcCell, objectVertex.getInitialPoint()); - edgeMap.put(alias.getMethodExecution().getThisClassName() + "." + fieldName, new Edge(fieldName, TypeName.Create, edge)); - setCellsStyle(); - deltaAnimation.setVertexAnimation((mxICell)vertex, new mxPoint(objectVertex.getInitialX(), objectVertex.getInitialY())); - deltaAnimation.startVertexAnimation(); - } finally { - mxgraph.getModel().endUpdate(); + synchronized (mxgraph.getModel()) { + try { + // Creates a white cell of {@code ObjectVertex}. + ovCell = + (mxICell) mxgraph.insertDeltaVertex(getMxDefaultParent(), alias.getObjectId(), objectVertex.getLabel(), + srcCellAbsPt.getX() + overlapWidth, srcCellAbsPt.getY() + overlapHeight, + DEFAULT_OBJECT_VERTEX_SIZE.getWidth(), DEFAULT_OBJECT_VERTEX_SIZE.getHeight(), + "fillColor=white"); + objectVertex.setCell(ovCell); + mxICell edge = (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldName, null, srcCell, ovCell); + // setEdgePoint((mxCell)edge, srcCellAbsPt, objectVertex.getInitialPoint()); + edgeMap.put(methodExec.getThisClassName() + "." + fieldName, new Edge(fieldName, TypeName.Create, edge)); + // setCellsStyle(); + update(); + } finally { + mxgraph.getModel().endUpdate(); + } } + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(ovCell, objectVertex.getX(), objectVertex.getY(), threadPoolExecutor); + vertexAnim.syncPlay(); } /** - * Create ObjectVertex when CONSTRACTOR_INVOCATION is preceded by FORMAL_PARAMETER. + * Create {@code ObjectVertex} when CONSTRACTOR_INVOCATION is preceded by FORMAL_PARAMETER. + * * @param alias */ protected void createObjectVertexOnConstractorByFormalParameter(Alias alias) { @@ -241,840 +279,1079 @@ double srcHeight = srcCell.getGeometry().getHeight(); double overlapWidth = srcWidth * Math.sqrt(2) * 0.1; double overlapHeight = srcHeight - (srcHeight * Math.sqrt(2) * 0.1); - Point absPtSrcCell = getAbsolutePointforCell(srcCell); + Point2D srcCellAbsPt = getAbsolutePointforCell(srcCell); MethodInvocation methodInv; String fieldName = null; if (!methodExec.isCollectionType() && alias.getOccurrencePoint().getStatement() != null) { methodInv = (MethodInvocation)alias.getOccurrencePoint().getStatement(); fieldName = methodInv.getCallerSideMethodName(); } + mxICell ovCell; mxgraph.getModel().beginUpdate(); - try { - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, objectVertex.getLabel(), objectVertex.getLabel(), absPtSrcCell.getX() + overlapWidth, absPtSrcCell.getY() + overlapHeight, VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. - objectVertex.setCell(vertex); - Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldName, null, srcCell, vertex); - setEdgePoint((mxCell)edge, absPtSrcCell, objectVertex.getInitialPoint()); - edgeMap.put(methodExec.getThisClassName() + "." + fieldName, new Edge(fieldName, TypeName.Create, edge)); - setCellsStyle(); - deltaAnimation.setVertexAnimation((mxICell)vertex, new mxPoint(objectVertex.getInitialX(), objectVertex.getInitialY())); - deltaAnimation.startVertexAnimation(); - } finally { - mxgraph.getModel().endUpdate(); - } - } - - protected void createObjectRefrence(FieldUpdate fieldUpdateStatement, String fieldName) { - String sourceObjectId = fieldUpdateStatement.getContainerObjId(); - String targetObjectId = fieldUpdateStatement.getValueObjId(); - mxICell sourceCell = (mxICell)objectToVertexMap.get(sourceObjectId).getCell(); - mxICell targetCell = (mxICell)objectToVertexMap.get(targetObjectId).getCell(); - Point absolutePointTargetCell = getAbsolutePointforCell(targetCell); - - targetCell.getParent().remove(targetCell); - targetCell.setParent(mxDefaultParent); - targetCell.getGeometry().setX(absolutePointTargetCell.getX()); - targetCell.getGeometry().setY(absolutePointTargetCell.getY()); - Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldUpdateStatement.getFieldName(), fieldName, objectToVertexMap.get(sourceObjectId).getCell(), objectToVertexMap.get(targetObjectId).getCell()); -// ((mxCell)edge).setStyle("exitX=0;exitY=0.5;exitPerimeter=1;entryX=1;entryY=0.5;entryPerimeter=1;strokeColor=red;"); - ((mxCell)edge).setStyle("strokeColor=red;"); -// mxgraph.orderCells(true, new Object[] {edge}); - edgeMap.put(fieldUpdateStatement.getFieldName(), new Edge(fieldName, TypeName.Reference, edge)); - // System.out.println("last" + objectToVertexMap.get(targetObjectId).getInitialX() + ", " + objectToVertexMap.get(targetObjectId).getInitialY()); - deltaAnimation.setVertexAnimation(targetCell, new mxPoint(objectToVertexMap.get(targetObjectId).getInitialX(), objectToVertexMap.get(targetObjectId).getInitialY())); - deltaAnimation.startVertexAnimation(); - targetCell.getGeometry().setX(objectToVertexMap.get(targetObjectId).getInitialX()); - targetCell.getGeometry().setY(objectToVertexMap.get(targetObjectId).getInitialY()); - } - - protected void createObjectRefrence(String srcClassName, String srcObjId, String tgtObjId) { - mxICell targetCell; -// if (objectToVertexMap.containsKey(targetObjId)) { - targetCell = (mxICell)objectToVertexMap.get(tgtObjId).getCell(); -// } else { -// targetObjId = methodExec.getCallerMethodExecution().getArguments().get(0).getId(); -// targetCell = (mxICell)objectToVertexMap.get(targetObjId).getCell(); -// } - Point absolutePointTargetCell = getAbsolutePointforCell(targetCell); - - // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. - mxgraph.getModel().beginUpdate(); - try { - targetCell.getParent().remove(targetCell); - targetCell.setParent(mxDefaultParent); - targetCell.getGeometry().setX(absolutePointTargetCell.getX()); - targetCell.getGeometry().setY(absolutePointTargetCell.getY()); - Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, tgtObjId, null, objectToVertexMap.get(srcObjId).getCell(), objectToVertexMap.get(tgtObjId).getCell()); -// ((mxCell)edge).setStyle("exitX=0;exitY=0.5;exitPerimeter=1;entryX=1;entryY=0.5;entryPerimeter=1;strokeColor=red;"); - ((mxCell)edge).setStyle("strokeColor=red;"); -// mxgraph.orderCells(true, new Object[] {edge}); - edgeMap.put(tgtObjId, new Edge(null, TypeName.Reference, edge)); -// System.out.println("last" + objectToVertexMap.get(targetObjectId).getInitialX() + ", " + objectToVertexMap.get(targetObjectId).getInitialY()); - deltaAnimation.setVertexAnimation(targetCell, new mxPoint(objectToVertexMap.get(tgtObjId).getInitialX(), objectToVertexMap.get(tgtObjId).getInitialY())); - deltaAnimation.startVertexAnimation(); - targetCell.getGeometry().setX(objectToVertexMap.get(tgtObjId).getInitialX()); - targetCell.getGeometry().setY(objectToVertexMap.get(tgtObjId).getInitialY()); - } finally { - mxgraph.getModel().endUpdate(); + synchronized (mxgraph.getModel()) { + try { + // Creates a white cell of {@code ObjectVertex}. + ovCell = + (mxICell) mxgraph.insertDeltaVertex(getMxDefaultParent(), objectVertex.getLabel(), objectVertex.getLabel(), + srcCellAbsPt.getX() + overlapWidth, srcCellAbsPt.getY() + overlapHeight, + DEFAULT_OBJECT_VERTEX_SIZE.getWidth(), DEFAULT_OBJECT_VERTEX_SIZE.getHeight(), + "fillColor=white"); + objectVertex.setCell(ovCell); + mxICell edge = (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldName, null, srcCell, ovCell); + setEdgePoint(edge, srcCellAbsPt, objectVertex.getInitialPoint()); + edgeMap.put(methodExec.getThisClassName() + "." + fieldName, new Edge(fieldName, TypeName.Create, edge)); + // setCellsStyle(); + update(); + } finally { + mxgraph.getModel().endUpdate(); + } } - - System.out.println("rTHIS " + srcClassName + ", " + tgtObjId); + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(ovCell, objectVertex.getInitialX(), objectVertex.getInitialY(), threadPoolExecutor); + vertexAnim.syncPlay(); } /** - * SourceVertex move targetVertex. + * + * @param fieldUpdateStatement + * @param fieldName + */ + protected void createObjectRefrence(FieldUpdate fieldUpdateStatement, String fieldName) { + String srcObjId = fieldUpdateStatement.getContainerObjId(); + String dstObjId = fieldUpdateStatement.getValueObjId(); + ObjectVertex dstObjVertex = objectToVertexMap.get(dstObjId); + mxICell dstCell = (mxICell)dstObjVertex.getCell(); + Point2D dstCellAbsPt = getAbsolutePointforCell(dstCell); + + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + if (!dstCell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + dstCell.getParent().remove(dstCell); + dstCell.setParent(getMxDefaultParent()); + } + dstCell.getGeometry().setX(dstCellAbsPt.getX()); + dstCell.getGeometry().setY(dstCellAbsPt.getY()); + mxICell edge = + (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldUpdateStatement.getFieldName(), fieldName, + objectToVertexMap.get(srcObjId).getCell(), objectToVertexMap.get(dstObjId).getCell()); + edge.setStyle("strokeColor=red;"); +// mxgraph.orderCells(true, new Object[] {edge}); + edgeMap.put(fieldUpdateStatement.getFieldName(), new Edge(fieldName, TypeName.Reference, edge)); + } finally { + mxgraph.getModel().endUpdate(); + } + } + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(dstCell, dstObjVertex.getInitialX(), dstObjVertex.getInitialY(), threadPoolExecutor); + vertexAnim.syncPlay(); + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + dstCell.getGeometry().setX(dstObjVertex.getInitialX()); + dstCell.getGeometry().setY(dstObjVertex.getInitialY()); + } finally { + mxgraph.getModel().endUpdate(); + } + } + } + + /** + * + * @param sourceClassName + * @param sourceObjectId + * @param destinationObjectId + */ + protected void createObjectRefrence(String sourceClassName, String sourceObjectId, String destinationObjectId) { + ObjectVertex dstObjVertex = objectToVertexMap.get(destinationObjectId); + mxICell dstCell = (mxICell)dstObjVertex.getCell(); + Point2D dstCellAbsPt = getAbsolutePointforCell(dstCell); + + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + if (!dstCell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + dstCell.getParent().remove(dstCell); + dstCell.setParent(getMxDefaultParent()); + } + dstCell.getGeometry().setX(dstCellAbsPt.getX()); + dstCell.getGeometry().setY(dstCellAbsPt.getY()); + mxICell edge = + (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), destinationObjectId, null, + objectToVertexMap.get(sourceObjectId).getCell(), objectToVertexMap.get(destinationObjectId).getCell()); + edge.setStyle("strokeColor=red;"); + edgeMap.put(destinationObjectId, new Edge(null, TypeName.Reference, edge)); + } finally { + mxgraph.getModel().endUpdate(); + } + } + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(dstCell, dstObjVertex.getInitialX(), dstObjVertex.getInitialY(), threadPoolExecutor); + vertexAnim.syncPlay(); + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + dstCell.getGeometry().setX(dstObjVertex.getInitialX()); + dstCell.getGeometry().setY(dstObjVertex.getInitialY()); + } finally { + mxgraph.getModel().endUpdate(); + } + } + } + + /** + * Move to position of destination {@code ObjectVertex} from source {@code ObjectVertex}. * * @param alias */ protected void moveObjectVertex(Alias alias) { - // sourceVertex - ObjectVertex sourceObjectVertex = objectToVertexMap.get(alias.getObjectId()); + // source {@code ObjectVertex} + ObjectVertex srcObjVertex = objectToVertexMap.get(alias.getObjectId()); if (alias.getMethodExecution().isStatic() && !methodExecToVertexMap.containsKey(alias.getMethodExecution())) { createMethodExecutionVertex(alias.getObjectId(), alias.getMethodExecution().getSignature(), alias.getMethodExecution()); + sleepMainThread(POSTPONE_ANIMATION_MILLIS); } - // targetVertex - MethodExecutionVertex targetMethodExecVertex = methodExecToVertexMap.get(alias.getMethodExecution()); - System.out.println("moveObjectVertex: " + targetMethodExecVertex); - System.out.println("moveObjectVertex: " + alias.getMethodExecution().isStatic()); - moveObjectVertex(alias, sourceObjectVertex, targetMethodExecVertex); + // destination {@code ObjectVertex} + MethodExecutionVertex dstMethodExecVertex = methodExecToVertexMap.get(alias.getMethodExecution()); + moveObjectVertex(alias, srcObjVertex, dstMethodExecVertex); updateObjectVertices(); } /** - * Parent : Source VertexObject move target VertexMethodExecution. + * Parent: Move to position of destination {@code ObjectVertex} from source {@code ObjectVertex}. * * @param alias - * @param sourceVertexObject Source VertexObject. - * @param targetVertexMethodExec Target VertexMethodExecution. + * @param sourceVertexObject: source {@code ObjectVertex} + * @param destinationVertexMethodExec: destination {@code MethodExecutionVertex} */ - private void moveObjectVertex(Alias alias, ObjectVertex sourceVertexObject, MethodExecutionVertex targetVertexMethodExec) { + private void moveObjectVertex(Alias alias, ObjectVertex sourceObjectVertex, MethodExecutionVertex destinationMethodExecutionVertex) { MethodExecution methodExec = alias.getMethodExecution(); if (alias.getAliasType().equals(AliasType.RETURN_VALUE) || alias.getAliasType().equals(AliasType.METHOD_INVOCATION)) { - if (sourceVertexObject.getCell() == null && methodExec.isCollectionType()) { + if (sourceObjectVertex.getCell() == null && methodExec.isCollectionType()) { if (methodExec.getArguments().isEmpty()) { createObjectVertexOnConstractor(alias); } else { createObjectVertexOnConstractorByFormalParameter(alias); } } - moveLocalObjectVertex(methodExec, sourceVertexObject, targetVertexMethodExec); + if (alias.getAliasType().equals(AliasType.RETURN_VALUE)) { + MagnetRONAnimation.waitAnimationEnd(); + } + moveLocalObjectVertex(methodExec, sourceObjectVertex, destinationMethodExecutionVertex); } else if (alias.getAliasType().equals(AliasType.FORMAL_PARAMETER)) { - moveArgumentObjectVertex(methodExec, sourceVertexObject, targetVertexMethodExec); + moveArgumentObjectVertex(methodExec, sourceObjectVertex, destinationMethodExecutionVertex); } else if (alias.getAliasType().equals(AliasType.ACTUAL_ARGUMENT)) { - moveActualArgumentObjectVertex(methodExec, sourceVertexObject, targetVertexMethodExec); + moveActualArgumentObjectVertex(methodExec, sourceObjectVertex, destinationMethodExecutionVertex); } } /** - * Source VertexObject move target VertexMethodExecution to Local position from caller MethodExecution. + * Move to local position of destination {@code MethodExecutionVertex} from caller {@code MethodExecution} of source {@code ObjectVertex}. * - * @param callerMethodExec Caller MethodExecution. - * @param sourceVertexObject - * @param targetVertexMethodExec + * @param callerMethodExecution: caller {@code MethodExecution} + * @param sourceObjectVertex + * @param destinationMethodExecutionVertex */ - private void moveLocalObjectVertex(MethodExecution callerMethodExec, ObjectVertex sourceVertexObject, MethodExecutionVertex targetVertexMethodExec) { - mxICell sourceCell = (mxICell)sourceVertexObject.getCell(); - mxICell targetCell = (mxICell) targetVertexMethodExec.getCell(); + private void moveLocalObjectVertex(MethodExecution callerMethodExecution, ObjectVertex sourceObjectVertex, MethodExecutionVertex destinationMethodExecutionVertex) { + mxICell srcCell = (mxICell)sourceObjectVertex.getCell(); + mxICell dstCell = (mxICell) destinationMethodExecutionVertex.getCell(); - if (sourceCell == targetCell.getParent()) { - System.out.println("nothing."); + if (srcCell.equals(dstCell.getParent())) { return; } - // Remove sourceVertex from Locals and Arguments Vertex of MethodExecution's Vertex. - if (methodExecToVertexMap.containsKey(callerMethodExec) && methodExecToVertexMap.get(callerMethodExec).getLocals().contains(sourceVertexObject)) { - methodExecToVertexMap.get(callerMethodExec).getLocals().remove(sourceVertexObject); - System.out.println(methodExecToVertexMap.get(callerMethodExec).getLabel() + " :removeLocal: " + sourceVertexObject.getLabel()); + // Remove sourceObjectVertex from Locals and Arguments of MethodExecution's Vertex. + if (methodExecToVertexMap.containsKey(callerMethodExecution) && methodExecToVertexMap.get(callerMethodExecution).getLocals().contains(sourceObjectVertex)) { + methodExecToVertexMap.get(callerMethodExecution).getLocals().remove(sourceObjectVertex); } - if (methodExecToVertexMap.containsKey(callerMethodExec) && methodExecToVertexMap.get(callerMethodExec).getArguments().contains(sourceVertexObject)) { - methodExecToVertexMap.get(callerMethodExec).getArguments().remove(sourceVertexObject); - System.out.println(methodExecToVertexMap.get(callerMethodExec).getLabel() + " :removeArgument: " + sourceVertexObject.getLabel()); + if (methodExecToVertexMap.containsKey(callerMethodExecution) && methodExecToVertexMap.get(callerMethodExecution).getArguments().contains(sourceObjectVertex)) { + methodExecToVertexMap.get(callerMethodExecution).getArguments().remove(sourceObjectVertex); } + int time = destinationMethodExecutionVertex.getLocals().size(); + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. mxgraph.getModel().beginUpdate(); - try { - int time = targetVertexMethodExec.getLocals().size(); - double sourceX = sourceCell.getGeometry().getX(); - double sourceY = sourceCell.getGeometry().getY(); + synchronized (mxgraph.getModel()) { + try { + double srcCellCoordX = srcCell.getGeometry().getX(); + double srcCellCoordY = srcCell.getGeometry().getY(); - // System.out.println(time); + if(srcCell.getParent().getValue() != null) { + Point2D absolutePointSourceCell = getAbsolutePointforCell(srcCell); + srcCellCoordX = absolutePointSourceCell.getX(); + srcCellCoordY = absolutePointSourceCell.getY(); + srcCell.getParent().remove(srcCell); + } - if(sourceCell.getParent().getValue() != null) { - Point absolutePointSourceCell = getAbsolutePointforCell(sourceCell); - sourceX = absolutePointSourceCell.getX(); - sourceY = absolutePointSourceCell.getY(); - sourceCell.getParent().remove(sourceCell); + mxgraph.orderCells(true, new Object[] {srcCell}); + if (srcCell.getParent() == null || !srcCell.getParent().equals(dstCell.getParent())) { + // TODO: Confirm why not need following comment out. +// if (srcCell.getParent() != null) srcCell.getParent().remove(srcCell); + srcCell.setParent(dstCell.getParent()); + dstCell.getParent().insert(srcCell); + } + + Point2D dstCellAbsPt = getAbsolutePointforCell(srcCell.getParent()); + srcCell.getGeometry().setX(srcCellCoordX - dstCellAbsPt.getX()); + srcCell.getGeometry().setY(srcCellCoordY - dstCellAbsPt.getY()); + } finally { + mxgraph.getModel().endUpdate(); } + } - mxgraph.orderCells(true, new Object[] {sourceCell}); - sourceCell.setParent(targetCell.getParent()); - targetCell.getParent().insert(sourceCell); - System.out.println("moveLocalObjectVertex: " + sourceCell.getId() + " (" + sourceCell.hashCode() + ")" + ", " + sourceCell.getParent().getId() + " (" + sourceCell.getParent().hashCode() + ")"); - System.out.println(" " + targetCell.getId() + " (" + targetCell.hashCode() + ")" + ", " + targetCell.getParent().getId() + " (" + targetCell.getParent().hashCode() + ")"); + double srcCellWidth = srcCell.getGeometry().getWidth(); + double dstCellHeight = dstCell.getGeometry().getHeight(); - Point absolutePointTargetCell = getAbsolutePointforCell(sourceCell.getParent()); - sourceCell.getGeometry().setX(sourceX - absolutePointTargetCell.getX()); - sourceCell.getGeometry().setY(sourceY - absolutePointTargetCell.getY()); - - double sourceWidth = sourceCell.getGeometry().getWidth(); - double sourceHeight = sourceCell.getGeometry().getHeight(); - double targetWidth = targetCell.getGeometry().getWidth(); - double targetHeight = targetCell.getGeometry().getHeight(); - double overlapWidth = sourceWidth - (sourceWidth * Math.sqrt(2) * 0.1); - double overlapHeight = sourceHeight - (sourceHeight * Math.sqrt(2) * 0.1); - -// deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - overlapWidth, targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time))); -// deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - overlapWidth + (sourceWidth * time), targetCell.getGeometry().getY() - overlapHeight + sourceHeight)); - deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - (sourceWidth / Math.sqrt(2.5)) + (sourceWidth * time), targetCell.getGeometry().getY() + targetHeight)); - deltaAnimation.startVertexAnimation(); - - sourceCell.setParent(targetCell.getParent()); - targetCell.getParent().insert(sourceCell); -// sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth); -// sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time)); -// sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth + (sourceWidth * time)); -// sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + sourceHeight); - sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - (sourceWidth / Math.sqrt(2.5)) + (sourceWidth * time)); - sourceCell.getGeometry().setY(targetCell.getGeometry().getY() + targetHeight); - targetVertexMethodExec.getLocals().add(sourceVertexObject); - System.out.println("moveLocalObjectVertex: " + targetVertexMethodExec.getLabel() + " :Local: " + sourceVertexObject.getLabel()); - } finally { - mxgraph.getModel().endUpdate(); + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(srcCell, + dstCell.getGeometry().getX() - (srcCellWidth / Math.sqrt(2.5)) + (srcCellWidth * time), dstCell.getGeometry().getY() + dstCellHeight, + threadPoolExecutor); + vertexAnim.syncPlay(); + + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + if (!srcCell.getParent().equals(dstCell.getParent())) { + srcCell.getParent().remove(srcCell); + srcCell.setParent(dstCell.getParent()); + dstCell.getParent().insert(srcCell); + } + srcCell.getGeometry().setX(dstCell.getGeometry().getX() - (srcCellWidth / Math.sqrt(2.5)) + (srcCellWidth * time)); + srcCell.getGeometry().setY(dstCell.getGeometry().getY() + dstCellHeight); + destinationMethodExecutionVertex.getLocals().add(sourceObjectVertex); + } finally { + mxgraph.getModel().endUpdate(); + } } } /** - * Source VertexObject move target VertexMethodExecution to Argument position from MethodExecution. + * Move to position of destination {@code MethodExecutionVertex}'s argument from {@code MethodExecution} of source {@code VertexObject}. * - * @param methodExec MethodExecution. - * @param sourceVertexObject move - * @param targetVertexMethodExec + * @param methodExecution: {@code MethodExecution} + * @param sourceVertexObject: moving {@code VertexObject} + * @param destinationMethodExecutionVertex */ - protected void moveArgumentObjectVertex(MethodExecution methodExec, ObjectVertex sourceVertexObject, MethodExecutionVertex targetVertexMethodExec) { - mxICell sourceCell = (mxICell)sourceVertexObject.getCell(); - mxICell targetCell = (mxICell) targetVertexMethodExec.getCell(); - // mxICell parentTargetMethodExecCell = targetMethodExecCell.getParent(); + protected void moveArgumentObjectVertex(MethodExecution methodExecution, ObjectVertex sourceObjectVertex, MethodExecutionVertex destinationMethodExecutionVertex) { + mxICell srcCell = (mxICell)sourceObjectVertex.getCell(); + mxICell dstCell = (mxICell) destinationMethodExecutionVertex.getCell(); - // Remove sourceVertex from Locals and Arguments Vertex of MethodExecution's Vertex. - MethodExecution callerMethodExecution = methodExec.getCallerMethodExecution(); - if (methodExecToVertexMap.containsKey(callerMethodExecution) && methodExecToVertexMap.get(callerMethodExecution).getLocals().contains(sourceVertexObject)) { - methodExecToVertexMap.get(callerMethodExecution).getLocals().remove(sourceVertexObject); - System.out.println(methodExecToVertexMap.get(callerMethodExecution).getLabel() + " :removeLocal: " + sourceVertexObject.getLabel()); + // Remove source {@code VertexObject} from Locals and Arguments of {@code MethodExecution}'s Vertex. + MethodExecution callerMethodExec = methodExecution.getCallerMethodExecution(); + if (methodExecToVertexMap.containsKey(callerMethodExec) && methodExecToVertexMap.get(callerMethodExec).getLocals().contains(sourceObjectVertex)) { + methodExecToVertexMap.get(callerMethodExec).getLocals().remove(sourceObjectVertex); } - if (methodExecToVertexMap.containsKey(callerMethodExecution) && methodExecToVertexMap.get(callerMethodExecution).getArguments().contains(sourceVertexObject)) { - methodExecToVertexMap.get(callerMethodExecution).getArguments().remove(sourceVertexObject); - System.out.println(methodExecToVertexMap.get(callerMethodExecution).getLabel() + " :removeArgument: " + sourceVertexObject.getLabel()); + if (methodExecToVertexMap.containsKey(callerMethodExec) && methodExecToVertexMap.get(callerMethodExec).getArguments().contains(sourceObjectVertex)) { + methodExecToVertexMap.get(callerMethodExec).getArguments().remove(sourceObjectVertex); } + int time = destinationMethodExecutionVertex.getArguments().size(); + double srcCoordX = srcCell.getGeometry().getX(); + double srcCoordY = srcCell.getGeometry().getY(); + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. mxgraph.getModel().beginUpdate(); - try { - int time = targetVertexMethodExec.getArguments().size(); - double sourceX = sourceCell.getGeometry().getX(); - double sourceY = sourceCell.getGeometry().getY(); + synchronized (mxgraph.getModel()) { + try { + if(srcCell.getParent().getValue() != null) { + Point2D srcCellAbsPt = getAbsolutePointforCell(srcCell); + srcCoordX = srcCellAbsPt.getX(); + srcCoordY = srcCellAbsPt.getY(); + srcCell.getParent().remove(srcCell); + } + } finally { + mxgraph.getModel().endUpdate(); + } + } - // System.out.println(time); - - if(sourceCell.getParent().getValue() != null) { - Point absolutePointSourceCell = getAbsolutePointforCell(sourceCell); - sourceX = absolutePointSourceCell.getX(); - sourceY = absolutePointSourceCell.getY(); - sourceCell.getParent().remove(sourceCell); + if (!isParent(dstCell, srcCell)) { + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + mxgraph.orderCells(true, new Object[] {srcCell}); + if (srcCell.getParent() == null || !srcCell.getParent().equals(dstCell.getParent())) { + // TODO: Confirm why not need following comment out. +// if (srcCell.getParent() != null) srcCell.getParent().remove(srcCell); + srcCell.setParent(dstCell.getParent()); + dstCell.getParent().insert(srcCell); + } + Point2D srcParentCellAbsPt = getAbsolutePointforCell(srcCell.getParent()); + srcCell.getGeometry().setX(srcCoordX - srcParentCellAbsPt.getX()); + srcCell.getGeometry().setY(srcCoordY - srcParentCellAbsPt.getY()); + } finally { + mxgraph.getModel().endUpdate(); + } } - if (!isParent(targetCell, sourceCell)) { - mxgraph.orderCells(true, new Object[] {sourceCell}); - sourceCell.setParent(targetCell.getParent()); - targetCell.getParent().insert(sourceCell); - Point absolutePointSourceParentCell = getAbsolutePointforCell(sourceCell.getParent()); - sourceCell.getGeometry().setX(sourceX - absolutePointSourceParentCell.getX()); - sourceCell.getGeometry().setY(sourceY - absolutePointSourceParentCell.getY()); + double srcCellWidth = srcCell.getGeometry().getWidth(); + double srcCellHeight = srcCell.getGeometry().getHeight(); + double overlapWidth = srcCellWidth - (srcCellWidth * Math.sqrt(2) * 0.1); + double overlapHeight = srcCellHeight - (srcCellHeight * Math.sqrt(2) * 0.1); - double sourceWidth = sourceCell.getGeometry().getWidth(); - double sourceHeight = sourceCell.getGeometry().getHeight(); - double overlapWidth = sourceWidth - (sourceWidth * Math.sqrt(2) * 0.1); - double overlapHeight = sourceHeight - (sourceHeight * Math.sqrt(2) * 0.1); + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(srcCell, + dstCell.getGeometry().getX() - overlapWidth, dstCell.getGeometry().getY() - overlapHeight + (srcCellHeight * time), + threadPoolExecutor); + sleepMainThread(POSTPONE_ANIMATION_MILLIS); + vertexAnim.syncPlay(); - deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - overlapWidth, targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time))); - deltaAnimation.startVertexAnimation(); - - // sourceCell.setParent(targetCell.getParent()); - // targetCell.getParent().insert(sourceCell); - sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth); - sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time)); - targetVertexMethodExec.getArguments().add(sourceVertexObject); - System.out.println("moveArgumentObejctVertex" + targetVertexMethodExec.getLabel() + " :Argument: " + sourceVertexObject.getLabel()); - } else { // �d�l��̃o�O, ���[�v������ - outputLog(); -// try { - // ObjectVertex(sourceCell)�̃N���[������ -// mxICell cloneSourceCell = (mxICell) mxgraph.addCell(sourceCell.clone()); -// -// cloneSourceCell.setStyle("fillColor=#ffffff;opacity=50;shape=ellipse"); -// cloneSourceCell.setId("clone" + cloneSourceCell.getId()); -// cloneSourceCell.setValue(null); -// cloneSourceCell.setParent(sourceCell); -// sourceCell.insert(cloneSourceCell); -// cloneSourceCell.getGeometry().setX(0); -// cloneSourceCell.getGeometry().setX(0); -// cloneSourceCell.getGeometry().setY(0); - - // ����ObjectVertex - Point absPtSourceCell = getAbsolutePointforCell(sourceCell); - Point absPtTargetParentCell = getAbsolutePointforCell(targetCell.getParent()); - - sourceCell.remove(targetCell.getParent()); - targetCell.getParent().setParent(mxDefaultParent); - sourceCell.setParent(targetCell.getParent()); - targetCell.getParent().insert(sourceCell); - - targetCell.getParent().getGeometry().setX(absPtTargetParentCell.getX()); - targetCell.getParent().getGeometry().setY(absPtTargetParentCell.getY()); - sourceCell.getGeometry().setX(absPtSourceCell.getX() - absPtTargetParentCell.getX()); - sourceCell.getGeometry().setY(absPtSourceCell.getY() - absPtTargetParentCell.getY()); - sourceCell.setStyle("opacity=50;shape=ellipse"); - - double sourceWidth = sourceCell.getGeometry().getWidth(); - double sourceHeight = sourceCell.getGeometry().getHeight(); -// double overlapWidth = targetCell.getGeometry().getWidth() / 2; - double overlapWidth = sourceWidth - (sourceWidth * Math.sqrt(2) * 0.1); - double overlapHeight = sourceHeight - (sourceHeight * Math.sqrt(2) * 0.1); - -// deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() + overlapWidth, targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time))); - deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - overlapWidth + (sourceWidth * time), targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time))); - deltaAnimation.startVertexAnimation(); - outputLog(); -// sourceCell.getGeometry().setX(targetCell.getGeometry().getX() + overlapWidth); - sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth + (sourceWidth * time)); - sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time)); - - targetVertexMethodExec.getArguments().add(sourceVertexObject); - -// } catch (CloneNotSupportedException e) { -// e.printStackTrace(); -// } + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + srcCell.getGeometry().setX(dstCell.getGeometry().getX() - overlapWidth); + srcCell.getGeometry().setY(dstCell.getGeometry().getY() - overlapHeight + (srcCellHeight * time)); + } finally { + mxgraph.getModel().endUpdate(); + } } - } finally { - mxgraph.getModel().endUpdate(); + + destinationMethodExecutionVertex.getArguments().add(sourceObjectVertex); + } else { // TODO: �d�l��̃o�O�A���[�v������ + // ���� ObjectVertex + Point2D srcCellAbsPt = getAbsolutePointforCell(srcCell); + Point2D dstParentCellAbsPt = getAbsolutePointforCell(dstCell.getParent()); + + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + if (dstCell.getParent() != null + || dstCell.getParent().getParent() != null + || srcCell.getParent() != null + || !dstCell.getParent().getParent().equals(getMxDefaultParent()) + || !srcCell.getParent().equals(dstCell.getParent())) { + srcCell.remove(dstCell.getParent()); + dstCell.getParent().setParent(getMxDefaultParent()); + // TODO: Confirm why not need following comment out. +// dstCell.getParent().remove(dstCell); + // TODO: Confirm why not need following comment out. +// srcCell.getParent().remove(srcCell); + srcCell.setParent(dstCell.getParent()); + dstCell.getParent().insert(srcCell); + } + + dstCell.getParent().getGeometry().setX(dstParentCellAbsPt.getX()); + dstCell.getParent().getGeometry().setY(dstParentCellAbsPt.getY()); + srcCell.getGeometry().setX(srcCellAbsPt.getX() - dstParentCellAbsPt.getX()); + srcCell.getGeometry().setY(srcCellAbsPt.getY() - dstParentCellAbsPt.getY()); + srcCell.setStyle("opacity=50;shape=ellipse"); + } finally { + mxgraph.getModel().endUpdate(); + } + } + + double srcCellWidth = srcCell.getGeometry().getWidth(); + double srcCellHeight = srcCell.getGeometry().getHeight(); + double overlapWidth = srcCellWidth - (srcCellWidth * Math.sqrt(2) * 0.1); + double overlapHeight = srcCellHeight - (srcCellHeight * Math.sqrt(2) * 0.1); + + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(srcCell, + dstCell.getGeometry().getX() - overlapWidth + (srcCellWidth * time), dstCell.getGeometry().getY() - overlapHeight + (srcCellHeight * time), + threadPoolExecutor); + vertexAnim.syncPlay(); + + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + srcCell.getGeometry().setX(dstCell.getGeometry().getX() - overlapWidth + (srcCellWidth * time)); + srcCell.getGeometry().setY(dstCell.getGeometry().getY() - overlapHeight + (srcCellHeight * time)); + } finally { + mxgraph.getModel().endUpdate(); + } + } + + destinationMethodExecutionVertex.getArguments().add(sourceObjectVertex); } } /** - * Source VertexObject move target VertexMethodExecution to Argument position from MethodExecution. * - * @param methodExec MethodExecution. - * @param sourceVertexObject - * @param targetVertexMethodExec + * @param methodExecution: {@code MethodExecution} + * @param sourceVertexObject: moving {@code VertexObject} + * @param destinationVertexMethodExec */ - private void moveActualArgumentObjectVertex(MethodExecution methodExec, ObjectVertex sourceVertexObject, MethodExecutionVertex targetVertexMethodExec) { - mxICell sourceCell = (mxICell)sourceVertexObject.getCell(); - mxICell targetCell = (mxICell) targetVertexMethodExec.getCell(); - // mxICell parentTargetMethodExecCell = targetMethodExecCell.getParent(); - if (sourceCell == targetCell.getParent()) { - System.out.println("nothing."); + /** + * Move to position of destination {@code MethodExecutionVertex}'s actual argument from {@code MethodExecution} of source {@code VertexObject}. + * + * @param methodExecution: {@code MethodExecution} + * @param sourceObjectVertex + * @param destinationMethodExecutionVertex + */ + private void moveActualArgumentObjectVertex(MethodExecution methodExecution, ObjectVertex sourceObjectVertex, MethodExecutionVertex destinationMethodExecutionVertex) { + mxICell srcCell = (mxICell)sourceObjectVertex.getCell(); + mxICell dstCell = (mxICell) destinationMethodExecutionVertex.getCell(); + + if (srcCell.equals(dstCell.getParent())) { + System.out.println("Nothing to moveActualArgumentObjectVertex()."); return; } - // Remove sourceVertex from Locals and Arguments Vertex of MethodExecution's Vertex. - // MethodExecution callerMethodExecution = methodExec.getCallerMethodExecution(); - System.out.println(methodExec.getSignature()); - System.out.println(sourceVertexObject.getLabel()); - // if (methodExecToVertexMap.containsKey(callerMethodExecution) && methodExecToVertexMap.get(callerMethodExecution).getLocals().contains(sourceVertexObject)) { - // methodExecToVertexMap.get(callerMethodExecution).getLocals().remove(sourceVertexObject); - // System.out.println(methodExecToVertexMap.get(callerMethodExecution).getLabel() + " :removeLocal: " + sourceVertexObject.getLabel()); - // } - // - // if (methodExecToVertexMap.containsKey(callerMethodExecution) && methodExecToVertexMap.get(callerMethodExecution).getArguments().contains(sourceVertexObject)) { - // methodExecToVertexMap.get(callerMethodExecution).getArguments().remove(sourceVertexObject); - // System.out.println(methodExecToVertexMap.get(callerMethodExecution).getLabel() + " :removeArgument: " + sourceVertexObject.getLabel()); - // } - if (methodExecToVertexMap.containsKey(methodExec) && methodExecToVertexMap.get(methodExec).getLocals().contains(sourceVertexObject)) { - methodExecToVertexMap.get(methodExec).getLocals().remove(sourceVertexObject); - System.out.println(methodExecToVertexMap.get(methodExec).getLabel() + " :removeLocal: " + sourceVertexObject.getLabel()); + // Remove sourceVertex from Locals and Arguments of MethodExecution's Vertex. + if (methodExecToVertexMap.containsKey(methodExecution) && methodExecToVertexMap.get(methodExecution).getLocals().contains(sourceObjectVertex)) { + methodExecToVertexMap.get(methodExecution).getLocals().remove(sourceObjectVertex); } - if (methodExecToVertexMap.containsKey(methodExec) && methodExecToVertexMap.get(methodExec).getArguments().contains(sourceVertexObject)) { - methodExecToVertexMap.get(methodExec).getArguments().remove(sourceVertexObject); - System.out.println(methodExecToVertexMap.get(methodExec).getLabel() + " :removeArgument: " + sourceVertexObject.getLabel()); + if (methodExecToVertexMap.containsKey(methodExecution) && methodExecToVertexMap.get(methodExecution).getArguments().contains(sourceObjectVertex)) { + methodExecToVertexMap.get(methodExecution).getArguments().remove(sourceObjectVertex); } + int time = destinationMethodExecutionVertex.getLocals().size(); + double srcCellCoordX = srcCell.getGeometry().getX(); + double srcCellCoordY = srcCell.getGeometry().getY(); + + MagnetRONAnimation.waitAnimationEnd(); + + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + if(srcCell.getParent().getValue() != null) { + Point2D srcCellAbsPt = getAbsolutePointforCell(srcCell); + srcCellCoordX = srcCellAbsPt.getX(); + srcCellCoordY = srcCellAbsPt.getY(); + srcCell.getParent().remove(srcCell); + } + + if (srcCell.getParent() == null || !srcCell.getParent().equals(dstCell.getParent())) { + // TODO: Confirm why not need following comment out. +// if (srcCell.getParent() != null) srcCell.getParent().remove(srcCell); + srcCell.setParent(dstCell.getParent()); + dstCell.getParent().insert(srcCell); + } + Point2D srcParentCellAbsPt = getAbsolutePointforCell(srcCell.getParent()); + srcCell.getGeometry().setX(srcCellCoordX - srcParentCellAbsPt.getX()); + srcCell.getGeometry().setY(srcCellCoordY - srcParentCellAbsPt.getY()); + } finally { + mxgraph.getModel().endUpdate(); + } + } + + double srcCellWidth = srcCell.getGeometry().getWidth(); + double dstCellHeight = dstCell.getGeometry().getHeight(); + Point2D srcCellDstPoint = new Point2D.Double(dstCell.getGeometry().getX() - (srcCellWidth / Math.sqrt(3)) + (srcCellWidth * time), + dstCell.getGeometry().getY() + dstCellHeight); + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(srcCell, srcCellDstPoint.getX(), srcCellDstPoint.getY(), threadPoolExecutor); + vertexAnim.syncPlay(); + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. mxgraph.getModel().beginUpdate(); - try { -// int time = targetVertexMethodExec.getArguments().size(); -// int time = targetVertexMethodExec.getLocals().size() + 1; - int time = targetVertexMethodExec.getLocals().size(); - double sourceX = sourceCell.getGeometry().getX(); - double sourceY = sourceCell.getGeometry().getY(); - - System.out.println(time + ", " + targetVertexMethodExec.getLocals().size()); - // if (time == 0) time = 1; - - if(sourceCell.getParent().getValue() != null) { - Point absolutePointSourceCell = getAbsolutePointforCell(sourceCell); - sourceX = absolutePointSourceCell.getX(); - sourceY = absolutePointSourceCell.getY(); - sourceCell.getParent().remove(sourceCell); + synchronized (mxgraph.getModel()) { + try { + srcCell.getGeometry().setX(srcCellDstPoint.getX()); + srcCell.getGeometry().setY(srcCellDstPoint.getY()); + } finally { + mxgraph.getModel().endUpdate(); } - - sourceCell.setParent(targetCell.getParent()); - targetCell.getParent().insert(sourceCell); - Point absolutePointSourceParentCell = getAbsolutePointforCell(sourceCell.getParent()); - sourceCell.getGeometry().setX(sourceX - absolutePointSourceParentCell.getX()); - sourceCell.getGeometry().setY(sourceY - absolutePointSourceParentCell.getY()); - - double sourceWidth = sourceCell.getGeometry().getWidth(); - double sourceHeight = sourceCell.getGeometry().getHeight(); - double targetWidth = targetCell.getGeometry().getWidth(); - double targetHeight = targetCell.getGeometry().getHeight(); - double overlapWidth = sourceWidth - (sourceWidth * Math.sqrt(2) * 0.1); - double overlapHeight = sourceHeight - (sourceHeight * Math.sqrt(2) * 0.1); - -// deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - overlapWidth, targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time))); - deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - (sourceWidth / Math.sqrt(3)) + (sourceWidth * time), targetCell.getGeometry().getY() + targetHeight)); - deltaAnimation.startVertexAnimation(); -// sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth); -// sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time)); - sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - (sourceWidth / Math.sqrt(3)) + (sourceWidth * time)); - sourceCell.getGeometry().setY(targetCell.getGeometry().getY() + targetHeight); - - targetVertexMethodExec.getArguments().add(sourceVertexObject); - System.out.println("moveActualArgumentObjectVertex: " + targetVertexMethodExec.getLabel() + " :Argument: " + sourceVertexObject.getLabel()); - } finally { - mxgraph.getModel().endUpdate(); } + + destinationMethodExecutionVertex.getArguments().add(sourceObjectVertex); } - /** Update ObjectVertices size and position. */ + /** + * Update size and position of all {@code ObjectVertex}. + */ protected void updateObjectVertices() { - // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology - mxgraph.getModel().beginUpdate(); - try { - for (ObjectVertex objectVertex: objectToVertexMap.values()) { - mxCell objectVertexCell = ((mxCell) objectVertex.getCell()); - if (objectVertexCell != null) { - int time = 0; - for (int i = 0; i < objectVertexCell.getChildCount(); i++) { - if (!(objectVertexCell.getChildAt(i).getId()).contains("clone")) { - time++; + MagnetRONAnimation.waitAnimationEnd(); + for (ObjectVertex ov: objectToVertexMap.values()) { + mxICell ovCell = (mxICell) ov.getCell(); + if (ovCell == null) continue; + Dimension2D curDim = new Dimension((int) ovCell.getGeometry().getWidth(), (int) ovCell.getGeometry().getHeight()); + int sizeScale = 0; + for (int i = 0; i < ovCell.getChildCount(); i++) { + if (!ovCell.getChildAt(i).getId().contains("clone")) sizeScale++; + } + if (sizeScale == 0) sizeScale = 1; + Dimension2D dstDim = + new Dimension((int) DEFAULT_OBJECT_VERTEX_SIZE.getWidth() * sizeScale, + (int) DEFAULT_OBJECT_VERTEX_SIZE.getHeight() * sizeScale); + Point2D dstPt = new Point2D.Double(ovCell.getGeometry().getX(), ovCell.getGeometry().getY()); + + if(!curDim.equals(dstDim)) { + // Test code (will be deleted) + System.out.println(TAG + ": Update size of ObjectVertex " + ovCell.getId() + ". " + curDim.getWidth() + "->" + dstDim.getWidth()); + if (!ovCell.getParent().equals(getMxDefaultParent()) + && (ovCell.getChildCount() != 0 || (curDim.getWidth() > dstDim.getWidth() && curDim.getHeight() > dstDim.getHeight()))) { + double overlapX = (dstDim.getWidth() - curDim.getWidth()) / 2 / Math.sqrt(2); + double overlapY = (dstDim.getHeight() - curDim.getHeight()) / 2 / Math.sqrt(2); + dstPt.setLocation(ovCell.getGeometry().getX() - overlapX, ovCell.getGeometry().getY() + overlapY); + + // If two and over ObjectVertex are arranged side by side as an argument or local, shift the Y coordinate of ObjectVertex slightly. + for (MethodExecutionVertex methodExecVertex: methodExecToVertexMap.values()) { + List locals = methodExecVertex.getLocals(); + if (locals != null && locals.contains(ov) && locals.indexOf(ov) >= 1) { + overlapY = (dstDim.getHeight() - ovCell.getGeometry().getHeight()) / 2; + dstPt.setLocation(dstPt.getX(), ovCell.getGeometry().getY() + overlapY); + break; } - } -// time = countChildVertex(objectVertex); - if (time == 0) { - time = 1; - } - if(objectVertexCell.getGeometry().getWidth() != VERTEX_OBJECT_SIZE.getWidth() * time) { - System.out.println("updateVertexObjectSize: " + objectVertexCell.getGeometry().getWidth() + "->" + VERTEX_OBJECT_SIZE.getWidth() * time+ ", " + objectVertexCell.getId()); - Dimension targetDimension = new Dimension(); - targetDimension.setSize(VERTEX_OBJECT_SIZE.getWidth() * time, VERTEX_OBJECT_SIZE.getHeight() * time); - if (objectVertexCell.getParent() != mxDefaultParent && (objectVertexCell.getChildCount() != 0 || objectVertexCell.getGeometry().getWidth() > VERTEX_OBJECT_SIZE.getWidth() * time)) { - double overlapX = (targetDimension.getWidth() - objectVertexCell.getGeometry().getWidth()) / 2 / Math.sqrt(2); - double overlapY = (targetDimension.getHeight() - objectVertexCell.getGeometry().getHeight()) / 2 / Math.sqrt(2); - System.out.println("updateVertexObjectPosition: " + objectVertexCell.getGeometry().getX() + " - " + overlapX); - mxPoint targetPoint = new mxPoint(objectVertexCell.getGeometry().getX() - overlapX, objectVertexCell.getGeometry().getY() + overlapY); - int idxFromParent = objectVertexCell.getParent().getIndex(objectVertexCell); - if (idxFromParent >= 2) { - overlapY = (targetDimension.getHeight() - objectVertexCell.getGeometry().getHeight()) / 2; - targetPoint.setY(objectVertexCell.getGeometry().getY() + overlapY); - } - for (MethodExecutionVertex methodExecVertex: methodExecToVertexMap.values()) { - List arguments = methodExecVertex.getArguments(); - if (arguments != null && arguments.contains(objectVertex)) { - targetPoint.setY(objectVertexCell.getGeometry().getY() - overlapY); - break; - } - } - deltaAnimation.setVertexAnimation(objectVertexCell, targetPoint); - deltaAnimation.startVertexAnimation(); + List arguments = methodExecVertex.getArguments(); + if (arguments != null && arguments.contains(ov)) { + dstPt.setLocation(dstPt.getX(), ovCell.getGeometry().getY() - overlapY); + break; } - deltaAnimation.setResizeVertexAnimation(objectVertexCell, targetDimension); - deltaAnimation.startResizeVertexAnimation(); } } + dstPt.setLocation(dstPt.getX() - (dstDim.getWidth() - curDim.getWidth()) / 2, dstPt.getY() - (dstDim.getHeight() - curDim.getHeight()) / 2); + // Test code (will be deleted) + System.out.println(TAG + ": Translate " + ovCell.getId() + ". Current point=" + ovCell.getGeometry().getPoint() + ", Destination Point=" + dstPt); + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(ovCell, dstPt.getX(), dstPt.getY(), threadPoolExecutor); + vertexAnim.play(); + MagnetRONAnimation vertexResizeAnim = new VertexResizeAnimation(mxgraph, getGraphComponent()); + vertexResizeAnim.setTotalCycleCount(10); + vertexResizeAnim.setDelay(100); + vertexResizeAnim.init(ovCell, dstDim.getWidth(), dstDim.getHeight(), threadPoolExecutor); + vertexResizeAnim.play(); + for (int i = 0; i < ovCell.getChildCount(); i++) { + mxICell childCell = ovCell.getChildAt(i); + double childCellCurX = childCell.getGeometry().getX(); + double childCellCurY = childCell.getGeometry().getY(); + Point2D childDstPt = + new Point2D.Double(childCellCurX + (dstDim.getWidth() - curDim.getWidth()) / 2, + childCellCurY + (dstDim.getHeight() - curDim.getHeight()) / 2); + // Test code (will be deleted) + System.out.println(TAG + ": Translate " + childCell.getId() + " of " + ovCell.getId() + ". Current point=" + childCell.getGeometry().getPoint() + ", Destination Point=" + childDstPt); + MagnetRONAnimation childVertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + childVertexAnim.setTotalCycleCount(10); + childVertexAnim.setDelay(100); + childVertexAnim.init(childCell, childDstPt.getX(), childDstPt.getY(), threadPoolExecutor); + childVertexAnim.play(); + } + MagnetRONAnimation.waitAnimationEnd(); } - } finally { - mxgraph.getModel().endUpdate(); } } abstract protected void createMethodExecutionVertex(Alias alias); /** - * Parent : Create MethodExecutionVertex. + * Parent: Create {@code MethodExecutionVertex}. * - * @param objId - * @param methodSignature Called or this MethodSignature. - * @param methodExec Called or this MethodExecution. + * @param objectId + * @param methodSignature: called or this method signature + * @param methodExec: called or this {@code MethodExecution} */ - protected void createMethodExecutionVertex(String objId, String methodSignature, MethodExecution methodExec) { - if (methodSignature == null) methodSignature = methodExec.getSignature(); + protected void createMethodExecutionVertex(String objectId, String methodSignature, MethodExecution methodExecution) { + if (methodSignature == null) { + methodSignature = methodExecution.getSignature(); + } if (methodSignature.matches(".+\\(.*\\)")) { - System.out.println(methodSignature); - methodSignature = formatMethodSignature(methodSignature, methodExec.getThisClassName()); + methodSignature = formatMethodSignature(methodSignature, methodExecution.getThisClassName()); } + if (methodExecution.isStatic() && !objectId.equals("0")) { + objectId = methodExecution.getCallerMethodExecution().getThisObjId(); + } + + mxICell parentCell = (mxICell) objectToVertexMap.get(objectId).getCell(); + double coordX = DEFAULT_OBJECT_VERTEX_SIZE.getWidth() * 0.1; + double coordY = DEFAULT_OBJECT_VERTEX_SIZE.getHeight() * 0.5; + double stdX = coordX; + double stdY = 0; + int time = objectToVertexMap.get(objectId).getVertexMethodExecutions().size(); + if (time >= 1) { + mxICell stdCell = (mxICell) objectToVertexMap.get(objectId).getVertexMethodExecutions().get(0).getCell(); + stdX = stdCell.getGeometry().getX(); + stdY = stdCell.getGeometry().getY(); + time -= 1; + } + + mxICell cell = null; + MethodExecutionVertex methodExecVertex = null; // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. mxgraph.getModel().beginUpdate(); - try { - if (methodExec.isStatic() && !objId.equals("0")) { - objId = methodExec.getCallerMethodExecution().getThisObjId(); + synchronized (mxgraph.getModel()) { + try { + // Creates a white cell of MethodExecutionVertex. + cell = (mxICell) mxgraph.insertDeltaVertex(parentCell, methodSignature, methodSignature, "fillColor=white"); + mxgraph.orderCells(false, new Object[] {cell}); + methodExecVertex = + new MethodExecutionVertex(methodSignature, cell, stdX, coordY * (time + 1) + stdY, + DEFAULT_METHOD_EXECUTION_VERTEX_SIZE.getWidth(), DEFAULT_METHOD_EXECUTION_VERTEX_SIZE.getHeight()); + methodExecToVertexMap.put(methodExecution, methodExecVertex); + if(methodExecToVertexMap.size() > 1) { + // Caution: If synchronized block is split here, {@code cell} is visible instantly until cell#setVisible(false) is executed. + cell.setVisible(false); + } + } finally { + mxgraph.getModel().endUpdate(); } - - Object object = objectToVertexMap.get(objId).getCell(); - -// if (object != null) { - double xCor = VERTEX_OBJECT_SIZE.getWidth() * 0.1; - double yCor = VERTEX_OBJECT_SIZE.getHeight() * 0.5; - double standardX = xCor; - double standardY = 0; - int time = objectToVertexMap.get(objId).getVertexMethodExecutions().size(); - System.out.println(time); - if (time >= 1) { - mxICell standardCell = (mxICell) objectToVertexMap.get(objId).getVertexMethodExecutions().get(0).getCell(); - standardX = standardCell.getGeometry().getX(); - standardY = standardCell.getGeometry().getY(); - time-=1; - } - - Object vertex = mxgraph.insertDeltaVertex(object, methodSignature, methodSignature, "fillColor=white"); //creates a white vertex. - mxgraph.orderCells(false, new Object[] {vertex}); - System.out.println("makeVertexMethodExecution: " + ((mxICell)vertex).getId() + " in " + objId + " (" + standardX + ", " + yCor * (time + 1) + standardY + ")"); - - MethodExecutionVertex vertexMethodExecution = new MethodExecutionVertex(methodSignature, vertex, standardX , yCor * (time + 1) + standardY, VERTEX_METHOD_EXECUTION_SIZE.getWidth(), VERTEX_METHOD_EXECUTION_SIZE.getHeight()); - // Object vertex = mxgraph.insertVertex(object, methodSignature, methodSignature, 0, 0, 0, 0, "fillColor=white", true); //creates a white vertex. - // Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, methodSignature, methodSignature, "fillColor=white"); //creates a white vertex. - // VertexMethodExecution vertexMethodExecution = new VertexMethodExecution(methodSignature, vertex, getXForCell(objectId) + (xCor * (time + 1)), getYForCell(objectId) + (yCor * (time + 1)), VERTEX_METHOD_EXECUTION_SIZE.getWidth(), VERTEX_METHOD_EXECUTION_SIZE.getHeight()); - methodExecToVertexMap.put(methodExec, vertexMethodExecution); - if(methodExecToVertexMap.size() > 1) { - ((mxICell)vertex).setVisible(false); - createEdgeToMethodExecution(); - } - objectToVertexMap.get(objId).addMethodExecution(vertexMethodExecution); -// } - } finally { - mxgraph.getModel().endUpdate(); } - setCellsStyle(); + if(methodExecToVertexMap.size() > 1) { + createEdgesToMethodExecutions(); + } + objectToVertexMap.get(objectId).addMethodExecution(methodExecVertex); +// setCellsStyle(); + update(); } /** - * Remove VertexMethodExecution on AliasType is MethodInvocation of alias. + * Remove {@code MethodExecutionVertex} on AliasType is {@code AliasType.METHOD_INVOCATION}. * * @param alias */ private void removeMethodExecutionVertex(Alias alias) { - // sourceVertex - ObjectVertex sourceVertexObject = objectToVertexMap.get(alias.getObjectId()); + // source {@code ObjectVertex} + ObjectVertex srcObjVertex = objectToVertexMap.get(alias.getObjectId()); MethodExecution methodExec = alias.getMethodExecution(); if(alias.getAliasType().equals(AliasType.METHOD_INVOCATION) || alias.getAliasType().equals(AliasType.CONSTRACTOR_INVOCATION)) { MethodExecution calledMethodExec = ((MethodInvocation) alias.getOccurrencePoint().getStatement()).getCalledMethodExecution(); - // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. - mxgraph.getModel().beginUpdate(); - try { - List arguments = new ArrayList<>(methodExecToVertexMap.get(calledMethodExec).getArguments()); - List locals = new ArrayList<>(methodExecToVertexMap.get(calledMethodExec).getLocals()); - if (arguments.size() != 0) { - for (ObjectVertex vo: arguments) { - if (vo != sourceVertexObject) { - System.out.println("argumentRemove"); - mxICell cell = (mxICell)vo.getCell(); - if (!cell.getParent().equals(mxDefaultParent)) { - Point absolutePointCell = getAbsolutePointforCell(cell); - cell.getParent().remove(cell); - cell.setParent(mxDefaultParent); - cell.getGeometry().setX(absolutePointCell.getX()); - cell.getGeometry().setY(absolutePointCell.getY()); - deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); - deltaAnimation.startVertexAnimation(); + List arguments = new ArrayList<>(methodExecToVertexMap.get(calledMethodExec).getArguments()); + List locals = new ArrayList<>(methodExecToVertexMap.get(calledMethodExec).getLocals()); + if (arguments.size() != 0) { + for (ObjectVertex vo: arguments) { + if (vo != srcObjVertex) { + mxICell cell = (mxICell)vo.getCell(); + if (!cell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + Point2D cellAbsPt = getAbsolutePointforCell(cell); + cell.getParent().remove(cell); + cell.setParent(getMxDefaultParent()); + cell.getGeometry().setX(cellAbsPt.getX()); + cell.getGeometry().setY(cellAbsPt.getY()); + } finally { + mxgraph.getModel().endUpdate(); + } } + + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(cell, vo.getInitialX(), vo.getInitialY(), threadPoolExecutor); + vertexAnim.play(); methodExecToVertexMap.get(calledMethodExec).getArguments().remove(vo); } } } if (locals.size() != 0) { for (ObjectVertex vo: locals) { - if (vo != sourceVertexObject) { - System.out.println("localRemove"); + if (vo != srcObjVertex) { mxICell cell = (mxICell)vo.getCell(); - Point absolutePointCell = getAbsolutePointforCell(cell); - cell.getParent().remove(cell); - cell.setParent(mxDefaultParent); - cell.getGeometry().setX(absolutePointCell.getX()); - cell.getGeometry().setY(absolutePointCell.getY()); - deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); - deltaAnimation.startVertexAnimation(); - methodExecToVertexMap.get(calledMethodExec).getLocals().remove(vo); + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + Point2D cellAbsPt = getAbsolutePointforCell(cell); + if (!cell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + cell.getParent().remove(cell); + cell.setParent(getMxDefaultParent()); + } + cell.getGeometry().setX(cellAbsPt.getX()); + cell.getGeometry().setY(cellAbsPt.getY()); + } finally { + mxgraph.getModel().endUpdate(); + } + } + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(cell, vo.getInitialX(), vo.getInitialY(), threadPoolExecutor); + vertexAnim.play(); } } } + } + MagnetRONAnimation.waitAnimationEnd(); + if (alias.getAliasType().equals(AliasType.CONSTRACTOR_INVOCATION)) { + sleepMainThread(500L); + } + removeCalledMethodExecutionVertex(srcObjVertex, methodExec, calledMethodExec); + } else { + removeMethodExecutionVertex(srcObjVertex, methodExec); + } + } + + /** + * Remove {@code MethodExecutionVertex} on AliasType is {@code AliasType.METHOD_INVOCATION}. + * + * @param sourceObjectVertex + * @param methodExecution + */ + private void removeMethodExecutionVertex(ObjectVertex sourceObjectVertex, MethodExecution methodExecution) { + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + // Remove source {@code ObjectVertex} from Locals and Arguments of called {@code MethodExecution}'s Vertex. + if (methodExecToVertexMap.containsKey(methodExecution)) { + mxCell dstMethodExecVertexCell = (mxCell)methodExecToVertexMap.get(methodExecution).getCell(); + if (!dstMethodExecVertexCell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + dstMethodExecVertexCell.getParent().remove(dstMethodExecVertexCell); + dstMethodExecVertexCell.setParent(getMxDefaultParent()); + } + mxgraph.removeCells(new Object[] {dstMethodExecVertexCell}); + objectToVertexMap.get(methodExecution.getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(methodExecution)); + methodExecToVertexMap.remove(methodExecution); + edgeMap.remove(methodExecution.getSignature()); + updateObjectVertices(); + } } finally { mxgraph.getModel().endUpdate(); } - - - removeCalledMethodExecutionVertex(sourceVertexObject, methodExec, calledMethodExec); - } else { - removeMethodExecutionVertex(sourceVertexObject, methodExec); } } /** - * Remove VertexMethodExecution on AliasType is MethodInvocation of alias. + * Remove called {@code MethodExecutionVertex} with alias type {@code AliasType#METHOD_INVOCATION}. * - * @param sourceVertexObject - * @param methodExec + * @param sourceVertexObject: source object vertex that a called method execution has temporarily + * @param methodExec: current method execution + * @param calledMethodExec: called method execution */ - private void removeMethodExecutionVertex(ObjectVertex sourceVertexObject, MethodExecution methodExec) { - // Remove sourceVertex from Locals and Arguments Vertex of CalledMethodExecution's Vertex. - if (methodExecToVertexMap.containsKey(methodExec)) { - mxCell targetVertexCell = (mxCell)methodExecToVertexMap.get(methodExec).getCell(); - targetVertexCell.getParent().remove(targetVertexCell); - targetVertexCell.setParent(mxDefaultParent); - mxgraph.removeCells(new Object[] {targetVertexCell}); - objectToVertexMap.get(methodExec.getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(methodExec)); - methodExecToVertexMap.remove(methodExec); - edgeMap.remove(methodExec.getSignature()); - updateObjectVertices(); - } - } + protected void removeCalledMethodExecutionVertex(ObjectVertex sourceObjectVertex, MethodExecution methodExecution, MethodExecution calledMethodExecution) { + MagnetRONAnimation.waitAnimationEnd(); + // Remove ObjectVertex other than sourceObjectVertex from locals and arguments of called MethodExecutionVertex. + if (methodExecToVertexMap.containsKey(calledMethodExecution)) { + MethodExecutionVertex calledMethodExecVertex = methodExecToVertexMap.get(calledMethodExecution); - /** - * Remove CalledVertexMethodExecution on AliasType is MethodInvocation of alias. - * - * @param sourceVertexObject - * @param methodExec - * @param calledMethodExec - */ - protected void removeCalledMethodExecutionVertex(ObjectVertex sourceVertexObject, MethodExecution methodExec, MethodExecution calledMethodExec) { - outputLog(); - - // Remove sourceVertex from Locals and Arguments Vertex of CalledMethodExecution's Vertex. - if (methodExecToVertexMap.containsKey(calledMethodExec)) { - mxICell sourceVertexCell = null; - mxCell targetVertexCell = null; - - if (methodExec != null) { - sourceVertexCell = (mxICell)methodExecToVertexMap.get(methodExec).getCell(); - targetVertexCell = (mxCell)methodExecToVertexMap.get(calledMethodExec).getCell(); - } -// if(!calledMethodExec.isStatic()) { - // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. - mxgraph.getModel().beginUpdate(); - try { - // Dangerous - List arguments = new ArrayList<>(methodExecToVertexMap.get(calledMethodExec).getArguments()); - List locals = new ArrayList<>(methodExecToVertexMap.get(calledMethodExec).getLocals()); + // TODO: Confirm bug. + List arguments = new ArrayList<>(calledMethodExecVertex.getArguments()); if (arguments.size() != 0) { for (ObjectVertex vo: arguments) { - if (vo != sourceVertexObject) { + if (vo != sourceObjectVertex) { mxICell cell = (mxICell)vo.getCell(); - Point absolutePointCell = getAbsolutePointforCell(cell); - System.out.println(cell); - System.out.println(vo.getInitialX() + ", " + vo.getInitialY()); - System.out.println(cell.getGeometry().getX() + ", " + cell.getGeometry().getY()); - System.out.println(absolutePointCell); - if (cell.getParent() != mxDefaultParent) { - cell.getParent().remove(cell); - cell.setParent(mxDefaultParent); + Point2D cellAbsPt = getAbsolutePointforCell(cell); + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + if (!cell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + cell.getParent().remove(cell); + cell.setParent(getMxDefaultParent()); + } + } finally { + mxgraph.getModel().endUpdate(); + } } - if (!absolutePointCell.equals(vo.getInitialPoint())) { - cell.getGeometry().setX(absolutePointCell.getX()); - cell.getGeometry().setY(absolutePointCell.getY()); - deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); - deltaAnimation.startVertexAnimation(); + if (!cellAbsPt.equals(vo.getInitialPoint())) { + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + cell.getGeometry().setX(cellAbsPt.getX()); + cell.getGeometry().setY(cellAbsPt.getY()); + } finally { + mxgraph.getModel().endUpdate(); + } + } + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(cell, vo.getInitialX(), vo.getInitialY(), threadPoolExecutor); + vertexAnim.syncPlay(); } - methodExecToVertexMap.get(calledMethodExec).getArguments().remove(vo); + methodExecToVertexMap.get(calledMethodExecution).getArguments().remove(vo); } } } + + List locals = new ArrayList<>(calledMethodExecVertex.getLocals()); if (locals.size() != 0) { for (ObjectVertex vo: locals) { - if (vo != sourceVertexObject) { + if (vo != sourceObjectVertex) { mxICell cell = (mxICell)vo.getCell(); - Point absolutePointCell = getAbsolutePointforCell(cell); - System.out.println(cell); - System.out.println(vo.getInitialX() + ", " + vo.getInitialY()); - System.out.println(cell.getGeometry().getX() + ", " + cell.getGeometry().getY()); - System.out.println(absolutePointCell); - if (cell.getParent() != mxDefaultParent) { - cell.getParent().remove(cell); - cell.setParent(mxDefaultParent); + Point2D cellAbsPt = getAbsolutePointforCell(cell); + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + if (!cell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + cell.getParent().remove(cell); + cell.setParent(getMxDefaultParent()); + } + } finally { + mxgraph.getModel().endUpdate(); + } } - if (!absolutePointCell.equals(vo.getInitialPoint())) { - cell.getGeometry().setX(absolutePointCell.getX()); - cell.getGeometry().setY(absolutePointCell.getY()); - deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY())); - deltaAnimation.startVertexAnimation(); + if (!cellAbsPt.equals(vo.getInitialPoint())) { + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + cell.getGeometry().setX(cellAbsPt.getX()); + cell.getGeometry().setY(cellAbsPt.getY()); + } finally { + mxgraph.getModel().endUpdate(); + } + } + MagnetRONAnimation vertexAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + vertexAnim.setTotalCycleCount(10); + vertexAnim.setDelay(100); + vertexAnim.init(cell, vo.getInitialX(), vo.getInitialY(), threadPoolExecutor); + vertexAnim.syncPlay(); } - methodExecToVertexMap.get(calledMethodExec).getLocals().remove(vo); + methodExecToVertexMap.get(calledMethodExecution).getLocals().remove(vo); } } } + + if (methodExecution == null) { + return; + } + + mxICell srcMethodExecVertexCell = (mxICell)methodExecToVertexMap.get(methodExecution).getCell(); + mxICell dstMethodExecVertexCell = (mxICell)calledMethodExecVertex.getCell(); - if (sourceVertexCell == null || targetVertexCell == null) return; - - mxgraph.removeCells(mxgraph.getEdgesBetween(sourceVertexCell, targetVertexCell)); + try { + Point2D srcMethodExecVertexCellAbsPt = null; + Point2D dstMethodExecVertexCellAbsPt = null; + final mxICell[] clonedstMethodExecVertexCell = new mxICell[1]; + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + mxgraph.removeCells(mxgraph.getEdgesBetween(srcMethodExecVertexCell, dstMethodExecVertexCell)); + srcMethodExecVertexCellAbsPt = getAbsolutePointforCell(srcMethodExecVertexCell); + dstMethodExecVertexCellAbsPt = getAbsolutePointforCell(dstMethodExecVertexCell); + clonedstMethodExecVertexCell[0] = (mxICell) mxgraph.addCell(dstMethodExecVertexCell.clone()); + clonedstMethodExecVertexCell[0].getGeometry().setX(dstMethodExecVertexCellAbsPt.getX()); + clonedstMethodExecVertexCell[0].getGeometry().setY(dstMethodExecVertexCellAbsPt.getY()); + clonedstMethodExecVertexCell[0].setStyle("fillColor=none;strokeColor=none;fontColor=#008000;"); + clonedstMethodExecVertexCell[0].setValue(null); + mxICell tmpEdge = (mxICell) mxgraph.insertEdge(getMxDefaultParent(), null, null, srcMethodExecVertexCell, clonedstMethodExecVertexCell[0]); + tmpEdge.setStyle("dashed=1;strokeColor=#008000;exitX=0.5;exitY=1;exitPerimeter=1;entryX=0.5;entryY=0;entryPerimeter=1;endArrow=none"); + } finally { + mxgraph.getModel().endUpdate(); + } + } + // Animate an edge to shrink. + MagnetRONAnimation edgeAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + edgeAnim.setTotalCycleCount(10); + edgeAnim.setDelay(100); + edgeAnim.init(clonedstMethodExecVertexCell[0], srcMethodExecVertexCellAbsPt.getX(), srcMethodExecVertexCellAbsPt.getY() + srcMethodExecVertexCell.getGeometry().getHeight(), threadPoolExecutor); + edgeAnim.setOnFinished(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + // Test code (will be deleted) + System.out.println(TAG + ": Shrink edge animation action performed."); + mxgraph.removeCells(new Object[]{clonedstMethodExecVertexCell[0]}); + + // TODO: Confirm execution order. + if (!dstMethodExecVertexCell.getParent().equals(getMxDefaultParent())) { + // If parent of ObjectVertex cell isn't mxDefaltParent, reset parent. + dstMethodExecVertexCell.getParent().remove(dstMethodExecVertexCell); + dstMethodExecVertexCell.setParent(getMxDefaultParent()); + } + mxgraph.removeCells(new Object[] {dstMethodExecVertexCell}); + update(); + } finally { + mxgraph.getModel().endUpdate(); + } + } + } + }); + edgeAnim.play(); + + if (!calledMethodExecution.isStatic()) { + objectToVertexMap.get(calledMethodExecution.getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(calledMethodExecution)); + } else { + objectToVertexMap.get(calledMethodExecution.getCallerMethodExecution().getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(calledMethodExecution)); + } + methodExecToVertexMap.get(calledMethodExecution).getLocals().remove(sourceObjectVertex); + methodExecToVertexMap.remove(calledMethodExecution); + edgeMap.remove(methodExecution.getSignature()); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + sleepMainThread(POSTPONE_ANIMATION_MILLIS); + } + } + + /** + * Create an edge between method execution While animating the edge to stretch. + */ + private void createEdgesToMethodExecutions() { + List methodExecList = new ArrayList<>(methodExecToVertexMap.keySet()); + + // TODO: Fix a bug where an edge orientation is reversed. + for (int i = 0; i < methodExecList.size() - 1; i++) { + MethodExecution srcMethodExec = methodExecList.get(i); + MethodExecution dstMethodExec = methodExecList.get(i + 1); + String methodSig = srcMethodExec.getSignature(); + if (!edgeMap.containsKey(methodSig)) { + // Draw an edge from sourceVertexCell to destinationVertexCell. + mxICell srcMethodExecVertexCell = (mxICell)methodExecToVertexMap.get(srcMethodExec).getCell(); + mxICell dstMethodExecVertexCell = (mxICell)methodExecToVertexMap.get(dstMethodExec).getCell(); + Point2D srcMethodExecVertexCellAbsPt = getAbsolutePointforCell(srcMethodExecVertexCell); + Point2D dstMethodExecVertexCellAbsPt = getAbsolutePointforCell(dstMethodExecVertexCell); + + MagnetRONAnimation.waitAnimationEnd(); try { - mxICell cloneTargetVertexCell = (mxICell) mxgraph.addCell(targetVertexCell.clone()); - Point absolutPointSourceVertexCell = getAbsolutePointforCell(sourceVertexCell); - Point absolutPointTargetVertexCell = getAbsolutePointforCell(targetVertexCell); - cloneTargetVertexCell.getGeometry().setX(absolutPointTargetVertexCell.getX()); - cloneTargetVertexCell.getGeometry().setY(absolutPointTargetVertexCell.getY()); - cloneTargetVertexCell.setStyle("fillColor=none;strokeColor=none;fontColor=#008000;"); - cloneTargetVertexCell.setValue(null); - Object tempEdge = mxgraph.insertEdge(mxDefaultParent, null, null, sourceVertexCell, cloneTargetVertexCell); - ((mxCell)tempEdge).setStyle("dashed=1;strokeColor=#008000;exitX=0.5;exitY=1;exitPerimeter=1;entryX=0.5;entryY=0;entryPerimeter=1;endArrow=none"); - deltaAnimation.setReductionEdgeAnimation(cloneTargetVertexCell, new mxPoint(absolutPointSourceVertexCell.getX(), absolutPointSourceVertexCell.getY() + sourceVertexCell.getGeometry().getHeight())); - deltaAnimation.startReductionEdgeAnimation(); -// deltaAnimation.setReductionEdgeAnimation(new mxPoint(absolutPointSourceVertexCell.getX() + (sourceVertexCell.getGeometry().getWidth() / 2), absolutPointSourceVertexCell.getY() + sourceVertexCell.getGeometry().getHeight()), new mxPoint(absolutPointTargetVertexCell.getX() + (targetVertexCell.getGeometry().getWidth() / 2), absolutPointTargetVertexCell.getY())); -// deltaAnimation.startReductionEdgeAnimation(); - mxgraph.removeCells(new Object[]{cloneTargetVertexCell}); + final mxICell[] clonedstMethodExecVertexCell = new mxICell[1]; + + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + clonedstMethodExecVertexCell[0] = (mxICell) mxgraph.addCell(dstMethodExecVertexCell.clone()); + clonedstMethodExecVertexCell[0].getGeometry().setX(srcMethodExecVertexCellAbsPt.getX()); + clonedstMethodExecVertexCell[0].getGeometry().setY(srcMethodExecVertexCellAbsPt.getY() + dstMethodExecVertexCell.getGeometry().getHeight()); + clonedstMethodExecVertexCell[0].setStyle("fillColor=none;strokeColor=none;fontColor=#008000;"); + clonedstMethodExecVertexCell[0].setValue(null); + clonedstMethodExecVertexCell[0].setVisible(true); + mxICell tmpEdge = (mxICell) mxgraph.insertEdge(getMxDefaultParent(), null, null, srcMethodExecVertexCell, clonedstMethodExecVertexCell[0]); + tmpEdge.setStyle("dashed=1;strokeColor=#008000;exitX=0.5;exitY=1;exitPerimeter=1;entryX=0.5;entryY=0;entryPerimeter=1;endArrow=none"); + dstMethodExecVertexCell.setVisible(true); + } finally { + mxgraph.getModel().endUpdate(); + } + } + // Animate an edge to stretch. + MagnetRONAnimation edgeAnim = new TranslateAnimation(mxgraph, getGraphComponent()); + edgeAnim.setTotalCycleCount(10); + edgeAnim.setDelay(100); + edgeAnim.init(clonedstMethodExecVertexCell[0], dstMethodExecVertexCellAbsPt.getX(), dstMethodExecVertexCellAbsPt.getY(), threadPoolExecutor); + edgeAnim.setOnFinished(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + // Test code (will be deleted) + System.out.println(TAG + ": Stretch edge animation action performed. "); + mxICell edge = (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), methodSig, null, srcMethodExecVertexCell, dstMethodExecVertexCell); + if (!edge.getParent().equals(getMxDefaultParent())) { + // If parent of Edge cell isn't mxDefaltParent, reset parent. + edge.getParent().remove(edge); + edge.setParent(getMxDefaultParent()); + } + mxgraph.orderCells(false, new Object[] {edge}); + edge.setStyle("exitX=0.5;exitY=1;exitPerimeter=1;entryX=0.5;entryY=0;entryPerimeter=1;"); + edgeMap.put(methodSig, new Edge(methodSig, TypeName.Call, edge)); + mxgraph.removeCells(new Object[]{clonedstMethodExecVertexCell[0]}); + update(); + } finally { + mxgraph.getModel().endUpdate(); + } + } + } + }); + edgeAnim.play(); + // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + mxgraph.getModel().beginUpdate(); + synchronized (mxgraph.getModel()) { + try { + update(); + } finally { + mxgraph.getModel().endUpdate(); + } + } } catch (CloneNotSupportedException e) { e.printStackTrace(); } - } finally { - mxgraph.getModel().endUpdate(); } - ((mxCell)targetVertexCell.getParent()).remove(targetVertexCell); - targetVertexCell.setParent(mxDefaultParent); - mxgraph.removeCells(new Object[] {targetVertexCell}); - if (!calledMethodExec.isStatic()) { - objectToVertexMap.get(calledMethodExec.getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(calledMethodExec)); - } else { - objectToVertexMap.get(calledMethodExec.getCallerMethodExecution().getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(calledMethodExec)); - } - methodExecToVertexMap.get(calledMethodExec).getLocals().remove(sourceVertexObject); - methodExecToVertexMap.remove(calledMethodExec); - edgeMap.remove(methodExec.getSignature()); -// moveInitialVertexObject(methodExec); -// updateObjectVerticesSize(); + } + } + + /** + * + * @param edge + * @param srcCellAbsPt + * @param dstCellAbsPt + */ + protected void setEdgePoint(mxICell edge, Point2D srcCellAbsPt, Point2D dstCellAbsPt) { +// mxgraph.orderCells(true, new Object[] {edge}); +// if(srcCellAbsPt.getX() <= dstCellAbsPt.getX()) { +// // �E�����獶��փG�b�W������ +// edge.setStyle("exitX=0.5;exitY=0.5;exitPerimeter=1;entryX=0;entryY=0.5;entryPerimeter=1;"); // } else { -// ((mxCell)targetVertexCell.getParent()).remove(targetVertexCell); -// targetVertexCell.setParent(mxDefaultParent); -// mxgraph.removeCells(new Object[] {targetVertexCell}); -// methodExecToVertexMap.get(calledMethodExec).getLocals().remove(sourceVertexObject); -// methodExecToVertexMap.remove(calledMethodExec); +// // ��������E��փG�b�W������ +// edge.setStyle("exitX=0.5;exitY=0.5;exitPerimeter=1;entryX=1;entryY=0.5;entryPerimeter=1;"); // } } - outputLog(); - } - /** Make EdgeMethodExecution. */ - private void createEdgeToMethodExecution() { - List methodExecList = new ArrayList<>(methodExecToVertexMap.keySet()); - - // BUG : Edge Orientation Reverse. - for (int i = 0; i < methodExecList.size() - 1; i++) { - MethodExecution sourceMethodExec = methodExecList.get(i); - MethodExecution targetMethodExec = methodExecList.get(i + 1); - String methodSignature = sourceMethodExec.getSignature(); - if (!edgeMap.containsKey(methodSignature)) { - mxICell sourceVertexCell = (mxICell)methodExecToVertexMap.get(sourceMethodExec).getCell(); - mxICell targetVertexCell = (mxICell)methodExecToVertexMap.get(targetMethodExec).getCell(); -// if (!targetMethodExec.isStatic()) { - Point absolutPointSourceVertexCell = getAbsolutePointforCell(sourceVertexCell); - Point absolutPointTargetVertexCell = getAbsolutePointforCell(targetVertexCell); - // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology - mxgraph.getModel().beginUpdate(); - try { - try { - mxICell cloneTargetVertexCell = (mxICell) mxgraph.addCell(targetVertexCell.clone()); - cloneTargetVertexCell.getGeometry().setX(absolutPointSourceVertexCell.getX()); - cloneTargetVertexCell.getGeometry().setY(absolutPointSourceVertexCell.getY() + targetVertexCell.getGeometry().getHeight()); - cloneTargetVertexCell.setStyle("fillColor=none;strokeColor=none;fontColor=#008000;"); - cloneTargetVertexCell.setValue(null); - cloneTargetVertexCell.setVisible(true); - Object tempEdge = mxgraph.insertEdge(mxDefaultParent, null, null, sourceVertexCell, cloneTargetVertexCell); - ((mxCell)tempEdge).setStyle("dashed=1;strokeColor=#008000;exitX=0.5;exitY=1;exitPerimeter=1;entryX=0.5;entryY=0;entryPerimeter=1;endArrow=none"); - deltaAnimation.setExpandEdgeAnimation(cloneTargetVertexCell, new mxPoint(absolutPointTargetVertexCell.getX(), absolutPointTargetVertexCell.getY())); - deltaAnimation.startExpandEdgeAnimation(); - targetVertexCell.setVisible(true); -// deltaAnimation.setExpandEdgeAnimation(new mxPoint(absolutPointSourceVertexCell.getX() + (sourceVertexCell.getGeometry().getWidth() / 2), absolutPointSourceVertexCell.getY() + sourceVertexCell.getGeometry().getHeight()), new mxPoint(absolutPointTargetVertexCell.getX() + (targetVertexCell.getGeometry().getWidth() / 2), absolutPointTargetVertexCell.getY())); -// deltaAnimation.startExpandEdgeAnimation(); - Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, methodSignature, null, sourceVertexCell, targetVertexCell); - ((mxCell)edge).getParent().remove(((mxCell)edge)); - ((mxCell)edge).setParent(mxDefaultParent); - mxgraph.orderCells(false, new Object[] {edge}); - ((mxCell)edge).setStyle("exitX=0.5;exitY=1;exitPerimeter=1;entryX=0.5;entryY=0;entryPerimeter=1;"); - mxgraph.removeCells(new Object[]{cloneTargetVertexCell}); - edgeMap.put(methodSignature, new Edge(methodSignature, TypeName.Call, edge)); - } catch (CloneNotSupportedException e) { - e.printStackTrace(); - } - } finally { - mxgraph.getModel().endUpdate(); - } -// } else { -// targetVertexCell.setVisible(true); -// } - - } - } - } - - protected void setEdgePoint(mxICell edge, Point absPtSrcCell, Point absPtTgtCell) { -// mxgraph.orderCells(true, new Object[] {edge}); -// if(absPtSrcCell.getX() <= absPtTgtCell.getX()) { -// // �E�����獶��փG�b�W������ -// edge.setStyle("exitX=0.5;exitY=0.5;exitPerimeter=1;entryX=0;entryY=0.5;entryPerimeter=1;"); -// } else { -// // ��������E��փG�b�W������ -// edge.setStyle("exitX=0.5;exitY=0.5;exitPerimeter=1;entryX=1;entryY=0.5;entryPerimeter=1;"); -// } - } - - /** Set style of All cells. */ + /** + * Styles all cells on the graph. + */ protected void setCellsStyle() { - List vertexObject = new ArrayList<>(); - List staticVertexObject = new ArrayList<>(); - List alignMiddleVertex = new ArrayList<>(); - List alignTopVertex = new ArrayList<>(); - List edgeObject = new ArrayList<>(); - List edgeObjectCreate = new ArrayList<>(); - List edgeMethodExec = new ArrayList<>(); + List objectVertex = new ArrayList<>(); + List staticObjectVertex = new ArrayList<>(); + List alignMidObjectVertex = new ArrayList<>(); + List alignTopObjectVertex = new ArrayList<>(); + List refEdge = new ArrayList<>(); + List refCreateEdge = new ArrayList<>(); + List methodExecEdge = new ArrayList<>(); List roundEdge = new ArrayList<>(); for (Entry objectToVertexEntry: objectToVertexMap.entrySet()) { String key = objectToVertexEntry.getKey(); - ObjectVertex objectVertex = objectToVertexEntry.getValue(); + ObjectVertex ov = objectToVertexEntry.getValue(); if (key.matches("0")) { - staticVertexObject.add(objectVertex.getCell()); + staticObjectVertex.add(ov.getCell()); } else { - vertexObject.add(objectVertex.getCell()); + objectVertex.add(ov.getCell()); } - if(objectVertex.getVertexMethodExecutions().size() == 0) { - alignMiddleVertex.add(objectVertex.getCell()); + if(ov.getVertexMethodExecutions().size() == 0) { + alignMidObjectVertex.add(ov.getCell()); } else { - alignTopVertex.add(objectVertex.getCell()); + alignTopObjectVertex.add(ov.getCell()); } } - List vertexMethodExecList = new ArrayList<>(methodExecToVertexMap.values()); - Collections.reverse(vertexMethodExecList); - for (int i = 0; i < vertexMethodExecList.size(); i++) { + List methodExecVertexList = new ArrayList<>(methodExecToVertexMap.values()); + Collections.reverse(methodExecVertexList); + for (int i = 0; i < methodExecVertexList.size(); i++) { switch(i) { - case 0: - ((mxICell)vertexMethodExecList.get(i).getCell()).setStyle("fillColor=#ff7fbf"); - break; - case 1: - ((mxICell)vertexMethodExecList.get(i).getCell()).setStyle("fillColor=#ff99cc"); - break; - case 2: - ((mxICell)vertexMethodExecList.get(i).getCell()).setStyle("fillColor=#ffb2d8"); - break; - case 3: - ((mxICell)vertexMethodExecList.get(i).getCell()).setStyle("fillColor=#ffcce5"); - break; - case 4: - ((mxICell)vertexMethodExecList.get(i).getCell()).setStyle("fillColor=#ffe0ef"); - break; - default: - break; + case 0: + ((mxICell)methodExecVertexList.get(i).getCell()).setStyle("fillColor=#ff7fbf"); + break; + case 1: + ((mxICell)methodExecVertexList.get(i).getCell()).setStyle("fillColor=#ff99cc"); + break; + case 2: + ((mxICell)methodExecVertexList.get(i).getCell()).setStyle("fillColor=#ffb2d8"); + break; + case 3: + ((mxICell)methodExecVertexList.get(i).getCell()).setStyle("fillColor=#ffcce5"); + break; + case 4: + ((mxICell)methodExecVertexList.get(i).getCell()).setStyle("fillColor=#ffe0ef"); + break; + default: + break; } } @@ -1082,80 +1359,72 @@ roundEdge.add(edge.getCell()); switch(edge.getTypeName()) { case Reference: - edgeObject.add(edge.getCell()); + refEdge.add(edge.getCell()); break; case Create: - edgeObject.add(edge.getCell()); - edgeObjectCreate.add(edge.getCell()); + refEdge.add(edge.getCell()); + refCreateEdge.add(edge.getCell()); break; case Call: - edgeMethodExec.add(edge.getCell()); + methodExecEdge.add(edge.getCell()); break; default: break; } } - /*Given a cell, we can change it's style attributes, for example the color. NOTE that you have to call the graphComponent.refresh() function, otherwise you won't see the difference! */ - mxgraph.setCellStyles(mxConstants.STYLE_SHAPE, mxConstants.SHAPE_ELLIPSE, vertexObject.toArray(new Object[vertexObject.size()])); - mxgraph.setCellStyles(mxConstants.STYLE_PERIMETER, mxConstants.PERIMETER_ELLIPSE, vertexObject.toArray(new Object[vertexObject.size()])); - mxgraph.setCellStyleFlags(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_UNDERLINE, true, vertexObject.toArray(new Object[vertexObject.size()])); - mxgraph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE, alignMiddleVertex.toArray(new Object[alignMiddleVertex.size()])); - mxgraph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_TOP, alignTopVertex.toArray(new Object[alignTopVertex.size()])); - mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_TOPTOBOTTOM, edgeObject.toArray(new Object[edgeObject.size()])); - mxgraph.setCellStyleFlags(mxConstants.STYLE_DASHED, 1, true, edgeObjectCreate.toArray(new Object[edgeObjectCreate.size()])); - // mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_ENTITY_RELATION, edgeObject.toArray(new Object[edgeObject.size()])); - // mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_ORTHOGONAL, edgeObject.toArray(new Object[edgeObject.size()])); + // Styles ObjectVertex. + mxgraph.setCellStyles(mxConstants.STYLE_SHAPE, mxConstants.SHAPE_ELLIPSE, objectVertex.toArray(new Object[objectVertex.size()])); + mxgraph.setCellStyles(mxConstants.STYLE_PERIMETER, mxConstants.PERIMETER_ELLIPSE, objectVertex.toArray(new Object[objectVertex.size()])); + mxgraph.setCellStyleFlags(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_UNDERLINE, true, objectVertex.toArray(new Object[objectVertex.size()])); + mxgraph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE, alignMidObjectVertex.toArray(new Object[alignMidObjectVertex.size()])); + mxgraph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_TOP, alignTopObjectVertex.toArray(new Object[alignTopObjectVertex.size()])); + // Styles Edge. + mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_TOPTOBOTTOM, refEdge.toArray(new Object[refEdge.size()])); + mxgraph.setCellStyleFlags(mxConstants.STYLE_DASHED, 1, true, refCreateEdge.toArray(new Object[refCreateEdge.size()])); mxgraph.setCellStyleFlags(mxConstants.STYLE_ROUNDED, 1, true, roundEdge.toArray(new Object[roundEdge.size()])); mxgraph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_TOP, roundEdge.toArray(new Object[roundEdge.size()])); mxgraph.setCellStyles(mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_BOTTOM, roundEdge.toArray(new Object[roundEdge.size()])); - // mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.SHAPE_CURVE, edgeObject.toArray(new Object[edgeObject.size()])); - mxgraph.setCellStyles(mxConstants.STYLE_STROKECOLOR, "#008000", edgeMethodExec.toArray(new Object[edgeMethodExec.size()])); - mxgraph.setCellStyleFlags(mxConstants.STYLE_DASHED, 1, true, edgeMethodExec.toArray(new Object[edgeMethodExec.size()])); - // mxgraph.setCellStyleFlags(mxConstants.STYLE_AUTOSIZE, 1, true, vertexObject.toArray(new Object[vertexObject.size()])); - // mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_ORTHOGONAL, edgeMethodExec.toArray(new Object[edgeMethodExec.size()])); - // mxgraph.setCellStyles(mxConstants.STYLE_ELBOW, mxConstants.ELBOW_VERTICAL, edgeMethodExec.toArray(new Object[edgeMethodExec.size()])); + // Styles MethodExecutionVertex. + mxgraph.setCellStyles(mxConstants.STYLE_STROKECOLOR, "#008000", methodExecEdge.toArray(new Object[methodExecEdge.size()])); + mxgraph.setCellStyleFlags(mxConstants.STYLE_DASHED, 1, true, methodExecEdge.toArray(new Object[methodExecEdge.size()])); } - private void setFrameSize(int width, int height) { - DEFAULT_SIZE.setSize(width, height); - } - - protected Point getAbsolutePointforCell(mxICell cell) { - Point p1 = cell.getGeometry().getPoint(); - if(cell.getParent().getValue() == null || cell == cell.getParent()) { + protected Point2D getAbsolutePointforCell(mxICell cell) { + Point2D p1 = new Point2D.Double(cell.getGeometry().getX(), cell.getGeometry().getY());; + if(cell.getParent() == null + || cell.getParent().getValue() == null + || cell.equals(cell.getParent())) { return p1; } - System.out.println(cell.getId() + ", " + cell.getParent().getId()); - Point p2 = getAbsolutePointforCell(cell.getParent()); - return new Point((int) (p1.getX() + p2.getX()), (int) (p1.getY() + p2.getY())); + Point2D p2 = getAbsolutePointforCell(cell.getParent()); + return new Point2D.Double(p1.getX() + p2.getX(), p1.getY() + p2.getY()); } - /** Update graph on JFrame and set Cell style. */ + /** + * Update the graph on the JFrame by styling the cells and refreshing the mxgraphComponent. + */ protected void update() { + /* Given a cell, we can change it's style attributes, for example the color. + * NOTE that you have to call the graphComponent.refresh() function, + * otherwise you won't see the difference! */ setCellsStyle(); mxgraphComponent.refresh(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } } - private int countChildVertex(ObjectVertex vertexObject) { - int time = vertexObject.getVertexMethodExecutions().size(); + private int countChildVertex(ObjectVertex objectVertex) { + int time = objectVertex.getVertexMethodExecutions().size(); if(time == 0) { return 1; } - for(MethodExecutionVertex vertexMethodExecution: vertexObject.getVertexMethodExecutions()) { - for(ObjectVertex vo: vertexMethodExecution.getLocals()) { - time += countChildVertex(vo); + for(MethodExecutionVertex mev: objectVertex.getVertexMethodExecutions()) { + for(ObjectVertex ov: mev.getLocals()) { + time += countChildVertex(ov); } - for(ObjectVertex vo: vertexMethodExecution.getArguments()) { - return countChildVertex(vo); + for(ObjectVertex ov: mev.getArguments()) { + return countChildVertex(ov); } } - System.out.println(vertexObject.getLabel() + ": " + time); return time; } @@ -1169,28 +1438,27 @@ } protected String formatMethodSignature(String methodSignature, String thisClassName) { - // TODO Modify algorithm formatMethodSignature(). + // TODO: Modify algorithm formatMethodSignature(). // Step1 : split "(" -// String[] methodSignatures = methodSignature.split("\\("); methodSignature = methodSignature.substring(0, methodSignature.lastIndexOf('(')); // Step2 : split " " - String[] methodSignatures = methodSignature.split(" "); - String tmpMethodSignature = methodSignatures[methodSignatures.length-1]; + String[] methodSigs = methodSignature.split(" "); + String tmpMethodSig = methodSigs[methodSigs.length-1]; // Step3 : split "." String[] thisClassNames = thisClassName.split("\\."); - methodSignatures = tmpMethodSignature.split("\\."); + methodSigs = tmpMethodSig.split("\\."); StringBuffer sb = new StringBuffer(); - int i = methodSignatures.length - 2; + int i = methodSigs.length - 2; int count = methodSignature.split("\\(").length - 1; if (count > 0) i -= count; - if (i >= 0 && !thisClassNames[thisClassNames.length - 1].equals(methodSignatures[i])) { - if (thisClassNames[thisClassNames.length - 1].equals(methodSignatures[i + 1])) i += 1; - sb.append(methodSignatures[i]); - if (methodSignatures.length - i > 1) sb.append("."); + if (i >= 0 && !thisClassNames[thisClassNames.length - 1].equals(methodSigs[i])) { + if (thisClassNames[thisClassNames.length - 1].equals(methodSigs[i + 1])) i += 1; + sb.append(methodSigs[i]); + if (methodSigs.length - i > 1) sb.append("."); } - for (i = i + 1; i < methodSignatures.length; i++) { - sb.append(methodSignatures[i]); - if (methodSignatures.length - i > 1) sb.append("."); + for (i = i + 1; i < methodSigs.length; i++) { + sb.append(methodSigs[i]); + if (methodSigs.length - i > 1) sb.append("."); } sb.append("()"); @@ -1217,11 +1485,18 @@ return sb.toString(); } + private void setWindowSize(int width, int height) { + DEFAULT_WINDOW_SIZE.setSize(width, height); + } + + /** + * Test code (will be deleted) + */ protected void outputLog() { - for (Object object: mxgraph.getChildCells(mxDefaultParent)) { - System.out.println(object + " " + object.hashCode()); - for (int i = 0; i < ((mxICell)object).getChildCount(); i++) { - System.out.println(" " + ((mxICell)object).getChildAt(i) + " " + object.hashCode()); + for (Object obj: mxgraph.getChildCells(getMxDefaultParent())) { + System.out.println(obj + " " + obj.hashCode()); + for (int i = 0; i < ((mxICell)obj).getChildCount(); i++) { + System.out.println(" " + ((mxICell)obj).getChildAt(i) + " " + obj.hashCode()); } } System.out.println("\nObject"); @@ -1251,31 +1526,31 @@ } } } - + /** - * Whether sourceCell parents contain targetCell. + * Whether sourceCell parents contain destinationCell. + * * @param sourceCell - * @param targetCell + * @param destinationCell * @return */ - private boolean isParent(mxICell sourceCell, mxICell targetCell) { - mxICell sourceParentCell = sourceCell.getParent(); - if (sourceParentCell == null || sourceParentCell.getValue() == null) { + private boolean isParent(mxICell sourceCell, mxICell destinationCell) { + mxICell srcParentCell = sourceCell.getParent(); + if (srcParentCell == null || srcParentCell.getValue() == null || destinationCell == null) { return false; } - if (sourceParentCell == targetCell) { + if (srcParentCell.equals(destinationCell)) { return true; } - System.out.println(sourceCell.getId() + ", " + sourceParentCell.getId()); - return isParent(sourceParentCell, targetCell); + return isParent(srcParentCell, destinationCell); } protected void reflectCoordinates(DeltaGraphAdapter mxgraph) { // TODO Auto-generated method stub } - public static Map.Entry getRelatedInformation(TracePoint rp) { - Statement rpStatement = rp.getStatement(); + public static Map.Entry getRelatedInformation(TracePoint relatedPoint) { + Statement rpStatement = relatedPoint.getStatement(); String rpSrcObjId = null; String rpDstObjId = null; String rpSrcClassName = null; @@ -1329,7 +1604,19 @@ } return new AbstractMap.SimpleEntry<>(new Reference(rpSrcObjId, rpDstObjId, rpSrcClassName, rpDstClassName), rpFieldName); } + + public void sleepMainThread(long millis) { + try { + // Test code (will be deleted) + System.out.println(TAG + ": Sleep Main thread " + millis + "millis. ThreadId=" + Thread.currentThread().getId()); + Thread.sleep(millis); + System.out.println(TAG + ": Resume Main thread."); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + protected class CurvedCanvas extends mxInteractiveCanvas { mxIShape shape = new CurvedConnector(); @@ -1392,8 +1679,8 @@ if (state.getAbsolutePointCount() == 4) { double sx = state.getAbsolutePoint(0).getX(); double sy = state.getAbsolutePoint(0).getY(); - double tx1 = state.getAbsolutePoint(1).getX(); - double ty1 = state.getAbsolutePoint(1).getY(); +// double tx1 = state.getAbsolutePoint(1).getX(); +// double ty1 = state.getAbsolutePoint(1).getY(); double tx2 = state.getAbsolutePoint(2).getX(); double ty2 = state.getAbsolutePoint(2).getY(); double ex = state.getAbsolutePoint(3).getX(); diff --git a/src/org/ntlab/deltaViewer/Vertex.java b/src/org/ntlab/deltaViewer/Vertex.java index a5ea317..d5952ff 100644 --- a/src/org/ntlab/deltaViewer/Vertex.java +++ b/src/org/ntlab/deltaViewer/Vertex.java @@ -1,6 +1,6 @@ package org.ntlab.deltaViewer; -import java.awt.Point; +import java.awt.geom.Point2D; import com.mxgraph.model.mxICell; @@ -97,8 +97,8 @@ } - public Point getInitialPoint() { - return new Point((int)initialX, (int)initialY); + public Point2D getInitialPoint() { + return new Point2D.Double(initialX, initialY); } public void setInitialPoint(double initX, double initY) {