/*
* 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.ide.DataManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.LocalTimeCounter;
import jetbrains.mps.RuntimeFlags;
import jetbrains.mps.ide.actions.MPSCommonDataKeys;
import jetbrains.mps.logging.Logger;
import jetbrains.mps.nodeEditor.commands.CommandContextImpl;
import jetbrains.mps.nodeEditor.commands.CommandContextWithVF;
import jetbrains.mps.nodeEditor.configuration.EditorConfiguration;
import jetbrains.mps.nodeEditor.configuration.EditorConfigurationBuilder;
import jetbrains.mps.nodeEditor.selection.SingularSelectionListenerAdapter;
import jetbrains.mps.nodefs.MPSNodeVirtualFile;
import jetbrains.mps.openapi.editor.selection.SingularSelection;
import jetbrains.mps.project.Project;
import org.apache.log4j.LogManager;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.module.SRepository;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
public class NodeEditorComponent extends EditorComponent {
private static Logger LOG = Logger.wrap(LogManager.getLogger(NodeEditorComponent.class));
private SNode myLastInspectedNode = null;
private CommandContextWithVF myCommandContext;
public NodeEditorComponent(SRepository repository) {
this(repository, new EditorConfigurationBuilder().showErrorsGutter(true).build());
}
public NodeEditorComponent(SRepository repository, EditorConfigurationBuilder confBuilder) {
this(repository, confBuilder.showErrorsGutter(true).build());
}
private NodeEditorComponent(SRepository repository, EditorConfiguration configuration) {
super(repository, configuration);
getSelectionManager().addSelectionListener(new SingularSelectionListenerAdapter() {
@Override
protected void selectionChangedTo(jetbrains.mps.openapi.editor.EditorComponent editorComponent, SingularSelection newSelection) {
final SNode[] toSelect = new SNode[]{newSelection.getEditorCell().getSNode()};
getRepository().getModelAccess().runReadAction(new Runnable() {
@Override
public void run() {
if (isShowing() || RuntimeFlags.getTestMode().isInsideTestEnvironment()) {
inspect(toSelect[0]);
}
}
});
}
});
addHierarchyListener(new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent hierarchyEvent) {
if (HierarchyEvent.SHOWING_CHANGED != (hierarchyEvent.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED)) {
return;
}
if (!isShowing()) {
return;
}
adjustInspector();
}
});
}
@Override
protected boolean notifiesCreation() {
return true;
}
private void adjustInspector() {
getRepository().getModelAccess().runReadAction(new Runnable() {
@Override
public void run() {
SNode selectedNode = getSelectedNode();
if (selectedNode == null) {
inspect(null);
return;
}
if (selectedNode.getModel() == null) {
return;
}
inspect(selectedNode);
}
});
}
public SNode getLastInspectedNode() {
return myLastInspectedNode;
}
private void inspect(final SNode toSelect) {
myLastInspectedNode = toSelect;
if (getInspector() == null) {
return;
}
DataContext dataContext = DataManager.getInstance().getDataContext(this);
FileEditor fileEditor = MPSCommonDataKeys.FILE_EDITOR.getData(dataContext);
String[] inspectorInitialEditorHints = getEditorHintsForNode(toSelect);
if (getInspectorTool() != null) {
getInspectorTool().inspect(toSelect, fileEditor, inspectorInitialEditorHints);
}
}
@Override
public void rebuildEditorContent() {
SNode editedNode = getEditedNode();
if (editedNode == null || !org.jetbrains.mps.openapi.model.SNodeUtil.isAccessible(editedNode, getEditorContext().getRepository())) {
return;
}
super.rebuildEditorContent();
}
public EditorComponent getInspector() {
if (getInspectorTool() == null) {
return null;
}
return getInspectorTool().getInspector();
}
@Nullable
public InspectorTool getInspectorTool() {
final Project p = getCurrentProject();
if (p == null || p.isDisposed()) {
return null;
}
return p.getComponent(InspectorTool.class);
}
@Override
public void dispose() {
notifyDisposal();
InspectorTool inspectorTool = getInspectorTool();
if (inspectorTool != null && inspectorTool.getInspector() != null) {
if (inspectorTool.getInspector().getEditedNode() == this.getLastInspectedNode()) {
inspectorTool.inspect(null, null, null);
}
}
myLastInspectedNode = null;
super.dispose();
}
@Override
protected CommandContextImpl createCommandContext() {
return myCommandContext = new CommandContextWithVF(this, getRepository());
}
@Nullable
public MPSNodeVirtualFile getVirtualFile() {
return myCommandContext.getContextVirtualFile();
}
@Override
public void touch() {
if (getVirtualFile() != null) {
getVirtualFile().setModificationStamp(LocalTimeCounter.currentTime());
}
}
@Nullable
@Override
public Object getData(@NonNls String dataId) {
if (dataId.equals(PlatformDataKeys.VIRTUAL_FILE_ARRAY.getName())) {
return getVirtualFile() != null ? new VirtualFile[]{getVirtualFile()} : new VirtualFile[0];
}
return super.getData(dataId);
}
}