package jetbrains.mps.vcs.annotate;
/*Generated by MPS */
import jetbrains.mps.nodeEditor.leftHighlighter.AbstractLeftColumn;
import java.awt.Color;
import jetbrains.mps.openapi.editor.style.StyleRegistry;
import java.awt.Font;
import jetbrains.mps.nodeEditor.EditorSettings;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import java.util.Map;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.HashMap;
import com.intellij.openapi.vcs.annotate.FileAnnotation;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.history.VcsFileRevision;
import com.intellij.openapi.vcs.annotate.LineAnnotationAspect;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.mps.openapi.model.EditableSModel;
import jetbrains.mps.smodel.persistence.lines.LineContent;
import jetbrains.mps.vcs.diff.changes.ModelChange;
import java.util.Set;
import com.intellij.util.messages.MessageBusConnection;
import jetbrains.mps.nodeEditor.leftHighlighter.LeftEditorHighlighter;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.model.SNodeId;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.HashSet;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import org.jetbrains.mps.openapi.language.SAbstractConcept;
import jetbrains.mps.internal.collections.runtime.ISelector;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.baseLanguage.closures.runtime.Wrappers;
import jetbrains.mps.smodel.persistence.def.ModelReadException;
import jetbrains.mps.vcspersistence.VCSPersistenceSupport;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.vcs.changes.ui.ChangesViewContentManager;
import com.intellij.openapi.ui.MessageType;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import com.intellij.openapi.vcs.actions.AnnotationColors;
import com.intellij.ui.ColorUtil;
import jetbrains.mps.vcs.changesmanager.CurrentDifferenceRegistry;
import jetbrains.mps.vcs.changesmanager.CurrentDifference;
import jetbrains.mps.smodel.ModelAccess;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import jetbrains.mps.nodeEditor.highlighter.EditorComponentCreateListener;
import jetbrains.mps.vcs.diff.changes.SetPropertyChange;
import jetbrains.mps.smodel.persistence.lines.PropertyLineContent;
import jetbrains.mps.vcs.diff.changes.SetReferenceChange;
import jetbrains.mps.smodel.persistence.lines.ReferenceLineContent;
import jetbrains.mps.vcs.diff.changes.NodeGroupChange;
import jetbrains.mps.util.IterableUtil;
import jetbrains.mps.smodel.persistence.lines.NodeLineContent;
import java.awt.Graphics;
import jetbrains.mps.nodeEditor.EditorComponent;
import java.awt.Graphics2D;
import jetbrains.mps.nodeEditor.cells.FontRegistry;
import java.awt.FontMetrics;
import jetbrains.mps.internal.collections.runtime.ILeftCombinator;
import org.jetbrains.annotations.Nullable;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.nodeEditor.messageTargets.CellFinder;
import java.util.Collections;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import java.util.Iterator;
import jetbrains.mps.baseLanguage.closures.runtime.YieldingIterator;
import java.awt.event.MouseEvent;
import java.awt.Cursor;
import com.intellij.openapi.vcs.annotate.LineAnnotationAspectAdapter;
import javax.swing.JPopupMenu;
import com.intellij.openapi.actionSystem.AnAction;
import jetbrains.mps.workbench.action.BaseAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Separator;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.util.ui.TextTransferable;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import jetbrains.mps.workbench.action.ActionUtils;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.project.Project;
import jetbrains.mps.vcs.changesmanager.CurrentDifferenceAdapter;
import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.vcs.changes.BackgroundFromStartOption;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.vcs.CommittedChangesProvider;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangesUtil;
import java.io.File;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.fileTypes.FileType;
import jetbrains.mps.fileTypes.MPSFileTypeFactory;
import jetbrains.mps.vcspersistence.VCSPersistenceUtil;
import jetbrains.mps.util.FileUtil;
import jetbrains.mps.project.MPSExtentions;
import jetbrains.mps.vcs.diff.merge.MergeTemporaryModel;
import jetbrains.mps.ide.project.ProjectHelper;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.DiffContentFactory;
import com.intellij.diff.requests.DiffRequest;
import com.intellij.diff.requests.SimpleDiffRequest;
import jetbrains.mps.vcs.platform.integration.ModelDiffViewer;
import com.intellij.diff.DiffManager;
import com.intellij.openapi.vcs.VcsException;
import jetbrains.mps.vcs.diff.ChangeSet;
public class AnnotationColumn extends AbstractLeftColumn {
private static final Color ANNOTATION_COLOR = StyleRegistry.getInstance().getColor("ANNOTATIONS_COLOR");
private Font myFont = EditorSettings.getInstance().getDefaultEditorFont();
private List<AnnotationAspectSubcolumn> myAspectSubcolumns = ListSequence.fromList(new ArrayList<AnnotationAspectSubcolumn>());
private List<Integer> myPseudoLinesY;
private List<Integer> myPseudoLinesToFileLines;
private int mySubcolumnInterval;
private Map<String, Color> myAuthorsToColors = MapSequence.fromMap(new HashMap<String, Color>());
private FileAnnotation myFileAnnotation;
private Map<VcsRevisionNumber, VcsFileRevision> myRevisionNumberToRevision = MapSequence.fromMap(new HashMap<VcsRevisionNumber, VcsFileRevision>());
private LineAnnotationAspect myAuthorAnnotationAspect;
private AbstractVcs myVcs;
private VirtualFile myVirtualFile;
private EditableSModel myModel;
private List<LineContent> myFileLineToContent;
private Map<ModelChange, LineContent[]> myChangesToLineContents = MapSequence.fromMap(new HashMap<ModelChange, LineContent[]>());
private Set<Integer> myCurrentPseudoLines = null;
private VcsRevisionRange myRevisionRange;
private ViewActionGroup myViewActionGroup;
private AnnotationColumn.MyDifferenceListener myDifferenceListener = new AnnotationColumn.MyDifferenceListener();
private boolean myShowAdditionalInfo = false;
private MessageBusConnection myMessageBusConnection;
public AnnotationColumn(LeftEditorHighlighter leftEditorHighlighter, SNode root, FileAnnotation fileAnnotation, final AbstractVcs vcs, VirtualFile virtualFile) {
super(leftEditorHighlighter);
Set<SNodeId> descendantIds = SetSequence.fromSetWithValues(new HashSet<SNodeId>(), ListSequence.fromList(SNodeOperations.getNodeDescendants(root, null, true, new SAbstractConcept[]{})).select(new ISelector<SNode, SNodeId>() {
public SNodeId select(SNode n) {
return n.getNodeId();
}
}));
SModel model = SNodeOperations.getModel(root);
myFileAnnotation = fileAnnotation;
for (VcsFileRevision rev : ListSequence.fromList(fileAnnotation.getRevisions())) {
MapSequence.fromMap(myRevisionNumberToRevision).put(rev.getRevisionNumber(), rev);
}
final Wrappers._T<ModelReadException> mre = new Wrappers._T<ModelReadException>(null);
try {
myFileLineToContent = VCSPersistenceSupport.getLineToContentMap(myFileAnnotation.getAnnotatedContent());
} catch (ModelReadException e) {
mre.value = e;
}
if (myFileLineToContent == null) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
String msg = "Couldn't show annotation";
if (mre.value != null && mre.value.getCause() != null) {
msg += ": " + mre.value.getCause().getMessage();
}
ToolWindowManager.getInstance(vcs.getProject()).notifyByBalloon(ChangesViewContentManager.TOOLWINDOW_ID, MessageType.WARNING, msg);
close();
}
});
return;
}
myAuthorAnnotationAspect = Sequence.fromIterable(Sequence.fromArray(myFileAnnotation.getAspects())).findFirst(new IWhereFilter<LineAnnotationAspect>() {
public boolean accept(LineAnnotationAspect a) {
return LineAnnotationAspect.AUTHOR.equals(a.getId());
}
});
Map<SNodeId, Integer> nodeIdToFileLine = MapSequence.fromMap(new HashMap<SNodeId, Integer>());
for (int line = 0; line < ListSequence.fromList(myFileLineToContent).count(); line++) {
SNode node = null;
SNodeId id = check_5mnya_a0b0k0v(ListSequence.fromList(myFileLineToContent).getElement(line));
if (id != null && SetSequence.fromSet(descendantIds).contains(id)) {
node = model.getNode(id);
}
if (node == null) {
continue;
}
if (MapSequence.fromMap(nodeIdToFileLine).containsKey(id)) {
MapSequence.fromMap(nodeIdToFileLine).put(id, getFileLineWithMaxRevision(MapSequence.fromMap(nodeIdToFileLine).get(id), line));
} else {
MapSequence.fromMap(nodeIdToFileLine).put(id, line);
}
}
ListSequence.fromList(myAspectSubcolumns).addSequence(Sequence.fromIterable(Sequence.fromArray(fileAnnotation.getAspects())).select(new ISelector<LineAnnotationAspect, AnnotationAspectSubcolumn>() {
public AnnotationAspectSubcolumn select(LineAnnotationAspect a) {
return new AnnotationAspectSubcolumn(AnnotationColumn.this, a);
}
}));
ListSequence.fromList(myAspectSubcolumns).addElement(new CommitNumberSubcolumn(this, myFileAnnotation));
for (VcsFileRevision revision : ListSequence.fromList(myFileAnnotation.getRevisions())) {
String author = revision.getAuthor();
if (!(MapSequence.fromMap(myAuthorsToColors).containsKey(author))) {
Color color = AnnotationColors.BG_COLORS[MapSequence.fromMap(myAuthorsToColors).count() % AnnotationColors.BG_COLORS.length];
if (StyleRegistry.getInstance().isDarkTheme()) {
color = ColorUtil.shift(color, 0.3);
}
MapSequence.fromMap(myAuthorsToColors).put(author, color);
}
}
myViewActionGroup = new ViewActionGroup(this, myAspectSubcolumns);
myRevisionRange = new VcsRevisionRange(this, myFileAnnotation);
ListSequence.fromList(myAspectSubcolumns).addElement(new HighlightRevisionSubcolumn(this, myRevisionRange));
myVirtualFile = virtualFile;
myModel = (EditableSModel) model;
myVcs = vcs;
final CurrentDifferenceRegistry registry = CurrentDifferenceRegistry.getInstance(getProject());
registry.getCommandQueue().runTask(new Runnable() {
public void run() {
final CurrentDifference currentDifference = registry.getCurrentDifference(myModel);
ModelAccess.instance().runReadAction(new Runnable() {
public void run() {
ListSequence.fromList(check_5mnya_a0a0a0a1a0a0v0v(currentDifference.getChangeSet())).visitAll(new IVisitor<ModelChange>() {
public void visit(ModelChange ch) {
saveChange(ch);
}
});
}
});
currentDifference.addDifferenceListener(myDifferenceListener);
}
});
myMessageBusConnection = getProject().getMessageBus().connect();
myMessageBusConnection.subscribe(EditorComponentCreateListener.EDITOR_COMPONENT_CREATION, new AnnotationColumn.MyEditorComponentCreateListener());
}
private void saveChange(ModelChange ch) {
if (ch instanceof SetPropertyChange) {
SetPropertyChange spc = (SetPropertyChange) ch;
MapSequence.fromMap(myChangesToLineContents).put(ch, new LineContent[]{new PropertyLineContent(spc.getAffectedNodeId(), spc.getPropertyName())});
} else if (ch instanceof SetReferenceChange) {
SetReferenceChange src = (SetReferenceChange) ch;
MapSequence.fromMap(myChangesToLineContents).put(ch, new LineContent[]{new ReferenceLineContent(src.getAffectedNodeId(), src.getRole())});
} else if (ch instanceof NodeGroupChange) {
NodeGroupChange ngc = (NodeGroupChange) ch;
List<? extends SNode> newChildren = IterableUtil.asList(myModel.getNode(ngc.getParentNodeId()).getChildren(ngc.getRole()));
MapSequence.fromMap(myChangesToLineContents).put(ch, ListSequence.fromList(newChildren).page(ngc.getResultBegin(), ngc.getResultEnd()).select(new ISelector<SNode, NodeLineContent>() {
public NodeLineContent select(SNode n) {
return new NodeLineContent(n.getNodeId());
}
}).toGenericArray(NodeLineContent.class));
}
}
private void calculateCurrentPseudoLinesLater() {
ModelAccess.instance().runReadInEDT(new Runnable() {
public void run() {
myCurrentPseudoLines = SetSequence.fromSet(new HashSet<Integer>());
for (LineContent[] lineContents : MapSequence.fromMap(myChangesToLineContents).values()) {
for (LineContent lc : lineContents) {
SetSequence.fromSet(myCurrentPseudoLines).addSequence(Sequence.fromIterable(getPseudoLinesForContent(lc)));
}
}
getLeftEditorHighlighter().repaint();
}
});
}
@Override
public String getName() {
return "Annotations";
}
@Override
public void paint(Graphics graphics) {
graphics.setFont(myFont);
EditorComponent.turnOnAliasingIfPossible((Graphics2D) graphics);
Map<AnnotationAspectSubcolumn, Integer> subcolumnToX = MapSequence.fromMap(new HashMap<AnnotationAspectSubcolumn, Integer>());
int x = getX() + 1;
for (AnnotationAspectSubcolumn subcolumn : ListSequence.fromList(myAspectSubcolumns)) {
MapSequence.fromMap(subcolumnToX).put(subcolumn, x);
if (subcolumn.isEnabled() || myShowAdditionalInfo) {
x += subcolumn.getWidth() + mySubcolumnInterval;
}
}
for (int pseudoLine = 0; pseudoLine < ListSequence.fromList(myPseudoLinesY).count(); pseudoLine++) {
if (SetSequence.fromSet(myCurrentPseudoLines).contains(pseudoLine)) {
continue;
}
int fileLine = ListSequence.fromList(myPseudoLinesToFileLines).getElement(pseudoLine);
int height = (pseudoLine == ListSequence.fromList(myPseudoLinesY).count() - 1 ? getEditorComponent().getHeight() - ListSequence.fromList(myPseudoLinesY).last() : ListSequence.fromList(myPseudoLinesY).getElement(pseudoLine + 1) - ListSequence.fromList(myPseudoLinesY).getElement(pseudoLine));
if (myAuthorAnnotationAspect != null && ViewAction.isSet(ViewAction.COLORS)) {
String author = myAuthorAnnotationAspect.getValue(fileLine);
graphics.setColor(MapSequence.fromMap(myAuthorsToColors).get(author));
graphics.fillRect(getX(), ListSequence.fromList(myPseudoLinesY).getElement(pseudoLine), getWidth(), height);
}
graphics.setColor(ANNOTATION_COLOR);
if (myRevisionRange.isFileLineHighlighted(fileLine)) {
graphics.setFont(FontRegistry.getInstance().getFont(myFont.getName(), myFont.getStyle() | Font.BOLD, myFont.getSize()));
}
FontMetrics metrics = graphics.getFontMetrics();
if (height < metrics.getHeight()) {
continue;
}
for (AnnotationAspectSubcolumn subcolumn : ListSequence.fromList(myAspectSubcolumns).where(new IWhereFilter<AnnotationAspectSubcolumn>() {
public boolean accept(AnnotationAspectSubcolumn s) {
return myShowAdditionalInfo || s.isEnabled();
}
})) {
String text = subcolumn.getTextForFileLine(fileLine);
int textX = MapSequence.fromMap(subcolumnToX).get(subcolumn);
if (subcolumn.isRightAligned()) {
textX += subcolumn.getWidth() - metrics.stringWidth(text);
}
graphics.drawString(text, textX, metrics.getAscent() + ListSequence.fromList(myPseudoLinesY).getElement(pseudoLine));
}
}
}
@Override
public int getWidth() {
return (ListSequence.fromList(myAspectSubcolumns).isEmpty() ? 0 : ListSequence.fromList(myAspectSubcolumns).select(new ISelector<AnnotationAspectSubcolumn, Integer>() {
public Integer select(AnnotationAspectSubcolumn s) {
return (s.isEnabled() || myShowAdditionalInfo ? s.getWidth() : 0);
}
}).reduceLeft(new ILeftCombinator<Integer, Integer>() {
public Integer combine(Integer a, Integer b) {
return a + mySubcolumnInterval + b;
}
}) + 1 + mySubcolumnInterval / 2);
}
@Nullable
private EditorCell findCellForContent(@Nullable LineContent content) {
if (content == null) {
return null;
}
EditorComponent editor = getEditorComponent();
SNode editedNode = editor.getEditedNode();
SNode node = editedNode.getModel().getNode(content.getNodeId());
if (node == null || !(ListSequence.fromList(SNodeOperations.getNodeAncestors(node, null, true)).contains(editedNode))) {
return null;
}
if (content instanceof NodeLineContent) {
return editor.getBigValidCellForNode(node);
} else if (content instanceof PropertyLineContent) {
return CellFinder.getCellForProperty(editor, node, ((PropertyLineContent) content).getName());
} else if (content instanceof ReferenceLineContent) {
return CellFinder.getCellForReference(editor, node, ((ReferenceLineContent) content).getRole());
} else {
return null;
}
}
private Iterable<Integer> getPseudoLinesForContent(@Nullable LineContent content) {
EditorCell cell = findCellForContent(content);
if (cell == null) {
return Sequence.fromIterable(Collections.<Integer>emptyList());
}
final int startPseudoLine = Collections.binarySearch((List) myPseudoLinesY, cell.getY());
final Wrappers._int endPseudoLine = new Wrappers._int(Collections.binarySearch((List) myPseudoLinesY, cell.getY() + cell.getHeight()));
if (endPseudoLine.value < 0) {
endPseudoLine.value = -endPseudoLine.value - 1;
}
return new _FunctionTypes._return_P0_E0<Iterable<Integer>>() {
public Iterable<Integer> invoke() {
return new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new YieldingIterator<Integer>() {
private int __CP__ = 0;
protected boolean moveToNext() {
__loop__:
do {
__switch__:
switch (this.__CP__) {
case -1:
assert false : "Internal error";
return false;
case 2:
this._2_pseudoLine = startPseudoLine;
case 3:
if (!(_2_pseudoLine < endPseudoLine.value)) {
this.__CP__ = 1;
break;
}
this.__CP__ = 4;
break;
case 5:
_2_pseudoLine++;
this.__CP__ = 3;
break;
case 6:
this.__CP__ = 5;
this.yield(_2_pseudoLine);
return true;
case 0:
this.__CP__ = 2;
break;
case 4:
this.__CP__ = 6;
break;
default:
break __loop__;
}
} while (true);
return false;
}
private int _2_pseudoLine;
};
}
};
}
}.invoke();
}
@Override
public void relayout() {
EditorComponent editor = getEditorComponent();
if (editor == null || editor.isDisposed()) {
return;
}
Iterable<EditorCell> nonTrivialCells = Sequence.fromIterable(EditorUtils.getCellDescendants(editor.getRootCell())).where(new IWhereFilter<EditorCell>() {
public boolean accept(EditorCell cell) {
return cell.getWidth() * cell.getHeight() != 0;
}
});
Set<Integer> yCoordinatesSet = SetSequence.fromSetWithValues(new HashSet<Integer>(), Sequence.fromIterable(nonTrivialCells).select(new ISelector<EditorCell, Integer>() {
public Integer select(EditorCell cell) {
return cell.getY();
}
}));
myPseudoLinesY = SetSequence.fromSet(yCoordinatesSet).sort(new ISelector<Integer, Integer>() {
public Integer select(Integer y) {
return y;
}
}, true).toListSequence();
myPseudoLinesToFileLines = ListSequence.fromList(new ArrayList<Integer>());
ListSequence.fromList(myPseudoLinesY).visitAll(new IVisitor<Integer>() {
public void visit(Integer t) {
ListSequence.fromList(myPseudoLinesToFileLines).addElement(-1);
}
});
ModelAccess.instance().runReadAction(new Runnable() {
public void run() {
for (int fileLine = 0; fileLine < ListSequence.fromList(myFileLineToContent).count(); fileLine++) {
for (int pseudoLine : getPseudoLinesForContent(ListSequence.fromList(myFileLineToContent).getElement(fileLine))) {
int currentFileLine = ListSequence.fromList(myPseudoLinesToFileLines).getElement(pseudoLine);
ListSequence.fromList(myPseudoLinesToFileLines).setElement(pseudoLine, getFileLineWithMaxRevision(currentFileLine, fileLine));
}
}
}
});
FontMetrics metrics = FontRegistry.getInstance().getFontMetrics(myFont);
for (AnnotationAspectSubcolumn aspectSubcolumn : ListSequence.fromList(myAspectSubcolumns)) {
aspectSubcolumn.computeWidth(metrics, myPseudoLinesToFileLines);
}
mySubcolumnInterval = metrics.stringWidth(" ");
calculateCurrentPseudoLinesLater();
}
@Override
public String getTooltipText(MouseEvent event) {
int fileLine = findFileLineByY(event.getY());
if (fileLine == -1) {
return null;
} else {
return myFileAnnotation.getToolTip(fileLine);
}
}
@Nullable
@Override
public Cursor getCursor(MouseEvent event) {
return (findFileLineByY(event.getY()) == -1 ? null : new Cursor(Cursor.HAND_CURSOR));
}
@Override
public void mousePressed(MouseEvent event) {
if (event.getButton() == MouseEvent.BUTTON1 && event.getID() == MouseEvent.MOUSE_RELEASED) {
event.consume();
int fileLine = findFileLineByY(event.getY());
((LineAnnotationAspectAdapter) myFileAnnotation.getAspects()[0]).doAction(fileLine);
} else {
super.mousePressed(event);
}
}
@Override
public void dispose() {
myMessageBusConnection.disconnect();
myFileAnnotation.dispose();
final CurrentDifferenceRegistry registry = CurrentDifferenceRegistry.getInstance(getProject());
registry.getCommandQueue().runTask(new Runnable() {
public void run() {
registry.getCurrentDifference(myModel).removeDifferenceListener(myDifferenceListener);
}
});
}
public void close() {
getLeftEditorHighlighter().removeLeftColumn(this);
dispose();
}
private int findPseudoLineByY(int y) {
int pseudoLine = Collections.binarySearch((List) myPseudoLinesY, y);
if (pseudoLine < 0) {
pseudoLine = -pseudoLine - 2;
}
if (pseudoLine < 0 || pseudoLine >= ListSequence.fromList(myPseudoLinesToFileLines).count()) {
return -1;
}
return pseudoLine;
}
private int findFileLineByY(int y) {
int pseudoLine = findPseudoLineByY(y);
if (pseudoLine == -1) {
return -1;
} else {
if (SetSequence.fromSet(myCurrentPseudoLines).contains(pseudoLine)) {
return -1;
}
return ListSequence.fromList(myPseudoLinesToFileLines).getElement(pseudoLine);
}
}
@Override
public JPopupMenu getPopupMenu(MouseEvent event) {
List<AnAction> actions = ListSequence.fromList(new ArrayList<AnAction>());
final int fileLine = findFileLineByY(event.getY());
ListSequence.fromList(actions).addElement(new BaseAction("Close Annotations") {
@Override
protected void doExecute(AnActionEvent e, Map<String, Object> _params) {
close();
}
});
ListSequence.fromList(actions).addElement(Separator.getInstance());
ListSequence.fromList(actions).addElement(myViewActionGroup);
if (fileLine != -1) {
ListSequence.fromList(actions).addElement(new AnnotationColumn.ShowDiffFromAnnotationAction(fileLine));
ListSequence.fromList(actions).addElement(new BaseAction("Copy revision number") {
@Override
protected void doExecute(AnActionEvent e, Map<String, Object> params) {
String asString = myFileAnnotation.getLineRevisionNumber(fileLine).asString();
CopyPasteManager.getInstance().setContents(new TextTransferable(asString, asString));
}
});
}
ListSequence.fromList(actions).addElement(Separator.getInstance());
ListSequence.fromList(actions).addElement(myRevisionRange);
ListSequence.fromList(actions).addElement(new ShowAdditionalInfoAction(this));
DefaultActionGroup actionGroup = ActionUtils.groupFromActions(ListSequence.fromList(actions).toGenericArray(AnAction.class));
return ActionManager.getInstance().createActionPopupMenu(ActionPlaces.UNKNOWN, actionGroup).getComponent();
}
private int getFileLineWithMaxRevision(int a, int b) {
if (b == -1) {
return a;
}
if (a == -1) {
return b;
}
VcsRevisionNumber aRevision = myFileAnnotation.getLineRevisionNumber(a);
VcsRevisionNumber bRevision = myFileAnnotation.getLineRevisionNumber(b);
if (bRevision == null) {
return a;
}
if (aRevision == null) {
return b;
}
int c = aRevision.compareTo(bRevision);
if (MapSequence.fromMap(myRevisionNumberToRevision).get(aRevision) != null && MapSequence.fromMap(myRevisionNumberToRevision).get(bRevision) != null) {
c = MapSequence.fromMap(myRevisionNumberToRevision).get(aRevision).getRevisionDate().compareTo(MapSequence.fromMap(myRevisionNumberToRevision).get(bRevision).getRevisionDate());
}
if (c < 0) {
return b;
}
return a;
}
public void invalidateLayout() {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
getLeftEditorHighlighter().relayout(false);
}
});
}
public boolean isShowAdditionalInfo() {
return myShowAdditionalInfo;
}
public void setShowAdditionalInfo(boolean showAdditionalInfo) {
myShowAdditionalInfo = showAdditionalInfo;
invalidateLayout();
}
public List<VcsFileRevision> getRevisions() {
return myFileAnnotation.getRevisions();
}
public Project getProject() {
return myVcs.getProject();
}
private class MyDifferenceListener extends CurrentDifferenceAdapter {
public MyDifferenceListener() {
}
@Override
public void changeUpdateFinished() {
calculateCurrentPseudoLinesLater();
}
@Override
public void changeRemoved(@NotNull ModelChange change) {
MapSequence.fromMap(myChangesToLineContents).removeKey(change);
}
@Override
public void changeAdded(@NotNull ModelChange change) {
saveChange(change);
}
}
private class ShowDiffFromAnnotationAction extends AnAction {
private int myFileLine;
public ShowDiffFromAnnotationAction(int fileLine) {
super("Show Diff");
myFileLine = fileLine;
}
@Override
public void actionPerformed(AnActionEvent event) {
final VcsRevisionNumber revisionNumber = myFileAnnotation.getLineRevisionNumber(myFileLine);
if (revisionNumber == null) {
return;
}
final Project project = getProject();
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Loading revision " + revisionNumber.asString() + " contents", true, BackgroundFromStartOption.getInstance()) {
@Override
public void run(@NotNull ProgressIndicator pi) {
CommittedChangesProvider<CommittedChangeList, ChangeBrowserSettings> provider = myVcs.getCommittedChangesProvider();
try {
Pair<CommittedChangeList, FilePath> pair = null;
if (provider != null) {
pair = provider.getOneList(myVirtualFile, revisionNumber);
}
FilePath targetPath = (check_5mnya_a0a0c0c0a0a0a0e0c54(pair) == null ? new FilePathImpl(myVirtualFile) : check_5mnya_a0a2a2a0a0a0a4a2tb(pair));
CommittedChangeList cl = check_5mnya_a0d0c0a0a0a0e0c54(pair);
if (cl == null) {
VcsBalloonProblemNotifier.showOverChangesView(project, "Cannot load data for showing diff", MessageType.ERROR);
return;
}
List<Change> changes = Sequence.fromIterable(((Iterable<Change>) cl.getChanges())).sort(new ISelector<Change, String>() {
public String select(Change c) {
return ChangesUtil.getFilePath(c).getName().toLowerCase();
}
}, true).toListSequence();
final File ioFile = targetPath.getIOFile();
Change change = ListSequence.fromList(changes).findFirst(new IWhereFilter<Change>() {
public boolean accept(Change c) {
return c.getAfterRevision() != null && c.getAfterRevision().getFile().getIOFile().equals(ioFile);
}
});
if (change != null) {
final String name = ioFile.getName();
change = ListSequence.fromList(changes).findFirst(new IWhereFilter<Change>() {
public boolean accept(Change c) {
return c.getAfterRevision() != null && c.getAfterRevision().getFile().getName().equals(name);
}
});
ContentRevision before = change.getBeforeRevision();
ContentRevision after = change.getAfterRevision();
if (pi.isCanceled()) {
return;
}
pi.setText("Loading model after change");
assert after != null;
FileType[] filetypes = {(before == null ? null : before.getFile().getFileType()), after.getFile().getFileType()};
boolean isPerRoot = MPSFileTypeFactory.MPS_ROOT_FILE_TYPE.equals(filetypes[1]) || MPSFileTypeFactory.MPS_HEADER_FILE_TYPE.equals(filetypes[1]);
final SModel afterModel = VCSPersistenceUtil.loadModel(after.getContent().getBytes(FileUtil.DEFAULT_CHARSET), (isPerRoot ? MPSExtentions.MODEL : filetypes[1].getDefaultExtension()));
if (pi.isCanceled()) {
return;
}
pi.setText("Loading model before change");
final Wrappers._T<SModel> beforeModel = new Wrappers._T<SModel>();
if (before == null) {
beforeModel.value = new MergeTemporaryModel(myModel.getReference(), true);
} else {
beforeModel.value = VCSPersistenceUtil.loadModel(before.getContent().getBytes(FileUtil.DEFAULT_CHARSET), (isPerRoot ? MPSExtentions.MODEL : filetypes[0].getDefaultExtension()));
}
final Wrappers._T<SNodeId> rootId = new Wrappers._T<SNodeId>();
final Wrappers._T<String> rootName = new Wrappers._T<String>();
ProjectHelper.fromIdeaProject(project).getModelAccess().runReadAction(new _Adapters._return_P0_E0_to_Runnable_adapter(new _FunctionTypes._return_P0_E0<String>() {
public String invoke() {
SNodeId nodeId = check_5mnya_a0a0a0a22a8a2a0a0a0a4a2tb(ListSequence.fromList(myFileLineToContent).getElement(myFileLine));
SNode node = afterModel.getNode(nodeId);
if ((node == null)) {
node = beforeModel.value.getNode(nodeId);
}
SNode root = SNodeOperations.getContainingRoot(node);
rootId.value = check_5mnya_a0e0a0a22a8a2a0a0a0a4a2tb(root);
return rootName.value = (((root == null) ? "" : root.getName())) + " (" + SModelOperations.getModelName(afterModel) + ")";
}
}));
List<DiffContent> contents = ListSequence.fromListAndArray(new ArrayList<DiffContent>(), DiffContentFactory.getInstance().create((before == null ? "" : before.getContent()), filetypes[0]), DiffContentFactory.getInstance().create(after.getContent(), filetypes[1]));
List<String> titles = ListSequence.fromListAndArray(new ArrayList<String>(), (before == null ? "<no revision>" : before.getRevisionNumber().asString()), after.getRevisionNumber().asString());
final DiffRequest request = new SimpleDiffRequest(rootName.value, contents, titles);
// put hint to show only one root
request.putUserData(ModelDiffViewer.DIFF_SHOW_ROOTID, rootId.value);
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
DiffManager.getInstance().showDiff(project, request);
}
});
}
} catch (final VcsException ve) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
VcsBalloonProblemNotifier.showOverChangesView(project, "Cannot show diff: " + ve.getMessage(), MessageType.ERROR);
}
});
}
}
});
}
}
private class MyEditorComponentCreateListener implements EditorComponentCreateListener {
public MyEditorComponentCreateListener() {
}
@Override
public void editorComponentCreated(@NotNull EditorComponent ec) {
}
@Override
public void editorComponentDisposed(@NotNull EditorComponent ec) {
if (ec == getEditorComponent()) {
close();
}
}
}
private static SNodeId check_5mnya_a0b0k0v(LineContent checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getNodeId();
}
return null;
}
private static List<ModelChange> check_5mnya_a0a0a0a1a0a0v0v(ChangeSet checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getModelChanges();
}
return null;
}
private static FilePath check_5mnya_a0a2a2a0a0a0a4a2tb(Pair<CommittedChangeList, FilePath> checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getSecond();
}
return null;
}
private static FilePath check_5mnya_a0a0c0c0a0a0a0e0c54(Pair<CommittedChangeList, FilePath> checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getSecond();
}
return null;
}
private static CommittedChangeList check_5mnya_a0d0c0a0a0a0e0c54(Pair<CommittedChangeList, FilePath> checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getFirst();
}
return null;
}
private static SNodeId check_5mnya_a0a0a0a22a8a2a0a0a0a4a2tb(LineContent checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getNodeId();
}
return null;
}
private static SNodeId check_5mnya_a0e0a0a22a8a2a0a0a0a4a2tb(SNode checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getNodeId();
}
return null;
}
}