com.mxgraph.swing.handler.mxMovePreview Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jgraphx Show documentation
Show all versions of jgraphx Show documentation
JGraphX Swing Component - Java Graph Visualization Library
This is a binary & source redistribution of the original, unmodified JGraphX library originating from:
"https://github.com/jgraph/jgraphx/archive/v3.4.1.3.zip".
The purpose of this redistribution is to make the library available to other Maven projects.
/**
* $Id: mxMovePreview.java,v 1.9 2012/01/13 13:19:25 david Exp $
* Copyright (c) 2008-2012, JGraph Ltd
*/
package com.mxgraph.swing.handler;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.LinkedList;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.swing.util.mxSwingConstants;
import com.mxgraph.swing.view.mxCellStatePreview;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxEventSource;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.view.mxCellState;
import com.mxgraph.view.mxGraph;
/**
* Connection handler creates new connections between cells. This control is used to display the connector
* icon, while the preview is used to draw the line.
*/
public class mxMovePreview extends mxEventSource
{
/**
*
*/
protected mxGraphComponent graphComponent;
/**
* Maximum number of cells to preview individually. Default is 200.
*/
protected int threshold = 200;
/**
* Specifies if the placeholder rectangle should be used for all
* previews. Default is false. This overrides all other preview
* settings if true.
*/
protected boolean placeholderPreview = false;
/**
* Specifies if the preview should use clones of the original shapes.
* Default is true.
*/
protected boolean clonePreview = true;
/**
* Specifies if connected, unselected edges should be included in the
* preview. Default is true. This should not be used if cloning is
* enabled.
*/
protected boolean contextPreview = true;
/**
* Specifies if the selection cells handler should be hidden while the
* preview is visible. Default is false.
*/
protected boolean hideSelectionHandler = false;
/**
*
*/
protected transient mxCellState startState;
/**
*
*/
protected transient mxCellState[] previewStates;
/**
*
*/
protected transient Object[] movingCells;
/**
*
*/
protected transient Rectangle initialPlaceholder;
/**
*
*/
protected transient Rectangle placeholder;
/**
*
*/
protected transient mxRectangle lastDirty;
/**
*
*/
protected transient mxCellStatePreview preview;
/**
* Constructs a new rubberband selection for the given graph component.
*
* @param graphComponent Component that contains the rubberband.
*/
public mxMovePreview(mxGraphComponent graphComponent)
{
this.graphComponent = graphComponent;
// Installs the paint handler
graphComponent.addListener(mxEvent.AFTER_PAINT, new mxIEventListener()
{
public void invoke(Object sender, mxEventObject evt)
{
Graphics g = (Graphics) evt.getProperty("g");
paint(g);
}
});
}
/**
*
*/
public int getThreshold()
{
return threshold;
}
/**
*
*/
public void setThreshold(int value)
{
threshold = value;
}
/**
*
*/
public boolean isPlaceholderPreview()
{
return placeholderPreview;
}
/**
*
*/
public void setPlaceholderPreview(boolean value)
{
placeholderPreview = value;
}
/**
*
*/
public boolean isClonePreview()
{
return clonePreview;
}
/**
*
*/
public void setClonePreview(boolean value)
{
clonePreview = value;
}
/**
*
*/
public boolean isContextPreview()
{
return contextPreview;
}
/**
*
*/
public void setContextPreview(boolean value)
{
contextPreview = value;
}
/**
*
*/
public boolean isHideSelectionHandler()
{
return hideSelectionHandler;
}
/**
*
*/
public void setHideSelectionHandler(boolean value)
{
hideSelectionHandler = value;
}
/**
*
*/
public boolean isActive()
{
return startState != null;
}
/**
* FIXME: Cells should be assigned outside of getPreviewStates
*/
public Object[] getMovingCells()
{
return movingCells;
}
/**
*
*/
public Object[] getCells(mxCellState initialState)
{
mxGraph graph = graphComponent.getGraph();
return graph.getMovableCells(graph.getSelectionCells());
}
/**
* Returns the states that are affected by the move operation.
*/
protected mxCellState[] getPreviewStates()
{
mxGraph graph = graphComponent.getGraph();
Collection result = new LinkedList();
for (Object cell : movingCells)
{
mxCellState cellState = graph.getView().getState(cell);
if (cellState != null)
{
result.add(cellState);
// Terminates early if too many cells
if (result.size() >= threshold)
{
return null;
}
if (isContextPreview())
{
Object[] edges = graph.getAllEdges(new Object[] { cell });
for (Object edge : edges)
{
if (!graph.isCellSelected(edge))
{
mxCellState edgeState = graph.getView().getState(
edge);
if (edgeState != null)
{
// Terminates early if too many cells
if (result.size() >= threshold)
{
return null;
}
result.add(edgeState);
}
}
}
}
}
}
return result.toArray(new mxCellState[result.size()]);
}
/**
*
*/
protected boolean isCellOpaque(Object cell)
{
return startState != null && startState.getCell() == cell;
}
/**
* Sets the translation of the preview.
*/
public void start(MouseEvent e, mxCellState state)
{
startState = state;
movingCells = getCells(state);
previewStates = (!placeholderPreview) ? getPreviewStates() : null;
if (previewStates == null || previewStates.length >= threshold)
{
placeholder = getPlaceholderBounds(startState).getRectangle();
initialPlaceholder = new Rectangle(placeholder);
graphComponent.getGraphControl().repaint(placeholder);
}
fireEvent(new mxEventObject(mxEvent.START, "event", e, "state",
startState));
}
/**
*
*/
protected mxRectangle getPlaceholderBounds(mxCellState startState)
{
mxGraph graph = graphComponent.getGraph();
return graph.getView().getBounds(graph.getSelectionCells());
}
/**
*
*/
public mxCellStatePreview createCellStatePreview()
{
return new mxCellStatePreview(graphComponent, isClonePreview())
{
protected float getOpacityForCell(Object cell)
{
if (isCellOpaque(cell))
{
return 1;
}
return super.getOpacityForCell(cell);
}
};
}
/**
* Sets the translation of the preview.
*/
public void update(MouseEvent e, double dx, double dy, boolean clone)
{
mxGraph graph = graphComponent.getGraph();
if (placeholder != null)
{
Rectangle tmp = new Rectangle(placeholder);
placeholder.x = initialPlaceholder.x + (int) dx;
placeholder.y = initialPlaceholder.x + (int) dy;
tmp.add(placeholder);
graphComponent.getGraphControl().repaint(tmp);
}
else if (previewStates != null)
{
preview = createCellStatePreview();
preview.setOpacity(graphComponent.getPreviewAlpha());
// Combines the layout result with the move preview
for (mxCellState previewState : previewStates)
{
preview.moveState(previewState, dx, dy, false, false);
// FIXME: Move into show-handler?
boolean visible = true;
if ((dx != 0 || dy != 0) && clone && isContextPreview())
{
visible = false;
Object tmp = previewState.getCell();
while (!visible && tmp != null)
{
visible = graph.isCellSelected(tmp);
tmp = graph.getModel().getParent(tmp);
}
}
}
mxRectangle dirty = lastDirty;
lastDirty = preview.show();
if (dirty != null)
{
dirty.add(lastDirty);
}
else
{
dirty = lastDirty;
}
if (dirty != null)
{
repaint(dirty);
}
}
if (isHideSelectionHandler())
{
graphComponent.getSelectionCellsHandler().setVisible(false);
}
fireEvent(new mxEventObject(mxEvent.CONTINUE, "event", e, "dx", dx,
"dy", dy));
}
/**
*
*/
protected void repaint(mxRectangle dirty)
{
if (dirty != null)
{
graphComponent.getGraphControl().repaint(dirty.getRectangle());
}
else
{
graphComponent.getGraphControl().repaint();
}
}
/**
*
*/
protected void reset()
{
mxGraph graph = graphComponent.getGraph();
if (placeholder != null)
{
Rectangle tmp = placeholder;
placeholder = null;
graphComponent.getGraphControl().repaint(tmp);
}
if (isHideSelectionHandler())
{
graphComponent.getSelectionCellsHandler().setVisible(true);
}
// Revalidates the screen
// TODO: Should only revalidate moved cells
if (!isClonePreview() && previewStates != null)
{
graph.getView().revalidate();
}
previewStates = null;
movingCells = null;
startState = null;
preview = null;
if (lastDirty != null)
{
graphComponent.getGraphControl().repaint(lastDirty.getRectangle());
lastDirty = null;
}
}
/**
*
*/
public Object[] stop(boolean commit, MouseEvent e, double dx, double dy,
boolean clone, Object target)
{
Object[] cells = movingCells;
reset();
mxGraph graph = graphComponent.getGraph();
graph.getModel().beginUpdate();
try
{
if (commit)
{
double s = graph.getView().getScale();
cells = graph.moveCells(cells, dx / s, dy / s, clone, target,
e.getPoint());
}
fireEvent(new mxEventObject(mxEvent.STOP, "event", e, "commit",
commit));
}
finally
{
graph.getModel().endUpdate();
}
return cells;
}
/**
*
*/
public void paint(Graphics g)
{
if (placeholder != null)
{
mxSwingConstants.PREVIEW_BORDER.paintBorder(graphComponent, g,
placeholder.x, placeholder.y, placeholder.width,
placeholder.height);
}
if (preview != null)
{
preview.paint(g);
}
}
}