📄 mxgraphview.java
字号:
return (mxPerimeterFunction) perimeter; } return null; } /** * Returns the nearest point in the list of absolute points or the center * of the opposite terminal. * * @param state Cell state that represents the edge. * @param opposite Cell that represents the opposite terminal. * @param isSource Boolean indicating if the next point for the source or target * should be returned. * @return Returns the nearest point of the opposite side. */ public mxPoint getNextPoint(mxCellState state, Object opposite, boolean isSource) { mxPoint point = null; List pts = state.getAbsolutePoints(); if (pts != null && (isSource || pts.size() > 2 || opposite == null)) { int count = pts.size(); int index = (isSource) ? Math.min(1, count - 1) : Math.max(0, count - 2); point = (mxPoint) pts.get(index); } if (point == null && opposite != null) { mxCellState oppositeState = getState(opposite); if (oppositeState != null) { point = new mxPoint(oppositeState.getCenterX(), oppositeState .getCenterY()); } } return point; } /** * Returns the nearest ancestor terminal that is visible. The edge appears * to be connected to this terminal on the display. * * @param edge Cell whose visible terminal should be returned. * @param isSource Boolean that specifies if the source or target terminal * should be returned. * @return Returns the visible source or target terminal. */ public Object getVisibleTerminal(Object edge, boolean isSource) { mxIGraphModel model = graph.getModel(); Object result = model.getTerminal(edge, isSource); Object best = result; while (result != null && result != currentRoot) { if (!graph.isCellVisible(best) || graph.isCellCollapsed(result)) { best = result; } result = model.getParent(result); } return best; } /** * Updates the given state using the bounding box of the absolute points. * Also updates terminal distance, length and segments. * * @param state Cell state whose bounds should be updated. */ public void updateEdgeBounds(mxCellState state) { List points = state.getAbsolutePoints(); if (points != null && points.size() > 0) { mxPoint p0 = (mxPoint) points.get(0); mxPoint pe = (mxPoint) points.get(points.size() - 1); if (p0 == null || pe == null) { // Note: This is an error that normally occurs // if a connected edge has a null-terminal, ie. // source is null and/or target is null and no // additional control points are defined removeState(state.getCell()); } else { if (p0.getX() != pe.getX() || p0.getY() != pe.getY()) { double dx = pe.getX() - p0.getX(); double dy = pe.getY() - p0.getY(); state.setTerminalDistance(Math.sqrt(dx * dx + dy * dy)); } else { state.setTerminalDistance(0); } double length = 0; double[] segments = new double[points.size() - 1]; mxPoint pt = p0; if (pt != null) { double minX = pt.getX(); double minY = pt.getY(); double maxX = minX; double maxY = minY; for (int i = 1; i < points.size(); i++) { mxPoint tmp = (mxPoint) points.get(i); if (tmp != null) { double dx = pt.getX() - tmp.getX(); double dy = pt.getY() - tmp.getY(); double segment = Math.sqrt(dx * dx + dy * dy); segments[i - 1] = segment; length += segment; pt = tmp; minX = Math.min(pt.getX(), minX); minY = Math.min(pt.getY(), minY); maxX = Math.max(pt.getX(), maxX); maxY = Math.max(pt.getY(), maxY); } } state.setLength(length); state.setSegments(segments); double markerSize = 1; // TODO: include marker size state.setX(minX); state.setY(minY); state.setWidth(Math.max(markerSize, maxX - minX)); state.setHeight(Math.max(markerSize, maxY - minY)); } else { state.setLength(0); } } } } /** * Returns the absolute center point along the given edge. */ public mxPoint getPoint(mxCellState state) { return getPoint(state, null); } /** * Returns the absolute point on the edge for the given relative * geometry as a point. The edge is represented by the given cell state. * * @param state Represents the state of the parent edge. * @param geometry Optional geometry that represents the relative location. * @return Returns the mxpoint that represents the absolute location * of the given relative geometry. */ public mxPoint getPoint(mxCellState state, mxGeometry geometry) { double x = state.getCenterX(); double y = state.getCenterY(); if (state.getSegments() != null && (geometry == null || geometry.isRelative())) { double gx = (geometry != null) ? geometry.getX() / 2 : 0; int pointCount = state.getAbsolutePointCount(); double dist = (gx + 0.5) * state.getLength(); double[] segments = state.getSegments(); double segment = segments[0]; double length = 0; int index = 1; while (dist > length + segment && index < pointCount - 1) { length += segment; segment = segments[index++]; } if (segment != 0) { double factor = (dist - length) / segment; mxPoint p0 = state.getAbsolutePoint(index - 1); mxPoint pe = state.getAbsolutePoint(index); if (p0 != null && pe != null) { double gy = 0; double offsetX = 0; double offsetY = 0; if (geometry != null) { gy = geometry.getY(); mxPoint offset = geometry.getOffset(); if (offset != null) { offsetX = offset.getX(); offsetY = offset.getY(); } } double dx = pe.getX() - p0.getX(); double dy = pe.getY() - p0.getY(); double nx = dy / segment; double ny = dx / segment; x = p0.getX() + dx * factor + (nx * gy + offsetX) * scale; y = p0.getY() + dy * factor - (ny * gy - offsetY) * scale; } } } else if (geometry != null) { mxPoint offset = geometry.getOffset(); if (offset != null) { x += offset.getX(); y += offset.getY(); } } return new mxPoint(x, y); } /** * Gets the relative point that describes the given, absolute label * position for the given edge state. */ public mxPoint getRelativePoint(mxCellState edgeState, double x, double y) { mxIGraphModel model = graph.getModel(); mxGeometry geometry = model.getGeometry(edgeState.getCell()); if (geometry != null) { int pointCount = edgeState.getAbsolutePointCount(); if (geometry.isRelative() && pointCount > 1) { double totalLength = edgeState.getLength(); double[] segments = edgeState.getSegments(); // Works which line segment the point of the label is closest to mxPoint p0 = edgeState.getAbsolutePoint(0); mxPoint pe = edgeState.getAbsolutePoint(1); Line2D line = new Line2D.Double(p0.getPoint(), pe.getPoint()); double minDist = line.ptSegDistSq(x, y); int index = 0; double tmp = 0; double length = 0; for (int i = 2; i < pointCount; i++) { tmp += segments[i - 2]; pe = edgeState.getAbsolutePoint(i); line = new Line2D.Double(p0.getPoint(), pe.getPoint()); double dist = line.ptSegDistSq(x, y); if (dist < minDist) { minDist = dist; index = i - 1; length = tmp; } p0 = pe; } double seg = segments[index]; p0 = edgeState.getAbsolutePoint(index); pe = edgeState.getAbsolutePoint(index + 1); double x2 = p0.getX(); double y2 = p0.getY(); double x1 = pe.getX(); double y1 = pe.getY(); double px = x; double py = y; double xSegment = x2 - x1; double ySegment = y2 - y1; px -= x1; py -= y1; double projlenSq = 0; px = xSegment - px; py = ySegment - py; double dotprod = px * xSegment + py * ySegment; if (dotprod <= 0.0) { projlenSq = 0; } else { projlenSq = dotprod * dotprod / (xSegment * xSegment + ySegment * ySegment); } double projlen = Math.sqrt(projlenSq); if (projlen > seg) { projlen = seg; } double yDistance = Line2D.ptLineDist(p0.getX(), p0.getY(), pe .getX(), pe.getY(), x, y); int direction = Line2D.relativeCCW(p0.getX(), p0.getY(), pe .getX(), pe.getY(), x, y); if (direction == -1) { yDistance = -yDistance; } // Constructs the relative point for the label return new mxPoint( Math .round(((totalLength / 2 - length - projlen) / totalLength) * -2), Math.round(yDistance / scale)); } } return new mxPoint(); } /** * Returns the states for the given array of cells. The array contains all * states that are not null, that is, the returned array may have less * elements than the given array. */ public mxCellState[] getCellStates(Object[] cells) { List result = new ArrayList(cells.length); for (int i = 0; i < cells.length; i++) { Object state = getState(cells[i]); if (state != null) { result.add(state); } } return (mxCellState[]) result.toArray(); } /** * Returns the state for the given cell or null if no state is defined for * the cell. * * @param cell Cell whose state should be returned. * @return Returns the state for the given cell. */ public mxCellState getState(Object cell) { return getState(cell, false); } /** * Returns the cell state for the given cell. If create is true, then * the state is created if it does not yet exist. * * @param cell Cell for which a new state should be returned. * @param create Boolean indicating if a new state should be created if it * does not yet exist. * @return Returns the state for the given cell. */ public mxCellState getState(Object cell, boolean create) { mxCellState state = null; if (cell != null) { state = (mxCellState) states.get(cell); if (state == null && create && graph.isCellVisible(cell)) { state = createState(cell); states.put(cell, state); } } return state; } /** * Removes and returns the mxCellState for the given cell. * * @param cell mxCell for which the mxCellState should be removed. * @return Returns the mxCellState that has been removed. */ public mxCellState removeState(Object cell) { return (cell != null) ? (mxCellState) states.remove(cell) : null; } /** * Creates and returns a cell state for the given cell. * * @param cell Cell for which a new state should be created. * @return Returns a new state for the given cell. */ public mxCellState createState(Object cell) { return new mxCellState(this, cell, graph.getCellStyle(cell)); } /** * Action to change the current root in a view. */ public static class mxCurrentRootChange implements mxUndoableChange { /** * */ protected mxGraphView view; /** * */ protected Object root, previous; /** * */ protected boolean up; /** * Constructs a change of the current root in the given view. */ public mxCurrentRootChange(mxGraphView view, Object root) { this.view = view; this.root = root; this.previous = this.root; this.up = (root == null); if (!up) { Object tmp = view.getCurrentRoot(); mxIGraphModel model = view.graph.getModel(); while (tmp != null) { if (tmp == root) { up = true; break; } tmp = model.getParent(tmp); } } } /** * */ public mxGraphView getView() { return view; } /** * */ public Object getRoot() { return root; } /** * * @return */ public Object getPrevious() { return previous; } /** * * @return */ public boolean isUp() { return up; } /** * Changes the current root of the view. */ public void execute() { Object tmp = view.getCurrentRoot(); view.currentRoot = previous; previous = tmp; mxPoint translate = view.graph.getTranslateForRoot(view .getCurrentRoot()); if (translate != null) { view.translate = new mxPoint(-translate.getX(), translate .getY()); } // Removes all existing cell states and revalidates view.reload(); up = !up; String eventName = (up) ? mxEvent.UP : mxEvent.DOWN; view.fireEvent(eventName, new mxEventObject(new Object[] { previous, view.currentRoot })); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -