de.mprengemann.intellij.plugin.androidicons.dialogs.AndroidBatchScaleImporter.java Source code

Java tutorial

Introduction

Here is the source code for de.mprengemann.intellij.plugin.androidicons.dialogs.AndroidBatchScaleImporter.java

Source

/*
 * Copyright 2015 Marc Prengemann
 *
 * 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 de.mprengemann.intellij.plugin.androidicons.dialogs;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PathMacroManager;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.ex.FileDrop;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileVisitor;
import com.intellij.ui.table.JBTable;
import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
import de.mprengemann.intellij.plugin.androidicons.IconApplication;
import de.mprengemann.intellij.plugin.androidicons.controllers.batchscale.BatchScaleImporterController;
import de.mprengemann.intellij.plugin.androidicons.controllers.batchscale.BatchScaleImporterObserver;
import de.mprengemann.intellij.plugin.androidicons.controllers.batchscale.IBatchScaleImporterController;
import de.mprengemann.intellij.plugin.androidicons.controllers.batchscale.additem.AddItemBatchScaleImporterController;
import de.mprengemann.intellij.plugin.androidicons.controllers.batchscale.additem.IAddItemBatchScaleImporterController;
import de.mprengemann.intellij.plugin.androidicons.controllers.defaults.IDefaultsController;
import de.mprengemann.intellij.plugin.androidicons.controllers.settings.ISettingsController;
import de.mprengemann.intellij.plugin.androidicons.model.ImageInformation;
import de.mprengemann.intellij.plugin.androidicons.util.ImageUtils;
import de.mprengemann.intellij.plugin.androidicons.util.MathUtils;
import de.mprengemann.intellij.plugin.androidicons.widgets.FileBrowserField;
import org.apache.commons.io.FilenameUtils;
import org.intellij.images.fileTypes.ImageFileTypeManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class AndroidBatchScaleImporter extends DialogWrapper implements BatchScaleImporterObserver {

    private final Project project;
    private final Module module;
    private final IconApplication container;
    private JPanel uiContainer;
    private JTable table;
    private JLabel imageContainer;
    private JButton addButton;
    private JButton deleteButton;
    private JButton editButton;
    private ImageTableModel tableModel;
    private final BatchScaleImporterController controller;
    private final Consumer<List<VirtualFile>> fileChooserConsumer = new Consumer<List<VirtualFile>>() {
        @Override
        public void consume(final List<VirtualFile> virtualFiles) {
            if (virtualFiles == null || virtualFiles.size() == 0) {
                return;
            }
            final VirtualFile file = virtualFiles.get(0);
            if (file == null) {
                return;
            }
            container.getControllerFactory().getSettingsController().saveLastImageFolder(file.getCanonicalPath());
            if (virtualFiles.size() == 1 && !file.isDirectory()) {
                addSingleFile(file);
            } else {
                new Task.Modal(project, "Adding Files...", true) {
                    @Override
                    public void run(@NotNull ProgressIndicator progressIndicator) {
                        progressIndicator.setIndeterminate(true);
                        try {
                            addMultipleFiles(virtualFiles, progressIndicator);
                        } catch (ProcessCanceledException ignored) {
                        }
                    }
                }.queue();
            }
        }
    };

    public AndroidBatchScaleImporter(final Project project, final Module module) {
        super(project);
        this.project = project;
        this.container = ApplicationManager.getApplication().getComponent(IconApplication.class);
        this.controller = new BatchScaleImporterController();
        this.controller.addObserver(this);
        this.module = module;

        setTitle("Batch Drawable Importer");

        initButtons(project);
        initDragDrop();
        initTable();
        init();
        pack();
    }

    private void initButtons(final Project project) {
        addButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                FileChooser.chooseFiles(FileBrowserField.IMAGE_FILES_FOLDER_CHOOSER, project, getInitialFile(),
                        fileChooserConsumer);
            }
        });
        deleteButton.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                controller.removeImages(table.getSelectedRows());
            }
        });
        editButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                controller.editImages(project, module, table.getSelectedRows());
            }
        });
    }

    private void initDragDrop() {
        new FileDrop(table, new FileDrop.Target() {
            @Override
            public FileChooserDescriptor getDescriptor() {
                return FileBrowserField.IMAGE_FILES_FOLDER_CHOOSER;
            }

            @Override
            public boolean isHiddenShown() {
                return false;
            }

            @Override
            public void dropFiles(final List<VirtualFile> virtualFiles) {
                fileChooserConsumer.consume(virtualFiles);
            }
        });
    }

    private void addMultipleFiles(List<VirtualFile> virtualFiles, final ProgressIndicator progressIndicator)
            throws ProcessCanceledException {
        for (final VirtualFile file : virtualFiles) {
            progressIndicator.checkCanceled();
            if (file.isDirectory()) {
                progressIndicator.setText2(file.getCanonicalPath());
                VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
                    @Override
                    public boolean visitFile(@NotNull VirtualFile child) throws ProcessCanceledException {
                        if (file.equals(child)) {
                            return true;
                        }
                        progressIndicator.checkCanceled();
                        addMultipleFiles(Arrays.asList(child), progressIndicator);
                        return true;
                    }
                });
                continue;
            }
            addSingleFileImmediately(file);
        }
    }

    private void addSingleFileImmediately(VirtualFile file) {
        if (!file.getFileType().equals(ImageFileTypeManager.getInstance().getImageFileType())) {
            return;
        }
        // Hack
        String path = file.getCanonicalPath();
        if (path == null) {
            return;
        }
        final File realFile = new File(path);
        final ISettingsController settingsController = container.getControllerFactory().getSettingsController();
        final IDefaultsController defaultsController = container.getControllerFactory().getDefaultsController();
        final VirtualFile root = settingsController.getResourceRoot();
        final IAddItemBatchScaleImporterController addItemController = new AddItemBatchScaleImporterController(
                defaultsController, root, realFile);
        controller.addImage(addItemController.getSourceResolution(),
                addItemController.getImageInformation(project));
        addItemController.tearDown();
    }

    private void addSingleFile(VirtualFile file) {
        container.getControllerFactory().getSettingsController().saveLastImageFolder(file.getCanonicalPath());
        AddItemBatchScaleDialog addItemBatchScaleDialog = new AddItemBatchScaleDialog(project, module, controller,
                file);
        addItemBatchScaleDialog.show();
    }

    private void initTable() {
        tableModel = new ImageTableModel(controller);
        table.setModel(tableModel);

        initRenderers();
        initRowSelection();
        initColumnSizes();
    }

    private void initRenderers() {
        final DefaultTableCellRenderer fileCellRenderer = new DefaultTableCellRenderer() {
            @Override
            protected void setValue(Object o) {
                File file = (File) o;
                if (file == null) {
                    setText("");
                    return;
                }
                if (file.isDirectory()) {
                    setText(file.getAbsolutePath());
                } else {
                    setText(FilenameUtils.removeExtension(file.getName()));
                }
            }
        };
        fileCellRenderer.setHorizontalTextPosition(DefaultTableCellRenderer.TRAILING);
        table.setDefaultRenderer(File.class, fileCellRenderer);
        table.setDefaultRenderer(ArrayList.class, new DefaultTableCellRenderer() {
            @Override
            protected void setValue(Object o) {
                if (o == null) {
                    setText("");
                } else {
                    ArrayList list = (ArrayList) o;
                    Collections.sort(list);
                    StringBuilder buffer = new StringBuilder();
                    Iterator iterator = list.iterator();
                    while (iterator.hasNext()) {
                        Object val = iterator.next();
                        buffer.append(val.toString());
                        if (iterator.hasNext()) {
                            buffer.append(", ");
                        }
                    }
                    setText(buffer.toString());
                }
            }
        });
    }

    private void initRowSelection() {
        table.getColumnModel().setColumnSelectionAllowed(false);
        table.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting()) {
                    return;
                }
                int selectedRow = table.getSelectedRow();
                if (table.getSelectedRowCount() == 1) {
                    updateImage(controller.getImage(selectedRow));
                } else {
                    updateImage(null);
                }
            }
        });
    }

    private void initColumnSizes() {
        table.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent componentEvent) {
                super.componentResized(componentEvent);
                Dimension tableSize = table.getSize();
                final int[] columnSizes = new int[] { 20, 20, 20, 40 };
                for (int i = 0; i < table.getColumnCount(); i++) {
                    TableColumn column = table.getColumnModel().getColumn(i);
                    column.setPreferredWidth((int) (tableSize.width * (columnSizes[i] / 100f)));
                }
            }
        });
    }

    private void updateImage(ImageInformation item) {
        if (imageContainer == null) {
            return;
        }
        if (item == null) {
            imageContainer.setIcon(null);
            return;
        }
        ImageUtils.updateImage(imageContainer, item.getImageFile(), item.getFormat());
    }

    protected VirtualFile getInitialFile() {
        String directoryName = container.getControllerFactory().getSettingsController().getLastImageFolder();
        VirtualFile path;
        String expandPath = expandPath(directoryName);
        if (expandPath == null) {
            return null;
        }
        for (path = LocalFileSystem.getInstance().findFileByPath(expandPath); path == null
                && directoryName.length() > 0; path = LocalFileSystem.getInstance().findFileByPath(directoryName)) {
            int pos = directoryName.lastIndexOf(47);
            if (pos <= 0) {
                break;
            }
            directoryName = directoryName.substring(0, pos);
        }

        return path;
    }

    private String expandPath(String dirName) {
        if (project != null) {
            dirName = PathMacroManager.getInstance(project).expandPath(dirName);
        }
        if (module != null) {
            dirName = PathMacroManager.getInstance(module).expandPath(dirName);
        }
        return dirName;
    }

    @Nullable
    @Override
    protected JComponent createCenterPanel() {
        return uiContainer;
    }

    private void createUIComponents() {
        table = new JBTable() {
            @NotNull
            @Override
            public Component prepareRenderer(@NotNull TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                c.setEnabled(isCellEditable(row, column));
                return c;
            }
        };
        addButton = new JButton(getIcon("ic_action_add"));
        editButton = new JButton(getIcon("ic_action_edit"));
        deleteButton = new JButton(getIcon("ic_action_trash"));
    }

    @NotNull
    private Icon getIcon(String name) {
        boolean isDarkTheme = UIUtil.isUnderDarcula();
        final String asset = String.format("/icons/%s%s.png", name, isDarkTheme ? "_dark" : "");
        return IconLoader.getIcon(asset);
    }

    @Override
    protected void doOKAction() {
        controller.getExportTask(project).queue();
        super.doOKAction();
    }

    @Override
    public void updated() {
        UIUtil.invokeLaterIfNeeded(new Runnable() {
            @Override
            public void run() {
                updateTable();
            }
        });
    }

    private void updateTable() {
        if (table == null || tableModel == null) {
            return;
        }
        int selectedRow = table.getSelectedRow();
        tableModel.fireTableDataChanged();
        if (table.getRowCount() > 0) {
            selectedRow = MathUtils.clamp(selectedRow, 0, table.getRowCount());
            table.setRowSelectionInterval(selectedRow, selectedRow);
        } else {
            imageContainer.setDisabledIcon(null);
        }
    }

    private static class ImageTableModel extends AbstractTableModel {
        private static final List<String> columnNames = Arrays.asList("Source-File", "Target-Resolutions",
                "Target-Name", "Target-Root");
        private IBatchScaleImporterController controller;

        public ImageTableModel(IBatchScaleImporterController controller) {
            this.controller = controller;
        }

        @Override
        public int getRowCount() {
            return controller.getImageCount();
        }

        @Override
        public int getColumnCount() {
            return columnNames.size();
        }

        @Override
        public String getColumnName(int col) {
            return columnNames.get(col);
        }

        @Override
        public Object getValueAt(int row, int col) {
            ImageInformation information = controller.getImage(row);
            switch (col) {
            case 0:
                return information.getImageFile();
            case 1:
                return controller.getTargetResolutions(information);
            case 2:
                return information.getExportName();
            case 3:
                return information.getExportPath();
            }
            return information;
        }

        @Override
        public Class<?> getColumnClass(int col) {
            return getValueAt(0, col).getClass();
        }
    }
}