/* * Copyright 2003-2016 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 com.intellij.openapi.wm.IdeFocusManager; import jetbrains.mps.ide.ThreadUtils; import jetbrains.mps.ide.project.ProjectHelper; import jetbrains.mps.nodeEditor.assist.DisabledContextAssistantManager; import jetbrains.mps.nodeEditor.cells.EditorCell_Label; import jetbrains.mps.nodeEditor.configuration.EditorConfiguration; import jetbrains.mps.nodeEditor.configuration.EditorConfigurationBuilder; import jetbrains.mps.nodeEditor.inspector.InspectorEditorComponent; import jetbrains.mps.openapi.editor.EditorComponentState; import jetbrains.mps.openapi.editor.EditorInspector; import jetbrains.mps.openapi.editor.EditorPanelManager; import jetbrains.mps.openapi.editor.assist.ContextAssistantManager; import jetbrains.mps.openapi.editor.cells.EditorCell; import jetbrains.mps.openapi.editor.cells.EditorCellFactory; import jetbrains.mps.openapi.editor.selection.SelectionManager; import jetbrains.mps.project.GlobalOperationContext; import jetbrains.mps.project.ModuleContext; import jetbrains.mps.project.Project; import jetbrains.mps.project.ProjectOperationContext; import jetbrains.mps.smodel.IOperationContext; import jetbrains.mps.smodel.ModelAccess; import jetbrains.mps.util.Computable; import jetbrains.mps.util.performance.IPerformanceTracer; import jetbrains.mps.util.performance.PerformanceTracer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.model.EditableSModel; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.module.SModule; import org.jetbrains.mps.openapi.module.SRepository; import java.util.List; /** * Author: Sergey Dmitriev * Created Sep 14, 2003 */ public class EditorContext implements jetbrains.mps.openapi.editor.EditorContext { private final EditorComponent myNodeEditorComponent; private final SRepository myRepository; private final SModel myModel; private final EditorConfiguration myConfiguration; private EditorManager myEditorManager; private EditorCell myContextCell; private IPerformanceTracer myPerformanceTracer = null; @NotNull private final ContextAssistantManager myContextAssistantManager; public EditorContext(@NotNull EditorComponent editorComponent, @Nullable SModel model, @NotNull SRepository repository) { this(editorComponent, model, repository, EditorConfigurationBuilder.buildDefault(), new DisabledContextAssistantManager()); } public EditorContext(@NotNull EditorComponent editorComponent, @Nullable SModel model, @NotNull SRepository repository, EditorConfiguration configuration, @NotNull ContextAssistantManager contextAssistantManager) { myNodeEditorComponent = editorComponent; myModel = model; myRepository = repository; myContextAssistantManager = contextAssistantManager; myConfiguration = configuration; } public EditorComponent getNodeEditorComponent() { return myNodeEditorComponent; } @NotNull @Override public jetbrains.mps.openapi.editor.EditorComponent getEditorComponent() { return myNodeEditorComponent; } @Override public boolean isEditable() { SNode node = myNodeEditorComponent.getRootCell().getSNode(); if (node == null) { return false; } SModel model = node.getModel(); return model instanceof EditableSModel && !model.isReadOnly(); } @Override public boolean isInspector() { return myNodeEditorComponent instanceof InspectorEditorComponent; } @Override public EditorCell getSelectedCell() { return myNodeEditorComponent.getSelectedCell(); } public String getSelectedCellText() { EditorCell selectedCell = getSelectedCell(); if (selectedCell instanceof EditorCell_Label) { return ((EditorCell_Label) selectedCell).getRenderedText(); } return null; } @NotNull @Override public SRepository getRepository() { return myRepository; } @Override public SNode getSelectedNode() { return myNodeEditorComponent.getSelectedNode(); } @Override public SModel getModel() { return myModel; } @Override public IOperationContext getOperationContext() { Project project = ProjectHelper.getProject(myRepository); if (project == null) { return new GlobalOperationContext() { @Override public <T> T getComponent(Class<T> clazz) { if (EditorManager.class == clazz) { return (T) getEditorManager(); } return super.getComponent(clazz); } }; } SModule module = myModel == null ? null : myModel.getModule(); if (module == null) { return new ProjectOperationContext(project) { @Override public <T> T getComponent(@NotNull Class<T> clazz) { if (EditorManager.class == clazz) { return (T) getEditorManager(); } return super.getComponent(clazz); } }; } return new ModuleContext(module, project) { @Override public <T> T getComponent(@NotNull Class<T> clazz) { if (EditorManager.class == clazz) { return (T) getEditorManager(); } return super.getComponent(clazz); } }; } @Override public void flushEvents() { // TODO: replace all usages by updater.flushModelEvents() ? myNodeEditorComponent.getUpdater().flushModelEvents(); } /** * @deprecated Since MPS 3.4 use getState() */ @Deprecated @Override public Object createMemento() { return getEditorComponentState(); } @Override public EditorComponentState getEditorComponentState() { return new Memento(this, false); } /** * @deprecated Since MPS 3.4 use getState() */ @Deprecated @Override public boolean setMemento(Object o) { if (o instanceof EditorComponentState) { restoreEditorComponentState((EditorComponentState) o); return true; } return false; } @Override public void restoreEditorComponentState(EditorComponentState state) { if (state instanceof Memento) { Memento memento = (Memento) state; ModelAccess.instance().runReadAction(() -> { myNodeEditorComponent.relayout(); memento.restore(myNodeEditorComponent); }); myNodeEditorComponent.getUpdater().flushModelEvents(); } } @Override public void select(final SNode node) { flushEvents(); getNodeEditorComponent().selectNode(node); } @Override public void selectRange(SNode first, SNode last) { flushEvents(); SelectionManager selectionManager = getNodeEditorComponent().getSelectionManager(); selectionManager.setSelection(selectionManager.createRangeSelection(first, last)); } @Override public void selectWRTFocusPolicy(final SNode node) { selectWRTFocusPolicy(node, true); } @Override public EditorInspector getInspector() { return getOperationContext().getComponent(InspectorTool.class); } @Override public void selectWRTFocusPolicy(final SNode node, final boolean force) { flushEvents(); if (!force && getNodeEditorComponent().getSelectedNode() == node) { return; } EditorCell cell = getNodeEditorComponent().findNodeCell(node); if (cell != null) { getNodeEditorComponent().changeSelectionWRTFocusPolicy(cell); } } @Override public void selectWRTFocusPolicy(EditorCell editorCell) { getNodeEditorComponent().changeSelectionWRTFocusPolicy(editorCell); } @Override public void openInspector() { ThreadUtils.runInUIThreadNoWait(() -> IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> { final InspectorTool inspector = getOperationContext().getComponent(InspectorTool.class); if (inspector != null) { inspector.openTool(true); } })); } @Override public EditorCell getContextCell() { if (myContextCell == null) { return getNodeEditorComponent().getSelectedCell(); } return myContextCell; } @Override public void runWithContextCell(EditorCell contextCell, final Runnable r) { runWithContextCell(contextCell, () -> { r.run(); return null; }); } @Override public <T> T runWithContextCell(EditorCell contextCell, Computable<T> r) { EditorCell oldContextCell = myContextCell; myContextCell = contextCell; try { return r.compute(); } finally { myContextCell = oldContextCell; } } @Override public List<SNode> getSelectedNodes() { return myNodeEditorComponent.getSelectedNodes(); } void startTracing(String name) { assert myPerformanceTracer == null; myPerformanceTracer = new PerformanceTracer(name); } String stopTracing() { assert myPerformanceTracer != null; String result = myPerformanceTracer.report(); myPerformanceTracer = null; return result; } boolean isTracing() { return myPerformanceTracer != null; } public void pushTracerTask(String message, boolean isMajor) { if (myPerformanceTracer == null) { return; } myPerformanceTracer.push(message, isMajor); } public void popTracerTask() { if (myPerformanceTracer == null) { return; } myPerformanceTracer.pop(); } @Override public EditorCellFactory getCellFactory() { return getEditorComponent().getUpdater().getCurrentUpdateSession().getCellFactory(); } @Override public SelectionManager getSelectionManager() { return myNodeEditorComponent.getSelectionManager(); } @NotNull @Override public ContextAssistantManager getContextAssistantManager() { return myContextAssistantManager; } public EditorManager getEditorManager() { if (myEditorManager == null) { myEditorManager = new EditorManager(this); } return myEditorManager; } void reset() { myEditorManager = null; } @Nullable @Override public EditorPanelManager getEditorPanelManager() { return myConfiguration.editorPanelManager; } }