package jetbrains.mps.vcs.changesmanager.editor; /*Generated by MPS */ import jetbrains.mps.openapi.editor.message.EditorMessageOwner; import jetbrains.mps.nodeEditor.EditorComponent; import java.util.Map; import jetbrains.mps.vcs.diff.changes.ModelChange; import java.util.List; import jetbrains.mps.vcs.diff.ui.common.ChangeEditorMessage; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.HashMap; import jetbrains.mps.vcs.changesmanager.CurrentDifference; import org.jetbrains.annotations.NotNull; import com.intellij.openapi.project.Project; import jetbrains.mps.vcs.changesmanager.CurrentDifferenceRegistry; import org.jetbrains.mps.openapi.module.SRepository; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.EditableSModel; import jetbrains.mps.vcs.diff.ChangeSet; import jetbrains.mps.internal.collections.runtime.ListSequence; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import jetbrains.mps.internal.collections.runtime.IVisitor; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.ide.ThreadUtils; import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; import jetbrains.mps.vcs.diff.changes.AddRootChange; import jetbrains.mps.vcs.diff.ui.common.ChangeEditorMessageFactory; import java.util.ArrayList; import jetbrains.mps.internal.collections.runtime.SetSequence; import org.jetbrains.annotations.Nullable; import jetbrains.mps.nodeEditor.NodeHighlightManager; import jetbrains.mps.nodeEditor.leftHighlighter.LeftEditorHighlighter; import jetbrains.mps.vcs.changesmanager.CurrentDifferenceAdapter; public class EditorHighlighter implements EditorMessageOwner { private EditorComponent myEditorComponent; private final Map<ModelChange, List<ChangeEditorMessage>> myChangesMessages = MapSequence.fromMap(new HashMap<ModelChange, List<ChangeEditorMessage>>()); private CurrentDifference myCurrentDifference; private ChangeStripsPainter myStripsPainter; private EditorHighlighter.MyCurrentDifferenceListener myListener; private final Object myDisposedLock = new Object(); private boolean myDisposed = false; public EditorHighlighter(@NotNull final Project project, @NotNull final EditorComponent editorComponent) { myEditorComponent = editorComponent; CurrentDifferenceRegistry.getInstance(project).getCommandQueue().runTask(new Runnable() { public void run() { final SRepository repo = editorComponent.getEditorContext().getRepository(); repo.getModelAccess().runReadAction(new Runnable() { public void run() { synchronized (myDisposedLock) { if (myDisposed) { return; } final SNode editedNode = (editorComponent.getEditedNodePointer() == null ? null : editorComponent.getEditedNodePointer().resolve(repo)); if (editedNode == null) { return; } final SModel model = editedNode.getModel(); if (model instanceof EditableSModel && !(model.isReadOnly())) { myCurrentDifference = CurrentDifferenceRegistry.getInstance(project).getCurrentDifference((EditableSModel) model); myListener = new EditorHighlighter.MyCurrentDifferenceListener(); } if (myListener != null) { myCurrentDifference.setEnabled(true); ChangeSet changeSet = myCurrentDifference.getChangeSet(); if (changeSet != null) { ListSequence.fromList(changeSet.getModelChanges()).where(new IWhereFilter<ModelChange>() { public boolean accept(ModelChange c) { return editedNode.getNodeId().equals(c.getRootId()); } }).visitAll(new IVisitor<ModelChange>() { public void visit(ModelChange c) { createMessages(c); } }); } synchronized (myChangesMessages) { Sequence.fromIterable(MapSequence.fromMap(myChangesMessages).values()).visitAll(new IVisitor<List<ChangeEditorMessage>>() { public void visit(List<ChangeEditorMessage> messages) { ListSequence.fromList(messages).visitAll(new IVisitor<ChangeEditorMessage>() { public void visit(ChangeEditorMessage m) { getHighlightManager().mark(m); } }); } }); } getHighlightManager().repaintAndRebuildEditorMessages(); ThreadUtils.runInUIThreadNoWait(new Runnable() { public void run() { myStripsPainter = new ChangeStripsPainter(EditorHighlighter.this); myEditorComponent.getLeftEditorHighlighter().addFoldingAreaPainter(myStripsPainter); // .relayout() is called as a part of .addFoldingAreaPainter() method execution } }); myCurrentDifference.addDifferenceListener(myListener); } } } }); } }); } private List<ChangeEditorMessage> createMessages(final ModelChange change) { final Wrappers._T<List<ChangeEditorMessage>> messages = new Wrappers._T<List<ChangeEditorMessage>>(null); if (!(change instanceof AddRootChange)) { final SRepository repo = myEditorComponent.getEditorContext().getRepository(); repo.getModelAccess().runReadAction(new Runnable() { public void run() { SNode editedNode = (myEditorComponent.getEditedNodePointer() == null ? null : myEditorComponent.getEditedNodePointer().resolve(repo)); if (editedNode == null) { return; } SModel model = editedNode.getModel(); messages.value = ChangeEditorMessageFactory.createMessages(model, change.getChangeSet().getNewModel() != model, change, EditorHighlighter.this, null, false); } }); } if (messages.value == null) { messages.value = ListSequence.fromList(new ArrayList<ChangeEditorMessage>()); } synchronized (myChangesMessages) { if (MapSequence.fromMap(myChangesMessages).containsKey(change)) { return ListSequence.fromList(new ArrayList<ChangeEditorMessage>()); } MapSequence.fromMap(myChangesMessages).put(change, messages.value); } return messages.value; } private List<ChangeEditorMessage> removeMessages(ModelChange change) { synchronized (myChangesMessages) { List<ChangeEditorMessage> messages = MapSequence.fromMap(myChangesMessages).get(change); if (messages == null || getHighlightManager() == null || ListSequence.fromList(messages).any(new IWhereFilter<ChangeEditorMessage>() { public boolean accept(ChangeEditorMessage m) { return m.getNode() == null; } })) { return ListSequence.fromList(new ArrayList<ChangeEditorMessage>()); } MapSequence.fromMap(myChangesMessages).removeKey(change); return messages; } } /*package*/ List<ChangeEditorMessage> getMessages(ModelChange change) { synchronized (myChangesMessages) { return MapSequence.fromMap(myChangesMessages).get(change); } } public void dispose() { synchronized (myDisposedLock) { myDisposed = true; try { synchronized (myChangesMessages) { SetSequence.fromSet(MapSequence.fromMap(myChangesMessages).keySet()).toListSequence().visitAll(new IVisitor<ModelChange>() { public void visit(ModelChange ch) { removeMessages(ch); } }); } getHighlightManager().clearForOwner(this); if (myStripsPainter != null) { getLeftEditorHighlighter().removeFoldingAreaPainter(myStripsPainter); myStripsPainter.dispose(); } } finally { if (myCurrentDifference != null) { myCurrentDifference.removeDifferenceListener(myListener); myListener = null; } } } } @Nullable /*package*/ ChangeSet getChangeSet() { return check_urq9my_a0a21(myCurrentDifference); } /*package*/ ChangeStripsPainter getStripsPainter() { return myStripsPainter; } /*package*/ EditorComponent getEditorComponent() { return myEditorComponent; } /*package*/ NodeHighlightManager getHighlightManager() { return myEditorComponent.getHighlightManager(); } /*package*/ LeftEditorHighlighter getLeftEditorHighlighter() { return myEditorComponent.getLeftEditorHighlighter(); } public class MyCurrentDifferenceListener extends CurrentDifferenceAdapter { private List<ChangeEditorMessage> myAddedMessages = ListSequence.fromList(new ArrayList<ChangeEditorMessage>()); private List<ChangeEditorMessage> myRemovedMessages = ListSequence.fromList(new ArrayList<ChangeEditorMessage>()); public MyCurrentDifferenceListener() { } @Override public void changeAdded(@NotNull ModelChange change) { List<ChangeEditorMessage> messages = createMessages(change); ListSequence.fromList(myRemovedMessages).removeSequence(ListSequence.fromList(messages)); ListSequence.fromList(myAddedMessages).addSequence(ListSequence.fromList(messages)); } @Override public void changeRemoved(@NotNull ModelChange change) { List<ChangeEditorMessage> messages = removeMessages(change); ListSequence.fromList(myRemovedMessages).addSequence(ListSequence.fromList(messages)); ListSequence.fromList(myAddedMessages).removeSequence(ListSequence.fromList(messages)); } @Override public void changeUpdateFinished() { if (myEditorComponent.isDisposed()) { return; } if (!(ListSequence.fromList(myAddedMessages).isEmpty()) || !(ListSequence.fromList(myRemovedMessages).isEmpty())) { NodeHighlightManager nodeHighlightManager = getHighlightManager(); for (ChangeEditorMessage removedMessage : ListSequence.fromList(myRemovedMessages)) { nodeHighlightManager.unmark(removedMessage); } for (ChangeEditorMessage addedMessage : ListSequence.fromList(myAddedMessages)) { nodeHighlightManager.mark(addedMessage); } check_urq9my_a3a1a5r(myStripsPainter); nodeHighlightManager.repaintAndRebuildEditorMessages(); ListSequence.fromList(myAddedMessages).clear(); ListSequence.fromList(myRemovedMessages).clear(); } } } private static ChangeSet check_urq9my_a0a21(CurrentDifference checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getChangeSet(); } return null; } private static void check_urq9my_a3a1a5r(ChangeStripsPainter checkedDotOperand) { if (null != checkedDotOperand) { checkedDotOperand.relayout(); } } }