com.intellij.util.ui.classpath.ChooseLibrariesDialogBase.java Source code

Java tutorial

Introduction

Here is the source code for com.intellij.util.ui.classpath.ChooseLibrariesDialogBase.java

Source

/*
 * 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.icons.AllIcons;
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.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.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(300, 80));
        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(AllIcons.Icon16);
            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(AllIcons.Nodes.Module);
            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(AllIcons.Nodes.PpLib);
            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;
        }
    }
}