Some final cleanup
This commit is contained in:
		
							parent
							
								
									e2ebb3085f
								
							
						
					
					
						commit
						6da3127427
					
				
							
								
								
									
										2
									
								
								pom.xml
								
								
								
								
							
							
						
						
									
										2
									
								
								pom.xml
								
								
								
								
							| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
 | 
			
		||||
    <groupId>nl.andrewlalis</groupId>
 | 
			
		||||
    <artifactId>BlockBookBinder</artifactId>
 | 
			
		||||
    <version>1.0.0</version>
 | 
			
		||||
    <version>1.1.0</version>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
        <maven.compiler.source>12</maven.compiler.source>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,61 +0,0 @@
 | 
			
		|||
package nl.andrewlalis.blockbookbinder.control;
 | 
			
		||||
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.model.Book;
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.view.BookPreviewPanel;
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.view.export.ExportToBookDialog;
 | 
			
		||||
import org.jnativehook.GlobalScreen;
 | 
			
		||||
import org.jnativehook.NativeHookException;
 | 
			
		||||
 | 
			
		||||
import javax.swing.*;
 | 
			
		||||
import java.awt.*;
 | 
			
		||||
import java.awt.datatransfer.Clipboard;
 | 
			
		||||
import java.awt.event.ActionEvent;
 | 
			
		||||
import java.awt.event.ActionListener;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Action listener that is used for when a user decides to begin exporting a
 | 
			
		||||
 * book to minecraft.
 | 
			
		||||
 */
 | 
			
		||||
public class BookExportActionListener implements ActionListener {
 | 
			
		||||
	private final BookPreviewPanel bookPreviewPanel;
 | 
			
		||||
	private final Clipboard clipboard;
 | 
			
		||||
	private final JButton cancelExportButton;
 | 
			
		||||
 | 
			
		||||
	public BookExportActionListener(BookPreviewPanel bookPreviewPanel, JButton cancelExportButton) {
 | 
			
		||||
		this.bookPreviewPanel = bookPreviewPanel;
 | 
			
		||||
		this.cancelExportButton = cancelExportButton;
 | 
			
		||||
		this.clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void actionPerformed(ActionEvent e) {
 | 
			
		||||
		System.out.println("Starting export.");
 | 
			
		||||
		final Book book = this.bookPreviewPanel.getBook();
 | 
			
		||||
		int choice = JOptionPane.showConfirmDialog(
 | 
			
		||||
				this.bookPreviewPanel.getRootPane(),
 | 
			
		||||
				"Press OK to initialize export.",
 | 
			
		||||
				"Confirm Export",
 | 
			
		||||
				JOptionPane.OK_CANCEL_OPTION
 | 
			
		||||
		);
 | 
			
		||||
		if (choice == JOptionPane.CANCEL_OPTION) {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		this.cancelExportButton.setEnabled(true);
 | 
			
		||||
		BookPagePasteListener pasteListener = new BookPagePasteListener(book, clipboard, this.bookPreviewPanel, this.cancelExportButton);
 | 
			
		||||
		this.bookPreviewPanel.enableNavigation(false);
 | 
			
		||||
		pasteListener.exportNextPage(); // Start by exporting the first page right away.
 | 
			
		||||
		try {
 | 
			
		||||
			// For catching native events, set logging here.
 | 
			
		||||
			Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
 | 
			
		||||
			logger.setLevel(Level.WARNING);
 | 
			
		||||
			logger.setUseParentHandlers(false);
 | 
			
		||||
			GlobalScreen.registerNativeHook();
 | 
			
		||||
			GlobalScreen.addNativeKeyListener(pasteListener);
 | 
			
		||||
		} catch (NativeHookException nativeHookException) {
 | 
			
		||||
			System.err.println("Could not register native hook.");
 | 
			
		||||
			nativeHookException.printStackTrace();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,125 +0,0 @@
 | 
			
		|||
package nl.andrewlalis.blockbookbinder.control;
 | 
			
		||||
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.model.Book;
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.view.BookPreviewPanel;
 | 
			
		||||
import org.jnativehook.GlobalScreen;
 | 
			
		||||
import org.jnativehook.NativeHookException;
 | 
			
		||||
import org.jnativehook.keyboard.NativeKeyEvent;
 | 
			
		||||
import org.jnativehook.keyboard.NativeKeyListener;
 | 
			
		||||
 | 
			
		||||
import javax.swing.*;
 | 
			
		||||
import java.awt.*;
 | 
			
		||||
import java.awt.datatransfer.Clipboard;
 | 
			
		||||
import java.awt.datatransfer.StringSelection;
 | 
			
		||||
import java.awt.event.ActionListener;
 | 
			
		||||
import java.awt.event.KeyEvent;
 | 
			
		||||
import java.awt.event.MouseEvent;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Listener that listens for native key-presses that indicate the user has
 | 
			
		||||
 * pasted something into a book.
 | 
			
		||||
 */
 | 
			
		||||
public class BookPagePasteListener implements NativeKeyListener {
 | 
			
		||||
	private final Book book;
 | 
			
		||||
	private final Clipboard clipboard;
 | 
			
		||||
	private final BookPreviewPanel bookPreviewPanel;
 | 
			
		||||
	private final JButton cancelExportButton;
 | 
			
		||||
	private final ActionListener cancelExportActionListener;
 | 
			
		||||
	private Robot robot;
 | 
			
		||||
	private int nextPage;
 | 
			
		||||
 | 
			
		||||
	public BookPagePasteListener(Book book, Clipboard clipboard, BookPreviewPanel bookPreviewPanel, JButton cancelExportButton) {
 | 
			
		||||
		this.book = book;
 | 
			
		||||
		this.clipboard = clipboard;
 | 
			
		||||
		this.bookPreviewPanel = bookPreviewPanel;
 | 
			
		||||
		this.cancelExportButton = cancelExportButton;
 | 
			
		||||
		this.nextPage = 0;
 | 
			
		||||
		this.cancelExportActionListener = (e) -> this.cancelExport();
 | 
			
		||||
		this.cancelExportButton.addActionListener(this.cancelExportActionListener);
 | 
			
		||||
		try {
 | 
			
		||||
			this.robot = new Robot();
 | 
			
		||||
		} catch (AWTException e) {
 | 
			
		||||
			e.printStackTrace();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void exportNextPage() {
 | 
			
		||||
		// Sleep a little bit to avoid rapid repeats.
 | 
			
		||||
		try {
 | 
			
		||||
			Thread.sleep(1000);
 | 
			
		||||
		} catch (InterruptedException e) {
 | 
			
		||||
			e.printStackTrace();
 | 
			
		||||
		}
 | 
			
		||||
		this.bookPreviewPanel.setCurrentPage(this.nextPage);
 | 
			
		||||
		boolean clipboardSuccess = false;
 | 
			
		||||
		while (!clipboardSuccess) {
 | 
			
		||||
			try {
 | 
			
		||||
				clipboard.setContents(
 | 
			
		||||
						new StringSelection(book.getPages().get(this.nextPage).toString()),
 | 
			
		||||
						null
 | 
			
		||||
				);
 | 
			
		||||
				clipboardSuccess = true;
 | 
			
		||||
			} catch (IllegalStateException e) {
 | 
			
		||||
				System.err.println("Could not open and set contents of system clipboard.");
 | 
			
		||||
			}
 | 
			
		||||
			if (!clipboardSuccess) {
 | 
			
		||||
				try {
 | 
			
		||||
					Thread.sleep(500);
 | 
			
		||||
				} catch (InterruptedException e) {
 | 
			
		||||
					e.printStackTrace();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		System.out.println("Copied page " + this.nextPage + " into clipboard.");
 | 
			
		||||
		this.nextPage++;
 | 
			
		||||
 | 
			
		||||
		// If we've reached the end of the book, unregister this listener and remove native hooks.
 | 
			
		||||
		if (this.nextPage >= this.book.getPageCount()) {
 | 
			
		||||
			this.cancelExport();
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Automatically do a CTRL+V and click the mouse to go to the next page.
 | 
			
		||||
		this.robot.keyPress(KeyEvent.VK_CONTROL);
 | 
			
		||||
		this.robot.keyPress(KeyEvent.VK_V);
 | 
			
		||||
		try {
 | 
			
		||||
			Thread.sleep(50);
 | 
			
		||||
		} catch (InterruptedException e) {
 | 
			
		||||
			e.printStackTrace();
 | 
			
		||||
		}
 | 
			
		||||
		this.robot.keyRelease(KeyEvent.VK_V);
 | 
			
		||||
		this.robot.keyRelease(KeyEvent.VK_CONTROL);
 | 
			
		||||
 | 
			
		||||
		this.robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK);
 | 
			
		||||
		this.robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void cancelExport() {
 | 
			
		||||
		try {
 | 
			
		||||
			this.bookPreviewPanel.enableNavigation(true);
 | 
			
		||||
			this.cancelExportButton.setEnabled(false);
 | 
			
		||||
			this.cancelExportButton.removeActionListener(this.cancelExportActionListener);
 | 
			
		||||
			GlobalScreen.removeNativeKeyListener(this);
 | 
			
		||||
			GlobalScreen.unregisterNativeHook();
 | 
			
		||||
			System.out.println("Done pasting.");
 | 
			
		||||
		} catch (NativeHookException nativeHookException) {
 | 
			
		||||
			System.err.println("Could not unregister a native hook.");
 | 
			
		||||
			nativeHookException.printStackTrace();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void nativeKeyTyped(NativeKeyEvent nativeKeyEvent) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void nativeKeyPressed(NativeKeyEvent nativeKeyEvent) {
 | 
			
		||||
		if (nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_V && (nativeKeyEvent.getModifiers() & NativeKeyEvent.CTRL_MASK) > 0) {
 | 
			
		||||
			this.exportNextPage();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void nativeKeyReleased(NativeKeyEvent nativeKeyEvent) {}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3,10 +3,13 @@ package nl.andrewlalis.blockbookbinder.control.export;
 | 
			
		|||
import lombok.Setter;
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.model.Book;
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.util.ApplicationProperties;
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.view.export.ExportStatusPanel;
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.view.export.ExportToBookDialog;
 | 
			
		||||
import org.jnativehook.GlobalScreen;
 | 
			
		||||
import org.jnativehook.NativeHookException;
 | 
			
		||||
 | 
			
		||||
import javax.sound.sampled.*;
 | 
			
		||||
import javax.swing.*;
 | 
			
		||||
import java.awt.*;
 | 
			
		||||
import java.awt.datatransfer.Clipboard;
 | 
			
		||||
import java.awt.datatransfer.StringSelection;
 | 
			
		||||
| 
						 | 
				
			
			@ -24,10 +27,10 @@ import java.util.logging.Logger;
 | 
			
		|||
public class BookExporter implements Runnable {
 | 
			
		||||
	private final static int START_DELAY = 10;
 | 
			
		||||
	private final static int CLIPBOARD_RETRY_DELAY_MS = 100;
 | 
			
		||||
	private final static int ROBOT_ACTION_DELAY_MS = 100;
 | 
			
		||||
 | 
			
		||||
	private final Book book;
 | 
			
		||||
	private final boolean autoPaste;
 | 
			
		||||
	private final int autoPasteDelay;
 | 
			
		||||
 | 
			
		||||
	@Setter
 | 
			
		||||
	private volatile boolean running;
 | 
			
		||||
| 
						 | 
				
			
			@ -39,13 +42,19 @@ public class BookExporter implements Runnable {
 | 
			
		|||
	private final Clipboard clipboard;
 | 
			
		||||
	private Robot robot;
 | 
			
		||||
 | 
			
		||||
	private final ExportStatusPanel statusPanel;
 | 
			
		||||
	private final ExportToBookDialog dialog;
 | 
			
		||||
 | 
			
		||||
	// Some sound clips to play as user feedback.
 | 
			
		||||
	private final Clip beepClip;
 | 
			
		||||
	private final Clip beginningExportClip;
 | 
			
		||||
 | 
			
		||||
	public BookExporter(Book book, boolean autoPaste) {
 | 
			
		||||
	public BookExporter(ExportToBookDialog dialog, ExportStatusPanel exportStatusPanel, Book book, boolean autoPaste, int autoPasteDelay) {
 | 
			
		||||
		this.dialog = dialog;
 | 
			
		||||
		this.statusPanel = exportStatusPanel;
 | 
			
		||||
		this.book = book;
 | 
			
		||||
		this.autoPaste = autoPaste;
 | 
			
		||||
		this.autoPasteDelay = autoPasteDelay;
 | 
			
		||||
		this.beepClip = this.loadAudioClip(ApplicationProperties.getProp("export_dialog.beep_sound"));
 | 
			
		||||
		this.beginningExportClip = this.loadAudioClip(ApplicationProperties.getProp("export_dialog.beginning_export"));
 | 
			
		||||
		this.clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
 | 
			
		||||
| 
						 | 
				
			
			@ -77,26 +86,30 @@ public class BookExporter implements Runnable {
 | 
			
		|||
			}
 | 
			
		||||
			// Otherwise, export one page.
 | 
			
		||||
			if (!inStartPhase && this.nextPageRequested) {
 | 
			
		||||
				System.out.println("Page requested: " + nextPageToExport);
 | 
			
		||||
				this.nextPageRequested = false; // Reset the flag so that some other process has to set it before the next page is exported.
 | 
			
		||||
				// If this is the first time we're exporting, play a sound.
 | 
			
		||||
				if (lastPageExportedAt == 0) {
 | 
			
		||||
					this.initStatusPanel();
 | 
			
		||||
					this.initNativeListener();
 | 
			
		||||
					this.playAudioClip(this.beginningExportClip);
 | 
			
		||||
				}
 | 
			
		||||
				this.exportPageToClipboard(nextPageToExport);
 | 
			
		||||
				if (this.autoPaste) {
 | 
			
		||||
					this.pasteAndTurnPage();
 | 
			
		||||
				} else {
 | 
			
		||||
					this.addStatusMessage("Waiting to detect a CTRL+V keypress...");
 | 
			
		||||
				}
 | 
			
		||||
				this.playAudioClip(this.beepClip);
 | 
			
		||||
				nextPageToExport++;
 | 
			
		||||
				this.updateStatusProgressBar(nextPageToExport);
 | 
			
		||||
				// If we've reached the end of the book, stop the exporter.
 | 
			
		||||
				if (nextPageToExport >= this.book.getPageCount()) {
 | 
			
		||||
					System.out.println("Export finished: " + this.book.getPageCount() + " pages exported.");
 | 
			
		||||
					this.addStatusMessage("Export finished: " + this.book.getPageCount() + " pages exported.");
 | 
			
		||||
					if (!this.autoPaste) {
 | 
			
		||||
						this.stopNativeListener();
 | 
			
		||||
					}
 | 
			
		||||
					this.running = false;
 | 
			
		||||
					this.updateStatusLabel("Export finished");
 | 
			
		||||
					SwingUtilities.invokeLater(dialog::onExportFinished);
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				// Since there may be significant delay, get a fresh timestamp.
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +145,7 @@ public class BookExporter implements Runnable {
 | 
			
		|||
				throw new RuntimeException("Could not insert page into clipboard after " + attempts + " attempts.");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		System.out.println("Exported page " + page + " to clipboard.");
 | 
			
		||||
		this.addStatusMessage("Exported page " + (page + 1) + " to clipboard.");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			@ -143,26 +156,26 @@ public class BookExporter implements Runnable {
 | 
			
		|||
		this.robot.keyPress(KeyEvent.VK_CONTROL);
 | 
			
		||||
		this.robot.keyPress(KeyEvent.VK_V);
 | 
			
		||||
		try {
 | 
			
		||||
			Thread.sleep(ROBOT_ACTION_DELAY_MS);
 | 
			
		||||
			Thread.sleep(this.autoPasteDelay);
 | 
			
		||||
		} catch (InterruptedException e) {
 | 
			
		||||
			e.printStackTrace();
 | 
			
		||||
		}
 | 
			
		||||
		this.robot.keyRelease(KeyEvent.VK_V);
 | 
			
		||||
		this.robot.keyRelease(KeyEvent.VK_CONTROL);
 | 
			
		||||
		System.out.println("Pasted.");
 | 
			
		||||
		this.addStatusMessage("Pasted page into book.");
 | 
			
		||||
		this.robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK);
 | 
			
		||||
		try {
 | 
			
		||||
			Thread.sleep(ROBOT_ACTION_DELAY_MS);
 | 
			
		||||
			Thread.sleep(this.autoPasteDelay);
 | 
			
		||||
		} catch (InterruptedException e) {
 | 
			
		||||
			e.printStackTrace();
 | 
			
		||||
		}
 | 
			
		||||
		this.robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK);
 | 
			
		||||
		try { // Wait for minecraft to turn the page.
 | 
			
		||||
			Thread.sleep(ROBOT_ACTION_DELAY_MS);
 | 
			
		||||
			Thread.sleep(this.autoPasteDelay);
 | 
			
		||||
		} catch (InterruptedException e) {
 | 
			
		||||
			e.printStackTrace();
 | 
			
		||||
		}
 | 
			
		||||
		System.out.println("Clicked mouse.");
 | 
			
		||||
		this.addStatusMessage("Clicked to turn the page.");
 | 
			
		||||
		this.nextPageRequested = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -211,4 +224,34 @@ public class BookExporter implements Runnable {
 | 
			
		|||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void initStatusPanel() {
 | 
			
		||||
		SwingUtilities.invokeLater(() -> {
 | 
			
		||||
			JProgressBar bar = this.statusPanel.getExportProgressBar();
 | 
			
		||||
			bar.setMinimum(0);
 | 
			
		||||
			bar.setMaximum(this.book.getPageCount());
 | 
			
		||||
			bar.setStringPainted(true);
 | 
			
		||||
			this.updateStatusProgressBar(0);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void updateStatusLabel(String text) {
 | 
			
		||||
		SwingUtilities.invokeLater(() -> {
 | 
			
		||||
			this.statusPanel.getStatusLabel().setText(text);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void updateStatusProgressBar(int nextPage) {
 | 
			
		||||
		SwingUtilities.invokeLater(() -> {
 | 
			
		||||
			JProgressBar bar = this.statusPanel.getExportProgressBar();
 | 
			
		||||
			bar.setValue(nextPage);
 | 
			
		||||
			bar.setString(String.format("%d of %d pages exported", nextPage, this.book.getPageCount()));
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void addStatusMessage(String message) {
 | 
			
		||||
		SwingUtilities.invokeLater(() -> {
 | 
			
		||||
			this.statusPanel.getOutputTextArea().append(message + "\n");
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
package nl.andrewlalis.blockbookbinder.view;
 | 
			
		||||
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.control.BookExportActionListener;
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.control.ImportAction;
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.model.Book;
 | 
			
		||||
import nl.andrewlalis.blockbookbinder.util.ApplicationProperties;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
package nl.andrewlalis.blockbookbinder.view.export;
 | 
			
		||||
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
 | 
			
		||||
import javax.swing.*;
 | 
			
		||||
import java.awt.*;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -8,11 +10,29 @@ import java.awt.*;
 | 
			
		|||
 * job.
 | 
			
		||||
 */
 | 
			
		||||
public class ExportStatusPanel extends JPanel {
 | 
			
		||||
	private JProgressBar exportProgressBar;
 | 
			
		||||
	@Getter
 | 
			
		||||
	private final JLabel statusLabel;
 | 
			
		||||
	@Getter
 | 
			
		||||
	private final JTextArea outputTextArea;
 | 
			
		||||
	@Getter
 | 
			
		||||
	private final JProgressBar exportProgressBar;
 | 
			
		||||
 | 
			
		||||
	public ExportStatusPanel() {
 | 
			
		||||
		this.setLayout(new BorderLayout());
 | 
			
		||||
 | 
			
		||||
		this.statusLabel = new JLabel("Exporting...");
 | 
			
		||||
		this.add(this.statusLabel, BorderLayout.NORTH);
 | 
			
		||||
 | 
			
		||||
		this.outputTextArea = new JTextArea();
 | 
			
		||||
		this.outputTextArea.setEditable(false);
 | 
			
		||||
		this.outputTextArea.setLineWrap(true);
 | 
			
		||||
		this.outputTextArea.setWrapStyleWord(true);
 | 
			
		||||
		this.outputTextArea.setAutoscrolls(true);
 | 
			
		||||
		JScrollPane scrollPane = new JScrollPane(this.outputTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
 | 
			
		||||
		scrollPane.setAutoscrolls(true);
 | 
			
		||||
		this.add(scrollPane, BorderLayout.CENTER);
 | 
			
		||||
 | 
			
		||||
		this.exportProgressBar = new JProgressBar();
 | 
			
		||||
		this.add(this.exportProgressBar, BorderLayout.SOUTH);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@ public class ExportToBookDialog extends JDialog {
 | 
			
		|||
	private JCheckBox autoCheckbox;
 | 
			
		||||
	private JSpinner firstPageSpinner;
 | 
			
		||||
	private JSpinner lastPageSpinner;
 | 
			
		||||
	private JSpinner autoPasteDelaySpinner;
 | 
			
		||||
 | 
			
		||||
	private JButton startButton;
 | 
			
		||||
	private JButton stopButton;
 | 
			
		||||
| 
						 | 
				
			
			@ -54,10 +55,21 @@ public class ExportToBookDialog extends JDialog {
 | 
			
		|||
		setupPanel.setLayout(new BoxLayout(setupPanel, BoxLayout.PAGE_AXIS));
 | 
			
		||||
		this.autoCheckbox = new JCheckBox("Auto-paste", true);
 | 
			
		||||
		this.firstPageSpinner = new JSpinner(new SpinnerNumberModel(1, 1, this.book.getPageCount(), 1));
 | 
			
		||||
		JPanel firstPageSpinnerPanel = new JPanel(new BorderLayout());
 | 
			
		||||
		firstPageSpinnerPanel.add(new JLabel("First Page:"), BorderLayout.WEST);
 | 
			
		||||
		firstPageSpinnerPanel.add(this.firstPageSpinner, BorderLayout.CENTER);
 | 
			
		||||
		this.lastPageSpinner = new JSpinner(new SpinnerNumberModel(this.book.getPageCount(), 1, this.book.getPageCount(), 1));
 | 
			
		||||
		JPanel lastPageSpinnerPanel = new JPanel(new BorderLayout());
 | 
			
		||||
		lastPageSpinnerPanel.add(new JLabel("Last Page:"), BorderLayout.WEST);
 | 
			
		||||
		lastPageSpinnerPanel.add(this.lastPageSpinner, BorderLayout.CENTER);
 | 
			
		||||
		this.autoPasteDelaySpinner = new JSpinner(new SpinnerNumberModel(0.2, 0.1, 5.0, 0.1));
 | 
			
		||||
		JPanel autoPasteDelaySpinnerPanel = new JPanel(new BorderLayout());
 | 
			
		||||
		autoPasteDelaySpinnerPanel.add(new JLabel("Auto-Paste Delay (s):"), BorderLayout.WEST);
 | 
			
		||||
		autoPasteDelaySpinnerPanel.add(this.autoPasteDelaySpinner, BorderLayout.CENTER);
 | 
			
		||||
		setupPanel.add(this.autoCheckbox);
 | 
			
		||||
		setupPanel.add(this.firstPageSpinner);
 | 
			
		||||
		setupPanel.add(this.lastPageSpinner);
 | 
			
		||||
		setupPanel.add(firstPageSpinnerPanel);
 | 
			
		||||
		setupPanel.add(lastPageSpinnerPanel);
 | 
			
		||||
		setupPanel.add(autoPasteDelaySpinnerPanel);
 | 
			
		||||
 | 
			
		||||
		this.exportStatusPanel = new ExportStatusPanel();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +83,9 @@ public class ExportToBookDialog extends JDialog {
 | 
			
		|||
		JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
 | 
			
		||||
		this.startButton = new JButton("Start");
 | 
			
		||||
		this.startButton.addActionListener(e -> {
 | 
			
		||||
			if (!this.checkSpinnerValues()){
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			int choice = JOptionPane.showConfirmDialog(
 | 
			
		||||
					this.rootPane,
 | 
			
		||||
					"Exporting will begin after roughly 10 seconds.\n" +
 | 
			
		||||
| 
						 | 
				
			
			@ -97,21 +112,36 @@ public class ExportToBookDialog extends JDialog {
 | 
			
		|||
		return mainPanel;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Starts up the exporter thread.
 | 
			
		||||
	 */
 | 
			
		||||
	private void startExporter() {
 | 
			
		||||
		final int firstPage = (int) this.firstPageSpinner.getValue();
 | 
			
		||||
		final int lastPage = (int) this.lastPageSpinner.getValue();
 | 
			
		||||
		final Book pagesRange = this.book.getPageRange(firstPage - 1, lastPage - firstPage + 1);
 | 
			
		||||
 | 
			
		||||
		final double autoPasteDelay = (double) this.autoPasteDelaySpinner.getValue();
 | 
			
		||||
		final int autoPasteDelayMillis = (int) (autoPasteDelay * 1000);
 | 
			
		||||
 | 
			
		||||
		this.startButton.setEnabled(false);
 | 
			
		||||
		this.startButton.setVisible(false);
 | 
			
		||||
		this.stopButton.setEnabled(true);
 | 
			
		||||
		this.stopButton.setVisible(true);
 | 
			
		||||
		this.showCardByName(STATUS_CARD);
 | 
			
		||||
		this.exporterRunnable = new BookExporter(pagesRange, this.autoCheckbox.isSelected());
 | 
			
		||||
		this.exporterRunnable = new BookExporter(
 | 
			
		||||
				this,
 | 
			
		||||
				this.exportStatusPanel,
 | 
			
		||||
				pagesRange,
 | 
			
		||||
				this.autoCheckbox.isSelected(),
 | 
			
		||||
				autoPasteDelayMillis
 | 
			
		||||
		);
 | 
			
		||||
		this.exporterThread = new Thread(this.exporterRunnable);
 | 
			
		||||
		this.exporterThread.start();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Shuts down the exporter thread.
 | 
			
		||||
	 */
 | 
			
		||||
	private void stopExporter() {
 | 
			
		||||
		this.exporterRunnable.setRunning(false);
 | 
			
		||||
		try {
 | 
			
		||||
| 
						 | 
				
			
			@ -126,8 +156,49 @@ public class ExportToBookDialog extends JDialog {
 | 
			
		|||
		this.startButton.setVisible(true);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * This method is called by the exporter thread once it is done.
 | 
			
		||||
	 */
 | 
			
		||||
	public void onExportFinished() {
 | 
			
		||||
		JOptionPane.showMessageDialog(
 | 
			
		||||
				this,
 | 
			
		||||
				"Book export has finished.",
 | 
			
		||||
				"Export Complete",
 | 
			
		||||
				JOptionPane.INFORMATION_MESSAGE
 | 
			
		||||
		);
 | 
			
		||||
		this.stopExporter();
 | 
			
		||||
		this.dispose();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void showCardByName(String name) {
 | 
			
		||||
		CardLayout cl = (CardLayout) this.centerCardPanel.getLayout();
 | 
			
		||||
		cl.show(this.centerCardPanel, name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Checks the values of the spinners that are used to select the first and
 | 
			
		||||
	 * last pages, and shows a popup warning if they're not correct.
 | 
			
		||||
	 */
 | 
			
		||||
	private boolean checkSpinnerValues() {
 | 
			
		||||
		final int firstPage = (int) this.firstPageSpinner.getValue();
 | 
			
		||||
		final int lastPage = (int) this.lastPageSpinner.getValue();
 | 
			
		||||
 | 
			
		||||
		if (
 | 
			
		||||
				firstPage < 1
 | 
			
		||||
				|| lastPage > this.book.getPageCount()
 | 
			
		||||
				|| firstPage > lastPage
 | 
			
		||||
				|| (lastPage - firstPage + 1 > ApplicationProperties.getIntProp("book.max_pages"))
 | 
			
		||||
		) {
 | 
			
		||||
			JOptionPane.showMessageDialog(
 | 
			
		||||
					this,
 | 
			
		||||
					"Invalid page range. Please follow the rules below:\n" +
 | 
			
		||||
							"1. First page must be lower or equal to the last page.\n" +
 | 
			
		||||
							"2. Number of pages to export cannot exceed 100.\n",
 | 
			
		||||
					"Invalid Page Range",
 | 
			
		||||
					JOptionPane.WARNING_MESSAGE
 | 
			
		||||
			);
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue