| /* |
| * Copyright 2000-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 com.intellij.util.ui.classpath; |
| |
| import com.intellij.ide.CommonActionsManager; |
| import com.intellij.ide.DefaultTreeExpander; |
| import com.intellij.ide.TreeExpander; |
| import com.intellij.ide.projectView.PresentationData; |
| import com.intellij.ide.util.treeView.AbstractTreeBuilder; |
| import com.intellij.ide.util.treeView.AbstractTreeStructure; |
| import com.intellij.ide.util.treeView.NodeDescriptor; |
| import com.intellij.openapi.actionSystem.ActionManager; |
| import com.intellij.openapi.actionSystem.ActionPlaces; |
| import com.intellij.openapi.actionSystem.DefaultActionGroup; |
| import com.intellij.openapi.application.Application; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.module.ModuleManager; |
| import com.intellij.openapi.module.ModuleType; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.project.ProjectManager; |
| import com.intellij.openapi.roots.LibraryOrderEntry; |
| import com.intellij.openapi.roots.ModuleRootManager; |
| import com.intellij.openapi.roots.OrderEntry; |
| import com.intellij.openapi.roots.impl.libraries.LibraryTableImplUtil; |
| import com.intellij.openapi.roots.libraries.Library; |
| import com.intellij.openapi.roots.libraries.LibraryTable; |
| import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; |
| import com.intellij.openapi.roots.ui.CellAppearanceEx; |
| import com.intellij.openapi.roots.ui.OrderEntryAppearanceService; |
| import com.intellij.openapi.ui.DialogWrapper; |
| import com.intellij.openapi.util.Disposer; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.ui.DoubleClickListener; |
| import com.intellij.ui.ScrollPaneFactory; |
| import com.intellij.ui.SimpleColoredComponent; |
| import com.intellij.ui.SimpleTextAttributes; |
| import com.intellij.ui.treeStructure.SimpleNode; |
| import com.intellij.ui.treeStructure.SimpleTree; |
| import com.intellij.ui.treeStructure.SimpleTreeBuilder; |
| import com.intellij.ui.treeStructure.WeightBasedComparator; |
| import com.intellij.util.CommonProcessors; |
| import com.intellij.util.PlatformIcons; |
| import com.intellij.util.Processor; |
| import com.intellij.util.ui.UIUtil; |
| import gnu.trove.THashMap; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import javax.swing.event.TreeSelectionEvent; |
| import javax.swing.event.TreeSelectionListener; |
| import javax.swing.tree.DefaultMutableTreeNode; |
| import javax.swing.tree.DefaultTreeModel; |
| import java.awt.*; |
| import java.awt.event.KeyEvent; |
| import java.awt.event.MouseEvent; |
| import java.util.*; |
| import java.util.List; |
| |
| /** |
| * @author Gregory.Shrago |
| */ |
| |
| public abstract class ChooseLibrariesDialogBase extends DialogWrapper { |
| private final SimpleTree myTree = new SimpleTree(); |
| private AbstractTreeBuilder myBuilder; |
| private List<Library> myResult; |
| private final Map<Object, Object> myParentsMap = new THashMap<Object, Object>(); |
| |
| protected ChooseLibrariesDialogBase(final JComponent parentComponent, final String title) { |
| super(parentComponent, false); |
| setTitle(title); |
| } |
| |
| protected ChooseLibrariesDialogBase(Project project, String title) { |
| super(project, false); |
| setTitle(title); |
| } |
| |
| @Override |
| protected void init() { |
| super.init(); |
| updateOKAction(); |
| } |
| |
| private static String notEmpty(String nodeText) { |
| return StringUtil.isNotEmpty(nodeText) ? nodeText : "<unnamed>"; |
| } |
| |
| @Override |
| protected String getDimensionServiceKey() { |
| return "#com.intellij.util.ui.classpath.ChooseLibrariesDialog"; |
| } |
| |
| protected int getLibraryTableWeight(@NotNull LibraryTable libraryTable) { |
| return 0; |
| } |
| |
| protected boolean isAutoExpandLibraryTable(@NotNull LibraryTable libraryTable) { |
| return false; |
| } |
| |
| @Override |
| protected void doOKAction() { |
| processSelection(new CommonProcessors.CollectProcessor<Library>(myResult = new ArrayList<Library>())); |
| super.doOKAction(); |
| } |
| |
| private void updateOKAction() { |
| setOKActionEnabled(!processSelection(new CommonProcessors.FindFirstProcessor<Library>())); |
| } |
| |
| @Override |
| public JComponent getPreferredFocusedComponent() { |
| return myTree; |
| } |
| |
| @NotNull |
| public List<Library> getSelectedLibraries() { |
| return myResult == null? Collections.<Library>emptyList() : myResult; |
| } |
| |
| protected void queueUpdateAndSelect(@NotNull final Library library) { |
| myBuilder.queueUpdate().doWhenDone(new Runnable() { |
| @Override |
| public void run() { |
| myBuilder.select(library); |
| } |
| }); |
| } |
| |
| private boolean processSelection(final Processor<Library> processor) { |
| for (Object element : myBuilder.getSelectedElements()) { |
| if (element instanceof Library) { |
| if (!processor.process((Library)element)) return false; |
| } |
| } |
| return true; |
| } |
| |
| protected boolean acceptsElement(final Object element) { |
| return true; |
| } |
| |
| @Override |
| protected JComponent createNorthPanel() { |
| final DefaultActionGroup group = new DefaultActionGroup(); |
| final TreeExpander expander = new DefaultTreeExpander(myTree); |
| final CommonActionsManager actionsManager = CommonActionsManager.getInstance(); |
| group.add(actionsManager.createExpandAllAction(expander, myTree)); |
| group.add(actionsManager.createCollapseAllAction(expander, myTree)); |
| final JComponent component = ActionManager.getInstance().createActionToolbar(ActionPlaces.PROJECT_VIEW_TOOLBAR, group, true).getComponent(); |
| component.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.darkGray), component.getBorder())); |
| return component; |
| } |
| |
| @Override |
| @Nullable |
| protected JComponent createCenterPanel() { |
| myBuilder = new SimpleTreeBuilder(myTree, new DefaultTreeModel(new DefaultMutableTreeNode()), |
| new MyStructure(getProject()), |
| WeightBasedComparator.FULL_INSTANCE); |
| myBuilder.initRootNode(); |
| |
| myTree.setDragEnabled(false); |
| |
| myTree.setShowsRootHandles(true); |
| UIUtil.setLineStyleAngled(myTree); |
| |
| myTree.setRootVisible(false); |
| myTree.addTreeSelectionListener(new TreeSelectionListener() { |
| @Override |
| public void valueChanged(final TreeSelectionEvent e) { |
| updateOKAction(); |
| } |
| }); |
| new DoubleClickListener() { |
| @Override |
| protected boolean onDoubleClick(MouseEvent e) { |
| if (isOKActionEnabled()) { |
| doOKAction(); |
| return true; |
| } |
| return false; |
| } |
| }.installOn(myTree); |
| |
| myTree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ENTER"); |
| myTree.getActionMap().put("ENTER", getOKAction()); |
| final JScrollPane pane = ScrollPaneFactory.createScrollPane(myTree); |
| pane.setPreferredSize(new Dimension(500, 400)); |
| return pane; |
| } |
| |
| @NotNull |
| protected Project getProject() { |
| return ProjectManager.getInstance().getDefaultProject(); |
| } |
| |
| protected LibrariesTreeNodeBase<Library> createLibraryDescriptor(NodeDescriptor parentDescriptor, Library library) { |
| return new LibraryDescriptor(getProject(), parentDescriptor, library); |
| } |
| |
| protected void collectChildren(Object element, final List<Object> result) { |
| if (element instanceof Application) { |
| Collections.addAll(result, ProjectManager.getInstance().getOpenProjects()); |
| final LibraryTablesRegistrar instance = LibraryTablesRegistrar.getInstance(); |
| result.add(instance.getLibraryTable()); //1 |
| result.addAll(instance.getCustomLibraryTables()); //2 |
| } |
| else if (element instanceof Project) { |
| Collections.addAll(result, ModuleManager.getInstance((Project)element).getModules()); |
| result.add(LibraryTablesRegistrar.getInstance().getLibraryTable((Project)element)); |
| } |
| else if (element instanceof LibraryTable) { |
| Collections.addAll(result, ((LibraryTable)element).getLibraries()); |
| } |
| else if (element instanceof Module) { |
| for (OrderEntry entry : ModuleRootManager.getInstance((Module)element).getOrderEntries()) { |
| if (entry instanceof LibraryOrderEntry) { |
| final LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)entry; |
| if (LibraryTableImplUtil.MODULE_LEVEL.equals(libraryOrderEntry.getLibraryLevel())) { |
| final Library library = libraryOrderEntry.getLibrary(); |
| result.add(library); |
| } |
| } |
| } |
| } |
| } |
| |
| @Override |
| protected void dispose() { |
| Disposer.dispose(myBuilder); |
| super.dispose(); |
| } |
| |
| protected static class LibrariesTreeNodeBase<T> extends SimpleNode { |
| private final T myElement; |
| |
| protected LibrariesTreeNodeBase(Project project, NodeDescriptor parentDescriptor, T element) { |
| super(project, parentDescriptor); |
| myElement = element; |
| } |
| |
| @Override |
| public T getElement() { |
| return myElement; |
| } |
| |
| @Override |
| public SimpleNode[] getChildren() { |
| return NO_CHILDREN; |
| } |
| |
| @Override |
| public int getWeight() { |
| return 0; |
| } |
| |
| @NotNull |
| @Override |
| public Object[] getEqualityObjects() { |
| return new Object[] {myElement}; |
| } |
| |
| @Override |
| protected void update(PresentationData presentation) { |
| //todo[nik] this is workaround for bug in getTemplatePresentation().setIcons() |
| presentation.setIcon(getTemplatePresentation().getIcon(false)); |
| } |
| } |
| |
| private static class RootDescriptor extends LibrariesTreeNodeBase<Object> { |
| protected RootDescriptor(final Project project) { |
| super(project, null, ApplicationManager.getApplication()); |
| } |
| } |
| |
| private static class ProjectDescriptor extends LibrariesTreeNodeBase<Project> { |
| protected ProjectDescriptor(final Project project, final Project element) { |
| super(project, null, element); |
| getTemplatePresentation().setIcon(PlatformIcons.PROJECT_ICON); |
| getTemplatePresentation().addText(notEmpty(getElement().getName()), SimpleTextAttributes.REGULAR_ATTRIBUTES); |
| } |
| } |
| |
| private static class ModuleDescriptor extends LibrariesTreeNodeBase<Module> { |
| protected ModuleDescriptor(final Project project, final NodeDescriptor parentDescriptor, final Module element) { |
| super(project, parentDescriptor, element); |
| final PresentationData templatePresentation = getTemplatePresentation(); |
| templatePresentation.setIcon(ModuleType.get(element).getIcon()); |
| templatePresentation.addText(notEmpty(element.getName()), SimpleTextAttributes.REGULAR_ATTRIBUTES); |
| } |
| |
| @Override |
| public int getWeight() { |
| return 1; |
| } |
| } |
| |
| private static class LibraryDescriptor extends LibrariesTreeNodeBase<Library> { |
| protected LibraryDescriptor(final Project project, final NodeDescriptor parentDescriptor, final Library element) { |
| super(project, parentDescriptor, element); |
| final CellAppearanceEx appearance = OrderEntryAppearanceService.getInstance().forLibrary(project, element, false); |
| final SimpleColoredComponent coloredComponent = new SimpleColoredComponent(); |
| appearance.customize(coloredComponent); |
| final PresentationData templatePresentation = getTemplatePresentation(); |
| templatePresentation.setIcon(coloredComponent.getIcon()); |
| templatePresentation.addText(notEmpty(appearance.getText()), SimpleTextAttributes.REGULAR_ATTRIBUTES); |
| } |
| } |
| |
| private static class LibraryTableDescriptor extends LibrariesTreeNodeBase<LibraryTable> { |
| private final int myWeight; |
| private boolean myAutoExpand; |
| |
| protected LibraryTableDescriptor(final Project project, |
| final NodeDescriptor parentDescriptor, |
| final LibraryTable table, |
| final int weight, |
| boolean autoExpand) { |
| super(project, parentDescriptor, table); |
| myWeight = weight; |
| myAutoExpand = autoExpand; |
| getTemplatePresentation().setIcon(PlatformIcons.LIBRARY_ICON); |
| final String nodeText = table.getPresentation().getDisplayName(true); |
| getTemplatePresentation().addText(notEmpty(nodeText), SimpleTextAttributes.REGULAR_ATTRIBUTES); |
| } |
| |
| @Override |
| public boolean isAutoExpandNode() { |
| return myAutoExpand; |
| } |
| |
| @Override |
| public int getWeight() { |
| return myWeight; |
| } |
| } |
| |
| public boolean isEmpty() { |
| List<Object> children = new ArrayList<Object>(); |
| collectChildren(myBuilder.getTreeStructure().getRootElement(), children); |
| return children.isEmpty(); |
| } |
| |
| private class MyStructure extends AbstractTreeStructure { |
| private final Project myProject; |
| |
| public MyStructure(Project project) { |
| myProject = project; |
| } |
| |
| @Override |
| public Object getRootElement() { |
| return ApplicationManager.getApplication(); |
| } |
| |
| @Override |
| public Object[] getChildElements(Object element) { |
| final List<Object> result = new ArrayList<Object>(); |
| collectChildren(element, result); |
| final Iterator<Object> it = result.iterator(); |
| while (it.hasNext()) { |
| if (!acceptsElement(it.next())) it.remove(); |
| } |
| for (Object o : result) { |
| myParentsMap.put(o, element); |
| } |
| return result.toArray(); |
| } |
| |
| @Override |
| public Object getParentElement(Object element) { |
| if (element instanceof Application) return null; |
| if (element instanceof Project) return ApplicationManager.getApplication(); |
| if (element instanceof Module) return ((Module)element).getProject(); |
| if (element instanceof LibraryTable) return myParentsMap.get(element); |
| if (element instanceof Library) return myParentsMap.get(element); |
| throw new AssertionError(); |
| } |
| |
| @NotNull |
| @Override |
| public NodeDescriptor createDescriptor(Object element, NodeDescriptor parentDescriptor) { |
| if (element instanceof Application) return new RootDescriptor(myProject); |
| if (element instanceof Project) return new ProjectDescriptor(myProject, (Project)element); |
| if (element instanceof Module) return new ModuleDescriptor(myProject, parentDescriptor, (Module)element); |
| if (element instanceof LibraryTable) { |
| final LibraryTable libraryTable = (LibraryTable)element; |
| return new LibraryTableDescriptor(myProject, parentDescriptor, libraryTable, |
| getLibraryTableWeight(libraryTable), |
| isAutoExpandLibraryTable(libraryTable)); |
| } |
| if (element instanceof Library) return createLibraryDescriptor(parentDescriptor, (Library)element); |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public void commit() { |
| } |
| |
| @Override |
| public boolean hasSomethingToCommit() { |
| return false; |
| } |
| } |
| } |