/*
* Copyright 2003-2015 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.ide.IdeBundle;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.ui.awt.RelativePoint;
import jetbrains.mps.ide.icons.IconManager;
import jetbrains.mps.nodeEditor.cells.EditorCell_Error;
import jetbrains.mps.nodeEditor.cells.EditorCell_Label;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.smodel.SLanguageHierarchy;
import jetbrains.mps.smodel.SModelOperations;
import jetbrains.mps.smodel.action.NodeFactoryManager;
import jetbrains.mps.smodel.language.ConceptRegistry;
import jetbrains.mps.smodel.language.LanguageRegistry;
import jetbrains.mps.util.Setter;
import jetbrains.mps.util.ToStringComparator;
import jetbrains.mps.workbench.action.BaseAction;
import jetbrains.mps.workbench.action.BaseGroup;
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.language.SLanguage;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.util.Condition;
import java.awt.Component;
import java.awt.Point;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
public final class CreateFromUsageUtil {
private CreateFromUsageUtil() {
}
public static boolean isApplicable(jetbrains.mps.openapi.editor.EditorContext editorContext) {
boolean applicable = false;
EditorCell selectedCell = editorContext.getSelectedCell();
if (selectedCell instanceof EditorCell_Error) {
EditorCell_Label editorCell_Label = (EditorCell_Label) selectedCell;
applicable = editorCell_Label.getText().length() > 0;
}
return applicable;
}
public static String getText(jetbrains.mps.openapi.editor.EditorContext editorContext) {
EditorCell cell = editorContext.getSelectedCell();
if (cell instanceof EditorCell_Label) {
return ((EditorCell_Label) cell).getText();
}
return null;
}
public static void showCreateNewRootMenu(@NotNull jetbrains.mps.openapi.editor.EditorContext editorContext, @Nullable Setter<SNode> newRootHandler,
@Nullable Condition<SConcept> conceptsFilter) {
final EditorCell selectedCell = editorContext.getSelectedCell();
int x = selectedCell.getX();
int y = selectedCell.getY();
if (selectedCell instanceof EditorCell_Label) {
y += selectedCell.getHeight();
}
Component editorComponent = ((EditorContext) editorContext).getNodeEditorComponent();
final DataContext dataContext = DataManager.getInstance().getDataContext(editorComponent, x, y);
final SModel model = selectedCell.getSNode().getModel();
if (conceptsFilter == null) {
conceptsFilter = Condition.TRUE_CONDITION;
}
BaseGroup group = new BaseGroup("");
Set<SLanguage> modelLanguages = new SLanguageHierarchy(SModelOperations.getAllLanguageImports(model)).getExtended();
SLanguage[] languages = modelLanguages.toArray(new SLanguage[modelLanguages.size()]);
Arrays.sort(languages, new ToStringComparator());
for (SLanguage language : languages) {
boolean hasChildren = false;
for (SAbstractConcept ac : language.getConcepts()) {
if (!(ac instanceof SConcept)) {
continue;
}
final SConcept concept = (SConcept) ac;
if (concept.isRootable() && conceptsFilter.met(concept)) {
group.add(new AddNewRootAction(model, concept, newRootHandler));
hasChildren = true;
}
}
if (hasChildren) {
group.addSeparator();
}
}
ListPopup popup = JBPopupFactory.getInstance().createActionGroupPopup(IdeBundle.message("title.popup.new.element"),
group, dataContext, JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false);
// popup.showInBestPositionFor(dataContext);
popup.show(new RelativePoint(editorComponent, new Point(x, y)));
}
private static class AddNewRootAction extends BaseAction {
private final SModel myModel;
private final SConcept myConcept;
private final Setter<SNode> myNewRootCallback;
public AddNewRootAction(@NotNull SModel model, @NotNull SConcept concept, @Nullable Setter<SNode> newRootCallback) {
myModel = model;
myConcept = concept;
myNewRootCallback = newRootCallback;
setExecuteOutsideCommand(false);
final Presentation tp = getTemplatePresentation();
tp.setText(concept.getConceptAlias().isEmpty() ? concept.getName() : concept.getConceptAlias());
tp.setIcon(IconManager.getIcon(concept));
}
@Override
protected void doExecute(AnActionEvent e, Map<String, Object> params) {
SNode result = NodeFactoryManager.createNode(myConcept, null, null, myModel);
myModel.addRootNode(result);
if (myNewRootCallback != null) {
myNewRootCallback.set(result);
}
}
}
}