package com.jetbrains.lang.dart.projectWizard; import com.intellij.ide.util.projectWizard.ModuleBuilder; import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.internal.statistic.UsageTrigger; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.module.WebModuleBuilder; import com.intellij.openapi.module.WebModuleType; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableModelsProvider; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.vfs.VirtualFile; import com.jetbrains.lang.dart.DartBundle; import com.jetbrains.lang.dart.ide.actions.DartPubGetAction; import com.jetbrains.lang.dart.ide.runner.client.DartiumUtil; import com.jetbrains.lang.dart.sdk.DartSdk; import com.jetbrains.lang.dart.sdk.DartSdkLibUtil; import com.jetbrains.lang.dart.sdk.DartSdkUtil; import com.jetbrains.lang.dart.util.PubspecYamlUtil; import icons.DartIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.IOException; import java.util.Collection; public class DartModuleBuilder extends ModuleBuilder { private DartProjectWizardData myWizardData; @Override public String getName() { return DartBundle.message("dart.title"); } @Override public String getPresentableName() { return DartBundle.message("dart.title"); } @Override public String getDescription() { return DartBundle.message("dart.project.description"); } @Override public Icon getNodeIcon() { return DartIcons.Dart_16; } @Override public ModuleType getModuleType() { return WebModuleType.getInstance(); } @Override public String getParentGroup() { return WebModuleBuilder.GROUP_NAME; } @Nullable @Override public ModuleWizardStep getCustomOptionsStep(final WizardContext context, final Disposable parentDisposable) { final DartModuleWizardStep step = new DartModuleWizardStep(context); Disposer.register(parentDisposable, step); return step; } void setWizardData(final DartProjectWizardData wizardData) { myWizardData = wizardData; } @Override public void setupRootModel(final ModifiableRootModel modifiableRootModel) throws ConfigurationException { final ContentEntry contentEntry = doAddContentEntry(modifiableRootModel); final VirtualFile baseDir = contentEntry == null ? null : contentEntry.getFile(); if (baseDir != null) { setupProject(modifiableRootModel, baseDir, myWizardData); } } static void setupProject(@NotNull final ModifiableRootModel modifiableRootModel, @NotNull final VirtualFile baseDir, @NotNull final DartProjectWizardData wizardData) { final String templateName = wizardData.myTemplate == null ? "Empty project" : wizardData.myTemplate.getName(); UsageTrigger.trigger("DartProjectWizard." + templateName); setupSdkAndDartium(modifiableRootModel, wizardData); if (wizardData.myTemplate != null) { try { final Collection<VirtualFile> filesToOpen = wizardData.myTemplate.generateProject(wizardData.dartSdkPath, modifiableRootModel.getModule(), baseDir); if (!filesToOpen.isEmpty()) { scheduleFilesOpeningAndPubGet(modifiableRootModel.getModule(), filesToOpen); } } catch (IOException ignore) {/*unlucky*/} } } private static void setupSdkAndDartium(@NotNull final ModifiableRootModel modifiableRootModel, @NotNull final DartProjectWizardData wizardData) { // similar to DartConfigurable.apply() if (DartSdkUtil.isDartSdkHome(wizardData.dartSdkPath)) { final Project project = modifiableRootModel.getProject(); DartSdkUtil.updateKnownSdkPaths(project, wizardData.dartSdkPath); final LibraryTable.ModifiableModel libraryTableModifiableModel = ModifiableModelsProvider.SERVICE.getInstance().getLibraryTableModifiableModel(project); DartSdkLibUtil.ensureDartSdkConfigured(project, libraryTableModifiableModel, wizardData.dartSdkPath); if (libraryTableModifiableModel.isChanged()) { libraryTableModifiableModel.commit(); } else { ModifiableModelsProvider.SERVICE.getInstance().disposeLibraryTableModifiableModel(libraryTableModifiableModel); } modifiableRootModel.addInvalidLibrary(DartSdk.DART_SDK_LIB_NAME, LibraryTablesRegistrar.PROJECT_LEVEL); } DartiumUtil.applyDartiumSettings(FileUtilRt.toSystemIndependentName(wizardData.dartiumPath), wizardData.dartiumSettings); } private static void scheduleFilesOpeningAndPubGet(@NotNull final Module module, @NotNull final Collection<VirtualFile> files) { runWhenNonModalIfModuleNotDisposed(() -> { final FileEditorManager manager = FileEditorManager.getInstance(module.getProject()); for (VirtualFile file : files) { manager.openFile(file, true); if (PubspecYamlUtil.PUBSPEC_YAML.equals(file.getName())) { final AnAction pubGetAction = ActionManager.getInstance().getAction("Dart.pub.get"); if (pubGetAction instanceof DartPubGetAction) { ((DartPubGetAction)pubGetAction).performPubAction(module, file, false); } } } }, module); } static void runWhenNonModalIfModuleNotDisposed(@NotNull final Runnable runnable, @NotNull final Module module) { // runnable must not be executed immediately because the new project model might be not yet committed, so Dart SDK won't be found if (module.getProject().isInitialized()) { ApplicationManager.getApplication().invokeLater(runnable, ModalityState.NON_MODAL, module.getDisposed()); return; } StartupManager.getInstance(module.getProject()).runWhenProjectIsInitialized(() -> { if (ApplicationManager.getApplication().getCurrentModalityState() == ModalityState.NON_MODAL) { runnable.run(); } else { ApplicationManager.getApplication().invokeLater(runnable, ModalityState.NON_MODAL, o -> module.isDisposed()); } }); } }