first commit

This commit is contained in:
Bronson Graansma
2019-07-09 09:01:57 -04:00
commit 48c5f61002
4 changed files with 322 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*.iml
.idea/
target/

89
pom.xml Normal file
View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ingvonic</groupId>
<artifactId>pdfCombiner</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.15</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<finalName>PdfCombiner</finalName>
<archive>
<manifest>
<mainClass>PdfCombiner</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
<filter>
<artifact>org.apache.pdfbox:pdfbox</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>commons-logging:commons-logging</artifact>
<includes>
<include>**</include>
</includes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -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<String> {
private DefaultListModel<String> view;
private List<File> 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<File> 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;
}
}
}

View File

@@ -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
);
}
}