package jetbrains.mps.vcs.diff.ui.common;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import javax.swing.Icon;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ShortcutSet;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import java.util.List;
import jetbrains.mps.openapi.editor.EditorComponent;
import com.intellij.openapi.actionSystem.ActionToolbar;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.openapi.editor.selection.SelectionListener;
import jetbrains.mps.openapi.editor.selection.Selection;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.HashSet;
import jetbrains.mps.internal.collections.runtime.ITranslator2;
import java.util.Arrays;
import com.intellij.openapi.application.ApplicationManager;
import org.jetbrains.annotations.Nullable;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import org.apache.log4j.Level;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.baseLanguage.tuples.runtime.Tuples;
import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple;
import jetbrains.mps.workbench.action.BaseAction;
import jetbrains.mps.smodel.ModelAccess;
import jetbrains.mps.util.Computable;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.actionSystem.AnActionEvent;
import java.util.Map;
import org.jetbrains.mps.openapi.language.SConcept;
import org.jetbrains.mps.openapi.model.SNode;
public class NextPreviousTraverser {
private static final Logger LOG = LogManager.getLogger(NextPreviousTraverser.class);
private static final Icon PREVIOUS_ICON = AllIcons.Actions.PreviousOccurence;
private static final Icon NEXT_ICON = AllIcons.Actions.NextOccurence;
public static final ShortcutSet PREV_CHANGE_SHORTCUT = CustomShortcutSet.fromString("shift F7");
public static final ShortcutSet NEXT_CHANGE_SHORTCUT = CustomShortcutSet.fromString("F7");
private List<ChangeGroupLayout> myChangeGroupLayouts;
private EditorComponent myLastEditor;
private NextPreviousTraverser.TheAction myPreviousAction = new NextPreviousTraverser.TheAction(true);
private NextPreviousTraverser.TheAction myNextAction = new NextPreviousTraverser.TheAction(false);
private ActionToolbar myActionToolbar = null;
public NextPreviousTraverser(@NotNull List<ChangeGroupLayout> changeGroupLayouts, @NotNull EditorComponent firstEditor) {
myChangeGroupLayouts = changeGroupLayouts;
myLastEditor = firstEditor;
final SelectionListener selectionListener = new SelectionListener() {
public void selectionChanged(EditorComponent editorComponent, Selection oldSelection, Selection newSelection) {
if (oldSelection == newSelection) {
return;
}
setLastEditor(editorComponent);
updateToolbar();
}
};
ListSequence.fromList(myChangeGroupLayouts).visitAll(new IVisitor<ChangeGroupLayout>() {
public void visit(ChangeGroupLayout cgb) {
cgb.addInvalidateListener(new ChangeGroupInvalidateListener() {
public void changeGroupsInvalidated() {
updateToolbar();
}
});
}
});
SetSequence.fromSet(SetSequence.fromSetWithValues(new HashSet<EditorComponent>(), ListSequence.fromList(myChangeGroupLayouts).translate(new ITranslator2<ChangeGroupLayout, EditorComponent>() {
public Iterable<EditorComponent> translate(ChangeGroupLayout b) {
return Arrays.<EditorComponent>asList(b.getLeftComponent(), b.getRightComponent());
}
}))).visitAll(new IVisitor<EditorComponent>() {
public void visit(EditorComponent ec) {
ec.getSelectionManager().addSelectionListener(selectionListener);
}
});
}
public void setActionToolbar(ActionToolbar actionToolbar) {
myActionToolbar = actionToolbar;
}
private void updateToolbar() {
if (myActionToolbar != null) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
myActionToolbar.updateActionsImmediately();
}
});
}
}
@Nullable
private ChangeGroupLayout getLayoutAsLeft() {
return ListSequence.fromList(myChangeGroupLayouts).findFirst(new IWhereFilter<ChangeGroupLayout>() {
public boolean accept(ChangeGroupLayout b) {
return b.getLeftComponent() == myLastEditor;
}
});
}
@Nullable
private ChangeGroupLayout getLayoutAsRight() {
return ListSequence.fromList(myChangeGroupLayouts).findFirst(new IWhereFilter<ChangeGroupLayout>() {
public boolean accept(ChangeGroupLayout b) {
return b.getRightComponent() == myLastEditor;
}
});
}
private synchronized void setLastEditor(EditorComponent editor) {
myLastEditor = editor;
if (!(ListSequence.fromList(myChangeGroupLayouts).any(new IWhereFilter<ChangeGroupLayout>() {
public boolean accept(ChangeGroupLayout b) {
return b.getLeftComponent() == myLastEditor || b.getRightComponent() == myLastEditor;
}
}))) {
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error("last editor is uknown: " + myLastEditor, new AssertionError());
}
}
}
private Bounds findNeighbourGroupAsLeftOrRight(final int currentY, boolean previous, final boolean left) {
ChangeGroupLayout layout = (left ? getLayoutAsLeft() : getLayoutAsRight());
if (layout == null) {
return null;
}
List<ChangeGroup> changeGroups = layout.getChangeGroups();
ChangeGroup changeGroup;
if (previous) {
changeGroup = ListSequence.fromList(changeGroups).findLast(new IWhereFilter<ChangeGroup>() {
public boolean accept(ChangeGroup cg) {
return (int) cg.getBounds(left).end() < currentY;
}
});
} else {
changeGroup = ListSequence.fromList(changeGroups).findFirst(new IWhereFilter<ChangeGroup>() {
public boolean accept(ChangeGroup cg) {
return (int) cg.getBounds(left).start() > currentY;
}
});
}
return check_mf966z_a5a51(changeGroup, left);
}
private synchronized Bounds getNeighbourGroupBounds(boolean previous) {
// -1 means that group is not available
int currentY = ((jetbrains.mps.nodeEditor.EditorComponent) myLastEditor).getViewport().getViewPosition().y;
EditorCell selectedCell = ((jetbrains.mps.nodeEditor.EditorComponent) myLastEditor).getSelectedCell();
if (selectedCell != null) {
currentY = selectedCell.getY();
}
Bounds asLeft = findNeighbourGroupAsLeftOrRight(currentY, previous, true);
Bounds asRight = findNeighbourGroupAsLeftOrRight(currentY, previous, false);
Bounds max;
Bounds min;
if (asLeft == null) {
{
Tuples._2<Bounds, Bounds> _tmp_mf966z_a0j0q = MultiTuple.<Bounds,Bounds>from(null, asRight);
min = _tmp_mf966z_a0j0q._0();
max = _tmp_mf966z_a0j0q._1();
}
} else if (asRight == null) {
{
Tuples._2<Bounds, Bounds> _tmp_mf966z_a0a9a61 = MultiTuple.<Bounds,Bounds>from(null, asLeft);
min = _tmp_mf966z_a0a9a61._0();
max = _tmp_mf966z_a0a9a61._1();
}
} else {
if ((int) asLeft.start() < (int) asRight.start()) {
{
Tuples._2<Bounds, Bounds> _tmp_mf966z_a0a0a9a61 = MultiTuple.<Bounds,Bounds>from(asLeft, asRight);
min = _tmp_mf966z_a0a0a9a61._0();
max = _tmp_mf966z_a0a0a9a61._1();
}
} else {
{
Tuples._2<Bounds, Bounds> _tmp_mf966z_a0a0a0j0q = MultiTuple.<Bounds,Bounds>from(asRight, asLeft);
min = _tmp_mf966z_a0a0a0j0q._0();
max = _tmp_mf966z_a0a0a0j0q._1();
}
}
}
if (asLeft != null && asRight != null) {
return (previous ? max : min);
} else {
return max;
}
}
public BaseAction previousAction() {
return myPreviousAction;
}
public BaseAction nextAction() {
return myNextAction;
}
public void goToFirstChangeLater() {
Bounds firstGroup = getNeighbourGroupBounds(false);
EditorCell rc = myLastEditor.getRootCell();
final int minY = (firstGroup == null ? rc.getY() + 1 : (int) firstGroup.start());
final int maxY = rc.getY() + rc.getHeight() - 2;
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
goToBounds(new Bounds(minY, maxY));
}
});
}
public void goToBounds(Bounds bounds) {
if (!(myLastEditor.isDisposed())) {
goToY((int) bounds.end());
goToY((int) bounds.start());
}
}
private synchronized void goToY(int y) {
EditorCell editorCell = ((jetbrains.mps.nodeEditor.EditorComponent) myLastEditor).findCellWeak(1, y + 1);
if (editorCell != null) {
myLastEditor.changeSelection(editorCell);
} else {
if (LOG.isEnabledFor(Level.WARN)) {
LOG.warn(String.format("Could not find cell for coordinates (1, %d), editor for concept %s", y, ModelAccess.instance().<String>runReadAction(new Computable<String>() {
public String compute() {
return check_mf966z_a0a0a2a0a0b0v(check_mf966z_a0a0a0c0a0a1a12(myLastEditor.getEditedNode()));
}
})));
}
}
}
private class TheAction extends BaseAction implements DumbAware {
private boolean myPrevious;
private TheAction(boolean previous) {
super("Go to " + ((previous ? "Previous" : "Next")) + " Change", null, (previous ? NextPreviousTraverser.PREVIOUS_ICON : NextPreviousTraverser.NEXT_ICON));
setDisableOnNoProject(false);
setExecuteOutsideCommand(true);
myPrevious = previous;
}
@Override
protected void doExecute(AnActionEvent event, Map<String, Object> map) {
assert getNeighbourGroupBounds(myPrevious) != null;
goToBounds(getNeighbourGroupBounds(myPrevious));
}
@Override
protected void doUpdate(AnActionEvent event, Map<String, Object> map) {
event.getPresentation().setEnabled(getNeighbourGroupBounds(myPrevious) != null);
}
}
private static Bounds check_mf966z_a5a51(ChangeGroup checkedDotOperand, Boolean left) {
if (null != checkedDotOperand) {
return checkedDotOperand.getBounds(left);
}
return null;
}
private static String check_mf966z_a0a0a2a0a0b0v(SConcept checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getQualifiedName();
}
return null;
}
private static SConcept check_mf966z_a0a0a0c0a0a1a12(SNode checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getConcept();
}
return null;
}
}