/* * Copyright 2017 Laszlo Balazs-Csiki * * This file is part of Pixelitor. Pixelitor is free software: you * can redistribute it and/or modify it under the terms of the GNU * General Public License, version 3 as published by the Free * Software Foundation. * * Pixelitor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Pixelitor. If not, see <http://www.gnu.org/licenses/>. */ package pixelitor.automate; import pixelitor.Composition; import pixelitor.filters.comp.CompAction; import pixelitor.gui.ImageComponent; import pixelitor.gui.ImageComponents; import pixelitor.gui.ImageFrame; import pixelitor.gui.PixelitorWindow; import pixelitor.gui.utils.ValidatedDialog; import pixelitor.io.Directories; import pixelitor.io.FileExtensionUtils; import pixelitor.io.OpenSaveManager; import pixelitor.io.OutputFormat; import pixelitor.utils.Messages; import pixelitor.utils.Utils; import javax.swing.*; import java.awt.EventQueue; import java.io.File; import java.lang.reflect.InvocationTargetException; /** * Utility class with static methods to support batch processing */ public class Automate { private static final String OVERWRITE_YES = "Yes"; private static final String OVERWRITE_YES_ALL = "Yes, All"; private static final String OVERWRITE_NO = "No (Skip)"; private static final String OVERWRITE_CANCEL = "Cancel Processing"; private static volatile boolean overwriteAll = false; private static volatile boolean stopProcessing = false; private Automate() { } /** * Processes each file in the input directory with the given CompAction */ public static void processEachFile(CompAction action, boolean closeImagesAfterDone, String dialogTitle) { File lastOpenDir = Directories.getLastOpenDir(); if (lastOpenDir == null) { throw new IllegalStateException("lastOpenDir is null"); } if (!lastOpenDir.exists()) { throw new IllegalStateException("Last open dir " + lastOpenDir.getAbsolutePath() + " does not exist"); } File lastSaveDir = Directories.getLastSaveDir(); if (lastSaveDir == null) { throw new IllegalStateException("lastSaveDir is null"); } if (!lastSaveDir.exists()) { throw new IllegalStateException("Last save dir " + lastSaveDir.getAbsolutePath() + " does not exist"); } File[] inputFiles = FileExtensionUtils.getAllSupportedInputFilesInDir(lastOpenDir); if (inputFiles.length == 0) { Messages.showInfo("No files", "There are no supported files in " + lastOpenDir.getAbsolutePath()); return; } ProgressMonitor progressMonitor = Utils.createPercentageProgressMonitor(dialogTitle); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { @Override public Void doInBackground() { overwriteAll = false; for (int i = 0, nrOfFiles = inputFiles.length; i < nrOfFiles; i++) { if (progressMonitor.isCanceled()) { break; } File file = inputFiles[i]; progressMonitor.setProgress((int) ((float) i * 100 / nrOfFiles)); progressMonitor.setNote("Processing " + file.getName()); System.out.println("Processing " + file.getName()); Runnable edtTask = () -> processFile(file, action, lastSaveDir, closeImagesAfterDone); try { EventQueue.invokeAndWait(edtTask); } catch (InterruptedException | InvocationTargetException e) { Messages.showException(e); } if (stopProcessing) { break; } } // end of for loop progressMonitor.close(); return null; } // end of doInBackground }; worker.execute(); } private static void processFile(File file, CompAction action, File lastSaveDir, boolean closeImagesAfterDone) { OpenSaveManager.openFile(file); Composition comp = ImageComponents.getActiveCompOrNull(); ImageComponent ic = comp.getIC(); ImageFrame frame = ic.getFrame(); frame.paintImmediately(frame.getBounds()); action.process(comp); OutputFormat outputFormat = OutputFormat.getLastUsed(); String inputFileName = file.getName(); String outFileName = FileExtensionUtils.replaceExt(inputFileName, outputFormat.toString()); File outputFile = new File(lastSaveDir, outFileName); if (outputFile.exists() && (!overwriteAll)) { String message = String.format("File %s already exists. Overwrite?", outputFile); JOptionPane pane = new JOptionPane(message, JOptionPane.WARNING_MESSAGE); pane.setOptions(new String[]{OVERWRITE_YES, OVERWRITE_YES_ALL, OVERWRITE_NO, OVERWRITE_CANCEL}); pane.setInitialValue(OVERWRITE_NO); JDialog dialog = pane.createDialog(PixelitorWindow.getInstance(), "Warning"); dialog.setVisible(true); String value = (String) pane.getValue(); String answer; if (value == null) { // cancelled answer = OVERWRITE_CANCEL; } else { answer = value; } switch (answer) { case OVERWRITE_YES: outputFormat.saveComp(comp, outputFile, false); break; case OVERWRITE_YES_ALL: outputFormat.saveComp(comp, outputFile, false); overwriteAll = true; break; case OVERWRITE_NO: // do nothing break; case OVERWRITE_CANCEL: if (closeImagesAfterDone) { OpenSaveManager.warnAndCloseImage(ic); } stopProcessing = true; return; } } else { // the file does not exist or overwrite all was pressed previously frame.paintImmediately(frame.getBounds()); outputFormat.saveComp(comp, outputFile, false); } if (closeImagesAfterDone) { OpenSaveManager.warnAndCloseImage(ic); } stopProcessing = false; } /** * Lets the user select the input and output directory properties of the application. * * @param allowToBeTheSame * @param dialogTitle * @return true if a selection was made, false if the operation was cancelled */ public static boolean selectInputAndOutputDir(boolean allowToBeTheSame, String dialogTitle) { OpenSaveDirsPanel p = new OpenSaveDirsPanel(allowToBeTheSame); ValidatedDialog chooser = new ValidatedDialog(p, PixelitorWindow.getInstance(), dialogTitle); chooser.setVisible(true); if (!chooser.isOkPressed()) { return false; } p.saveValues(); return true; } }