commit 48c5f610023e83e1c1a493850e7046dea4f77ed9 Author: Bronson Graansma Date: Tue Jul 9 09:01:57 2019 -0400 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..395dde9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.iml +.idea/ +target/ \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..3655e9e --- /dev/null +++ b/pom.xml @@ -0,0 +1,89 @@ + + + 4.0.0 + + com.ingvonic + pdfCombiner + 1.0-SNAPSHOT + + + 1.8 + 1.8 + + + + + org.apache.pdfbox + pdfbox + 2.0.15 + + + + + + + maven-jar-plugin + 3.0.0 + + PdfCombiner + + + PdfCombiner + + + + + + maven-shade-plugin + 2.4.3 + + + package + + shade + + + true + false + false + + + org.apache.pdfbox:pdfbox + + ** + + + + commons-logging:commons-logging + + ** + + + + + + + + + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/classes/lib + true + true + true + + + + + + + \ No newline at end of file diff --git a/src/main/java/FileJList.java b/src/main/java/FileJList.java new file mode 100644 index 0000000..4cbe81a --- /dev/null +++ b/src/main/java/FileJList.java @@ -0,0 +1,95 @@ +import javax.swing.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * A JList that has files as elements, and can be reordered via drag and drop. + * + * created on 2019-07-05 + */ +class FileJList extends JList { + + private DefaultListModel view; + private List model; + + FileJList() { + super(); + + view = new DefaultListModel<>(); + model = new ArrayList<>(); + + setModel(view); + setDragEnabled(true); + setDropMode(DropMode.INSERT); + setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + setTransferHandler(new DragAndDrop()); + } + + List getElements() { + return new ArrayList<>(model); + } + + boolean isEmpty() { + return model.isEmpty() && view.isEmpty(); + } + + void addElement(int i, File file) { + model.add(i, file); + view.addElement(file.getName()); + } + + void addElement(File file) { + model.add(file); + view.addElement(file.getName()); + } + + File getElement(int i) { + return model.get(i); + } + + File removeElement(int i) { + view.remove(i); + return model.remove(i); + } + + void clear() { + view.clear(); + model.clear(); + } + + private class DragAndDrop extends TransferHandler { + private int index; + + @Override + public int getSourceActions(JComponent comp) { + return MOVE; + } + + @Override + public Transferable createTransferable(JComponent comp) { + index = getSelectedIndex(); + return new StringSelection(getSelectedValue()); + } + + @Override + public void exportDone(JComponent comp, Transferable trans, int action) { + removeElement(action == MOVE ? index + 1 : index); + } + + @Override + public boolean canImport(TransferHandler.TransferSupport support) { + return support.isDataFlavorSupported(DataFlavor.stringFlavor); + } + + @Override + public boolean importData(TransferHandler.TransferSupport support) { + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + addElement(dl.getIndex(), model.get(index)); + return true; + } + } +} diff --git a/src/main/java/PdfCombiner.java b/src/main/java/PdfCombiner.java new file mode 100644 index 0000000..f66fee3 --- /dev/null +++ b/src/main/java/PdfCombiner.java @@ -0,0 +1,135 @@ +import org.apache.pdfbox.io.MemoryUsageSetting; +import org.apache.pdfbox.multipdf.PDFMergerUtility; + +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.awt.*; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Arrays; + +/** + * Simple GUI to quickly merge multiple pdf files into a single pdf file. + * + * created on 2019-06-25 + */ +public class PdfCombiner extends JFrame { + private FileJList list; + private JFileChooser chooser; + + public static void main(String... args) { + EventQueue.invokeLater(PdfCombiner::new); + } + + private PdfCombiner() { + chooser = new JFileChooser(); + list = new FileJList(); + + chooser.setFileFilter(new FileNameExtensionFilter("Portable Document Format", "pdf")); + + setTitle("PDF Combiner"); + setLocationRelativeTo(null); + setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + + initialize(); + + pack(); + + setMinimumSize(getSize()); + setVisible(true); + } + + private void initialize() { + setLayout(new BorderLayout()); + + JScrollPane scroller = new JScrollPane(); + scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + scroller.setViewportView(list); + scroller.setMinimumSize(new Dimension(100, 100)); + + add(scroller, BorderLayout.CENTER); + + JPanel bottom = new JPanel(new GridLayout()); + + JButton addButton = new JButton("+"); + addButton.addActionListener(l -> add()); + bottom.add(addButton); + + JButton removeButton = new JButton("-"); + removeButton.addActionListener(l -> remove()); + bottom.add(removeButton); + + JButton clearButton = new JButton("Clear"); + clearButton.addActionListener(l -> list.clear()); + bottom.add(clearButton); + + JButton saveButton = new JButton("Save"); + saveButton.addActionListener(l -> save()); + bottom.add(saveButton); + + add(bottom, BorderLayout.SOUTH); + } + + private void remove() { + int[] indices = list.getSelectedIndices(); + + if(!list.isEmpty() && indices.length > 0) { + Arrays.sort(indices); + + for(int i = indices.length - 1; i >= 0; i--) { + list.removeElement(indices[i]); + } + } + } + + private void save() { + if(!list.isEmpty()) try { + PDFMergerUtility merger = new PDFMergerUtility(); + for(File pdf : list.getElements()) { + merger.addSource(pdf); + } + + chooser.setMultiSelectionEnabled(false); + chooser.showSaveDialog(this); + + String fileName = chooser.getSelectedFile().getAbsolutePath(); + + if(!fileName.toLowerCase().endsWith(".pdf")) { + fileName += ".pdf"; + } + + merger.setDestinationFileName(fileName); + merger.mergeDocuments(MemoryUsageSetting.setupTempFileOnly()); + } catch(FileNotFoundException e) { + warn("One or more of the selected files could not be found."); + } catch(IOException e) { + warn("An error occurred while saving."); + e.printStackTrace(); + } else { + warn("No PDFs were provided."); + } + } + + private void add() { + chooser.setMultiSelectionEnabled(true); + chooser.showOpenDialog(this); + + for(File pdf : chooser.getSelectedFiles()) { + if(!list.getElements().contains(pdf)) { + list.addElement(pdf); + } + } + } + + private void warn(String message) { + JOptionPane.showConfirmDialog( + this, + message, + "Error", + JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, + null + ); + } +}