/*
* 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.collapsing;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.graph.api.LinearGraph;
import com.intellij.vcs.log.graph.api.elements.GraphEdge;
import com.intellij.vcs.log.graph.api.elements.GraphElement;
import com.intellij.vcs.log.graph.api.elements.GraphNode;
import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo;
import com.intellij.vcs.log.graph.impl.facade.CascadeController;
import com.intellij.vcs.log.graph.impl.facade.GraphChanges;
import com.intellij.vcs.log.graph.impl.facade.ReachableNodes;
import com.intellij.vcs.log.graph.utils.UnsignedBitSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
public class CollapsedController extends CascadeController {
@NotNull private CollapsedGraph myCollapsedGraph;
public CollapsedController(@NotNull CascadeController delegateLinearGraphController,
@NotNull final PermanentGraphInfo<?> permanentGraphInfo,
@Nullable Set<Integer> idsOfVisibleBranches) {
super(delegateLinearGraphController, permanentGraphInfo);
UnsignedBitSet initVisibility =
ReachableNodes.getReachableNodes(permanentGraphInfo.getLinearGraph(), idsOfVisibleBranches);
myCollapsedGraph = CollapsedGraph.newInstance(getDelegateController().getCompiledGraph(), initVisibility);
}
@NotNull
@Override
protected LinearGraphAnswer delegateGraphChanged(@NotNull LinearGraphAnswer delegateAnswer) {
if (delegateAnswer.getGraphChanges() != null) {
LinearGraph delegateGraph = getDelegateController().getCompiledGraph();
myCollapsedGraph = CollapsedGraph.updateInstance(myCollapsedGraph, delegateGraph);
// some new edges and node appeared, so we expand them
applyDelegateChanges(delegateGraph, delegateAnswer.getGraphChanges());
}
return delegateAnswer; // if somebody outside actually uses changes we return here they are screwed
}
private void applyDelegateChanges(LinearGraph graph, GraphChanges<Integer> changes) {
Set<Integer> nodesToShow = ContainerUtil.newHashSet();
for (GraphChanges.Edge<Integer> e : changes.getChangedEdges()) {
if (!e.removed()) {
Integer upId = e.upNodeId();
if (upId != null) {
Integer upIndex = graph.getNodeIndex(upId);
if (upIndex != null) {
nodesToShow.add(upIndex);
}
}
Integer downId = e.downNodeId();
if (downId != null) {
Integer downIndex = graph.getNodeIndex(downId);
if (downIndex != null) {
nodesToShow.add(downIndex);
}
}
}
}
for (GraphChanges.Node<Integer> e : changes.getChangedNodes()) {
if (!e.removed()) {
Integer nodeIndex = graph.getNodeIndex(e.getNodeId());
if (nodeIndex != null) {
nodesToShow.add(nodeIndex);
}
}
}
CollapsedActionManager.expandNodes(myCollapsedGraph, nodesToShow);
}
@Nullable
@Override
protected LinearGraphAnswer performAction(@NotNull LinearGraphAction action) {
return CollapsedActionManager.performAction(this, action);
}
@NotNull
@Override
public LinearGraph getCompiledGraph() {
return myCollapsedGraph.getCompiledGraph();
}
@NotNull
protected CollapsedGraph getCollapsedGraph() {
return myCollapsedGraph;
}
@Nullable
@Override
protected GraphElement convertToDelegate(@NotNull GraphElement graphElement) {
return convertToDelegate(graphElement, myCollapsedGraph);
}
@Nullable
public static GraphElement convertToDelegate(@NotNull GraphElement graphElement, CollapsedGraph collapsedGraph) {
if (graphElement instanceof GraphEdge) {
Integer upIndex = ((GraphEdge)graphElement).getUpNodeIndex();
Integer downIndex = ((GraphEdge)graphElement).getDownNodeIndex();
if (upIndex != null && downIndex != null && collapsedGraph.isMyCollapsedEdge(upIndex, downIndex)) return null;
Integer convertedUpIndex = upIndex == null ? null : collapsedGraph.convertToDelegateNodeIndex(upIndex);
Integer convertedDownIndex = downIndex == null ? null : collapsedGraph.convertToDelegateNodeIndex(downIndex);
return new GraphEdge(convertedUpIndex, convertedDownIndex, ((GraphEdge)graphElement).getTargetId(),
((GraphEdge)graphElement).getType());
}
else if (graphElement instanceof GraphNode) {
return new GraphNode(collapsedGraph.convertToDelegateNodeIndex((((GraphNode)graphElement).getNodeIndex())),
((GraphNode)graphElement).getType());
}
return null;
}
}