package jetbrains.mps.ide.dialogs.project.creation; /*Generated by MPS */ import com.intellij.openapi.ui.DialogWrapper; import jetbrains.mps.project.MPSProject; import jetbrains.mps.project.AbstractModule; import javax.swing.JPanel; import java.awt.BorderLayout; import javax.swing.JTextField; import javax.swing.JComboBox; import org.jetbrains.mps.openapi.persistence.ModelRoot; import org.jetbrains.mps.openapi.persistence.ModelFactoryType; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.EditableSModel; import jetbrains.mps.project.Project; import java.awt.HeadlessException; import jetbrains.mps.ide.project.ProjectHelper; import org.jetbrains.mps.openapi.model.SModelName; import org.jetbrains.mps.openapi.module.SModule; import jetbrains.mps.smodel.Generator; import com.intellij.uiDesigner.core.GridLayoutManager; import java.awt.Dimension; import com.intellij.uiDesigner.core.GridConstraints; import javax.swing.JLabel; import javax.swing.DefaultComboBoxModel; import jetbrains.mps.smodel.Language; import jetbrains.mps.extapi.persistence.FileBasedModelRoot; import javax.swing.DefaultListCellRenderer; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import jetbrains.mps.persistence.DefaultModelRoot; import java.awt.Insets; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.List; import java.util.LinkedList; import java.util.Arrays; import jetbrains.mps.smodel.SModelStereotype; import com.intellij.ui.ColoredListCellRenderer; import javax.swing.JList; import jetbrains.mps.extapi.persistence.ModelFactoryService; import org.jetbrains.mps.openapi.persistence.Memento; import jetbrains.mps.persistence.MementoImpl; import jetbrains.mps.project.structure.model.ModelRootDescriptor; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; import java.io.File; import jetbrains.mps.project.structure.modules.LanguageDescriptor; import java.util.Iterator; import java.util.Objects; import jetbrains.mps.util.Reference; import jetbrains.mps.persistence.ModelCannotBeCreatedException; import jetbrains.mps.smodel.ModelAccessHelper; import jetbrains.mps.util.Computable; import org.jetbrains.annotations.NotNull; import jetbrains.mps.project.SModuleOperations; import jetbrains.mps.smodel.ModelImports; import jetbrains.mps.smodel.CopyUtil; import com.intellij.openapi.ui.Messages; import jetbrains.mps.ide.ui.dialogs.properties.MPSPropertiesConfigurable; import jetbrains.mps.ide.ui.dialogs.properties.ModelPropertiesConfigurable; import com.intellij.openapi.options.ex.SingleConfigurableEditor; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import jetbrains.mps.smodel.language.LanguageAspectSupport; import javax.lang.model.SourceVersion; import org.jetbrains.annotations.Nullable; import javax.swing.JComponent; public class NewModelDialog extends DialogWrapper { private final MPSProject myProject; private final AbstractModule myModule; private final JPanel myContentPane = new JPanel(new BorderLayout()); private final JTextField myModelName = new JTextField(); private final JComboBox<String> myModelStereotype = new JComboBox<String>(); private final JComboBox<ModelRoot> myModelRoots = new JComboBox<ModelRoot>(); private final JComboBox<ModelFactoryType> myModelStorageFormat = new JComboBox<ModelFactoryType>(); private SModel myClone; private boolean myPreserveIds; private EditableSModel myResult; private String myNamespace; public NewModelDialog(Project project, AbstractModule module, String namespace, String stereotype, boolean strict) throws HeadlessException { super(ProjectHelper.toIdeaProject(project)); setTitle("New Model"); myProject = (MPSProject) project; myModule = module; myNamespace = (namespace == null ? "" : namespace); project.getRepository().getModelAccess().runReadAction(new Runnable() { public void run() { assert myModule.getModelRoots().iterator().hasNext() : "Can't create a model in solution with no model roots"; initContentPane(); } }); if (stereotype != null) { myModelStereotype.setSelectedItem(stereotype); myModelStereotype.setEnabled(!(strict)); } init(); } public NewModelDialog(Project project, SModel cloneModel) { this(project, (AbstractModule) cloneModel.getModule(), null, cloneModel.getName().getStereotype(), false); myClone = cloneModel; myPreserveIds = false; SModelName originalName = myClone.getName(); setTitle(String.format("Clone Model %s", originalName.getValue())); myModelName.setText(new SModelName(originalName.getLongName() + "_clone").getValue()); check(); } public NewModelDialog(Project project, AbstractModule module, SModel cloneModel) { this(project, module, null, cloneModel.getName().getStereotype(), false); myClone = cloneModel; myPreserveIds = true; SModelName originalName = myClone.getName(); setTitle(String.format("Move Model %s", originalName.getValue())); myModelName.setText(originalName.getValue()); check(); } public static String getNamespace(SModel model) { SModule module = model.getModule(); if (module instanceof Generator) { Generator gen = (Generator) module; String name = gen.getModuleName(); String genNamespace = gen.getSourceLanguage().getModuleName() + ".generator"; if ((name == null || name.length() == 0)) { return genNamespace; } return genNamespace + "." + name; } return module.getModuleName(); } public EditableSModel getResult() { return myResult; } private void initContentPane() { JPanel mainPanel = new JPanel(new GridLayoutManager(6, 1)); mainPanel.setPreferredSize(new Dimension(200, 50)); GridConstraints constraints = new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null); mainPanel.add(new JLabel("Model root:"), constraints); constraints.setRow(constraints.getRow() + 1); mainPanel.add(myModelRoots, constraints); DefaultComboBoxModel<ModelRoot> model = new DefaultComboBoxModel<ModelRoot>(); for (ModelRoot root : myModule.getModelRoots()) { if (root.canCreateModels()) { model.addElement(root); } else if (myModule instanceof Language && root instanceof FileBasedModelRoot) { // Can fix only FileBased model root (default for language) model.addElement(root); } } if (model.getSize() == 0) { model.addElement(null); } myModelRoots.setRenderer(new DefaultListCellRenderer()); myModelRoots.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { check(); myModelStorageFormat.setVisible(myModelRoots.getSelectedItem() instanceof DefaultModelRoot); } }); myModelRoots.setModel(model); myModelName.setText((myNamespace.length() == 0 ? myNamespace : myNamespace + ".")); constraints.setRow(constraints.getRow() + 1); mainPanel.add(new JLabel("Model name:"), constraints); JPanel nameAndStereotype = new JPanel(new GridLayoutManager(1, 3, new Insets(0, 0, 0, 0), -1, -1)); GridConstraints nameConstraints = new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null); nameAndStereotype.add(myModelName, nameConstraints); myModelName.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent event) { check(); } }); final JLabel atSign = new JLabel(); nameConstraints.setColumn(nameConstraints.getColumn() + 1); nameConstraints.setHSizePolicy(GridConstraints.SIZEPOLICY_FIXED); nameAndStereotype.add(atSign, nameConstraints); List<String> stereotypes = new LinkedList<String>(Arrays.asList(SModelStereotype.values)); if (!(myModule instanceof Generator)) { stereotypes.remove(SModelStereotype.GENERATOR); } myModelStereotype.setEditable(true); myModelStereotype.setModel(new DefaultComboBoxModel<String>(stereotypes.toArray(new String[stereotypes.size()]))); myModelStereotype.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent event) { check(); } }); myModelStereotype.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent p0) { check(); atSign.setText((myModelStereotype.getSelectedItem().equals(SModelStereotype.NONE) ? "" : "@")); } }); nameConstraints.setColumn(nameConstraints.getColumn() + 1); nameAndStereotype.add(myModelStereotype, nameConstraints); constraints.setRow(constraints.getRow() + 1); mainPanel.add(nameAndStereotype, constraints); constraints.setRow(constraints.getRow() + 1); mainPanel.add(new JLabel("Storage format:"), constraints); constraints.setRow(constraints.getRow() + 1); myModelStorageFormat.setModel(new DefaultComboBoxModel<ModelFactoryType>(getStorageFormats())); myModelStorageFormat.setRenderer(new ColoredListCellRenderer<ModelFactoryType>() { protected void customizeCellRenderer(JList<? extends ModelFactoryType> p0, ModelFactoryType factoryType, int p2, boolean p3, boolean p4) { append(factoryType.getFormatTitle()); } }); myModelStorageFormat.setSelectedItem(ModelFactoryService.getInstance().getFactoryTypes().get(0)); mainPanel.add(myModelStorageFormat, constraints); myContentPane.add(mainPanel, BorderLayout.CENTER); } private ModelFactoryType[] getStorageFormats() { List<ModelFactoryType> result = ModelFactoryService.getInstance().getFactoryTypes(); return result.toArray(new ModelFactoryType[result.size()]); } @Override protected void doOKAction() { if (!(check())) { return; } if (!(((ModelRoot) myModelRoots.getSelectedItem()).canCreateModel(getFqName())) && myModule instanceof Language && myModelRoots.getSelectedItem() instanceof FileBasedModelRoot) { final FileBasedModelRoot selectedModelRoot = (FileBasedModelRoot) myModelRoots.getSelectedItem(); Memento memento = new MementoImpl(); selectedModelRoot.save(memento); final ModelRootDescriptor oldModelRootDescriptor = new ModelRootDescriptor(selectedModelRoot.getType(), memento); final FileBasedModelRoot newModelRoot = (FileBasedModelRoot) PersistenceFacade.getInstance().getModelRootFactory(selectedModelRoot.getType()).create(); newModelRoot.load(memento); newModelRoot.addFile(FileBasedModelRoot.SOURCE_ROOTS, newModelRoot.getContentRoot() + File.separator + "languageAccessories"); memento = new MementoImpl(); newModelRoot.save(memento); final ModelRootDescriptor newModelRootDescriptor = new ModelRootDescriptor(newModelRoot.getType(), memento); myProject.getRepository().getModelAccess().runWriteAction(new Runnable() { public void run() { final LanguageDescriptor languageDescriptor = ((Language) myModule).getModuleDescriptor(); Iterator<ModelRootDescriptor> iterator = languageDescriptor.getModelRootDescriptors().iterator(); while (iterator.hasNext()) { ModelRootDescriptor descriptor = iterator.next(); if (descriptor.getType().equals(oldModelRootDescriptor.getType()) && descriptor.getMemento().equals(oldModelRootDescriptor.getMemento())) { iterator.remove(); break; } } languageDescriptor.getModelRootDescriptors().add(newModelRootDescriptor); // see MPS-18743 myProject.getRepository().saveAll(); myModule.setModuleDescriptor(languageDescriptor); myModule.save(); } }); myProject.getRepository().getModelAccess().runReadAction(new Runnable() { public void run() { for (ModelRoot modelRoot : myModule.getModelRoots()) { if (modelRoot instanceof FileBasedModelRoot && Objects.equals(((FileBasedModelRoot) modelRoot).getContentRoot(), selectedModelRoot.getContentRoot())) { myModelRoots.addItem(modelRoot); myModelRoots.setSelectedItem(modelRoot); } } } }); } final Reference<ModelCannotBeCreatedException> refException = new Reference<ModelCannotBeCreatedException>(); myResult = new ModelAccessHelper(myProject.getModelAccess()).executeCommand(new Computable<EditableSModel>() { @Override public EditableSModel compute() { String fqName = getFqName(); ModelRoot mr = (ModelRoot) myModelRoots.getSelectedItem(); @NotNull EditableSModel result; try { if (mr instanceof DefaultModelRoot) { result = SModuleOperations.createModelWithAdjustments(fqName, mr, (ModelFactoryType) myModelStorageFormat.getSelectedItem()); } else { result = SModuleOperations.createModelWithAdjustments(fqName, mr, null); } } catch (ModelCannotBeCreatedException e) { refException.set(e); return null; } if (myClone == null) { return result; } ModelImports imports = new ModelImports(result); imports.copyImportedModelsFrom(myClone); imports.copyUsedLanguagesFrom(myClone); imports.copyEmployedDevKitsFrom(myClone); imports.copyLanguageEngagedOnGeneration(myClone); if (myPreserveIds) { CopyUtil.copyModelContentAndPreserveIds(myClone, result); } else { CopyUtil.copyModelContent(myClone, result); } result.setChanged(true); result.save(); return result; } }); if (!(refException.isNull())) { Messages.showErrorDialog(myProject.getProject(), "Could not create a new model because '" + refException.get().getMessage() + "'", "Error"); } super.doOKAction(); if (myResult != null) { MPSPropertiesConfigurable configurable = new ModelPropertiesConfigurable(myResult, myProject); final SingleConfigurableEditor configurableEditor = new SingleConfigurableEditor(ProjectHelper.toIdeaProject(myProject), configurable, "#MPSPropertiesConfigurable"); ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { configurableEditor.show(); } }, ModalityState.current()); } } private String getFqName() { String stereo = myModelStereotype.getSelectedItem().toString().trim(); return myModelName.getText() + ((stereo.length() > 0 ? "@" + stereo : "")); } private boolean check() { Object selected = myModelRoots.getSelectedItem(); if (!((selected instanceof ModelRoot))) { setErrorText("Model root is not selected"); return false; } ModelRoot mr = ((ModelRoot) selected); String modelName = myModelName.getText(); if (modelName.length() == 0) { setErrorText("Empty model name isn't allowed"); return false; } if (modelName.lastIndexOf(".") == modelName.length()) { setErrorText("Empty model short name isn't allowed"); return false; } if (myModule instanceof Language) { if (LanguageAspectSupport.isLanguageModelNameForbidden(modelName)) { String shortName = modelName.substring(modelName.lastIndexOf(".") + 1); setErrorText("This name isn't allowed because '" + shortName + "' is language aspect name"); return false; } } if (!(SourceVersion.isName(modelName))) { setErrorText("Model name should be valid Java package"); return false; } if (!(mr.canCreateModel(getFqName()))) { boolean isLang = myModule instanceof Language; if (!(isLang) || !((mr instanceof FileBasedModelRoot))) { setErrorText("Can't create a model with this name under this model root"); return false; } } setErrorText(null); return true; } @Nullable @Override protected JComponent createCenterPanel() { return myContentPane; } @Nullable @Override public JComponent getPreferredFocusedComponent() { return myModelName; } }