com.intellij.execution.impl.BaseExecuteBeforeRunDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.intellij.execution.impl.BaseExecuteBeforeRunDialog.java

Source

/*
 * 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.execution.impl;

import com.intellij.execution.*;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Key;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.StringSetSpinAllocator;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;

public abstract class BaseExecuteBeforeRunDialog<T extends BeforeRunTask> extends DialogWrapper {
    private final Project myProject;
    private DefaultMutableTreeNode myRoot;

    public BaseExecuteBeforeRunDialog(final Project project) {
        super(project, true);
        myProject = project;
    }

    @Override
    protected void init() {
        super.init();
        setTitle(ExecutionBundle.message("execute.before.run.debug.dialog.title", getTargetDisplayString()));
    }

    @Override
    protected JComponent createCenterPanel() {
        JPanel panel = new JPanel(new BorderLayout());

        myRoot = buildNodes();
        final Tree tree = new Tree(myRoot);

        final MyTreeCellRenderer cellRenderer = new MyTreeCellRenderer();

        tree.setCellRenderer(cellRenderer);
        tree.setRootVisible(false);
        tree.setShowsRootHandles(true);
        tree.setLineStyleAngled();
        TreeUtil.installActions(tree);
        new TreeSpeedSearch(tree);

        tree.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                int row = tree.getRowForLocation(e.getX(), e.getY());
                if (row >= 0) {
                    Rectangle rowBounds = tree.getRowBounds(row);
                    cellRenderer.setBounds(rowBounds);
                    Rectangle checkBounds = cellRenderer.myCheckbox.getBounds();

                    checkBounds.setLocation(rowBounds.getLocation());
                    if (checkBounds.contains(e.getPoint())) {
                        toggleNode(tree, (DefaultMutableTreeNode) tree.getPathForRow(row).getLastPathComponent());
                        e.consume();
                        tree.setSelectionRow(row);
                    }
                }
            }
        });

        tree.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                    TreePath treePath = tree.getLeadSelectionPath();
                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
                    toggleNode(tree, node);
                    e.consume();
                }
            }
        });

        expacndChecked(tree);

        JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(tree);
        scrollPane.setPreferredSize(new Dimension(400, 400));
        panel.add(scrollPane, BorderLayout.CENTER);
        return panel;
    }

    private static void expacndChecked(Tree tree) {
        TreeNode root = (TreeNode) tree.getModel().getRoot();
        Enumeration factories = root.children();
        ArrayList<TreeNode[]> toExpand = new ArrayList<TreeNode[]>();
        while (factories.hasMoreElements()) {
            DefaultMutableTreeNode factoryNode = (DefaultMutableTreeNode) factories.nextElement();
            Enumeration configurations = factoryNode.children();
            while (configurations.hasMoreElements()) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) configurations.nextElement();
                ConfigurationDescriptor config = (ConfigurationDescriptor) node.getUserObject();
                if (config.isChecked()) {
                    toExpand.add(factoryNode.getPath());
                    break;
                }
            }
        }
        for (TreeNode[] treeNodes : toExpand) {
            tree.expandPath(new TreePath(treeNodes));
        }
    }

    private static void toggleNode(JTree tree, DefaultMutableTreeNode node) {
        Descriptor descriptor = (Descriptor) node.getUserObject();
        descriptor.setChecked(!descriptor.isChecked());
        tree.repaint();
    }

    private DefaultMutableTreeNode buildNodes() {
        DefaultMutableTreeNode root = new DefaultMutableTreeNode(new Descriptor());
        RunManager runManager = RunManager.getInstance(myProject);
        final ConfigurationType[] configTypes = runManager.getConfigurationFactories();

        for (final ConfigurationType type : configTypes) {
            final Icon icon = type.getIcon();
            DefaultMutableTreeNode typeNode = new DefaultMutableTreeNode(
                    new ConfigurationTypeDescriptor(type, icon, isConfigurationAssigned(type)));
            root.add(typeNode);
            final Set<String> addedNames = StringSetSpinAllocator.alloc();
            try {
                RunConfiguration[] configurations = runManager.getConfigurations(type);
                for (final RunConfiguration configuration : configurations) {
                    final String configurationName = configuration.getName();
                    if (addedNames.contains(configurationName)) {
                        // add only the first configuration if more than one has the same name
                        continue;
                    }
                    addedNames.add(configurationName);
                    typeNode.add(new DefaultMutableTreeNode(
                            new ConfigurationDescriptor(configuration, isConfigurationAssigned(configuration))));
                }
            } finally {
                StringSetSpinAllocator.dispose(addedNames);
            }
        }

        return root;
    }

    private boolean isConfigurationAssigned(ConfigurationType type) {
        final RunManagerEx runManager = RunManagerEx.getInstanceEx(myProject);
        for (ConfigurationFactory factory : type.getConfigurationFactories()) {
            final RunnerAndConfigurationSettings settings = ((RunManagerImpl) runManager)
                    .getConfigurationTemplate(factory);
            if (isConfigurationAssigned(settings.getConfiguration()))
                return true;
        }
        return false;
    }

    private boolean isConfigurationAssigned(RunConfiguration configuration) {
        final java.util.List<T> tasks = RunManagerEx.getInstanceEx(myProject).getBeforeRunTasks(configuration,
                getTaskID());
        for (T task : tasks) {
            if (isRunning(task))
                return true;
        }
        return false;
    }

    @Override
    protected void doOKAction() {
        final RunManagerImpl runManager = (RunManagerImpl) RunManagerEx.getInstanceEx(myProject);
        for (Enumeration nodes = myRoot.depthFirstEnumeration(); nodes.hasMoreElements();) {
            final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement();
            final Descriptor descriptor = (Descriptor) node.getUserObject();
            final boolean isChecked = descriptor.isChecked();

            if (descriptor instanceof ConfigurationTypeDescriptor) {
                ConfigurationTypeDescriptor typeDesc = (ConfigurationTypeDescriptor) descriptor;
                for (ConfigurationFactory factory : typeDesc.getConfigurationType().getConfigurationFactories()) {
                    RunnerAndConfigurationSettings settings = runManager.getConfigurationTemplate(factory);
                    update(settings.getConfiguration(), isChecked, runManager);
                }
            } else if (descriptor instanceof ConfigurationDescriptor) {
                ConfigurationDescriptor configDesc = (ConfigurationDescriptor) descriptor;
                update(configDesc.getConfiguration(), isChecked, runManager);
            }
        }

        RunManagerImpl.getInstanceImpl(myProject).fireBeforeRunTasksUpdated();
        close(OK_EXIT_CODE);
    }

    protected abstract String getTargetDisplayString();

    protected abstract Key<T> getTaskID();

    protected abstract boolean isRunning(T task);

    private void update(RunConfiguration config, boolean enabled, RunManagerImpl runManager) {
        List<BeforeRunTask> tasks = runManager.getBeforeRunTasks(config);
        BeforeRunTaskProvider<T> provider = BeforeRunTaskProvider.getProvider(myProject, getTaskID());
        if (provider == null)
            return;
        T task = provider.createTask(config);
        update(task);
        task.setEnabled(true);
        if (enabled) {
            if (!tasks.contains(task)) {
                tasks.add(task);
            }
        } else {
            if (tasks.contains(task)) {
                tasks.remove(task);
            }
        }
        runManager.setBeforeRunTasks(config, tasks, false);
    }

    protected abstract void update(T task);

    protected abstract void clear(T task);

    private static class Descriptor {
        private boolean myChecked;

        public final boolean isChecked() {
            return myChecked;
        }

        public final void setChecked(boolean checked) {
            myChecked = checked;
        }
    }

    private static final class ConfigurationTypeDescriptor extends Descriptor {
        private final ConfigurationType myConfigurationType;
        private final Icon myIcon;

        public ConfigurationTypeDescriptor(ConfigurationType type, Icon icon, boolean isChecked) {
            myConfigurationType = type;
            myIcon = icon;
            setChecked(isChecked);
        }

        public ConfigurationType getConfigurationType() {
            return myConfigurationType;
        }

        public Icon getIcon() {
            return myIcon;
        }
    }

    private static final class ConfigurationDescriptor extends Descriptor {
        private final RunConfiguration myConfiguration;

        public ConfigurationDescriptor(RunConfiguration configuration, boolean isChecked) {
            myConfiguration = configuration;
            setChecked(isChecked);
        }

        public ConfigurationType getConfigurationFactory() {
            return myConfiguration.getType();
        }

        public String getName() {
            return myConfiguration.getName();
        }

        public RunConfiguration getConfiguration() {
            return myConfiguration;
        }
    }

    private static final class MyTreeCellRenderer extends JPanel implements TreeCellRenderer {
        private final JLabel myLabel;
        public final JCheckBox myCheckbox;

        public MyTreeCellRenderer() {
            super(new BorderLayout());
            myCheckbox = new JCheckBox();
            myLabel = new JLabel();
            add(myCheckbox, BorderLayout.WEST);
            add(myLabel, BorderLayout.CENTER);
        }

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded,
                boolean leaf, int row, boolean hasFocus) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
            Descriptor descriptor = (Descriptor) node.getUserObject();

            myCheckbox.setSelected(descriptor.isChecked());

            myCheckbox.setBackground(UIUtil.getTreeTextBackground());
            setBackground(selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeTextBackground());
            final Color foreground = selected ? UIUtil.getTreeSelectionForeground()
                    : UIUtil.getTreeTextForeground();
            setForeground(foreground);
            myCheckbox.setForeground(foreground);
            myLabel.setForeground(foreground);
            myCheckbox.setEnabled(true);

            if (descriptor instanceof ConfigurationTypeDescriptor) {
                ConfigurationTypeDescriptor configurationTypeDescriptor = (ConfigurationTypeDescriptor) descriptor;
                myLabel.setFont(tree.getFont());
                myLabel.setText(configurationTypeDescriptor.getConfigurationType().getDisplayName());
                myLabel.setIcon(configurationTypeDescriptor.getIcon());
            } else if (descriptor instanceof ConfigurationDescriptor) {
                ConfigurationDescriptor configurationTypeDescriptor = (ConfigurationDescriptor) descriptor;
                myLabel.setFont(tree.getFont());
                myLabel.setText(configurationTypeDescriptor.getName());
                myLabel.setIcon(null);

                if (((ConfigurationTypeDescriptor) ((DefaultMutableTreeNode) node.getParent()).getUserObject())
                        .isChecked()) {
                    Color foregrnd = tree.getForeground();
                    Color backgrnd = tree.getBackground();
                    if (foregrnd == null)
                        foregrnd = Color.black;
                    if (backgrnd == null)
                        backgrnd = Color.white;

                    int red = (foregrnd.getRed() + backgrnd.getRed()) / 2;
                    int green = (foregrnd.getGreen() + backgrnd.getGreen()) / 2;
                    int blue = (foregrnd.getBlue() + backgrnd.getBlue()) / 2;
                    Color halftone = new Color(red, green, blue);
                    setForeground(halftone);
                    myCheckbox.setForeground(halftone);
                    myLabel.setForeground(halftone);
                    myCheckbox.setEnabled(false);
                }
            }

            return this;
        }

    }
}