blob: 91c8405896058cae488cfff3e9b65c454dcb40d0 [file] [log] [blame]
/*
* Copyright 2000-2013 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 com.intellij.openapi.roots.ui.configuration;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.EventDispatcher;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.EventListener;
import java.util.List;
/**
* @author Eugene Zhuravlev
* @since Oct 8, 2003
*/
@SuppressWarnings("UnusedDeclaration")
public abstract class ContentEntryEditor implements ContentRootPanel.ActionCallback {
private boolean myIsSelected;
private ContentRootPanel myContentRootPanel;
private JPanel myMainPanel;
protected EventDispatcher<ContentEntryEditorListener> myEventDispatcher;
private final String myContentEntryUrl;
private final List<ModuleSourceRootEditHandler<?>> myEditHandlers;
public interface ContentEntryEditorListener extends EventListener{
void editingStarted(@NotNull ContentEntryEditor editor);
void beforeEntryDeleted(@NotNull ContentEntryEditor editor);
void sourceFolderAdded(@NotNull ContentEntryEditor editor, SourceFolder folder);
void sourceFolderRemoved(@NotNull ContentEntryEditor editor, VirtualFile file);
void folderExcluded(@NotNull ContentEntryEditor editor, VirtualFile file);
void folderIncluded(@NotNull ContentEntryEditor editor, String fileUrl);
void navigationRequested(@NotNull ContentEntryEditor editor, VirtualFile file);
void sourceRootPropertiesChanged(@NotNull ContentEntryEditor editor, @NotNull SourceFolder folder);
}
public ContentEntryEditor(String url, List<ModuleSourceRootEditHandler<?>> editHandlers) {
myContentEntryUrl = url;
myEditHandlers = editHandlers;
}
protected final List<ModuleSourceRootEditHandler<?>> getEditHandlers() {
return myEditHandlers;
}
public String getContentEntryUrl() {
return myContentEntryUrl;
}
public void initUI() {
myMainPanel = new JPanel(new BorderLayout());
myMainPanel.setOpaque(false);
myMainPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
myEventDispatcher.getMulticaster().editingStarted(ContentEntryEditor.this);
}
@Override
public void mouseEntered(MouseEvent e) {
if (!myIsSelected) {
highlight(true);
}
}
@Override
public void mouseExited(MouseEvent e) {
if (!myIsSelected) {
highlight(false);
}
}
});
myEventDispatcher = EventDispatcher.create(ContentEntryEditorListener.class);
setSelected(false);
update();
}
@Nullable
protected ContentEntry getContentEntry() {
final ModifiableRootModel model = getModel();
if (model != null) {
final ContentEntry[] entries = model.getContentEntries();
for (ContentEntry entry : entries) {
if (entry.getUrl().equals(myContentEntryUrl)) return entry;
}
}
return null;
}
protected abstract ModifiableRootModel getModel();
@Override
public void deleteContentEntry() {
final String path = FileUtil.toSystemDependentName(VfsUtilCore.urlToPath(myContentEntryUrl));
final int answer = Messages.showYesNoDialog(ProjectBundle.message("module.paths.remove.content.prompt", path),
ProjectBundle.message("module.paths.remove.content.title"), Messages.getQuestionIcon());
if (answer != Messages.YES) { // no
return;
}
myEventDispatcher.getMulticaster().beforeEntryDeleted(this);
final ContentEntry entry = getContentEntry();
if (entry != null) {
getModel().removeContentEntry(entry);
}
}
@Override
public void deleteContentFolder(ContentEntry contentEntry, ContentFolder folder) {
if (folder instanceof SourceFolder) {
removeSourceFolder((SourceFolder)folder);
update();
}
else if (folder instanceof ExcludeFolder) {
removeExcludeFolder(folder.getUrl());
update();
}
}
@Override
public void navigateFolder(ContentEntry contentEntry, ContentFolder contentFolder) {
final VirtualFile file = contentFolder.getFile();
if (file != null) { // file can be deleted externally
myEventDispatcher.getMulticaster().navigationRequested(this, file);
}
}
@Override
public void onSourceRootPropertiesChanged(@NotNull SourceFolder folder) {
update();
myEventDispatcher.getMulticaster().sourceRootPropertiesChanged(this, folder);
}
public void addContentEntryEditorListener(ContentEntryEditorListener listener) {
myEventDispatcher.addListener(listener);
}
public void removeContentEntryEditorListener(ContentEntryEditorListener listener) {
myEventDispatcher.removeListener(listener);
}
public void setSelected(boolean isSelected) {
if (myIsSelected != isSelected) {
highlight(isSelected);
myIsSelected = isSelected;
}
}
private void highlight(boolean selected) {
if (myContentRootPanel != null) {
myContentRootPanel.setSelected(selected);
}
}
public JComponent getComponent() {
return myMainPanel;
}
public void update() {
if (myContentRootPanel != null) {
myMainPanel.remove(myContentRootPanel);
}
myContentRootPanel = createContentRootPane();
myContentRootPanel.initUI();
myContentRootPanel.setSelected(myIsSelected);
myMainPanel.add(myContentRootPanel, BorderLayout.CENTER);
myMainPanel.revalidate();
}
protected ContentRootPanel createContentRootPane() {
return new ContentRootPanel(this, myEditHandlers) {
@Override
protected ContentEntry getContentEntry() {
return ContentEntryEditor.this.getContentEntry();
}
};
}
@Nullable
public SourceFolder addSourceFolder(@NotNull final VirtualFile file, boolean isTestSource, String packagePrefix) {
return addSourceFolder(file, isTestSource ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE,
JpsJavaExtensionService.getInstance().createSourceRootProperties(packagePrefix));
}
@Nullable
public <P extends JpsElement> SourceFolder addSourceFolder(@NotNull final VirtualFile file, final JpsModuleSourceRootType<P> rootType,
final P properties) {
final ContentEntry contentEntry = getContentEntry();
if (contentEntry != null) {
final SourceFolder sourceFolder = contentEntry.addSourceFolder(file, rootType, properties);
myEventDispatcher.getMulticaster().sourceFolderAdded(this, sourceFolder);
update();
return sourceFolder;
}
return null;
}
@Nullable
protected SourceFolder doAddSourceFolder(@NotNull final VirtualFile file, final boolean isTestSource) {
final ContentEntry contentEntry = getContentEntry();
return contentEntry != null ? contentEntry.addSourceFolder(file, isTestSource) : null;
}
public void removeSourceFolder(@NotNull final SourceFolder sourceFolder) {
try {
doRemoveSourceFolder(sourceFolder);
}
finally {
myEventDispatcher.getMulticaster().sourceFolderRemoved(this, sourceFolder.getFile());
update();
}
}
protected void doRemoveSourceFolder(@NotNull final SourceFolder sourceFolder) {
final ContentEntry contentEntry = getContentEntry();
if (contentEntry != null) contentEntry.removeSourceFolder(sourceFolder);
}
@Nullable
public ExcludeFolder addExcludeFolder(@NotNull final VirtualFile file) {
try {
return doAddExcludeFolder(file);
}
finally {
myEventDispatcher.getMulticaster().folderExcluded(this, file);
update();
}
}
@Nullable
protected ExcludeFolder doAddExcludeFolder(@NotNull final VirtualFile file) {
final ContentEntry contentEntry = getContentEntry();
return contentEntry != null ? contentEntry.addExcludeFolder(file) : null;
}
public void removeExcludeFolder(@NotNull final String excludeRootUrl) {
try {
doRemoveExcludeFolder(excludeRootUrl);
}
finally {
myEventDispatcher.getMulticaster().folderIncluded(this, excludeRootUrl);
update();
}
}
protected void doRemoveExcludeFolder(@NotNull final String excludeRootUrl) {
final ContentEntry contentEntry = getContentEntry();
if (contentEntry != null) {
contentEntry.removeExcludeFolder(excludeRootUrl);
}
}
@Nullable
public JpsModuleSourceRootType<?> getRootType(@NotNull VirtualFile file) {
SourceFolder folder = getSourceFolder(file);
return folder != null ? folder.getRootType() : null;
}
public boolean isExcludedOrUnderExcludedDirectory(@NotNull final VirtualFile file) {
final ContentEntry contentEntry = getContentEntry();
if (contentEntry == null) {
return false;
}
for (VirtualFile excludedDir : contentEntry.getExcludeFolderFiles()) {
if (VfsUtilCore.isAncestor(excludedDir, file, false)) {
return true;
}
}
return false;
}
@Nullable
public SourceFolder getSourceFolder(@NotNull final VirtualFile file) {
final ContentEntry contentEntry = getContentEntry();
if (contentEntry == null) {
return null;
}
for (SourceFolder sourceFolder : contentEntry.getSourceFolders()) {
final VirtualFile f = sourceFolder.getFile();
if (f != null && f.equals(file)) {
return sourceFolder;
}
}
return null;
}
}