⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mxgraphview.java

📁 经典的java图像处理程序源码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/** * $Id: mxGraphView.java,v 1.123 2009/05/07 06:44:42 gaudenz Exp $ * Copyright (c) 2007, Gaudenz Alder */package com.mxgraph.view;import java.awt.geom.Line2D;import java.util.ArrayList;import java.util.Hashtable;import java.util.List;import com.mxgraph.model.mxGeometry;import com.mxgraph.model.mxIGraphModel;import com.mxgraph.util.mxConstants;import com.mxgraph.util.mxEvent;import com.mxgraph.util.mxEventObject;import com.mxgraph.util.mxEventSource;import com.mxgraph.util.mxPoint;import com.mxgraph.util.mxRectangle;import com.mxgraph.util.mxUndoableEdit;import com.mxgraph.util.mxUtils;import com.mxgraph.util.mxUndoableEdit.mxUndoableChange;import com.mxgraph.view.mxEdgeStyle.mxEdgeStyleFunction;import com.mxgraph.view.mxPerimeter.mxPerimeterFunction;/** * Implements a view for the graph. This class is in charge of computing the * absolute coordinates for the relative child geometries, the points for * perimeters and edge styles and keeping them cached in cell states for * faster retrieval. The states are updated whenever the model or the view * state (translate, scale) changes. The scale and translate are honoured in * the bounds. */public class mxGraphView extends mxEventSource{	/**	 * Reference to the enclosing graph.	 */	protected mxGraph graph;	/**	 * mxCell that acts as the root of the displayed cell hierarchy.	 */	protected Object currentRoot = null;	/**	 * Caches the current bounds of the graph.	 */	protected mxRectangle graphBounds = new mxRectangle();	/**	 * Specifies the scale. Default is 1 (100%).	 */	protected double scale = 1;	/**	 * Point that specifies the current translation. Default is a new	 * empty point.	 */	protected mxPoint translate = new mxPoint(0, 0);	/**	 * Maps from cells to cell states.	 */	protected Hashtable states = new Hashtable();	/**	 * Constructs a new view for the given graph.	 * 	 * @param graph Reference to the enclosing graph.	 */	public mxGraphView(mxGraph graph)	{		this.graph = graph;	}	/**	 * Returns the enclosing graph.	 * 	 * @return Returns the enclosing graph.	 */	public mxGraph getGraph()	{		return graph;	}	/**	 * Returns the dictionary that maps from cells to states.	 */	public Hashtable getStates()	{		return states;	}	/**	 * Returns the dictionary that maps from cells to states.	 */	public void setStates(Hashtable states)	{		this.states = states;	}	/**	 * Returns the cached diagram bounds.	 * 	 * @return Returns the diagram bounds.	 */	public mxRectangle getGraphBounds()	{		return graphBounds;	}	/**	 * Returns the cached diagram bounds.	 * 	 * @return Returns the diagram bounds.	 */	public void setGraphBounds(mxRectangle value)	{		graphBounds = value;	}	/**	 * Returns the current root.	 */	public Object getCurrentRoot()	{		return currentRoot;	}	/**	 * Sets and returns the current root and fires an undo event.	 * 	 * @param root mxCell that specifies the root of the displayed cell hierarchy.	 * @return Returns the object that represents the current root.	 */	public Object setCurrentRoot(Object root)	{		if (currentRoot != root)		{			mxCurrentRootChange change = new mxCurrentRootChange(this, root);			change.execute();			mxUndoableEdit edit = new mxUndoableEdit(this, false);			edit.add(change);			fireEvent(mxEvent.UNDO, new mxEventObject(new Object[] { edit }));		}		return root;	}	/**	 * Sets the scale and translation. Fires a "scaleAndTranslate"	 * event after calling revalidate. Revalidate is only called if	 * isEventsEnabled.	 * 	 * @param scale Decimal value that specifies the new scale (1 is 100%).	 * @param dx X-coordinate of the translation.	 * @param dy Y-coordinate of the translation.	 */	public void scaleAndTranslate(double scale, double dx, double dy)	{		double oldScale = scale;		Object oldTranslate = translate.clone();		if (scale != this.scale || dx != translate.getX()				|| dy != translate.getY())		{			this.scale = scale;			translate = new mxPoint(dx, dy);			if (isEventsEnabled())			{				revalidate();			}		}		fireEvent(mxEvent.SCALE_AND_TRANSLATE, new mxEventObject(new Object[] {				oldScale, scale, oldTranslate, translate }));	}	/**	 * Returns the current scale.	 * 	 * @return Returns the scale.	 */	public double getScale()	{		return scale;	}	/**	 * Sets the current scale and revalidates the view. Fires a "scale"	 * event after calling revalidate. Revalidate is only called if	 * isEventsEnabled.	 * 	 * @param value New scale to be used.	 */	public void setScale(double value)	{		double old = scale;		if (scale != value)		{			scale = value;			if (isEventsEnabled())			{				revalidate();			}		}		fireEvent(mxEvent.SCALE, new mxEventObject(new Object[] { old, scale }));	}	/**	 * Returns the current translation.	 * 	 * @return Returns the translation.	 */	public mxPoint getTranslate()	{		return translate;	}	/**	 * Sets the current translation and invalidates the view. Fires	 * a property change event for "translate" after calling	 * revalidate. Revalidate is only called if isEventsEnabled.	 * 	 * @param value New translation to be used.	 */	public void setTranslate(mxPoint value)	{		Object old = translate.clone();		if (value != null				&& (value.getX() != translate.getX() || value.getY() != translate						.getY()))		{			translate = value;			if (isEventsEnabled())			{				revalidate();			}		}		fireEvent(mxEvent.TRANSLATE, new mxEventObject(new Object[] { old,				translate }));	}	/**	 * Returns the bounding box for an array of cells or null, if no cells are	 * specified.	 * 	 * @param cells	 * @return Returns the bounding box for the given cells.	 */	public mxRectangle getBounds(Object[] cells)	{		return getBounds(cells, false);	}	/**	 * Returns the bounding box for an array of cells or null, if no cells are	 * specified.	 * 	 * @param cells	 * @return Returns the bounding box for the given cells.	 */	public mxRectangle getBoundingBox(Object[] cells)	{		return getBounds(cells, true);	}	/**	 * Returns the bounding box for an array of cells or null, if no cells are	 * specified.	 * 	 * @param cells	 * @return Returns the bounding box for the given cells.	 */	public mxRectangle getBounds(Object[] cells, boolean boundingBox)	{		mxRectangle result = null;		if (cells != null && cells.length > 0)		{			mxIGraphModel model = graph.getModel();						for (int i = 0; i < cells.length; i++)			{				if (model.isVertex(cells[i]) || model.isEdge(cells[i]))				{					mxCellState state = getState(cells[i]);					if (state != null)					{						mxRectangle tmp = (boundingBox) ? state								.getBoundingBox() : state;						if (tmp != null)						{							if (result == null)							{								result = new mxRectangle(tmp);							}							else							{								result.add(tmp);							}						}					}				}			}		}		return result;	}	/**	 * Removes all existing cell states and invokes revalidate.	 */	public void reload()	{		states.clear();		revalidate();	}	/**	 * 	 */	public void revalidate()	{		invalidate();		validate();	}	/**	 * Invalidates all cell states.	 */	public void invalidate()	{		invalidate(null);	}	/**	 * Removes the state of the given cell and all descendants if the given	 * cell is not the current root.	 * 	 * @param cell	 * @param force	 * @param recurse	 */	public void clear(Object cell, boolean force, boolean recurse)	{		removeState(cell);		if (recurse && (force || cell != currentRoot))		{			mxIGraphModel model = graph.getModel();			int childCount = model.getChildCount(cell);			for (int i = 0; i < childCount; i++)			{				clear(model.getChildAt(cell, i), force, recurse);			}		}		else		{			invalidate(cell);		}	}	/**	 * Invalidates the state of the given cell, all its descendants and	 * connected edges.	 */	public void invalidate(Object cell)	{		mxIGraphModel model = graph.getModel();		cell = (cell != null) ? cell : model.getRoot();		mxCellState state = getState(cell);		if (state == null || !state.isInvalid())		{			if (state != null)			{				state.setInvalid(true);			}			// Recursively invalidates all descendants			int childCount = model.getChildCount(cell);			for (int i = 0; i < childCount; i++)			{				Object child = model.getChildAt(cell, i);				invalidate(child);			}			// Propagates invalidation to all connected edges			int edgeCount = model.getEdgeCount(cell);			for (int i = 0; i < edgeCount; i++)			{				invalidate(model.getEdgeAt(cell, i));			}		}	}	/**	 * First validates all bounds and then validates all points recursively on	 * all visible cells.	 */	public void validate()	{		Object cell = (currentRoot != null) ? currentRoot : graph.getModel()				.getRoot();		if (cell != null)		{			validateBounds(null, cell);			setGraphBounds(validatePoints(null, cell));		}	}	/**	 * Validates the bounds of the given parent's child using the given parent	 * state as the origin for the child. The validation is carried out	 * recursively for all non-collapsed descendants.	 * 	 * @param parentState Object that represents the state of the parent cell.	 * @param cell Cell for which the bounds in the state should be updated.	 */	public void validateBounds(mxCellState parentState, Object cell)	{		mxIGraphModel model = graph.getModel();		mxCellState state = getState(cell, true);		if (state != null && state.isInvalid())		{			if (!graph.isCellVisible(cell))			{				removeState(cell);			}			else if (cell != currentRoot && parentState != null)			{				state.setOrigin(new mxPoint(parentState.getOrigin()));				mxGeometry geo = graph.getCellGeometry(cell);				if (geo != null)				{					if (!model.isEdge(cell))					{						mxPoint origin = state.getOrigin();						mxPoint offset = geo.getOffset();						if (offset == null)						{							offset = new mxPoint();						}						if (geo.isRelative())						{							origin.setX(origin.getX() + geo.getX()									* parentState.getWidth() / scale									+ offset.getX());							origin.setY(origin.getY() + geo.getY()									* parentState.getHeight() / scale									+ offset.getY());						}						else						{							state.setAbsoluteOffset(new mxPoint(scale									* offset.getX(), scale * offset.getY()));							origin.setX(origin.getX() + geo.getX());							origin.setY(origin.getY() + geo.getY());						}					}					// Updates the cell state's bounds					state.setX(scale							* (translate.getX() + state.getOrigin().getX()));					state.setY(scale							* (translate.getY() + state.getOrigin().getY()));					state.setWidth(scale * geo.getWidth());					state.setHeight(scale * geo.getHeight());					if (model.isVertex(cell))					{						updateVertexLabelOffset(state);					}				}			}			// Applies child offset to origin			mxPoint offset = graph.getChildOffsetForCell(cell);			if (offset != null)			{				state.getOrigin()						.setX(state.getOrigin().getX() + offset.getX());				state.getOrigin()						.setY(state.getOrigin().getY() + offset.getY());			}		}		// Recursively validates the child bounds		if (state != null				&& (!graph.isCellCollapsed(cell) || cell == currentRoot))		{			int childCount = model.getChildCount(cell);			for (int i = 0; i < childCount; i++)			{				validateBounds(state, model.getChildAt(cell, i));			}		}	}	/**	 * Updates the absoluteOffset of the given vertex cell state. This takes	 * into account the label position styles.	 * 	 * @param state Cell state whose absolute offset should be updated.	 */	public void updateVertexLabelOffset(mxCellState state)	{		String horizontal = mxUtils.getString(state.getStyle(),				mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER);		if (horizontal.equals(mxConstants.ALIGN_LEFT))		{			state.absoluteOffset.setX(state.absoluteOffset.getX()					- state.getWidth());		}		else if (horizontal.equals(mxConstants.ALIGN_RIGHT))		{			state.absoluteOffset.setX(state.absoluteOffset.getX()					+ state.getWidth());		}		String vertical = mxUtils.getString(state.getStyle(),				mxConstants.STYLE_VERTICAL_LABEL_POSITION,				mxConstants.ALIGN_MIDDLE);		if (vertical.equals(mxConstants.ALIGN_TOP))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -