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; } }