diff options
Diffstat (limited to 'platform/vcs-log/graph/src/com/intellij')
6 files changed, 236 insertions, 3 deletions
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/AbstractVisibleGraph.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/AbstractVisibleGraph.java index 18d7222d9257..83cb53fd8c8f 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/AbstractVisibleGraph.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/AbstractVisibleGraph.java @@ -85,6 +85,8 @@ public abstract class AbstractVisibleGraph<CommitId> implements VisibleGraph<Com @NotNull @Override public RowInfo<CommitId> getRowInfo(final int visibleRow) { + if (visibleRow < 0 || visibleRow >= getVisibleCommitCount()) + throw new IndexOutOfBoundsException("VisibleCommitCount is: " + getVisibleCommitCount() + ", but visibleRow: " + visibleRow); return new RowInfo<CommitId>() { @NotNull @Override diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/print/AbstractPrintElementsManager.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/print/AbstractPrintElementsManager.java index 8219c50a4851..8da596f026bf 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/print/AbstractPrintElementsManager.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/print/AbstractPrintElementsManager.java @@ -108,8 +108,8 @@ public abstract class AbstractPrintElementsManager<CommitId> implements PrintEle if (printElement != null) { GraphEdge graphEdge = containedCollapsedEdge(printElement.getGraphElement(), myPrintedLinearGraph); - if (graphEdge != null) { - mySelectedNodes = ContainerUtil.set(graphEdge.getUpNodeIndex(), graphEdge.getDownNodeIndex()); + if (graphEdge != null && allowSelectCollapsedEdge(graphEdge)) { + mySelectedNodes = ContainerUtil.set(graphEdge.getUpNodeIndex(), graphEdge.getDownNodeIndex()); } else { mySelectedNodes = getSelectedNodes(printElement.getGraphElement()); } @@ -150,4 +150,8 @@ public abstract class AbstractPrintElementsManager<CommitId> implements PrintEle @NotNull protected abstract Set<Integer> getSelectedNodes(@NotNull GraphElement graphElement); + + protected boolean allowSelectCollapsedEdge(@NotNull GraphEdge graphEdge) { + return true; + } } diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/print/FilterPrintElementsManager.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/print/FilterPrintElementsManager.java index 517128e01f4f..12ac6af5f388 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/print/FilterPrintElementsManager.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/print/FilterPrintElementsManager.java @@ -18,6 +18,7 @@ package com.intellij.vcs.log.graph.impl.print; import com.intellij.vcs.log.graph.GraphColorManager; import com.intellij.vcs.log.graph.api.LinearGraphWithCommitInfo; +import com.intellij.vcs.log.graph.api.elements.GraphEdge; import com.intellij.vcs.log.graph.api.elements.GraphElement; import org.jetbrains.annotations.NotNull; @@ -35,4 +36,9 @@ public class FilterPrintElementsManager<CommitId> extends AbstractPrintElementsM protected Set<Integer> getSelectedNodes(@NotNull GraphElement graphElement) { return Collections.emptySet(); } + + @Override + protected boolean allowSelectCollapsedEdge(@NotNull GraphEdge graphEdge) { + return false; + } } diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/DottedEdges.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/DottedEdges.java new file mode 100644 index 000000000000..d6ff4230b4df --- /dev/null +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/DottedEdges.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.vcs.log.graph.impl.visible; + +import com.intellij.util.ArrayUtil; +import com.intellij.util.SmartList; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class DottedEdges { + + @NotNull + public static DottedEdges newInstance(@NotNull MultiMap<Integer, Integer> delegate) { + int[] nodesWithEdges = ArrayUtil.toIntArray(delegate.keySet()); + Arrays.sort(nodesWithEdges); + + int[] startIndexes = new int[nodesWithEdges.length + 1]; + int[] edges = new int[delegate.values().size()]; + + int start = 0; + for (int i = 0; i < startIndexes.length - 1; i++) { + startIndexes[i] = start; + for (int toNode : delegate.get(nodesWithEdges[i])) { + edges[start] = toNode; + start++; + } + } + startIndexes[startIndexes.length - 1] = start; + + return new DottedEdges(nodesWithEdges, startIndexes, edges); + } + + @NotNull private final int[] sortedStartNodes; // graph is not oriented => end nodes are there as well + + @NotNull private final int[] startEdgesPosition; + + @NotNull private final int[] endNodes; + + public DottedEdges(@NotNull int[] sortedStartNodes, @NotNull int[] startEdgesPosition, @NotNull int[] endNodes) { + this.sortedStartNodes = sortedStartNodes; + this.startEdgesPosition = startEdgesPosition; + this.endNodes = endNodes; + } + + public List<Integer> getAdjacentNodes(int nodeIndex) { + int smallIndex = Arrays.binarySearch(sortedStartNodes, nodeIndex); + if (smallIndex < 0) + return Collections.emptyList(); + List<Integer> result = new SmartList<Integer>(); + + for (int i = startEdgesPosition[smallIndex]; i < startEdgesPosition[smallIndex + 1]; i++) + result.add(endNodes[i]); + return result; + } + +} diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/DottedEdgesComputer.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/DottedEdgesComputer.java new file mode 100644 index 000000000000..a5d9ef7cc15f --- /dev/null +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/DottedEdgesComputer.java @@ -0,0 +1,129 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.vcs.log.graph.impl.visible; + +import com.intellij.util.containers.MultiMap; +import com.intellij.vcs.log.graph.api.LinearGraph; +import com.intellij.vcs.log.graph.utils.Flags; +import org.jetbrains.annotations.NotNull; + +public class DottedEdgesComputer { + @NotNull + public static MultiMap<Integer, Integer> compute(@NotNull LinearGraph delegateGraph, @NotNull Flags visibleNodes) { + DottedEdgesComputer dottedEdgesComputer = new DottedEdgesComputer(delegateGraph, visibleNodes); + dottedEdgesComputer.compute(); + return dottedEdgesComputer.myDottedEdges; + } + + @NotNull + private final LinearGraph myDelegateGraph; + + @NotNull + private final Flags myVisibleNodes; + + @NotNull + private final MultiMap<Integer, Integer> myDottedEdges; + + @NotNull + private final int[] myNumbers; + + private DottedEdgesComputer(@NotNull LinearGraph delegateGraph, @NotNull Flags visibleNodes) { + assert delegateGraph.nodesCount() == visibleNodes.size(); + myDelegateGraph = delegateGraph; + myVisibleNodes = visibleNodes; + myDottedEdges = MultiMap.create(); + myNumbers = new int[myDelegateGraph.nodesCount()]; + } + + private void putEdge(int node1, int node2) { + myDottedEdges.putValue(node1, node2); + myDottedEdges.putValue(node2, node1); + } + + private void compute() { + downWalk(); + upWalk(); + } + + private void downWalk() { + for (int i = 0; i < myDelegateGraph.nodesCount() - 1; i++) { + if (myVisibleNodes.get(i)) { + int nearlyUp = Integer.MIN_VALUE; + int maxAdjNumber = Integer.MIN_VALUE; + for (int upNode : myDelegateGraph.getUpNodes(i)) { + if (myVisibleNodes.get(upNode)) + maxAdjNumber = Math.max(maxAdjNumber, myNumbers[upNode]); + else + nearlyUp = Math.max(nearlyUp, myNumbers[upNode]); + } + + if (nearlyUp == maxAdjNumber || nearlyUp == Integer.MIN_VALUE) { + myNumbers[i] = maxAdjNumber; + } else { + putEdge(i, nearlyUp); + myNumbers[i] = nearlyUp; + } + } else { + // node i invisible + + int nearlyUp = Integer.MIN_VALUE; + for (int upNode : myDelegateGraph.getUpNodes(i)) { + if (myVisibleNodes.get(upNode)) + nearlyUp = Math.max(nearlyUp, upNode); + else + nearlyUp = Math.max(nearlyUp, myNumbers[upNode]); + } + myNumbers[i] = nearlyUp; + } + } + } + + private void upWalk() { + for (int i = myDelegateGraph.nodesCount() - 1; i >= 0; i--) { + if (myVisibleNodes.get(i)) { + int nearlyDown = Integer.MAX_VALUE; + int minAdjNumber = Integer.MAX_VALUE; + for (int downNode : myDelegateGraph.getDownNodes(i)) { + if (downNode == LinearGraph.NOT_LOAD_COMMIT) continue; + if (myVisibleNodes.get(downNode)) + minAdjNumber = Math.min(minAdjNumber, myNumbers[downNode]); + else + nearlyDown = Math.min(nearlyDown, myNumbers[downNode]); + } + + if (nearlyDown == minAdjNumber || nearlyDown == Integer.MAX_VALUE) { + myNumbers[i] = minAdjNumber; + } else { + putEdge(i, nearlyDown); + myNumbers[i] = nearlyDown; + } + + } else { + // node i invisible + + int nearlyDown = Integer.MAX_VALUE; + for (int downNode : myDelegateGraph.getDownNodes(i)) { + if (downNode == LinearGraph.NOT_LOAD_COMMIT) continue; + if (myVisibleNodes.get(downNode)) + nearlyDown = Math.min(nearlyDown, downNode); + else + nearlyDown = Math.min(nearlyDown, myNumbers[downNode]); + } + myNumbers[i] = nearlyDown; + } + } + } +} diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/FilterGraphWithHiddenNodes.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/FilterGraphWithHiddenNodes.java index 72f02273d488..667b8c744fc4 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/FilterGraphWithHiddenNodes.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/FilterGraphWithHiddenNodes.java @@ -19,6 +19,7 @@ package com.intellij.vcs.log.graph.impl.visible; import com.intellij.openapi.util.Condition; import com.intellij.util.Consumer; import com.intellij.util.SmartList; +import com.intellij.util.containers.MultiMap; import com.intellij.vcs.log.graph.api.LinearGraph; import com.intellij.vcs.log.graph.api.LinearGraphWithHiddenNodes; import com.intellij.vcs.log.graph.api.elements.GraphEdge; @@ -39,6 +40,9 @@ public class FilterGraphWithHiddenNodes implements LinearGraphWithHiddenNodes { private final Flags myVisibleNodes; @NotNull + private final DottedEdges myDottedEdges; + + @NotNull private final SetListenerController<UpdateListener> myListenerController = new SetListenerController<UpdateListener>(); public FilterGraphWithHiddenNodes(@NotNull LinearGraphWithHiddenNodes delegateGraph, @NotNull Condition<Integer> isVisibleNode) { @@ -47,6 +51,10 @@ public class FilterGraphWithHiddenNodes implements LinearGraphWithHiddenNodes { for (int i = 0; i < delegateGraph.nodesCount(); i++) { myVisibleNodes.set(i, delegateGraph.nodeIsVisible(i) && isVisibleNode.value(i)); // todo: think about it: may be drop myVisibleNodes } + + MultiMap<Integer, Integer> edges = DottedEdgesComputer.compute(myDelegateGraph, myVisibleNodes); + myDottedEdges = DottedEdges.newInstance(edges); + addUpdateListener(); } @@ -78,7 +86,10 @@ public class FilterGraphWithHiddenNodes implements LinearGraphWithHiddenNodes { @NotNull @Override public GraphEdge.Type getEdgeType(int upNodeIndex, int downNodeIndex) { - return GraphEdge.Type.USUAL; + if (myDottedEdges.getAdjacentNodes(upNodeIndex).contains(downNodeIndex)) + return GraphEdge.Type.HIDE; + else + return GraphEdge.Type.USUAL; } @NotNull @@ -100,6 +111,10 @@ public class FilterGraphWithHiddenNodes implements LinearGraphWithHiddenNodes { if (nodeIsVisible(upNode)) upNodes.add(upNode); } + for (int adjNode : myDottedEdges.getAdjacentNodes(nodeIndex)) { + if (adjNode < nodeIndex) + upNodes.add(adjNode); + } return upNodes; } @@ -111,6 +126,10 @@ public class FilterGraphWithHiddenNodes implements LinearGraphWithHiddenNodes { if (downNode != LinearGraph.NOT_LOAD_COMMIT && nodeIsVisible(downNode)) downNodes.add(downNode); } + for (int adjNode : myDottedEdges.getAdjacentNodes(nodeIndex)) { + if (adjNode > nodeIndex) + downNodes.add(adjNode); + } return downNodes; } } |