/* * 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 implements VisibleGraph { @NotNull protected static LinearGraphAsGraphWithHiddenNodes createBranchesGraph(@NotNull final PermanentGraphInfo permanentGraph, @Nullable Set heads) { if (heads == null) { return new LinearGraphAsGraphWithHiddenNodes(permanentGraph.getPermanentLinearGraph()); } else { Set 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 COMMIT_ID_GRAPH_ANSWER = new GraphAnswerImpl(null, Cursor.getDefaultCursor()); @NotNull protected final LinearGraphWithCommitInfo myLinearGraphWithCommitInfo; @NotNull protected final PrintElementGenerator myPrintElementGenerator; @NotNull protected final PrintElementsManager myPrintElementsManager; @NotNull protected final Map> myCommitsWithNotLoadParent; protected AbstractVisibleGraph(@NotNull LinearGraphWithCommitInfo linearGraphWithCommitInfo, @NotNull Map> 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 getRowInfo(final int visibleRow) { if (visibleRow < 0 || visibleRow >= getVisibleCommitCount()) throw new IndexOutOfBoundsException("VisibleCommitCount is: " + getVisibleCommitCount() + ", but visibleRow: " + visibleRow); return new RowInfo() { @NotNull @Override public CommitId getCommit() { return myLinearGraphWithCommitInfo.getHashIndex(visibleRow); } @NotNull @Override public CommitId getOneOfHeads() { return myLinearGraphWithCommitInfo.getOneOfHeads(visibleRow); } @NotNull @Override public Collection getPrintElements() { return myPrintElementGenerator.getPrintElements(visibleRow); } }; } @Override public int getVisibleRowIndex(@NotNull CommitId commitId) { return myLinearGraphWithCommitInfo.getNodeIndex(commitId); } @NotNull @Override public ActionController getActionController() { return new ActionControllerImpl(); } abstract protected void setLinearBranchesExpansion(boolean collapse); @NotNull abstract protected GraphAnswer clickByElement(@NotNull GraphElement graphElement); @NotNull protected GraphAnswer 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 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 createJumpAnswer(int nodeIndex) { return createJumpAnswer(myLinearGraphWithCommitInfo.getHashIndex(nodeIndex)); } private GraphAnswerImpl createJumpAnswer(CommitId commitId) { myPrintElementGenerator.invalidate(); return new GraphAnswerImpl(commitId, null); } protected static class GraphAnswerImpl implements GraphAnswer { @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 { @NotNull @Override public GraphAnswer performMouseAction(@NotNull GraphMouseAction graphMouseAction) { PrintElementWithGraphElement printElement = getPrintElementWithGraphElement(graphMouseAction); switch (graphMouseAction.getType()) { case OVER: { Cursor cursor = myPrintElementsManager.performOverElement(printElement); return new GraphAnswerImpl(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(); } } }