/* * 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.lang.editor.menus.substitute; import jetbrains.mps.actions.runtime.impl.ActionsUtil; import jetbrains.mps.nodeEditor.EditorComponent; import jetbrains.mps.nodeEditor.EditorManager; import jetbrains.mps.nodeEditor.cellMenu.AbstractNodeSubstituteInfo; import jetbrains.mps.nodeEditor.cells.CellFinderUtil; import jetbrains.mps.openapi.editor.EditorContext; import jetbrains.mps.openapi.editor.cells.EditorCell; import jetbrains.mps.openapi.editor.menus.substitute.SubstituteMenuItem; import jetbrains.mps.smodel.action.NodeFactoryManager; import jetbrains.mps.smodel.presentation.NodePresentationUtil; import jetbrains.mps.smodel.runtime.IconResource; import jetbrains.mps.smodel.runtime.IconResourceUtil; import jetbrains.mps.typesystem.inference.TypeChecker; import jetbrains.mps.util.PatternUtil; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.language.SAbstractConcept; import org.jetbrains.mps.openapi.language.SConcept; import org.jetbrains.mps.openapi.model.SNode; /** * @author simon */ public class DefaultSubstituteMenuItem implements SubstituteMenuItem { private static final Logger LOG = LogManager.getLogger(DefaultSubstituteMenuItem.class); @NotNull private SAbstractConcept myConcept; @NotNull private final SNode myParentNode; @Nullable private final SNode myCurrentChild; @NotNull private EditorContext myEditorContext; public DefaultSubstituteMenuItem(@NotNull SAbstractConcept concept, @NotNull SNode parentNode, @Nullable SNode currentChild, @NotNull EditorContext editorContext) { myConcept = concept; myParentNode = parentNode; myCurrentChild = currentChild; myEditorContext = editorContext; } @Nullable @Override public SAbstractConcept getOutputConcept() { return myConcept; } @Nullable @Override public SNode getType(@NotNull String pattern) { SNode node = createNode(pattern); if (node == null) return null; if (node.getParent() != null) { LOG.warn("Node, created by " + this.getClass() + " action already has parent node.", new Throwable()); } if (ActionsUtil.isInstanceOfIType(node)) return node; //the following is for smart-type completion AbstractNodeSubstituteInfo.getModelForTypechecking().addRootNode(node); try { return TypeChecker.getInstance().getTypeOf(node); } finally { AbstractNodeSubstituteInfo.getModelForTypechecking().removeRootNode(node); } } @Nullable @Override public String getMatchingText(@NotNull String pattern) { return NodePresentationUtil.matchingText(myConcept); } @Nullable @Override public String getDescriptionText(@NotNull String pattern) { return NodePresentationUtil.descriptionText(myConcept); } @Override public boolean canExecute(@NotNull String pattern) { return PatternUtil.matchesPattern(pattern, getMatchingText(pattern)); } @Override public boolean canExecuteStrictly(@NotNull String pattern) { return pattern.equals(getMatchingText(pattern)); } @Nullable @Override public SNode createNode(@NotNull String pattern) { SNode currentChild = myCurrentChild; if (myCurrentChild != null) { final Object oldNodeForSubstitute = myCurrentChild.getUserObject(EditorManager.OLD_NODE_FOR_SUBSTITUTION); if (oldNodeForSubstitute != null) { currentChild = ((SNode) oldNodeForSubstitute); } } return NodeFactoryManager.createNode(myConcept, currentChild, myParentNode, myParentNode.getModel()); } @Nullable @Override public IconResource getIcon(@NotNull String pattern) { return IconResourceUtil.getIconResourceForConcept(myConcept); } @Override public void select(@NotNull SNode createdNode, @NotNull String pattern) { EditorComponent editorComponent = ((EditorComponent) myEditorContext.getEditorComponent()); EditorCell cell = editorComponent.findNodeCell(createdNode); if (cell != null) { EditorCell errorCell = CellFinderUtil.findFirstError(cell, true); if (errorCell != null) { editorComponent.changeSelectionWRTFocusPolicy(errorCell); } else { editorComponent.changeSelectionWRTFocusPolicy(cell); } } } @Nullable protected SNode getCurrentChild() { return myCurrentChild; } @NotNull protected SNode getParentNode() { return myParentNode; } }