blob: 3153711920659c4a4daaa0c8c9644a3715b8d566 [file] [log] [blame]
/*
* 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.facade;
import com.intellij.vcs.log.graph.*;
import com.intellij.vcs.log.graph.actions.ActionController;
import com.intellij.vcs.log.graph.actions.GraphAnswer;
import com.intellij.vcs.log.graph.actions.GraphMouseAction;
import com.intellij.vcs.log.graph.api.LinearGraph;
import com.intellij.vcs.log.graph.api.LinearGraphWithCommitInfo;
import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo;
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.printer.PrintElementGenerator;
import com.intellij.vcs.log.graph.api.printer.PrintElementWithGraphElement;
import com.intellij.vcs.log.graph.api.printer.PrintElementsManager;
import com.intellij.vcs.log.graph.impl.print.PrintElementGeneratorImpl;
import com.intellij.vcs.log.graph.impl.visible.CurrentBranches;
import com.intellij.vcs.log.graph.impl.visible.adapters.LinearGraphAsGraphWithHiddenNodes;
import com.intellij.vcs.log.graph.utils.Flags;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
public abstract class AbstractVisibleGraph<CommitId> implements VisibleGraph<CommitId> {
@NotNull
protected static <CommitId> LinearGraphAsGraphWithHiddenNodes createBranchesGraph(@NotNull final PermanentGraphInfo<CommitId> permanentGraph,
@Nullable Set<CommitId> heads) {
if (heads == null) {
return new LinearGraphAsGraphWithHiddenNodes(permanentGraph.getPermanentLinearGraph());
} else {
Set<Integer> headIndexes = permanentGraph.getPermanentCommitsInfo().convertToCommitIndexes(heads);
if (headIndexes.contains(-1))
throw new IllegalStateException();
Flags visibleNodes = CurrentBranches.getVisibleNodes(permanentGraph.getPermanentLinearGraph(), headIndexes);
return new LinearGraphAsGraphWithHiddenNodes(permanentGraph.getPermanentLinearGraph(), visibleNodes);
}
}
@NotNull
protected final GraphAnswerImpl<CommitId> COMMIT_ID_GRAPH_ANSWER = new GraphAnswerImpl<CommitId>(null, Cursor.getDefaultCursor());
@NotNull
protected final LinearGraphWithCommitInfo<CommitId> myLinearGraphWithCommitInfo;
@NotNull
protected final PrintElementGenerator myPrintElementGenerator;
@NotNull
protected final PrintElementsManager myPrintElementsManager;
@NotNull
protected final Map<CommitId, GraphCommit<CommitId>> myCommitsWithNotLoadParent;
protected AbstractVisibleGraph(@NotNull LinearGraphWithCommitInfo<CommitId> linearGraphWithCommitInfo,
@NotNull Map<CommitId, GraphCommit<CommitId>> commitsWithNotLoadParent,
@NotNull PrintElementsManager printElementsManager) {
myLinearGraphWithCommitInfo = linearGraphWithCommitInfo;
myCommitsWithNotLoadParent = commitsWithNotLoadParent;
myPrintElementsManager = printElementsManager;
myPrintElementGenerator = new PrintElementGeneratorImpl(linearGraphWithCommitInfo, printElementsManager);
}
@Override
public int getVisibleCommitCount() {
return myLinearGraphWithCommitInfo.nodesCount();
}
@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
public CommitId getCommit() {
return myLinearGraphWithCommitInfo.getHashIndex(visibleRow);
}
@NotNull
@Override
public CommitId getOneOfHeads() {
return myLinearGraphWithCommitInfo.getOneOfHeads(visibleRow);
}
@NotNull
@Override
public Collection<PrintElement> getPrintElements() {
return myPrintElementGenerator.getPrintElements(visibleRow);
}
@NotNull
@Override
public RowType getRowType() {
return RowType.NORMAL;
}
};
}
@Override
public int getVisibleRowIndex(@NotNull CommitId commitId) {
return myLinearGraphWithCommitInfo.getNodeIndex(commitId);
}
@NotNull
@Override
public ActionController<CommitId> getActionController() {
return new ActionControllerImpl();
}
abstract protected void setLinearBranchesExpansion(boolean collapse);
@NotNull
abstract protected GraphAnswer<CommitId> clickByElement(@NotNull GraphElement graphElement);
@NotNull
protected GraphAnswer<CommitId> clickByElement(@Nullable PrintElementWithGraphElement printElement) {
if (printElement == null) {
return COMMIT_ID_GRAPH_ANSWER;
}
if (printElement instanceof SimplePrintElement) {
SimplePrintElement simplePrintElement = (SimplePrintElement)printElement;
int upNodeIndex, downNodeIndex;
@NotNull GraphElement graphElement = printElement.getGraphElement();
switch (simplePrintElement.getType()) {
case NODE:
assert graphElement instanceof GraphNode;
return clickByElement(graphElement);
case UP_ARROW:
assert graphElement instanceof GraphEdge;
upNodeIndex = ((GraphEdge)graphElement).getUpNodeIndex();
return createJumpAnswer(upNodeIndex);
case DOWN_ARROW:
assert graphElement instanceof GraphEdge;
downNodeIndex = ((GraphEdge)graphElement).getDownNodeIndex();
if (downNodeIndex != LinearGraph.NOT_LOAD_COMMIT)
return createJumpAnswer(downNodeIndex);
else {
upNodeIndex = ((GraphEdge)graphElement).getUpNodeIndex();
int edgeIndex = myLinearGraphWithCommitInfo.getDownNodes(upNodeIndex).indexOf(LinearGraph.NOT_LOAD_COMMIT);
GraphCommit<CommitId> commitIdGraphCommit =
myCommitsWithNotLoadParent.get(myLinearGraphWithCommitInfo.getHashIndex(upNodeIndex));
CommitId jumpTo = commitIdGraphCommit.getParents().get(edgeIndex);
return createJumpAnswer(jumpTo);
}
default:
throw new IllegalStateException("Unsupported SimplePrintElement type: " + simplePrintElement.getType());
}
}
if (printElement instanceof EdgePrintElement) {
GraphElement graphElement = printElement.getGraphElement();
assert graphElement instanceof GraphEdge;
return clickByElement(graphElement);
}
return COMMIT_ID_GRAPH_ANSWER;
}
protected GraphAnswer<CommitId> createJumpAnswer(int nodeIndex) {
return createJumpAnswer(myLinearGraphWithCommitInfo.getHashIndex(nodeIndex));
}
private GraphAnswerImpl<CommitId> createJumpAnswer(CommitId commitId) {
myPrintElementGenerator.invalidate();
return new GraphAnswerImpl<CommitId>(commitId, null);
}
protected static class GraphAnswerImpl<CommitId> implements GraphAnswer<CommitId> {
@Nullable
private final CommitId myCommitId;
@Nullable
private final Cursor myCursor;
public GraphAnswerImpl(@Nullable CommitId commitId, @Nullable Cursor cursor) {
myCommitId = commitId;
myCursor = cursor;
}
@Nullable
@Override
public Cursor getCursorToSet() {
return myCursor;
}
@Nullable
@Override
public CommitId getCommitToJump() {
return myCommitId;
}
}
protected class ActionControllerImpl implements ActionController<CommitId> {
@NotNull
@Override
public GraphAnswer<CommitId> performMouseAction(@NotNull GraphMouseAction graphMouseAction) {
PrintElementWithGraphElement printElement = getPrintElementWithGraphElement(graphMouseAction);
switch (graphMouseAction.getType()) {
case OVER: {
Cursor cursor = myPrintElementsManager.performOverElement(printElement);
return new GraphAnswerImpl<CommitId>(null, cursor);
}
case CLICK:
myPrintElementsManager.performOverElement(printElement);
return AbstractVisibleGraph.this.clickByElement(printElement);
default: {
throw new IllegalStateException("Not supported GraphMouseAction type: " + graphMouseAction.getType());
}
}
}
@Nullable
private PrintElementWithGraphElement getPrintElementWithGraphElement(@NotNull GraphMouseAction graphMouseAction) {
PrintElement affectedElement = graphMouseAction.getAffectedElement();
if (affectedElement == null)
return null;
return myPrintElementGenerator.toPrintElementWithGraphElement(affectedElement);
}
@Override
public boolean areLongEdgesHidden() {
return myPrintElementGenerator.areLongEdgesHidden();
}
@Override
public void setLongEdgesHidden(boolean longEdgesHidden) {
myPrintElementGenerator.setLongEdgesHidden(longEdgesHidden);
}
@Override
public void setLinearBranchesExpansion(boolean collapse) {
AbstractVisibleGraph.this.setLinearBranchesExpansion(collapse);
myPrintElementGenerator.invalidate();
}
}
}