custom library detection and presentation

This commit is contained in:
nik
2010-09-21 11:38:35 +04:00
parent 4fa361ecd2
commit a58e6961fd
19 changed files with 567 additions and 31 deletions
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryRootsComponent">
<grid id="e9129" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="6" vgap="-1">
<grid id="e9129" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="6" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="91" y="83" width="403" height="352"/>
@@ -11,7 +11,7 @@
<grid id="1f4da" layout-manager="GridLayoutManager" row-count="9" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="0" vgap="6">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -90,7 +90,7 @@
<xy id="bc98" binding="myTreePanel" layout-manager="XYLayout" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false">
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false">
<preferred-size width="300" height="-1"/>
</grid>
</constraints>
@@ -98,6 +98,12 @@
<border type="none"/>
<children/>
</xy>
<component id="8c4b3" class="com.intellij.openapi.ui.ex.MultiLineLabel" binding="myPropertiesLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
</form>
@@ -0,0 +1,59 @@
/*
* Copyright 2000-2010 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.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import com.intellij.openapi.roots.ui.util.CellAppearance;
import com.intellij.openapi.roots.ui.util.OrderEntryCellAppearanceUtils;
import com.intellij.openapi.roots.ui.util.SimpleTextCellAppearance;
import javax.swing.*;
/**
* @author nik
*/
//todo[nik] extract service from OrderEntryCellAppearanceUtils and use this class as its implementation for idea-ui
public class ProjectStructureDialogCellAppearanceUtils {
private ProjectStructureDialogCellAppearanceUtils() {
}
public static CellAppearance forOrderEntry(OrderEntry orderEntry, StructureConfigurableContext context, boolean selected) {
if (orderEntry instanceof LibraryOrderEntry) {
final Library library = ((LibraryOrderEntry)orderEntry).getLibrary();
if (orderEntry.isValid()) {
return forLibrary(library, context);
}
}
return OrderEntryCellAppearanceUtils.forOrderEntry(orderEntry, selected);
}
public static CellAppearance forLibrary(Library library, StructureConfigurableContext context) {
final Icon icon = LibraryPresentationManager.getInstance().getCustomIcon(library, context);
if (icon != null) {
final String name = library.getName();
if (name != null) {
return SimpleTextCellAppearance.normal(name, icon);
}
}
return OrderEntryCellAppearanceUtils.forLibrary(library);
}
}
@@ -18,7 +18,6 @@ package com.intellij.openapi.roots.ui.configuration.classpath;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.project.Project;
@@ -27,10 +26,7 @@ import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.ui.configuration.LibraryTableModifiableModelProvider;
import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationState;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.roots.ui.configuration.*;
import com.intellij.openapi.roots.ui.configuration.dependencyAnalysis.AnalyzeDependenciesDialog;
import com.intellij.openapi.roots.ui.configuration.libraryEditor.ChooseModulesDialog;
import com.intellij.openapi.roots.ui.configuration.libraryEditor.EditExistingLibraryDialog;
@@ -69,8 +65,6 @@ import java.util.List;
import java.util.Set;
public class ClasspathPanelImpl extends JPanel implements ClasspathPanel {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.ui.configuration.classpath.ClasspathPanel");
private final Table myEntryTable;
private final ClasspathTableModel myModel;
private final EventDispatcher<OrderPanelListener> myListeners = EventDispatcher.create(OrderPanelListener.class);
@@ -90,7 +84,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel {
myEntryTable.setShowVerticalLines(false);
myEntryTable.setIntercellSpacing(new Dimension(0, 0));
myEntryTable.setDefaultRenderer(ClasspathTableItem.class, new TableItemRenderer());
myEntryTable.setDefaultRenderer(ClasspathTableItem.class, new TableItemRenderer(getStructureConfigurableContext()));
myEntryTable.setDefaultRenderer(Boolean.class, new ExportFlagRenderer(myEntryTable.getDefaultRenderer(Boolean.class)));
JComboBox scopeEditor = new JComboBox(new EnumComboBoxModel<DependencyScope>(DependencyScope.class));
@@ -117,7 +111,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel {
}
public String getElementText(Object element) {
return getCellAppearance((ClasspathTableItem)element, false).getText();
return getCellAppearance((ClasspathTableItem)element, getStructureConfigurableContext(), false).getText();
}
public void selectElement(Object element, String selectedText) {
@@ -384,7 +378,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel {
};
}
else {
provider = ProjectStructureConfigurable.getInstance(myState.getProject()).getContext().createModifiableModelProvider(table.getTableLevel());
provider = getStructureConfigurableContext().createModifiableModelProvider(table.getTableLevel());
}
EditExistingLibraryDialog dialog = EditExistingLibraryDialog.createDialog(ClasspathPanelImpl.this, provider, library, myState.getProject());
dialog.addFileChooserContext(LangDataKeys.MODULE_CONTEXT, getRootModel().getModule());
@@ -457,11 +451,10 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel {
private void initPopupActions() {
if (myPopupActions == null) {
final StructureConfigurableContext context = ProjectStructureConfigurable.getInstance(myState.getProject()).getContext();
int actionIndex = 1;
final List<AddItemPopupAction<?>> actions = new ArrayList<AddItemPopupAction<?>>();
actions.add(new AddSingleEntryModuleLibraryAction(this, actionIndex++));
actions.add(new AddLibraryAction(this, actionIndex++, ProjectBundle.message("classpath.add.library.action"), context));
actions.add(new AddLibraryAction(this, actionIndex++, ProjectBundle.message("classpath.add.library.action"), getStructureConfigurableContext()));
actions.add(new AddItemPopupAction<Module>(this, actionIndex, ProjectBundle.message("classpath.add.module.dependency.action"),
StdModuleTypes.JAVA.getNodeIcon(false)) {
protected ClasspathTableItem createTableItem(final Module item) {
@@ -482,6 +475,10 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel {
}
}
private StructureConfigurableContext getStructureConfigurableContext() {
return ProjectStructureConfigurable.getInstance(myState.getProject()).getContext();
}
private void enableModelUpdate() {
myInsideChange--;
@@ -596,24 +593,31 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel {
}
private static CellAppearance getCellAppearance(final ClasspathTableItem item, final boolean selected) {
private static CellAppearance getCellAppearance(final ClasspathTableItem item,
StructureConfigurableContext context,
final boolean selected) {
if (item instanceof InvalidJdkItem) {
return OrderEntryCellAppearanceUtils.forJdk(null, false, selected);
}
else {
return OrderEntryCellAppearanceUtils.forOrderEntry(item.getEntry(), selected);
return ProjectStructureDialogCellAppearanceUtils.forOrderEntry(item.getEntry(), context, selected);
}
}
private static class TableItemRenderer extends ColoredTableCellRenderer {
private final Border NO_FOCUS_BORDER = BorderFactory.createEmptyBorder(1, 1, 1, 1);
private StructureConfigurableContext myContext;
public TableItemRenderer(StructureConfigurableContext context) {
myContext = context;
}
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
setPaintFocusBorder(false);
setFocusBorderAroundIcon(true);
setBorder(NO_FOCUS_BORDER);
if (value instanceof ClasspathTableItem) {
getCellAppearance((ClasspathTableItem)value, selected).customize(this);
getCellAppearance((ClasspathTableItem)value, myContext, selected).customize(this);
}
}
}
@@ -20,6 +20,7 @@ import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesModifiableModel;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import com.intellij.openapi.util.Condition;
@@ -99,15 +100,19 @@ public class ProjectStructureChooseLibrariesDialog extends ChooseLibrariesFromTa
protected LibrariesTreeNodeBase<Library> createLibraryDescriptor(NodeDescriptor parentDescriptor,
Library library) {
final String libraryName = getLibraryName(library);
return new LibraryEditorDescriptor(getProject(), parentDescriptor, library, libraryName);
return new LibraryEditorDescriptor(getProject(), parentDescriptor, library, libraryName, myContext);
}
private static class LibraryEditorDescriptor extends LibrariesTreeNodeBase<Library> {
protected LibraryEditorDescriptor(final Project project, final NodeDescriptor parentDescriptor, final Library element,
String libraryName) {
String libraryName, StructureConfigurableContext context) {
super(project, parentDescriptor, element);
final PresentationData templatePresentation = getTemplatePresentation();
templatePresentation.setIcons(Icons.LIBRARY_ICON);
Icon icon = LibraryPresentationManager.getInstance().getCustomIcon(element, context);
if (icon == null) {
icon = Icons.LIBRARY_ICON;
}
templatePresentation.setIcons(icon);
templatePresentation.addText(libraryName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
}
@@ -0,0 +1,47 @@
/*
* Copyright 2000-2010 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.libraries;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
/**
* @author nik
*/
public abstract class LibraryPresentationManager {
public static LibraryPresentationManager getInstance() {
return ServiceManager.getService(LibraryPresentationManager.class);
}
@Nullable
public abstract Icon getCustomIcon(@NotNull Library library, @Nullable StructureConfigurableContext context);
@NotNull
public abstract List<Icon> getCustomIcons(@NotNull Library library, @Nullable StructureConfigurableContext context);
@NotNull
public abstract List<String> getDescriptions(@NotNull Library library, StructureConfigurableContext context);
@NotNull
public abstract List<String> getDescriptions(@NotNull VirtualFile[] classRoots);
}
@@ -0,0 +1,117 @@
/*
* Copyright 2000-2010 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.libraries;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.*;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesModifiableModel;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author nik
*/
public class LibraryPresentationManagerImpl extends LibraryPresentationManager {
private Map<LibraryKind<?>, LibraryPresentationProvider<?>> myPresentationProviders;
private <P extends LibraryProperties> LibraryPresentationProvider<P> getPresentationProvider(LibraryKind<P> kind) {
if (myPresentationProviders == null) {
final Map<LibraryKind<?>, LibraryPresentationProvider<?>> providers = new HashMap<LibraryKind<?>, LibraryPresentationProvider<?>>();
for (LibraryPresentationProvider provider : LibraryPresentationProvider.EP_NAME.getExtensions()) {
providers.put(provider.getKind(), provider);
}
myPresentationProviders = providers;
}
//noinspection unchecked
return (LibraryPresentationProvider<P>)myPresentationProviders.get(kind);
}
@Override
public Icon getCustomIcon(@NotNull Library library, StructureConfigurableContext context) {
final List<Icon> icons = getCustomIcons(library, context);
if (icons.size() == 1) {
return icons.get(0);
}
return null;
}
@NotNull
@Override
public List<Icon> getCustomIcons(@NotNull Library library, StructureConfigurableContext context) {
final VirtualFile[] files = getLibraryFiles(library, context);
final List<Icon> icons = new SmartList<Icon>();
LibraryDetectionManager.getInstance().processProperties(Arrays.asList(files), new LibraryDetectionManager.LibraryPropertiesProcessor() {
@Override
public <P extends LibraryProperties> boolean processProperties(@NotNull LibraryKind<P> kind, @NotNull P properties) {
final LibraryPresentationProvider<P> provider = getPresentationProvider(kind);
if (provider != null) {
ContainerUtil.addIfNotNull(icons, provider.getIcon());
}
return true;
}
});
return icons;
}
private static VirtualFile[] getLibraryFiles(Library library, StructureConfigurableContext context) {
if (context != null) {
final LibraryTable table = library.getTable();
if (table != null) {
final LibraryTable.ModifiableModel modifiableModel = context.getModifiableLibraryTable(table);
if (modifiableModel instanceof LibrariesModifiableModel) {
final LibrariesModifiableModel librariesModel = (LibrariesModifiableModel)modifiableModel;
if (librariesModel.hasLibraryEditor(library)) {
return librariesModel.getLibraryEditor(library).getFiles(OrderRootType.CLASSES);
}
}
}
}
return library.getFiles(OrderRootType.CLASSES);
}
@NotNull
@Override
public List<String> getDescriptions(@NotNull Library library, StructureConfigurableContext context) {
final VirtualFile[] files = getLibraryFiles(library, context);
return getDescriptions(files);
}
@NotNull
@Override
public List<String> getDescriptions(@NotNull VirtualFile[] classRoots) {
final SmartList<String> result = new SmartList<String>();
LibraryDetectionManager.getInstance().processProperties(Arrays.asList(classRoots), new LibraryDetectionManager.LibraryPropertiesProcessor() {
@Override
public <P extends LibraryProperties> boolean processProperties(@NotNull LibraryKind<P> kind, @NotNull P properties) {
final LibraryPresentationProvider<P> provider = getPresentationProvider(kind);
if (provider != null) {
ContainerUtil.addIfNotNull(result, provider.getDescription(properties));
}
return true;
}
});
return result;
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2000-2010 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.libraries;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.roots.libraries.LibraryKind;
import com.intellij.openapi.roots.libraries.LibraryProperties;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* @author nik
*/
public abstract class LibraryPresentationProvider<P extends LibraryProperties> {
public static final ExtensionPointName<LibraryPresentationProvider> EP_NAME = ExtensionPointName.create("com.intellij.library.presentationProvider");
private final LibraryKind<P> myKind;
protected LibraryPresentationProvider(LibraryKind<P> kind) {
myKind = kind;
}
public final LibraryKind<P> getKind() {
return myKind;
}
@Nullable
public abstract Icon getIcon();
@Nullable
public String getDescription(@NotNull P properties) {
return null;
}
}
@@ -36,8 +36,10 @@ import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.libraries.LibraryUtil;
import com.intellij.openapi.roots.ui.configuration.ModuleEditor;
import com.intellij.openapi.roots.ui.configuration.PathUIUtils;
import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesModifiableModel;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureConfigurable;
import com.intellij.openapi.ui.ex.MultiLineLabel;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.ui.popup.PopupStep;
@@ -90,6 +92,7 @@ public class LibraryRootsComponent implements Disposable {
private JPanel myTreePanel;
private JButton myAttachAnnotationsButton;
private JButton myAttachMoreButton;
private MultiLineLabel myPropertiesLabel;
private Tree myTree;
private LibraryTableTreeBuilder myTreeBuilder;
private static final Icon INVALID_ITEM_ICON = IconLoader.getIcon("/nodes/ppInvalid.png");
@@ -101,10 +104,21 @@ public class LibraryRootsComponent implements Disposable {
private final Map<DataKey, Object> myFileChooserUserData = new HashMap<DataKey, Object>();
private final LibraryEditor myLibraryEditor;
private LibraryRootsComponent(Project project,
LibraryEditor libraryEditor){
private LibraryRootsComponent(Project project, LibraryEditor libraryEditor) {
myProject = project;
myLibraryEditor = libraryEditor;
updateProperties();
}
private void updateProperties() {
StringBuilder text = new StringBuilder();
for (String description : LibraryPresentationManager.getInstance().getDescriptions(myLibraryEditor.getFiles(OrderRootType.CLASSES))) {
if (text.length() > 0) {
text.append("\n");
}
text.append(description);
}
myPropertiesLabel.setText(text.toString());
}
public static LibraryRootsComponent createComponent(final @Nullable Project project, @NotNull LibraryEditor libraryEditor) {
@@ -337,6 +351,7 @@ public class LibraryRootsComponent implements Disposable {
}
}
});
updateProperties();
myTreeBuilder.updateFromRoot();
}
return filesToAttach;
@@ -491,6 +506,7 @@ public class LibraryRootsComponent implements Disposable {
}
protected void librariesChanged(boolean putFocusIntoTree) {
updateProperties();
myTreeBuilder.updateFromRoot();
if (putFocusIntoTree) {
myTree.requestFocus();
@@ -119,7 +119,7 @@ public abstract class BaseLibrariesConfigurable extends BaseStructureConfigurabl
private void createLibrariesNode(final StructureLibraryTableModifiableModelProvider modelProvider) {
final Library[] libraries = modelProvider.getModifiableModel().getLibraries();
for (Library library : libraries) {
myRoot.add(new MyNode(new LibraryConfigurable(modelProvider, library, myProject, TREE_UPDATER)));
myRoot.add(new MyNode(new LibraryConfigurable(modelProvider, library, myContext, TREE_UPDATER)));
}
TreeUtil.sort(myRoot, new Comparator() {
public int compare(final Object o1, final Object o2) {
@@ -147,7 +147,7 @@ public abstract class BaseLibrariesConfigurable extends BaseStructureConfigurabl
if (table != null) {
final String level = table.getTableLevel();
final LibraryConfigurable configurable =
new LibraryConfigurable(myContext.createModifiableModelProvider(level), library, myProject, TREE_UPDATER);
new LibraryConfigurable(myContext.createModifiableModelProvider(level), library, myContext, TREE_UPDATER);
final MyNode node = new MyNode(configurable);
addNode(node, myRoot);
myContext.getDaemonAnalyzer().queueUpdate(new LibraryProjectStructureElement(myContext, library));
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager;
import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditor;
import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryRootsComponent;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.LibraryProjectStructureElement;
@@ -41,19 +42,20 @@ public class LibraryConfigurable extends ProjectStructureElementConfigurable<Lib
private LibraryRootsComponent myLibraryEditor;
private final Library myLibrary;
private final StructureLibraryTableModifiableModelProvider myModel;
private final StructureConfigurableContext myContext;
private final Project myProject;
private final LibraryProjectStructureElement myProjectStructureElement;
private boolean myUpdatingName;
protected LibraryConfigurable(final StructureLibraryTableModifiableModelProvider modelProvider,
final Library library,
final Project project,
final StructureConfigurableContext context,
final Runnable updateTree) {
super(true, updateTree);
myModel = modelProvider;
myProject = project;
myContext = context;
myProject = context.getProject();
myLibrary = library;
final StructureConfigurableContext context = ModuleStructureConfigurable.getInstance(myProject).getContext();
myProjectStructureElement = new LibraryProjectStructureElement(context, myLibrary);
}
@@ -132,6 +134,10 @@ public class LibraryConfigurable extends ProjectStructureElementConfigurable<Lib
}
public Icon getIcon() {
final Icon icon = LibraryPresentationManager.getInstance().getCustomIcon(myLibrary, myContext);
if (icon != null) {
return icon;
}
return ICON;
}
@@ -0,0 +1,67 @@
/*
* Copyright 2000-2010 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.impl.libraries;
import com.intellij.openapi.roots.libraries.LibraryDetectionManager;
import com.intellij.openapi.roots.libraries.LibraryDetector;
import com.intellij.openapi.roots.libraries.LibraryKind;
import com.intellij.openapi.roots.libraries.LibraryProperties;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author nik
*/
public class LibraryDetectionManagerImpl extends LibraryDetectionManager {
private final Map<List<VirtualFile>, List<Pair<LibraryKind, LibraryProperties>>> myCache = new HashMap<List<VirtualFile>, List<Pair<LibraryKind, LibraryProperties>>>();
@Override
public boolean processProperties(@NotNull List<VirtualFile> files, @NotNull LibraryPropertiesProcessor processor) {
for (Pair<LibraryKind, LibraryProperties> pair : getOrComputeKinds(files)) {
//noinspection unchecked
if (!processor.processProperties(pair.getFirst(), pair.getSecond())) {
return false;
}
}
return true;
}
private List<Pair<LibraryKind, LibraryProperties>> getOrComputeKinds(List<VirtualFile> files) {
List<Pair<LibraryKind, LibraryProperties>> result = myCache.get(files);
if (result == null) {
result = computeKinds(files);
myCache.put(files, result);
}
return result;
}
private static List<Pair<LibraryKind, LibraryProperties>> computeKinds(List<VirtualFile> files) {
final SmartList<Pair<LibraryKind, LibraryProperties>> result = new SmartList<Pair<LibraryKind, LibraryProperties>>();
for (LibraryDetector detector : LibraryDetector.EP_NAME.getExtensions()) {
final LibraryProperties properties = detector.detect(files);
if (properties != null) {
result.add(Pair.create(detector.getKind(), properties));
}
}
return result;
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2000-2010 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.libraries;
/**
* @author nik
*/
public class DummyLibraryProperties extends LibraryProperties<Object> {
public static final DummyLibraryProperties INSTANCE = new DummyLibraryProperties();
@Override
public Object getState() {
return null;
}
@Override
public void loadState(Object state) {
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2000-2010 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.libraries;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author nik
*/
public abstract class LibraryDetectionManager {
public static LibraryDetectionManager getInstance() {
return ServiceManager.getService(LibraryDetectionManager.class);
}
public abstract boolean processProperties(@NotNull List<VirtualFile> files, @NotNull LibraryPropertiesProcessor processor);
public interface LibraryPropertiesProcessor {
<P extends LibraryProperties> boolean processProperties(@NotNull LibraryKind<P> kind, @NotNull P properties);
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 2000-2010 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.libraries;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author nik
*/
public abstract class LibraryDetector<P extends LibraryProperties> {
public static final ExtensionPointName<LibraryDetector> EP_NAME = ExtensionPointName.create("com.intellij.library.detector");
private final LibraryKind<P> myKind;
protected LibraryDetector(LibraryKind<P> kind) {
myKind = kind;
}
public final LibraryKind<P> getKind() {
return myKind;
}
@Nullable
public abstract P detect(@NotNull List<VirtualFile> classesRoots);
}
@@ -0,0 +1,39 @@
/*
* Copyright 2000-2010 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.libraries;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public class LibraryKind<P extends LibraryProperties> {
private String myKindId;
public LibraryKind(@NotNull @NonNls String kindId) {
myKindId = kindId;
}
public String getKindId() {
return myKindId;
}
@Override
public String toString() {
return "LibraryKind:" + myKindId;
}
}
@@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.roots.ui.configuration.libraryEditor;
package com.intellij.openapi.roots.libraries;
import com.intellij.openapi.components.PersistentStateComponent;
/**
* @author nik
*/
public class LibraryRootsData {
public abstract class LibraryProperties<T> implements PersistentStateComponent<T> {
public static final LibraryProperties DUMMY_PROPERTIES = new DummyLibraryProperties();
}
@@ -276,6 +276,8 @@
<extensionPoint name="sdkType" interface="com.intellij.openapi.projectRoots.SdkType"/>
<extensionPoint name="library.detector" interface="com.intellij.openapi.roots.libraries.LibraryDetector"/>
<extensionPoint name="lang.implementationTextSelectioner"
beanClass="com.intellij.lang.LanguageExtensionPoint"/>
<extensionPoint name="lang.lineWrapStrategy"
@@ -110,6 +110,9 @@
<applicationService serviceInterface="com.intellij.openapi.roots.libraries.LibraryTablesRegistrar"
serviceImplementation="com.intellij.openapi.roots.impl.libraries.LibraryTablesRegistrarImpl"/>
<applicationService serviceInterface="com.intellij.openapi.roots.libraries.LibraryDetectionManager"
serviceImplementation="com.intellij.openapi.roots.impl.libraries.LibraryDetectionManagerImpl"/>
<applicationService serviceInterface="com.intellij.usageView.UsageTreeColorsScheme"
serviceImplementation="com.intellij.usageView.UsageTreeColorsScheme"/>
+4
View File
@@ -90,6 +90,8 @@
<extensionPoint name="OrderRootTypeUI"
beanClass="com.intellij.openapi.extensions.KeyedFactoryEPBean"/>
<extensionPoint name="library.presentationProvider" interface="com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationProvider"/>
<extensionPoint name="allOverridingMethodsSearch" interface="com.intellij.util.QueryExecutor"/>
<extensionPoint name="annotatedElementsSearch" interface="com.intellij.util.QueryExecutor"/>
<extensionPoint name="annotatedPackagesSearch" interface="com.intellij.util.QueryExecutor"/>
@@ -457,6 +459,8 @@
<applicationService serviceInterface="com.intellij.openapi.wm.impl.FrameTitleBuilder"
serviceImplementation="com.intellij.openapi.wm.IdeaFrameTitleBuilder"/>
<applicationService serviceInterface="com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager"
serviceImplementation="com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManagerImpl"/>
<projectService serviceInterface="com.intellij.openapi.roots.ui.configuration.dependencyAnalysis.AnalyzeDependenciesSettings"
serviceImplementation="com.intellij.openapi.roots.ui.configuration.dependencyAnalysis.AnalyzeDependenciesSettings"/>