summaryrefslogtreecommitdiff
path: root/platform/vcs-log/graph/src/com/intellij/vcs
diff options
context:
space:
mode:
Diffstat (limited to 'platform/vcs-log/graph/src/com/intellij/vcs')
-rw-r--r--platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/AbstractVisibleGraph.java2
-rw-r--r--platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/print/AbstractPrintElementsManager.java8
-rw-r--r--platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/print/FilterPrintElementsManager.java6
-rw-r--r--platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/DottedEdges.java73
-rw-r--r--platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/DottedEdgesComputer.java129
-rw-r--r--platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/visible/FilterGraphWithHiddenNodes.java21
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;
}
}