Browse Source

Belegscanner ist jetzt wieder funktionial, aber folgende Funktionen fehlen noch:

- aktuelle Einstellungen werden beim Scannen nicht gespeichert
- Seitenzähler wird nicht direkt beim reaktivieren des Scan-Buttons hochgezählt, sondern erst wenn die komplette Verarbeitung der aktuellen Seite durch ist

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
main
Stephan Richter 10 months ago
parent
commit
484d2855a0
  1. 315
      src/main/java/de/srsoftware/belegscanner/Worker.java
  2. 108
      src/main/java/de/srsoftware/belegscanner/gui/DocTable.java
  3. 13
      src/main/java/de/srsoftware/belegscanner/gui/FormatSelector.java
  4. 11
      src/main/java/de/srsoftware/belegscanner/gui/ImproveSelector.java
  5. 58
      src/main/java/de/srsoftware/belegscanner/gui/MainFrame.java
  6. 7
      src/main/java/de/srsoftware/belegscanner/gui/Preview.java
  7. 28
      src/main/java/de/srsoftware/belegscanner/gui/ResolutionSelector.java
  8. 48
      src/main/java/de/srsoftware/belegscanner/gui/RotationSelector.java
  9. 18
      src/main/java/de/srsoftware/belegscanner/gui/Toolbar.java
  10. 47
      src/main/java/de/srsoftware/belegscanner/model/ScanProject.java
  11. 9
      src/main/java/de/srsoftware/belegscanner/model/api/Project.java

315
src/main/java/de/srsoftware/belegscanner/Worker.java

@ -1,9 +1,10 @@ @@ -1,9 +1,10 @@
package de.srsoftware.belegscanner;
import de.srsoftware.belegscanner.gui.DocTable;
import de.srsoftware.belegscanner.gui.MainFrame;
import de.srsoftware.belegscanner.gui.StatusBar;
import de.srsoftware.belegscanner.gui.Toolbar;
import de.srsoftware.belegscanner.model.ScanProject;
import de.srsoftware.belegscanner.model.api.Page;
import de.srsoftware.belegscanner.model.api.Project;
import de.srsoftware.tools.gui.DateChooser;
import de.srsoftware.tools.gui.SelectComboBox;
@ -12,8 +13,13 @@ import org.slf4j.Logger; @@ -12,8 +13,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Optional;
import java.util.Vector;
import static de.srsoftware.belegscanner.Application.main;
import static de.srsoftware.belegscanner.Application.t;
import static de.srsoftware.belegscanner.Constants.CONFIG_TARGET;
import static de.srsoftware.belegscanner.Constants.JPG;
@ -23,15 +29,20 @@ import static de.srsoftware.belegscanner.Constants.PDF; @@ -23,15 +29,20 @@ import static de.srsoftware.belegscanner.Constants.PDF;
public class Worker {
private static final Logger LOG = LoggerFactory.getLogger(Worker.class);
private static final String HOME = System.getProperty("user.home");
private static final String YEAR = t("YEAR");
private static final String PAGE = t(Constants.PAGE);
private final Configuration config;
private SelectComboBox pathPicker;
private StatusBar statusBar;
private String category;
private DateChooser datePicker;
private String rawPath, resolvedPath;
private String category,rawPath, resolvedPath;
private Toolbar toolbar;
private DocTable docTable;
private boolean improveBrightness,scanning;
private int resolution;
private Dimension dimension;
private String mode = "Color";
private MainFrame mainFrame;
private int rotationAngle;
public Worker(Configuration config) {
this.config = config;
@ -72,7 +83,7 @@ public class Worker { @@ -72,7 +83,7 @@ public class Worker {
if (end>start+1){
var variable = resolvedPath.substring(start+1, end);
LOG.debug("…unresolved '{}'",variable);
String value = toolbar.requireField(variable);
var value = PAGE.equals(variable) ? "["+variable+"]":toolbar.requireField(variable);
variable = "$"+variable;
LOG.debug("replacing '{}' in '{}' by '{}'",variable,resolvedPath,value);
resolvedPath = resolvedPath.replace(variable,value);
@ -82,8 +93,7 @@ public class Worker { @@ -82,8 +93,7 @@ public class Worker {
}
}
toolbar.dropUnusedAdditionalFields();
resolvedPath+="."+extension();
statusBar.setPath(resolvedPath);
statusBar.setPath(resolvedPath+"."+extension());
}
private String extension() {
@ -106,16 +116,235 @@ public class Worker { @@ -106,16 +116,235 @@ public class Worker {
}
public void scan() {
new Thread(this::performScan).start();
}
private void performScan(){
LOG.debug("scan()");
var project = docTable.getProject(resolvedPath).orElseGet(this::createProject);
var project = docTable.getProject(resolvedPath).orElseGet(() -> docTable.createProject(resolvedPath));
int rotation = this.rotationAngle;
File targetFile = prepareProject(project);
var type = getType();
scanJpeg(targetFile,project);
improveJpeg(targetFile,project,rotation);
if (JPG.equals(type)) {
docTable.setState(project, t("Image scanned"));
var page = project.addPage(new File(targetFile+".jpg"));
preview(page);
return;
};
mainFrame.preview(new File(targetFile+".jpg"));
convertToPdf(targetFile,type, project);
if (PDF.equals(type)) {
var page = project.addPage(new File(targetFile+".pdf"));
docTable.setState(project, t("PDF created"));
preview(page);
return;
}
performTextRecognition(targetFile,project);
var page = project.addPage(new File(targetFile+".pdf"));
preview(page);
}
private void performTextRecognition(File targetFile, Project project) {
String pdf = targetFile.getName() + ".tmp.pdf";
String ocr = targetFile.getName() + ".pdf";
File folder = targetFile.getParentFile();
var cmd = new Vector<String>();
cmd.add("pdfsandwich");
cmd.add("-lang");
cmd.add("deu");
cmd.add("-rgb");
if (resolution>300) {
cmd.add("-resolution");
cmd.add(""+resolution);
}
cmd.add("-o");
cmd.add(ocr);
cmd.add(pdf);
LOG.debug("executing {}",cmd);
var builder = new ProcessBuilder(cmd);
builder.directory(folder);
try {
Process process = builder.start();
docTable.setState(project,t("Text recognition…"));
int errorCode = process.waitFor();
if (errorCode != 0) {
LOG.error("error code: {} for {}",errorCode,cmd);
docTable.setState(project, t("OCR failed."));
return;
}
if (!folder.toPath().resolve(ocr).toFile().exists()){
docTable.setState(project,t("OCR failed."));
return;
}
} catch (InterruptedException | IOException e) {
LOG.error("{} terminated: ",builder,e);
}
LOG.debug("removing {}",pdf);
folder.toPath().resolve(pdf).toFile().delete();
docTable.setState(project,t("Finished text recognition."));
}
private void convertToPdf(File targetFile, String type, Project project) {
var extension = PDF.equals(type) ? ".pdf" : ".tmp.pdf";
var raw = rawFile(targetFile);
String pdf = targetFile.getName() + extension;
File folder = targetFile.getParentFile();
var cmd = new Vector<String>();
cmd.add("convert");
cmd.add(raw);
cmd.add(pdf);
var builder = new ProcessBuilder(cmd);
builder.directory(folder);
try {
Process process = builder.start();
docTable.setState(project,t("Converting to PDF…"));
int errorCode = process.waitFor();
if (errorCode != 0) {
LOG.error("Error code: {} for {}",errorCode,cmd);
docTable.setState(project, t("Conversion failed."));
return;
}
} catch (InterruptedException | IOException e) {
LOG.error("{} terminated: ",builder,e);
}
LOG.debug("removing {}",raw);
folder.toPath().resolve(raw).toFile().delete();
}
private Project createProject() {
return new ScanProject(resolvedPath);
private String rawFile(File targetFile) {
return targetFile.getName()+".jpg";
}
private void improveJpeg(File target, Project project, int rotation) {
var raw = rawFile(target);
File folder = target.getParentFile();
if (improveBrightness) {
Vector<String> cmd = new Vector<>();
cmd.add("mogrify");
cmd.add("-contrast-stretch");
cmd.add("0x60%");
cmd.add(raw);
var builder = new ProcessBuilder(cmd);
builder.directory(folder);
try {
Process process = builder.start();
docTable.setState(project,t("Adjusting brightness…"));
int errorCode = process.waitFor();
if (errorCode != 0) {
LOG.error(t("Error code: {} for {}"),errorCode,cmd);
docTable.setState(project, t("Adjustment failed."));
setScanning(false);
return;
}
} catch (InterruptedException | IOException e) {
LOG.error(t("{} terminated: "),builder,e);
}
}
if (rotation != 0){
Vector<String> cmd = new Vector<>();
cmd.add("mogrify");
cmd.add("-rotate");
cmd.add(""+rotation);
cmd.add(raw);
var builder = new ProcessBuilder(cmd);
builder.directory(folder);
try {
Process process = builder.start();
docTable.setState(project,t("Rotating image…"));
int errorCode = process.waitFor();
if (errorCode != 0) {
LOG.error(t("Error code: {} for {}"),errorCode,cmd);
docTable.setState(project, t("Rotation failed."));
setScanning(false);
return;
}
} catch (InterruptedException | IOException e) {
LOG.error(t("{} terminated: "),builder,e);
}
}
}
private File prepareProject(Project project) {
var targetFile = project.nextFile();
docTable.setState(project,t("Scanning…"));
LOG.debug("scanning as {}",targetFile);
File folder = targetFile.getParentFile();
if (!folder.exists()) {
LOG.warn(t("Path '{}' does not exist!"),folder);
folder.mkdirs();
}
return targetFile;
}
private void scanJpeg(File targetFile, Project project) {
setScanning(true);
LOG.debug("scanning as {}",targetFile);
File folder = targetFile.getParentFile();
if (!folder.exists()) {
LOG.warn(t("Path '{}' does not exist!"),folder);
folder.mkdirs();
}
var raw = rawFile(targetFile);
Vector<String> cmd = new Vector<>();
cmd.add("scanimage");
cmd.add("-x");
cmd.add(dimension.width+"");
cmd.add("-y");
cmd.add(dimension.height+"");
cmd.add("--mode");
cmd.add(mode);
cmd.add("--resolution");
cmd.add(resolution+"");
cmd.add("-o");
cmd.add(raw);
LOG.debug("executing {}",cmd);
ProcessBuilder builder = new ProcessBuilder(cmd);
builder.directory(folder);
try {
Process process = builder.start();
docTable.setState(project,t("Scanning…"));
int errorCode = process.waitFor();
if (errorCode != 0) {
LOG.error(t("Error code: {} for {}"),errorCode,cmd);
docTable.setState(project, t("Scan failed."));
setScanning(false);
throw new RuntimeException(t("Scanning failed, error code = {}",errorCode));
}
} catch (InterruptedException | IOException e) {
LOG.error(t("{} terminated: "),builder,e);
}
setScanning(false);
}
public void preview(Page page) {
mainFrame.preview(page == null ? null : page.file());
}
private void setScanning(boolean isScanning) {
scanning = isScanning;
if (scanning) {
toolbar.disableScan();
} else {
toolbar.enableScan();
}
}
public void setDimension(Dimension dimension) {
LOG.debug("setDimension({})",dimension);
this.dimension = dimension;
}
public void setPath(String path) {
@ -163,4 +392,70 @@ public class Worker { @@ -163,4 +392,70 @@ public class Worker {
public void setDocTable(DocTable docTable) {
this.docTable = docTable;
}
public int setResolution(int resolution) {
return this.resolution = resolution;
}
public void setImproveBrightness(boolean newValue) {
improveBrightness = newValue;
}
public Worker setMainFrame(MainFrame mainFrame) {
this.mainFrame = mainFrame;
return this;
}
public void setRotation(int angle) {
LOG.debug("setRotation({})",angle);
rotationAngle = angle;
}
public void join(Project project) {
File targetFile = prepareProject(project);
File folder = targetFile.getParentFile();
var cmd = new Vector<String>();
cmd.add("pdftk");
var pages = project.pages();
Integer firstPage = null;
Integer lastPage = null;
int count = 0;
var joined = new ArrayList<Page>();
for (var page : pages){
count++;
var name = page.file().getName();
if (name.toLowerCase().endsWith(".pdf")) {
if (firstPage == null) firstPage = count;
lastPage = count;
cmd.add(name);
joined.add(page);
}
}
cmd.add("cat");
cmd.add("output");
File joinedPDF = new File(project.pattern().replace("["+PAGE+"]",firstPage+"…"+lastPage+".pdf"));
String target = joinedPDF.getName();
cmd.add(target);
LOG.debug("executing {}",cmd);
var builder = new ProcessBuilder(cmd);
builder.directory(folder);
try {
Process process = builder.start();
docTable.setState(project,t("Joining pdfs…"));
int errorCode = process.waitFor();
if (errorCode != 0) {
LOG.error("error code: {} for {}",errorCode,cmd);
docTable.setState(project, t("OCR failed."));
return;
}
} catch (InterruptedException | IOException e) {
LOG.error("{} terminated: ",builder,e);
}
joined.stream().map(Page::file).forEach(File::delete);
pages.removeAll(joined);
docTable.setState(project,t("PDFs joined."));
preview(project.addPage(joinedPDF));
}
}

108
src/main/java/de/srsoftware/belegscanner/gui/DocTable.java

@ -2,24 +2,20 @@ package de.srsoftware.belegscanner.gui; @@ -2,24 +2,20 @@ package de.srsoftware.belegscanner.gui;
import static de.srsoftware.belegscanner.Application.t;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.*;
import java.awt.event.ActionListener;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.*;
import javax.swing.border.MatteBorder;
import de.srsoftware.belegscanner.Worker;
import de.srsoftware.belegscanner.listeners.ProjectListener;
import de.srsoftware.belegscanner.model.ScanProject;
import de.srsoftware.belegscanner.model.api.Project;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -36,6 +32,7 @@ public class DocTable extends JPanel{ @@ -36,6 +32,7 @@ public class DocTable extends JPanel{
private static FilenameFilter PAGES = (dir,name) -> name.toLowerCase().endsWith("pdf") && name.toLowerCase().contains("page");
private static int rowCounter = 0;
private static Font btnFont = new Font("Arial", Font.PLAIN, 28);
private final Worker worker;
private List<Project> projects = new ArrayList<>();
@ -44,12 +41,78 @@ public class DocTable extends JPanel{ @@ -44,12 +41,78 @@ public class DocTable extends JPanel{
private static final long serialVersionUID = 1073955198529023744L;
private GridBagConstraints constraints;
private final HashMap<String,Row> rows = new HashMap<>();
private class Row{
private JLabel status;
private JLabel pathLabel;
private JPanel buttons;
private Project project;
private JButton joinButton;
public Row(Project project) {
this.project = project;
rows.put(project.pattern(), this);
constraints.gridy = ++rowCounter;
constraints.gridx = 0;
add(pathLabel = new JLabel(project.nextFile().getParent()), constraints);
constraints.gridx = 1;
add(status = new JLabel("neu"),constraints);
buttons = new JPanel();
buttons.setLayout(new FlowLayout());
buttons.add(button("⚁",t("open folder"),ev -> project.openDir()));
buttons.add(joinButton = button("⎗",t("join PDFs"),ev -> worker.join(project)));
buttons.add(button("✉",t("display preview"),ev -> worker.preview(project.lastPage())));
buttons.add(button("✓",t("done"),ev -> drop(this)));
buttons.add(button("❌",t("drop last page"),ev -> worker.preview(project.dropLastPage().lastPage())));
constraints.gridx = 2;
add(buttons,constraints);
}
/**
* drop the selected document from the table
* @param row
*/
private void drop(Row row) {
if (row.joinButton.isEnabled()) project.join();
remove(pathLabel);
remove(status);
remove(buttons);
invalidate();
repaint();
rows.remove(project.pattern());
projects.remove(project);
}
/**
* update status for selected document
* @param status
* @return
*/
public Row status(String status) {
this.status.setText(status);
return this;
}
/**
* remove the join button assigned with the selected document
*/
public void setJoinButton(boolean enabled) {
joinButton.setEnabled(enabled);
joinButton.setVisible(enabled);
}
}
/**
* create a new DocTable
*/
public DocTable(Worker worker) {
setLayout(new GridBagLayout());
this.worker = worker;
worker.setDocTable(this);
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
@ -70,7 +133,34 @@ public class DocTable extends JPanel{ @@ -70,7 +133,34 @@ public class DocTable extends JPanel{
add(actions,constraints);
}
/**
* helper method to create a button with given label, tooltip and action listener
* @param label
* @param tooltip
* @param listener
* @return
*/
private static JButton button(String label, String tooltip, ActionListener listener) {
JButton btn = new JButton(label);
btn.setFont(btnFont);
btn.setToolTipText(tooltip);
btn.addActionListener(listener);
return btn;
}
public Project createProject(String resolvedPath) {
var project = new ScanProject(resolvedPath);
new Row(project);
projects.add(project);
return project;
}
public Optional<Project> getProject(String resolvedPath) {
return projects.stream().filter(p -> resolvedPath.equals(p.pattern())).findAny();
}
public void setState(Project project, String status) {
var row = rows.get(project.pattern());
if (row != null) row.status.setText(status);
}
}

13
src/main/java/de/srsoftware/belegscanner/gui/FormatSelector.java

@ -18,9 +18,11 @@ import static java.awt.BorderLayout.WEST; @@ -18,9 +18,11 @@ import static java.awt.BorderLayout.WEST;
public class FormatSelector extends JPanel {
private static final Logger LOG = LoggerFactory.getLogger(FormatSelector.class);
private final JTextField height, width;
private final Worker worker;
public FormatSelector(Worker worker){
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
this.worker = worker;
JPanel widthSelector = new JPanel();
widthSelector.setLayout(new BorderLayout());
widthSelector.setMaximumSize(new Dimension(600, 40));
@ -44,9 +46,7 @@ public class FormatSelector extends JPanel { @@ -44,9 +46,7 @@ public class FormatSelector extends JPanel {
public void keyReleased(KeyEvent e) {
LOG.debug("updateDimensions()");
try {
int w = Integer.parseInt(width.getText().trim());
int h = Integer.parseInt(height.getText().trim());
worker.setDimension(new Dimension(w < 0 ? 0 : w, h < 0 ? 0 : h));
updateDim();
} catch (NumberFormatException nfe) {
LOG.warn("Invalid dimensions!");
}
@ -55,5 +55,12 @@ public class FormatSelector extends JPanel { @@ -55,5 +55,12 @@ public class FormatSelector extends JPanel {
width.addKeyListener(dimensionListener);
height.addKeyListener(dimensionListener);
updateDim();
}
private void updateDim() {
int w = Integer.parseInt(width.getText().trim());
int h = Integer.parseInt(height.getText().trim());
worker.setDimension(new Dimension(w < 0 ? 0 : w, h < 0 ? 0 : h));
}
}

11
src/main/java/de/srsoftware/belegscanner/gui/ImproveSelector.java

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
package de.srsoftware.belegscanner.gui;
import de.srsoftware.belegscanner.Worker;
import javax.swing.*;
import java.awt.*;
@ -11,7 +13,7 @@ public class ImproveSelector extends JPanel { @@ -11,7 +13,7 @@ public class ImproveSelector extends JPanel {
private boolean improveBrightness;
public ImproveSelector() {
public ImproveSelector(Worker worker) {
super(new BorderLayout());
ButtonGroup group = new ButtonGroup();
add(new JLabel(t("Adjustments")), NORTH);
@ -19,11 +21,8 @@ public class ImproveSelector extends JPanel { @@ -19,11 +21,8 @@ public class ImproveSelector extends JPanel {
add(checkbox,WEST);
setMaximumSize(new Dimension(600,200));
checkbox.addActionListener(e -> {
improveBrightness = checkbox.isSelected();
});
}
worker.setImproveBrightness(checkbox.isSelected());
public boolean improveBrightness(){
return improveBrightness;
});
}
}

58
src/main/java/de/srsoftware/belegscanner/gui/MainFrame.java

@ -3,9 +3,11 @@ package de.srsoftware.belegscanner.gui; @@ -3,9 +3,11 @@ package de.srsoftware.belegscanner.gui;
import de.srsoftware.belegscanner.Configuration;
import de.srsoftware.belegscanner.Worker;
import org.icepdf.ri.common.SwingController;
import org.icepdf.ri.common.views.DocumentViewController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.ByteArrayOutputStream;
@ -13,6 +15,7 @@ import java.io.File; @@ -13,6 +15,7 @@ import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
@ -48,6 +51,7 @@ public class MainFrame extends JFrame { @@ -48,6 +51,7 @@ public class MainFrame extends JFrame {
private static final String POLICY_FILE = "/etc/ImageMagick-6/policy.xml";
private final Worker worker;
private JComponent previewComponent;
private StatusBar statusBar;
private Toolbar toolbar;
@ -70,7 +74,7 @@ public class MainFrame extends JFrame { @@ -70,7 +74,7 @@ public class MainFrame extends JFrame {
private Dimension dimension = new Dimension(209, 297);
private JPanel pdfPreview;
private Preview pdfPreview;
/**
* Create application main frame.
@ -79,13 +83,13 @@ public class MainFrame extends JFrame { @@ -79,13 +83,13 @@ public class MainFrame extends JFrame {
public MainFrame(Configuration config) {
super("BelegScanner");
setLayout(new BorderLayout());
worker = new Worker(config);
worker = new Worker(config).setMainFrame(this);
add(toolbar = new Toolbar(worker),BorderLayout.EAST);
add(statusBar = new StatusBar(worker),BorderLayout.SOUTH);
add(docTable = new DocTable(worker),BorderLayout.NORTH);
add(pdfPreview = new Preview(worker),BorderLayout.CENTER);
previewComponent = pdfPreview;
int x = config.getOrCreate(APP_X, 20);
int y = config.getOrCreate(APP_Y, 20);
setLocation(new Point(x, y));
@ -196,4 +200,52 @@ public class MainFrame extends JFrame { @@ -196,4 +200,52 @@ public class MainFrame extends JFrame {
JOptionPane.WARNING_MESSAGE);
System.exit(-1);
}
/**
* open file in preview panel
* @param filePath
*/
public void preview(File file) {
SwingUtilities.invokeLater(() -> {
if (file == null){
if (previewComponent != null) remove(previewComponent);
previewComponent = null;
return;
}
String filename = file.toString();
if (filename.toLowerCase().endsWith("pdf")) {
if (previewComponent != pdfPreview) {
if (previewComponent != null) remove(previewComponent);
previewComponent = pdfPreview;
add(previewComponent,BorderLayout.CENTER);
pack();
}
pdfPreview.show(filename);
}
if (filename.toLowerCase().endsWith("jpg")) {
try {
Image img = ImageIO.read(file);
if (previewComponent != null) {
remove(previewComponent);
Dimension dim = previewComponent.getSize();
double w = img.getWidth(null);
double h = img.getHeight(null);
double factor = Math.min(dim.width/w, dim.height/h);
if (factor != 1.0) img = img.getScaledInstance((int)(w*factor), (int)(h*factor), Image.SCALE_DEFAULT);
}
ImageIcon icon = new ImageIcon(img);
JLabel label = new JLabel(icon);
previewComponent = label;
this.add(previewComponent, BorderLayout.CENTER);
pack();
} catch (IOException e) {
LOG.error("Was not able to preview {}:",file,e);
}
}
});
}
}

7
src/main/java/de/srsoftware/belegscanner/gui/Preview.java

@ -4,9 +4,11 @@ import de.srsoftware.belegscanner.Worker; @@ -4,9 +4,11 @@ import de.srsoftware.belegscanner.Worker;
import org.icepdf.ri.common.ComponentKeyBinding;
import org.icepdf.ri.common.SwingController;
import org.icepdf.ri.common.SwingViewBuilder;
import org.icepdf.ri.common.views.DocumentViewController;
import javax.swing.*;
import java.awt.*;
import java.nio.file.Path;
public class Preview extends JPanel {
private final SwingController pdfViewer;
@ -31,4 +33,9 @@ public class Preview extends JPanel { @@ -31,4 +33,9 @@ public class Preview extends JPanel {
add(fileName = new JLabel(),BorderLayout.SOUTH);
fileName.setHorizontalAlignment(SwingConstants.CENTER);
}
public void show(String file) {
pdfViewer.openDocument(file);
pdfViewer.setPageFitMode(DocumentViewController.PAGE_FIT_WINDOW_HEIGHT, false);
}
}

28
src/main/java/de/srsoftware/belegscanner/gui/ResolutionSelector.java

@ -1,47 +1,47 @@ @@ -1,47 +1,47 @@
package de.srsoftware.belegscanner.gui;
import de.srsoftware.belegscanner.Worker;
import javax.swing.*;
import java.awt.*;
import static de.srsoftware.belegscanner.Application.t;
import static java.awt.BorderLayout.CENTER;
import static java.awt.BorderLayout.EAST;
import static java.awt.BorderLayout.NORTH;
import static java.awt.BorderLayout.WEST;
public class ResolutionSelector extends JPanel{
private int resolution = 150;
public ResolutionSelector() {
private final Worker worker;
public ResolutionSelector(Worker worker) {
super(new BorderLayout());
this.worker = worker;
;
ButtonGroup group = new ButtonGroup();
JLabel label = new JLabel(t("current resolution") + ": " + resolution + "px");
JLabel label = new JLabel(t("current resolution") + ": " + worker.setResolution(150) + "px");
add(label, NORTH);
add(resolutionButton(group, label, 150), WEST);
add(resolutionButton(group, label, 300), CENTER);
add(resolutionButton(group, label, 600), BorderLayout.EAST);
add(resolutionButton(group, label, 600), EAST);
setMaximumSize(new Dimension(600, 200));
}
public int resolutiion(){
return resolution;
}
/**
* create one radio button for the resoultionSelector
* @param group
* @param label
* @param i
* @param resolution
* @return
*/
private JRadioButton resolutionButton(ButtonGroup group, JLabel label, int i) {
JRadioButton btn = new JRadioButton(i+" px");
private JRadioButton resolutionButton(ButtonGroup group, JLabel label, int resolution) {
JRadioButton btn = new JRadioButton(resolution+" px");
btn.addActionListener(ev -> {
resolution = i;
label.setText("aktuelle Auflösung: "+resolution+"px");
label.setText("aktuelle Auflösung: "+worker.setResolution(resolution)+"px");
});
group.add(btn);
if (i==150) btn.setSelected(true);
if (resolution==150) btn.setSelected(true);
return btn;
}
}

48
src/main/java/de/srsoftware/belegscanner/gui/RotationSelector.java

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
package de.srsoftware.belegscanner.gui;
import de.srsoftware.belegscanner.Worker;
import javax.swing.*;
import java.awt.*;
import static de.srsoftware.belegscanner.Application.t;
import static java.awt.BorderLayout.CENTER;
import static java.awt.BorderLayout.NORTH;
import static java.awt.BorderLayout.WEST;
public class RotationSelector extends JPanel {
private final Worker worker;
private final JRadioButton noRotation;
public RotationSelector(Worker worker) {
setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
this.worker = worker;
ButtonGroup group = new ButtonGroup();
worker.setRotation(0);
add(noRotation = rotatatonButton(group, 0));
add(rotatatonButton(group, 90));
add(rotatatonButton(group, 180));
add(rotatatonButton(group, -90));
noRotation.setSelected(true);
add(new JLabel(t("Rotation")));
setMaximumSize(new Dimension(600, 200));
}
/**
* create one radio button for the resoultionSelector
* @param group
* @param angle
* @return
*/
private JRadioButton rotatatonButton(ButtonGroup group, int angle) {
JRadioButton btn = new JRadioButton(angle+"°");
btn.addActionListener(ev -> {
worker.setRotation(angle);
});
group.add(btn);
if (angle==150) btn.setSelected(true);
return btn;
}
}

18
src/main/java/de/srsoftware/belegscanner/gui/Toolbar.java

@ -34,8 +34,6 @@ public class Toolbar extends JPanel { @@ -34,8 +34,6 @@ public class Toolbar extends JPanel {
private final SelectComboBox pathPicker, catPicker;
private static final int OFFSET = 2;
private class AdditionalInput {
private final JPanel panel;
private final SelectComboBox input;
@ -73,8 +71,9 @@ public class Toolbar extends JPanel { @@ -73,8 +71,9 @@ public class Toolbar extends JPanel {
add(input(t("Category"),catPicker = categoryPicker()));
add(input(t("Path"),pathPicker = pathPicker()));
add(new FormatSelector(worker));
add(new ResolutionSelector());
add(new ImproveSelector());
add(new ResolutionSelector(worker));
add(new ImproveSelector(worker));
add(new RotationSelector(worker));
add(new TypeSelector(worker));
add(scanButton());
add(Box.createGlue());
@ -144,9 +143,6 @@ public class Toolbar extends JPanel { @@ -144,9 +143,6 @@ public class Toolbar extends JPanel {
if (additionalInput == null) {
LOG.debug("Field missing, creating…");
var input = new SelectComboBox(new Vector<>());
if (varName.equals(t(Constants.PAGE))){
return "["+varName+"]";
}
input.onUpdateText(newText -> worker.resolvePath());
JPanel panel = input(varName,input);
additionalInputs.put(varName, additionalInput = new AdditionalInput(panel,input,true));
@ -176,4 +172,12 @@ public class Toolbar extends JPanel { @@ -176,4 +172,12 @@ public class Toolbar extends JPanel {
scanButton.addActionListener(ev -> worker.scan());
return scanButton;
}
public void disableScan() {
scanButton.setEnabled(false);
}
public void enableScan() {
scanButton.setEnabled(true);
}
}

47
src/main/java/de/srsoftware/belegscanner/model/ScanProject.java

@ -1,21 +1,33 @@ @@ -1,21 +1,33 @@
package de.srsoftware.belegscanner.model;
import de.srsoftware.belegscanner.Constants;
import de.srsoftware.belegscanner.model.api.Page;
import de.srsoftware.belegscanner.model.api.Project;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class ScanProject implements Project {
import static de.srsoftware.belegscanner.Application.t;
public class ScanProject implements Project {
private static final String PAGE = t(Constants.PAGE);
private final String pattern;
private List<Page> pageList = List.of();
private List<Page> pageList = new ArrayList<>();
public ScanProject(String resolvedPath){
this.pattern = resolvedPath;
}
@Override
public String pattern() {
return null;
return pattern;
}
@Override
public File nextFile() {
return new File(pattern.replace("["+PAGE+"]",nextPage()+""));
}
@Override
@ -30,12 +42,17 @@ public class ScanProject implements Project { @@ -30,12 +42,17 @@ public class ScanProject implements Project {
@Override
public void openDir() {
File dir = new File(pattern).getParentFile();
if (dir.exists()) try {
Desktop.getDesktop().open(dir);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void previewLastPage() {
public Page lastPage() {
return pageList.isEmpty() ? null : pageList.get(pageList.size()-1);
}
@Override
@ -44,7 +61,23 @@ public class ScanProject implements Project { @@ -44,7 +61,23 @@ public class ScanProject implements Project {
}
@Override
public void dropLastPage() {
public Page addPage(File file) {
Page newPage = new Page() {
@Override
public File file() {
return file;
}
};
pageList.add(newPage);
return newPage;
}
@Override
public Project dropLastPage() {
if (pageList.isEmpty()) return this;
var lastPage = pageList.remove(pageList.size()-1);
var file = lastPage.file();
if (file.exists()) file.delete();
return this;
}
}

9
src/main/java/de/srsoftware/belegscanner/model/api/Project.java

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
package de.srsoftware.belegscanner.model.api;
import java.io.File;
import java.util.List;
public interface Project {
@ -11,9 +12,13 @@ public interface Project { @@ -11,9 +12,13 @@ public interface Project {
void openDir();
void previewLastPage();
Page lastPage();
void join();
void dropLastPage();
Project dropLastPage();
File nextFile();
Page addPage(File file);
}

Loading…
Cancel
Save