various GUI improvements
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>BelegScanner</groupId>
|
||||
<artifactId>BelegScanner</artifactId>
|
||||
<version>0.0.10</version>
|
||||
<version>0.0.11</version>
|
||||
|
||||
<name>BelegScanner</name>
|
||||
<packaging>jar</packaging>
|
||||
@@ -53,7 +53,7 @@
|
||||
<dependency>
|
||||
<groupId>de.srsoftware</groupId>
|
||||
<artifactId>tools.gui.selectcombobox</artifactId>
|
||||
<version>0.1.3</version>
|
||||
<version>0.1.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package de.srsoftware.belegscanner.gui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Font;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
@@ -15,9 +18,12 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.MatteBorder;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -30,6 +36,7 @@ public class DocTable extends JPanel{
|
||||
private static FilenameFilter PAGES = (dir,name) -> name.toLowerCase().endsWith("pdf") && name.toLowerCase().startsWith("page");
|
||||
private static FilenameFilter PDFS = (dir,name) -> name.toLowerCase().endsWith("pdf");
|
||||
private static int rowCounter = 0;
|
||||
private static Font btnFont = new Font("Arial", Font.PLAIN, 28);
|
||||
|
||||
public interface PreviewListener{
|
||||
public void show(String filename);
|
||||
@@ -55,25 +62,16 @@ public class DocTable extends JPanel{
|
||||
buttons = new JPanel();
|
||||
buttons.setLayout(new FlowLayout());
|
||||
|
||||
JButton folderButton = new JButton("Ordner öffnen");
|
||||
folderButton.addActionListener(ev -> openFolder(path));
|
||||
buttons.add(folderButton);
|
||||
|
||||
joinButton = new JButton("Zusammenfügen");
|
||||
joinButton.addActionListener(ev -> joinDocs(path));
|
||||
buttons.add(joinButton);
|
||||
|
||||
JButton preview = new JButton("Vorschau");
|
||||
preview.addActionListener(ev -> preview(path));
|
||||
buttons.add(preview);
|
||||
|
||||
JButton drop = new JButton("Erledigt");
|
||||
drop.addActionListener(ev -> drop(this));
|
||||
buttons.add(drop);
|
||||
buttons.add(button("🗀","Ordner öffnen",ev -> openFolder(path)));
|
||||
buttons.add(joinButton = button("⎗","PDFs zusammenführen",ev -> joinDocs(path)));
|
||||
buttons.add(button("🖻","Vorschau",ev -> preview(path)));
|
||||
buttons.add(button("✓","fertig",ev -> drop(this)));
|
||||
|
||||
constraints.gridx = 2;
|
||||
add(buttons,constraints);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void drop(Row row) {
|
||||
remove(pathLabel);
|
||||
@@ -108,11 +106,18 @@ public class DocTable extends JPanel{
|
||||
constraints.insets = new Insets(3, 10, 3, 10);
|
||||
constraints.gridy = 0;
|
||||
constraints.gridx = 0;
|
||||
add(new JLabel("Ordner"),constraints);
|
||||
MatteBorder border = BorderFactory.createMatteBorder(0, 0, 1, 0, Color.black);
|
||||
JLabel ordner = new JLabel("Ordner",SwingConstants.CENTER);
|
||||
ordner.setBorder(border);
|
||||
add(ordner,constraints);
|
||||
constraints.gridx = 1;
|
||||
add(new JLabel("Status"),constraints);
|
||||
JLabel status = new JLabel("Status",SwingConstants.CENTER);
|
||||
status.setBorder(border);
|
||||
add(status,constraints);
|
||||
constraints.gridx = 2;
|
||||
add(new JLabel("Aktionen"),constraints);
|
||||
JLabel actions = new JLabel("Aktionen",SwingConstants.CENTER);
|
||||
actions.setBorder(border);
|
||||
add(actions,constraints);
|
||||
previewListeners = new HashSet<>();
|
||||
}
|
||||
|
||||
@@ -125,6 +130,14 @@ public class DocTable extends JPanel{
|
||||
return this;
|
||||
}
|
||||
|
||||
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 void joinDocs(String path) {
|
||||
LOG.debug("joinFiles({})",path);
|
||||
rows.get(path).removeJoinButton();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.srsoftware.belegscanner.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.ActionEvent;
|
||||
@@ -15,8 +16,11 @@ import java.util.Vector;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import org.icepdf.ri.common.ComponentKeyBinding;
|
||||
import org.icepdf.ri.common.SwingController;
|
||||
@@ -69,6 +73,10 @@ public class MainFrame extends JFrame {
|
||||
|
||||
private SwingController pdfViewer;
|
||||
|
||||
private JLabel fileName;
|
||||
|
||||
private boolean isScanning = false;
|
||||
|
||||
public MainFrame(Configuration config) {
|
||||
super("BelegScanner");
|
||||
this.config = config;
|
||||
@@ -99,21 +107,30 @@ public class MainFrame extends JFrame {
|
||||
int y = config.getOrCreate(APP_Y, 20);
|
||||
setLocation(new Point(x, y));
|
||||
|
||||
checkScanButton();
|
||||
|
||||
setPreferredSize(new Dimension(width,height));
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void addFieldsFor(String path) {
|
||||
Vector<String> marks = new Vector<>();
|
||||
Matcher matches = MARKEN.matcher(path);
|
||||
while (matches.find()) marks.add(matches.group(1));
|
||||
toolbar.addFieldsFor(marks);
|
||||
};
|
||||
|
||||
private void checkScanButton() {
|
||||
toolbar.readyToScanX(!(isScanning || patchedPath==null || patchedPath.isBlank() || patchedPath.contains("$")));
|
||||
}
|
||||
|
||||
private void performScan(String path, Dimension dimension) {
|
||||
LOG.debug("performScan({})",path);
|
||||
toolbar.readyToScan(false);
|
||||
setScanning(true);
|
||||
|
||||
File folder = new File(path);
|
||||
if (!folder.exists()) {
|
||||
LOG.warn("Path '{}' does not exist!",path);
|
||||
@@ -148,13 +165,14 @@ public class MainFrame extends JFrame {
|
||||
if (errorCode != 0) {
|
||||
LOG.error("error code: {} for {}",errorCode,cmd);
|
||||
docTable.setState(path, "Scannen fehlgeschlagen.");
|
||||
toolbar.readyToScan(true);
|
||||
setScanning(false);
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (InterruptedException | IOException e) {
|
||||
LOG.error("{} terminated: ",builder,e);
|
||||
}
|
||||
setScanning(false);
|
||||
|
||||
String pdf = "page."+timestamp+".pdf";
|
||||
cmd = new Vector<>();
|
||||
@@ -166,12 +184,10 @@ public class MainFrame extends JFrame {
|
||||
try {
|
||||
Process process = builder.start();
|
||||
docTable.setState(path,"Kovertiere zu PDF…");
|
||||
toolbar.readyToScan(true);
|
||||
int errorCode = process.waitFor();
|
||||
if (errorCode != 0) {
|
||||
LOG.error("error code: {} for {}",errorCode,cmd);
|
||||
docTable.setState(path, "Konvertierung fehlgeschlagen.");
|
||||
toolbar.readyToScan(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -197,7 +213,6 @@ public class MainFrame extends JFrame {
|
||||
try {
|
||||
Process process = builder.start();
|
||||
docTable.setState(path,"Texterkennung…");
|
||||
toolbar.readyToScan(true);
|
||||
int errorCode = process.waitFor();
|
||||
if (errorCode != 0) {
|
||||
LOG.error("error code: {} for {}",errorCode,cmd);
|
||||
@@ -213,8 +228,16 @@ public class MainFrame extends JFrame {
|
||||
docTable.preview(path);
|
||||
}
|
||||
|
||||
private void setScanning(boolean scanning) {
|
||||
isScanning = scanning;
|
||||
checkScanButton();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private JPanel preview() {
|
||||
// https://stackoverflow.com/a/48248739/1285585
|
||||
JPanel pane = new JPanel(new BorderLayout());
|
||||
|
||||
pdfViewer = new SwingController();
|
||||
SwingViewBuilder factory = new SwingViewBuilder(pdfViewer);
|
||||
@@ -224,14 +247,21 @@ public class MainFrame extends JFrame {
|
||||
ComponentKeyBinding.install(pdfViewer, viewerComponentPanel);
|
||||
// add interactive mouse link annotation support via callback
|
||||
pdfViewer.getDocumentViewController().setAnnotationCallback(new org.icepdf.ri.common.MyAnnotationCallback(pdfViewer.getDocumentViewController()));
|
||||
return viewerComponentPanel;
|
||||
|
||||
pane.add(viewerComponentPanel,BorderLayout.CENTER);
|
||||
pane.setBorder(BorderFactory.createLineBorder(Color.black));
|
||||
|
||||
pane.add(fileName = new JLabel(),BorderLayout.SOUTH);
|
||||
fileName.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
private void preview(String file) {
|
||||
pdfViewer.openDocument(file);
|
||||
//pdfViewer.setToolBarVisible(false);
|
||||
pdfViewer.setPageFitMode(DocumentViewController.PAGE_FIT_WINDOW_WIDTH, false);
|
||||
statusBar.setFile(file);
|
||||
fileName.setText(file);
|
||||
}
|
||||
|
||||
private void scan(ActionEvent ev) {
|
||||
@@ -313,5 +343,6 @@ public class MainFrame extends JFrame {
|
||||
addFieldsFor(patchedPath);
|
||||
for (Entry<String, String> entry : fields.entrySet()) patchedPath = patchedPath.replace("$"+entry.getKey(), entry.getValue());
|
||||
statusBar.setPath(patchedPath);
|
||||
checkScanButton();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package de.srsoftware.belegscanner.gui;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -15,15 +14,13 @@ public class StatusBar extends JPanel {
|
||||
|
||||
private static final long serialVersionUID = 8102800846089594705L;
|
||||
private JLabel path;
|
||||
private JLabel file;
|
||||
|
||||
//private JLabel action;
|
||||
|
||||
public StatusBar() {
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
//add(action = new JLabel("Bereit."));
|
||||
add(file = new JLabel());
|
||||
add(path = new JLabel("Kein Pfad gewält."));
|
||||
path.setBorder(new EmptyBorder(5,5,5,5));
|
||||
}
|
||||
|
||||
public StatusBar setPath(String path) {
|
||||
@@ -31,11 +28,4 @@ public class StatusBar extends JPanel {
|
||||
this.path.setText(path);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StatusBar setFile(String path) {
|
||||
File file = new File(path);
|
||||
String dir = file.getParentFile().getName();
|
||||
this.file.setText(dir + File.separator + file.getName());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,20 +7,22 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Vector;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
@@ -55,14 +57,13 @@ public class Toolbar extends JPanel {
|
||||
|
||||
public interface PathListener{
|
||||
public void setPath(String path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -5834326573752788233L;
|
||||
|
||||
private static final int OFFSET = 2;
|
||||
private static EmptyBorder BORDER = new EmptyBorder(0,5,5,5);
|
||||
|
||||
|
||||
private Vector<Object> categories = new Vector<>();
|
||||
private Vector<Object> paths = new Vector<>();
|
||||
|
||||
private HashMap<String,JPanel> additonalComponents = new HashMap<>();
|
||||
@@ -83,16 +84,18 @@ public class Toolbar extends JPanel {
|
||||
|
||||
private JTextField width;
|
||||
private JTextField height;
|
||||
private SelectComboBox catPicker;
|
||||
|
||||
public Toolbar(Configuration config) {
|
||||
this.config = config;
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
add(datePicker());
|
||||
add(input("Kategorie",categoryPicker(config)));
|
||||
add(input("Kategorie",catPicker = categoryPicker(config)));
|
||||
add(input("Pfad",pathPicker = pathPicker()));
|
||||
addFormatSelector();
|
||||
add(scanButton());
|
||||
add(new JPanel());
|
||||
add(Box.createGlue());
|
||||
Arrays.stream(getComponents()).filter(c -> c instanceof JPanel).map(JPanel.class::cast).forEach(p -> p.setBorder(BORDER));
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +104,7 @@ public class Toolbar extends JPanel {
|
||||
dummy.setLayout(new BorderLayout());
|
||||
dummy.setMaximumSize(new Dimension(600, 40));
|
||||
|
||||
dummy.add(new JLabel("Breite:"),BorderLayout.WEST);
|
||||
dummy.add(new JLabel("Breite: "),BorderLayout.WEST);
|
||||
dummy.add(width = new JTextField(209+""),BorderLayout.CENTER);
|
||||
dummy.add(new JLabel("px"),BorderLayout.EAST);
|
||||
add(dummy);
|
||||
@@ -110,7 +113,7 @@ public class Toolbar extends JPanel {
|
||||
dummy.setLayout(new BorderLayout());
|
||||
dummy.setMaximumSize(new Dimension(600, 40));
|
||||
|
||||
dummy.add(new JLabel("Höhe:"),BorderLayout.WEST);
|
||||
dummy.add(new JLabel("Höhe: "),BorderLayout.WEST);
|
||||
dummy.add(height = new JTextField(297+""),BorderLayout.CENTER);
|
||||
dummy.add(new JLabel("px"),BorderLayout.EAST);
|
||||
add(dummy);
|
||||
@@ -134,9 +137,9 @@ public class Toolbar extends JPanel {
|
||||
|
||||
for (String name : marks) {
|
||||
if (additonalComponents.containsKey(name)) continue;
|
||||
Vector<Object> knownValues = new Vector<>();
|
||||
SelectComboBox valuePicker = new SelectComboBox(knownValues).onUpdateText(newText -> updateField(name,newText));
|
||||
SelectComboBox valuePicker = new SelectComboBox(new Vector<>()).onUpdateText(newText -> updateField(name,newText));
|
||||
JPanel input = input(name, valuePicker);
|
||||
input.setBorder(BORDER);
|
||||
add(input,getComponentCount()-OFFSET);
|
||||
additonalComponents.put(name, input);
|
||||
}
|
||||
@@ -173,12 +176,11 @@ public class Toolbar extends JPanel {
|
||||
}
|
||||
|
||||
|
||||
private Component categoryPicker(Configuration config) {
|
||||
private SelectComboBox categoryPicker(Configuration config) {
|
||||
JSONObject elements = config.getOrCreate("app.categories",new JSONObject());
|
||||
Set<String> cats = elements.keySet().stream().map(Object::toString).map(String::trim).collect(Collectors.toSet());
|
||||
categories = new Vector<>(cats);
|
||||
categories.sort((a,b)->a.toString().compareTo(b.toString()));
|
||||
return new SelectComboBox(categories).onUpdateText(this::updateCat);
|
||||
return new SelectComboBox(elements.keySet())
|
||||
.onUpdateText(this::updateCat)
|
||||
.onDelete(this::dropCategory);
|
||||
}
|
||||
|
||||
private Component datePicker() {
|
||||
@@ -189,6 +191,16 @@ public class Toolbar extends JPanel {
|
||||
return date;
|
||||
}
|
||||
|
||||
private void dropCategory(String catName) {
|
||||
LOG.debug("dropCategory({})",catName);
|
||||
Object o = config.get("app.categories");
|
||||
if (o instanceof JSONObject) {
|
||||
JSONObject json = (JSONObject)o;
|
||||
json.remove(catName);
|
||||
catPicker.setElements(json.keySet());
|
||||
}
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date.getSelectedDate();
|
||||
}
|
||||
@@ -203,11 +215,12 @@ public class Toolbar extends JPanel {
|
||||
}
|
||||
|
||||
|
||||
private JPanel input(String caption, Component component) {
|
||||
private JPanel input(String caption, JComponent component) {
|
||||
component.setMaximumSize(new Dimension(600, 40));
|
||||
component.setToolTipText("Drücken Sie Umschalt + Entf um einen Eintrag zu löschen");
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
|
||||
panel.add(new JLabel(caption+" "));
|
||||
panel.add(new JLabel(caption+": "));
|
||||
panel.add(component);
|
||||
return panel;
|
||||
}
|
||||
@@ -232,9 +245,8 @@ public class Toolbar extends JPanel {
|
||||
scanListeners.forEach(l->l.actionPerformed(evt));
|
||||
}
|
||||
|
||||
public void readyToScan(boolean val) {
|
||||
public void readyToScanX(boolean val) {
|
||||
scanButton.setEnabled(val);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -257,10 +269,8 @@ public class Toolbar extends JPanel {
|
||||
path = prefix+"fields."+fieldName;
|
||||
|
||||
JSONArray arr = config.getOrCreateArray(path);
|
||||
TreeSet<Object> values = new TreeSet<>();
|
||||
arr.forEach(elem -> values.add(elem.toString().trim()));
|
||||
SelectComboBox selector = getSelector(additonalComponents.get(fieldName));
|
||||
if (selector != null) selector.setElements(values);
|
||||
if (selector != null) selector.setElements(arr.toList()).onDelete(tx -> selector.setElements(deleteValue(arr,tx)));
|
||||
}
|
||||
}
|
||||
LOG.debug("Trying to read size");
|
||||
@@ -274,6 +284,17 @@ public class Toolbar extends JPanel {
|
||||
} else LOG.debug("newCat is empty!");
|
||||
}
|
||||
|
||||
private List<Object> deleteValue(JSONArray arr, String tx) {
|
||||
for (int i = 0; i<arr.length(); i++) {
|
||||
if (arr.get(i).equals(tx)) {
|
||||
arr.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return arr.toList();
|
||||
}
|
||||
|
||||
|
||||
protected void updateDimensions() {
|
||||
LOG.debug("updateDimensions()");
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user