/* * Copyright 2003-2011 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.idea.core.facet.ui; import com.intellij.facet.ui.FacetEditorContext; import com.intellij.openapi.Disposable; import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import jetbrains.mps.extapi.persistence.SourceRoot; import jetbrains.mps.extapi.persistence.SourceRootKinds; import jetbrains.mps.ide.project.ProjectHelper; import jetbrains.mps.ide.ui.dialogs.properties.roots.editors.ModelRootContentEntriesEditor; import jetbrains.mps.ide.ui.dialogs.properties.roots.editors.ModelRootEntryContainer; import jetbrains.mps.ide.vfs.VirtualFileUtils; import jetbrains.mps.idea.core.facet.MPSConfigurationBean; import jetbrains.mps.idea.core.ui.SModuleConfigurationTab; import jetbrains.mps.persistence.DefaultModelRoot; import org.jetbrains.mps.openapi.persistence.ModelRoot; import org.jetbrains.mps.openapi.ui.persistence.ModelRootEntry.ModelRootEntryListener; import javax.swing.BorderFactory; import javax.swing.JPanel; import java.awt.BorderLayout; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; public class MPSFacetSourcesTab implements SModuleConfigurationTab { private JPanel myRootPanel; private FacetEditorContext myContext; private Disposable myParentDisposable; private ModelRootContentEntriesEditor myContentEntriesEditor; public MPSFacetSourcesTab(FacetEditorContext context, Disposable parentDisposable) { myContext = context; myParentDisposable = parentDisposable; myRootPanel = new JPanel(new BorderLayout()); myRootPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); } public JPanel getRootPanel() { return myRootPanel; } @Override public void onTabEntering() { } public void reset(MPSConfigurationBean data) { if(myContentEntriesEditor != null) { Disposer.dispose(myContentEntriesEditor); myContentEntriesEditor = null; } myContentEntriesEditor = new ModelRootContentEntriesEditor(data.getSolutionDescriptor(), ProjectHelper.getProjectRepository(myContext.getProject())); Disposer.register(myParentDisposable, myContentEntriesEditor); VirtualFile defaultFolder = myContext.getModule().getModuleFile() != null ? myContext.getModule().getModuleFile().getParent() : myContext.getProject().getBaseDir(); myContentEntriesEditor.setDefaultFolder(VirtualFileUtils.toIFile(defaultFolder)); myRootPanel.removeAll(); myRootPanel.add(myContentEntriesEditor.getComponent(), BorderLayout.CENTER); //Watch for changes in model root source folders for(ModelRootEntryContainer container : myContentEntriesEditor.getModelRootsEntries()) { container.getModelRootEntry().addModelRootEntryListener(new ModelRootEntryListener() { @Override public void fireDataChanged() { final ModifiableRootModel modifiableRootModel = myContext.getModifiableRootModel(); // NOTE: if an MPS source root is not under any of idea _content_ roots, it will not be // added to idea's source roots. It would require creating a new content root, rather // than just adding source root into existing content root. Seems like too much intrusion. // Fixme we don't remove source roots that we have added to idea module for (ModelRoot path : myContentEntriesEditor.getModelRoots()) { if(path instanceof DefaultModelRoot) { for(SourceRoot mpsSourceRoot : ((DefaultModelRoot) path).getSourceRoots(SourceRootKinds.SOURCES)) { VirtualFile mpsSourceRootVFile = VirtualFileUtils.getProjectVirtualFile(mpsSourceRoot.getAbsolutePath()); if (mpsSourceRootVFile == null) { // not in project; strange but why not continue; } for(ContentEntry contentEntry : modifiableRootModel.getContentEntries()) { VirtualFile contentRoot = contentEntry.getFile(); if (contentRoot == null) { // invalid content root continue; } if (!VfsUtilCore.isUnder(mpsSourceRootVFile, Collections.singleton(contentRoot))) { // a completely different content root continue; } Set<VirtualFile> ideaSourceFolders = new HashSet<>(Arrays.asList(contentEntry.getSourceFolderFiles())); if (VfsUtilCore.isUnder(mpsSourceRootVFile, ideaSourceFolders)) { // we're covered, no need to worry break; } //Just add new source/test folder - do not watch after delete contentEntry.addSourceFolder(mpsSourceRootVFile, false); } } } } } }); } } public void apply(MPSConfigurationBean data) { data.setModelRoots(myContentEntriesEditor.getModelRoots()); } public boolean isModified(MPSConfigurationBean data) { return myContentEntriesEditor.isModified(); } }