com.google.idea.blaze.base.run.exporter.ExportRunConfigurationDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.google.idea.blaze.base.run.exporter.ExportRunConfigurationDialog.java

Source

/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.google.idea.blaze.base.run.exporter;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.idea.blaze.base.io.FileAttributeProvider;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.projectview.ProjectViewManager;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.projectview.ProjectViewSet.ProjectViewFile;
import com.google.idea.blaze.base.run.BlazeRunConfiguration;
import com.google.idea.blaze.base.settings.Blaze;
import com.intellij.execution.RunManager;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.fileChooser.FileChooserDialog;
import com.intellij.openapi.fileChooser.FileChooserFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.AnActionButton;
import com.intellij.ui.BooleanTableCellEditor;
import com.intellij.ui.BooleanTableCellRenderer;
import com.intellij.ui.ColoredTableCellRenderer;
import com.intellij.ui.FieldPanel;
import com.intellij.ui.GuiUtils;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.table.JBTable;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.swing.DefaultCellEditor;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

/** UI for exporting blaze run configurations. */
public class ExportRunConfigurationDialog extends DialogWrapper {

    private final ImmutableList<RunConfiguration> blazeConfigurations;
    private final ExportRunConfigurationTableModel tableModel;
    private final JBTable table;
    private final FieldPanel outputDirectoryPanel;

    ExportRunConfigurationDialog(Project project) {
        super(project, true);
        blazeConfigurations = ImmutableList.copyOf(RunManager.getInstance(project).getAllConfigurationsList()
                .stream().filter((config) -> config instanceof BlazeRunConfiguration).collect(Collectors.toList()));
        tableModel = new ExportRunConfigurationTableModel(blazeConfigurations);
        table = new JBTable(tableModel);

        TableColumn booleanColumn = table.getColumnModel().getColumn(0);
        booleanColumn.setCellRenderer(new BooleanTableCellRenderer());
        booleanColumn.setCellEditor(new BooleanTableCellEditor());
        int width = table.getFontMetrics(table.getFont()).stringWidth(table.getColumnName(0)) + 10;
        booleanColumn.setPreferredWidth(width);
        booleanColumn.setMinWidth(width);
        booleanColumn.setMaxWidth(width);

        table.getColumnModel().getColumn(2)
                .setCellEditor(new DefaultCellEditor(GuiUtils.createUndoableTextField()));

        TableColumn nameColumn = table.getColumnModel().getColumn(1);
        nameColumn.setCellRenderer(new ColoredTableCellRenderer() {
            @Override
            protected void customizeCellRenderer(JTable table, Object value, boolean isSelected, boolean hasFocus,
                    int row, int col) {
                RunConfiguration config = blazeConfigurations.get(row);
                setIcon(config.getType().getIcon());
                append(config.getName());
            }
        });

        table.setPreferredSize(new Dimension(700, 700));
        table.setShowColumns(true);

        final ActionListener browseAction = e -> chooseDirectory();
        outputDirectoryPanel = new FieldPanel("Export configurations to directory:", null, browseAction, null);
        File defaultExportDirectory = defaultExportDirectory(project);
        if (defaultExportDirectory != null) {
            outputDirectoryPanel.setText(defaultExportDirectory.getPath());
        }

        String buildSystem = Blaze.buildSystemName(project);
        setTitle(String.format("Export %s Run Configurations", buildSystem));
        init();
    }

    /** Try to find a checked-in project view file. Otherwise, fall back to the workspace root. */
    @Nullable
    private static File defaultExportDirectory(Project project) {
        WorkspaceRoot workspaceRoot = WorkspaceRoot.fromProjectSafe(project);
        if (workspaceRoot == null) {
            return null;
        }
        ProjectViewSet projectViewSet = ProjectViewManager.getInstance(project).getProjectViewSet();
        if (projectViewSet != null) {
            for (ProjectViewFile projectViewFile : projectViewSet.getProjectViewFiles()) {
                File file = projectViewFile.projectViewFile;
                if (file != null && FileUtil.isAncestor(workspaceRoot.directory(), file, false)) {
                    return file.getParentFile();
                }
            }
        }
        return workspaceRoot.directory();
    }

    private String getOutputDirectoryPath() {
        return Strings.nullToEmpty(outputDirectoryPanel.getText()).trim();
    }

    private void chooseDirectory() {
        FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor()
                .withTitle("Export Directory Location")
                .withDescription("Choose directory to export run configurations to").withHideIgnored(false);
        FileChooserDialog chooser = FileChooserFactory.getInstance().createFileChooser(descriptor, null, null);

        final VirtualFile[] files;
        File existingLocation = new File(getOutputDirectoryPath());
        if (existingLocation.exists()) {
            VirtualFile toSelect = LocalFileSystem.getInstance()
                    .refreshAndFindFileByPath(existingLocation.getPath());
            files = chooser.choose(null, toSelect);
        } else {
            files = chooser.choose(null);
        }
        if (files.length == 0) {
            return;
        }
        VirtualFile file = files[0];
        outputDirectoryPanel.setText(file.getPath());
    }

    @Nullable
    @Override
    protected ValidationInfo doValidate() {
        String outputDir = getOutputDirectoryPath();
        if (outputDir.isEmpty()) {
            return new ValidationInfo("Choose an output directory");
        }
        if (!FileAttributeProvider.getInstance().exists(new File(outputDir))) {
            return new ValidationInfo("Invalid output directory");
        }
        Set<String> names = new HashSet<>();
        for (int i = 0; i < blazeConfigurations.size(); i++) {
            if (!tableModel.enabled[i]) {
                continue;
            }
            if (!names.add(tableModel.paths[i])) {
                return new ValidationInfo("Duplicate output file name '" + tableModel.paths[i] + "'");
            }
        }
        return null;
    }

    @Override
    protected void doOKAction() {
        File outputDir = new File(getOutputDirectoryPath());
        List<File> outputFiles = new ArrayList<>();
        for (int i = 0; i < blazeConfigurations.size(); i++) {
            if (!tableModel.enabled[i]) {
                continue;
            }
            File outputFile = new File(outputDir, tableModel.paths[i]);
            writeConfiguration(blazeConfigurations.get(i), outputFile);
            outputFiles.add(outputFile);
        }
        LocalFileSystem.getInstance().refreshIoFiles(outputFiles);
        super.doOKAction();
    }

    private static void writeConfiguration(RunConfiguration configuration, File outputFile) {
        try (FileOutputStream writer = new FileOutputStream(outputFile, false)) {
            XMLOutputter xmlOutputter = new XMLOutputter(Format.getCompactFormat());
            xmlOutputter.output(RunConfigurationSerializer.writeToXml(configuration), writer);
        } catch (IOException e) {
            throw new RuntimeException("Error exporting run configuration to file: " + outputFile);
        }
    }

    @Override
    protected JComponent createNorthPanel() {
        return outputDirectoryPanel;
    }

    @Override
    protected JComponent createCenterPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(IdeBorderFactory.createTitledBorder("Run Configurations", false));
        panel.add(ToolbarDecorator.createDecorator(table).addExtraAction(new SelectAllButton()).createPanel(),
                BorderLayout.CENTER);
        return panel;
    }

    private class SelectAllButton extends AnActionButton {

        boolean allSelected = false;

        private SelectAllButton() {
            super("Select All", AllIcons.Actions.Selectall);
        }

        @Override
        public synchronized void actionPerformed(AnActionEvent anActionEvent) {
            boolean newState = !allSelected;
            for (int i = 0; i < tableModel.enabled.length; i++) {
                table.setValueAt(newState, i, 0);
            }
            allSelected = newState;
            Presentation presentation = anActionEvent.getPresentation();
            if (allSelected) {
                presentation.setText("Deselect All");
                presentation.setIcon(AllIcons.Actions.Unselectall);
            } else {
                presentation.setText("Select All");
                presentation.setIcon(AllIcons.Actions.Selectall);
            }
            tableModel.fireTableDataChanged();
            table.revalidate();
            table.repaint();
        }
    }
}