/*
* Copyright 2003-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.nodeEditor;
import jetbrains.mps.editor.runtime.SideTransformInfoUtil;
import jetbrains.mps.nodeEditor.cells.APICellAdapter;
import jetbrains.mps.nodeEditor.sidetransform.EditorCell_STHint;
import jetbrains.mps.openapi.editor.EditorComponent;
import jetbrains.mps.openapi.editor.EditorComponentState;
import jetbrains.mps.openapi.editor.cells.CellInfo;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.openapi.editor.selection.Selection;
import jetbrains.mps.openapi.editor.selection.SelectionListener;
import jetbrains.mps.openapi.editor.selection.SingularSelection;
import jetbrains.mps.openapi.editor.update.UpdaterListener;
import jetbrains.mps.openapi.editor.update.UpdaterListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.model.SNode;
class AutoValidator {
@NotNull
private final MyCellSelectionListener mySelectionListener;
@NotNull
private final EditorComponent myEditorComponent;
@NotNull
private final MyUpdaterListener myUpdaterListener;
private boolean mySuppressSelectionChanges = false;
private boolean myEventsBlocked;
AutoValidator(@NotNull EditorComponent editorComponent) {
myEditorComponent = editorComponent;
myEditorComponent.getSelectionManager().addSelectionListener(mySelectionListener = new MyCellSelectionListener());
myEditorComponent.getUpdater().addListener(myUpdaterListener = new MyUpdaterListener());
}
private void validateErrorCell(CellInfo cellInfo, EditorComponent editorComponent) {
EditorCell cell = cellInfo.findCell(editorComponent);
if (cell == null) {
return;
}
EditorComponentState state = editorComponent.getEditorContext().getEditorComponentState();
mySuppressSelectionChanges = true;
try {
APICellAdapter.validate(cell, true, false);
editorComponent.getUpdater().flushModelEvents();
editorComponent.getEditorContext().restoreEditorComponentState(state);
} finally {
mySuppressSelectionChanges = false;
}
}
void dispose() {
mySelectionListener.dispose();
myEditorComponent.getSelectionManager().removeSelectionListener(mySelectionListener);
myEditorComponent.getUpdater().removeListener(myUpdaterListener);
}
private class MyCellSelectionListener implements SelectionListener {
private boolean myDisposed;
@Override
public void selectionChanged(final EditorComponent editorComponent, Selection oldSelection, Selection newSelection) {
if (mySuppressSelectionChanges || oldSelection == newSelection || !(oldSelection instanceof SingularSelection)) {
return;
}
final EditorCell editorCell = ((SingularSelection) oldSelection).getEditorCell();
// Do not perform any actions on moving within same EditorCell.
if (newSelection instanceof SingularSelection && ((SingularSelection) newSelection).getEditorCell() == editorCell) {
return;
}
if (editorComponent.isReadOnly() || myEventsBlocked) {
return;
}
final boolean wasInErrorState = editorCell.isErrorState();
final boolean wasStHint = editorCell instanceof EditorCell_STHint;
if (!wasInErrorState && !wasStHint) {
return;
}
final SNode node = editorCell.getSNode();
final CellInfo cellInfo = editorCell.getCellInfo();
myEditorComponent.getEditorContext().getRepository().getModelAccess().executeCommandInEDT(() -> {
if (myDisposed) {
return;
}
if (wasInErrorState) {
validateErrorCell(cellInfo, editorComponent);
} else {
SideTransformInfoUtil.removeTransformInfo(node);
}
});
}
public void dispose() {
myDisposed = true;
}
}
private class MyUpdaterListener extends UpdaterListenerAdapter implements UpdaterListener {
@Override
public void editorUpdateStarted(EditorComponent editorComponent) {
myEventsBlocked = true;
}
@Override
public void editorUpdated(EditorComponent editorComponent) {
myEventsBlocked = false;
}
}
}