blob: 6239cbbab4acfde19d888f959743876c7b4cc7f6 [file] [log] [blame]
/*
* Copyright 2000-2014 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.framework.detection.impl.exclude;
import com.intellij.framework.FrameworkType;
import com.intellij.framework.detection.impl.FrameworkDetectorRegistry;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.components.JBList;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;
/**
* @author nik
*/
public class DetectionExcludesConfigurable implements Configurable {
private final Project myProject;
private final DetectionExcludesConfigurationImpl myConfiguration;
private final SortedListModel<ExcludeListItem> myModel;
private JPanel myMainPanel;
private JCheckBox myEnabledDetectionCheckBox;
public DetectionExcludesConfigurable(@NotNull Project project, @NotNull DetectionExcludesConfigurationImpl configuration) {
myProject = project;
myConfiguration = configuration;
myModel = new SortedListModel<ExcludeListItem>(ExcludeListItem.COMPARATOR);
}
@Nls
@Override
@NotNull
public JComponent createComponent() {
myEnabledDetectionCheckBox = new JCheckBox("Enable framework detection");
myEnabledDetectionCheckBox.setBorder(new EmptyBorder(10, 10, 0, 0));
final JBList excludesList = new JBList(myModel);
final ColoredListCellRenderer renderer = new ColoredListCellRenderer() {
JPanel panel = new JPanel(new BorderLayout());
{
panel.setBorder(new EmptyBorder(2, 10, 2, 0));
panel.add(this);
}
@Override
protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
setIconTextGap(4);
if (value instanceof ExcludeListItem) {
((ExcludeListItem)value).renderItem(this);
setBorder(new EmptyBorder(0, 10, 0, 0));
}
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean selected, boolean hasFocus) {
super.getListCellRendererComponent(list, value, index, selected, hasFocus);
panel.setBackground(UIUtil.getListBackground(selected));
return panel;
}
};
renderer.setMyBorder(new EmptyBorder(0,0,0,0));
excludesList.setCellRenderer(renderer);
final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(excludesList)
.disableUpAction().disableDownAction()
.setAddAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
doAddAction(button);
}
});
if (Registry.is("ide.new.project.settings")) {
decorator.setPanelBorder(new CustomLineBorder(1, 0, 0, 0));
}
myMainPanel = new JPanel(new BorderLayout(0, 5));
myMainPanel.add(myEnabledDetectionCheckBox, BorderLayout.NORTH);
final LabeledComponent<JPanel> excludesComponent = LabeledComponent.create(decorator.createPanel(), " Exclude from detection:");
myMainPanel.add(excludesComponent);
myEnabledDetectionCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
GuiUtils.enableChildren(myEnabledDetectionCheckBox.isSelected(), excludesComponent);
}
});
myEnabledDetectionCheckBox.setSelected(true);
return myMainPanel;
}
private void doAddAction(AnActionButton button) {
final List<FrameworkType> types = new ArrayList<FrameworkType>();
for (FrameworkType type : FrameworkDetectorRegistry.getInstance().getFrameworkTypes()) {
if (!isExcluded(type)) {
types.add(type);
}
}
Collections.sort(types, new Comparator<FrameworkType>() {
@Override
public int compare(FrameworkType o1, FrameworkType o2) {
return o1.getPresentableName().compareToIgnoreCase(o2.getPresentableName());
}
});
types.add(0, null);
final ListPopup popup = JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<FrameworkType>("Framework to Exclude", types) {
@Override
public Icon getIconFor(FrameworkType value) {
return value != null ? value.getIcon() : null;
}
@NotNull
@Override
public String getTextFor(FrameworkType value) {
return value != null ? value.getPresentableName() : "All Frameworks...";
}
@Override
public boolean hasSubstep(FrameworkType selectedValue) {
return selectedValue != null;
}
@Override
public PopupStep onChosen(final FrameworkType frameworkType, boolean finalChoice) {
if (frameworkType == null) {
return doFinalStep(new Runnable() {
@Override
public void run() {
chooseDirectoryAndAdd(null);
}
});
}
else {
return addExcludedFramework(frameworkType);
}
}
});
final RelativePoint popupPoint = button.getPreferredPopupPoint();
if (popupPoint != null) {
popup.show(popupPoint);
}
else {
popup.showInCenterOf(myMainPanel);
}
}
private boolean isExcluded(@NotNull FrameworkType type) {
for (ExcludeListItem item : myModel.getItems()) {
if (type.getId().equals(item.getFrameworkTypeId()) && item.getFileUrl() == null) {
return true;
}
}
return false;
}
private PopupStep addExcludedFramework(final @NotNull FrameworkType frameworkType) {
final String projectItem = "In the whole project";
return new BaseListPopupStep<String>(null, new String[]{projectItem, "In directory..."}) {
@Override
public PopupStep onChosen(String selectedValue, boolean finalChoice) {
if (selectedValue.equals(projectItem)) {
addAndRemoveDuplicates(frameworkType, null);
return FINAL_CHOICE;
}
else {
return doFinalStep(new Runnable() {
@Override
public void run() {
chooseDirectoryAndAdd(frameworkType);
}
});
}
}
};
}
private void addAndRemoveDuplicates(@Nullable FrameworkType frameworkType, final @Nullable VirtualFile file) {
final Iterator<ExcludeListItem> iterator = myModel.iterator();
boolean add = true;
while (iterator.hasNext()) {
ExcludeListItem item = iterator.next();
final String fileUrl = item.getFileUrl();
VirtualFile itemFile = fileUrl != null ? VirtualFileManager.getInstance().findFileByUrl(fileUrl) : null;
final String itemTypeId = item.getFrameworkTypeId();
if (file == null) {
if (frameworkType != null && frameworkType.getId().equals(itemTypeId)) {
iterator.remove();
}
}
else if (itemFile != null) {
if (VfsUtil.isAncestor(file, itemFile, false) && (frameworkType == null || frameworkType.getId().equals(itemTypeId))) {
iterator.remove();
}
if (VfsUtil.isAncestor(itemFile, file, false) && (itemTypeId == null || frameworkType != null && itemTypeId.equals(frameworkType.getId()))) {
add = false;
}
}
}
if (add) {
myModel.add(new ValidExcludeListItem(frameworkType, file));
}
}
private void chooseDirectoryAndAdd(final @Nullable FrameworkType type) {
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
descriptor.setDescription((type != null ? type.getPresentableName() + " framework detection" : "Detection for all frameworks") + " will be disabled in selected directory");
final VirtualFile[] files = FileChooser.chooseFiles(descriptor, myMainPanel, myProject, myProject.getBaseDir());
final VirtualFile file = files.length > 0 ? files[0] : null;
if (file != null) {
addAndRemoveDuplicates(type, file);
}
}
@Override
public boolean isModified() {
return !Comparing.equal(computeState(), myConfiguration.getActualState());
}
@Override
public void apply() {
myConfiguration.loadState(computeState());
}
@Nullable
private ExcludesConfigurationState computeState() {
if (myModel.getItems().isEmpty() && myEnabledDetectionCheckBox.isSelected()) {
return null;
}
final ExcludesConfigurationState state = new ExcludesConfigurationState();
state.setDetectionEnabled(myEnabledDetectionCheckBox.isSelected());
for (ExcludeListItem item : myModel.getItems()) {
final String url = item.getFileUrl();
final String typeId = item.getFrameworkTypeId();
if (url == null) {
state.getFrameworkTypes().add(typeId);
}
else {
state.getFiles().add(new ExcludedFileState(url, typeId));
}
}
return state;
}
@Override
public void reset() {
myModel.clear();
final ExcludesConfigurationState state = myConfiguration.getActualState();
myEnabledDetectionCheckBox.setSelected(state == null || state.isDetectionEnabled());
if (state != null) {
for (String typeId : state.getFrameworkTypes()) {
final FrameworkType frameworkType = FrameworkDetectorRegistry.getInstance().findFrameworkType(typeId);
myModel.add(frameworkType != null ? new ValidExcludeListItem(frameworkType, null) : new InvalidExcludeListItem(typeId, null));
}
for (ExcludedFileState fileState : state.getFiles()) {
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(fileState.getUrl());
final String typeId = fileState.getFrameworkType();
if (typeId == null) {
myModel.add(file != null ? new ValidExcludeListItem(null, file) : new InvalidExcludeListItem(null, fileState.getUrl()));
}
else {
final FrameworkType frameworkType = FrameworkDetectorRegistry.getInstance().findFrameworkType(typeId);
myModel.add(frameworkType != null && file != null? new ValidExcludeListItem(frameworkType, file) : new InvalidExcludeListItem(typeId, fileState.getUrl()));
}
}
}
}
@Override
public void disposeUIResources() {
}
@Nls
@Override
public String getDisplayName() {
return "Framework Detection Excludes";
}
@Override
public String getHelpTopic() {
return null;
}
}