package jetbrains.mps.vcs.diff.ui.common;
/*Generated by MPS */
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.nodeEditor.EditorComponent;
import jetbrains.mps.vcs.diff.changes.ModelChange;
import jetbrains.mps.vcs.diff.ChangeSet;
import java.util.Map;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.HashMap;
import java.util.Set;
import jetbrains.mps.util.DisjointSets;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.ISelector;
import jetbrains.mps.internal.collections.runtime.ILeftCombinator;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import jetbrains.mps.nodeEditor.cells.EditorCell;
public abstract class ChangeGroupLayout {
private ChangeEditorMessage.ConflictChecker myConflictChecker;
protected boolean myInspector = false;
private boolean myMergeAdjacent;
private List<ChangeGroup> myChangeGroups = null;
private List<ChangeGroupInvalidateListener> myInvalidateListeners = ListSequence.fromList(new ArrayList<ChangeGroupInvalidateListener>());
protected ChangeGroupLayout(@Nullable ChangeEditorMessage.ConflictChecker conflictChecker, boolean inspector, boolean mergeAdjacent) {
myConflictChecker = conflictChecker;
myInspector = inspector;
myMergeAdjacent = mergeAdjacent;
}
@NotNull
public abstract EditorComponent getLeftComponent();
@NotNull
public abstract EditorComponent getRightComponent();
public boolean isValid() {
return !((getLeftComponent().isDisposed() || getRightComponent().isDisposed()));
}
protected abstract List<ChangeEditorMessage> getLeftMessages(ModelChange change);
protected abstract List<ChangeEditorMessage> getRightMessages(ModelChange change);
@Nullable
protected abstract ChangeSet getChangeSet();
private void calculateChangeGroups() {
final Map<ModelChange, Bounds> left = MapSequence.fromMap(new HashMap<ModelChange, Bounds>());
final Map<ModelChange, Bounds> right = MapSequence.fromMap(new HashMap<ModelChange, Bounds>());
for (ModelChange change : ListSequence.fromList(check_cuq72k_a2a21(getChangeSet(), this))) {
Bounds leftBounds = findBounds(getLeftMessages(change), getLeftComponent());
Bounds rightBounds = findBounds(getRightMessages(change), getRightComponent());
if (leftBounds.length() <= 0 && rightBounds.length() <= 0) {
continue;
}
MapSequence.fromMap(left).put(change, leftBounds);
MapSequence.fromMap(right).put(change, rightBounds);
}
Set<ModelChange> changes = MapSequence.fromMap(left).keySet();
DisjointSets<ModelChange> ds = new DisjointSets<ModelChange>(changes);
for (ModelChange a : SetSequence.fromSet(changes)) {
for (ModelChange b : SetSequence.fromSet(changes)) {
if (!(areBoundsSeparate(MapSequence.fromMap(left).get(a), MapSequence.fromMap(left).get(b), myMergeAdjacent)) || !(areBoundsSeparate(MapSequence.fromMap(right).get(a), MapSequence.fromMap(right).get(b), myMergeAdjacent))) {
ds.unite(a, b);
}
}
}
myChangeGroups = ListSequence.fromList(new ArrayList<ChangeGroup>());
for (Set<ModelChange> s : Sequence.fromIterable(ds.getSets())) {
Bounds lb = SetSequence.fromSet(s).select(new ISelector<ModelChange, Bounds>() {
public Bounds select(ModelChange ch) {
return MapSequence.fromMap(left).get(ch);
}
}).reduceLeft(new ILeftCombinator<Bounds, Bounds>() {
public Bounds combine(Bounds a, Bounds b) {
return a.merge(b);
}
});
Bounds rb = SetSequence.fromSet(s).select(new ISelector<ModelChange, Bounds>() {
public Bounds select(ModelChange ch) {
return MapSequence.fromMap(right).get(ch);
}
}).reduceLeft(new ILeftCombinator<Bounds, Bounds>() {
public Bounds combine(Bounds a, Bounds b) {
return a.merge(b);
}
});
List<ModelChange> sortedChanges = SetSequence.fromSet(s).sort(new ISelector<ModelChange, Integer>() {
public Integer select(ModelChange ch) {
return (int) MapSequence.fromMap(right).get(ch).start();
}
}, true).sort(new ISelector<ModelChange, Integer>() {
public Integer select(ModelChange ch) {
return (int) MapSequence.fromMap(left).get(ch).start();
}
}, true).toListSequence();
ListSequence.fromList(myChangeGroups).addElement(new ChangeGroup(lb, rb, sortedChanges, myConflictChecker));
}
myChangeGroups = ListSequence.fromList(myChangeGroups).sort(new ISelector<ChangeGroup, Integer>() {
public Integer select(ChangeGroup g) {
return (int) g.getLeftBounds().start();
}
}, true).toListSequence();
}
public void addInvalidateListener(@NotNull ChangeGroupInvalidateListener listener) {
ListSequence.fromList(myInvalidateListeners).addElement(listener);
}
public void removeInvalidateListener(@NotNull ChangeGroupInvalidateListener listener) {
ListSequence.fromList(myInvalidateListeners).removeElement(listener);
}
@NotNull
public List<ChangeGroup> getChangeGroups() {
if (myChangeGroups == null) {
calculateChangeGroups();
}
assert myChangeGroups != null;
return myChangeGroups;
}
public void invalidate() {
myChangeGroups = null;
ListSequence.fromList(myInvalidateListeners).visitAll(new IVisitor<ChangeGroupInvalidateListener>() {
public void visit(ChangeGroupInvalidateListener it) {
it.changeGroupsInvalidated();
}
});
}
public int getEditorVerticalOffset() {
if (myInspector) {
return 0;
} else {
assert getLeftComponent().getExternalComponent().getY() == getRightComponent().getExternalComponent().getY();
return getLeftComponent().getExternalComponent().getY();
}
}
private static Bounds findBounds(Iterable<ChangeEditorMessage> messages, final EditorComponent editorComponent) {
Bounds bounds = null;
if (Sequence.fromIterable(messages).isNotEmpty()) {
bounds = Sequence.fromIterable(messages).select(new ISelector<ChangeEditorMessage, Bounds>() {
public Bounds select(ChangeEditorMessage m) {
return m.getBounds(editorComponent);
}
}).where(new IWhereFilter<Bounds>() {
public boolean accept(Bounds b) {
return b.length() > 0;
}
}).reduceLeft(new ILeftCombinator<Bounds, Bounds>() {
public Bounds combine(Bounds a, Bounds b) {
return a.merge(b);
}
});
}
if (bounds == null || bounds.length() <= 0) {
int y = check_cuq72k_a0a0c0s(check_cuq72k_a0a0a2a81(editorComponent));
return new Bounds(y, y);
} else {
return bounds;
}
}
private static boolean areBoundsSeparate(Bounds a, Bounds b, boolean canBeAdjacent) {
int tolerance = (canBeAdjacent ? 0 : 1);
return (int) a.end() - tolerance < (int) b.start() || (int) b.end() - tolerance < (int) a.start();
}
private static List<ModelChange> check_cuq72k_a2a21(ChangeSet checkedDotOperand, ChangeGroupLayout checkedDotThisExpression) {
if (null != checkedDotOperand) {
return checkedDotOperand.getModelChanges();
}
return null;
}
private static int check_cuq72k_a0a0c0s(EditorCell checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getY();
}
return 0;
}
private static EditorCell check_cuq72k_a0a0a2a81(EditorComponent checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getRootCell();
}
return null;
}
}