Browse Source

various GUI improvements

main
Stephan Richter 4 years ago
parent
commit
6576adf711
  1. 4
      pom.xml
  2. 49
      src/main/java/de/srsoftware/belegscanner/gui/DocTable.java
  3. 45
      src/main/java/de/srsoftware/belegscanner/gui/MainFrame.java
  4. 14
      src/main/java/de/srsoftware/belegscanner/gui/StatusBar.java
  5. 69
      src/main/java/de/srsoftware/belegscanner/gui/Toolbar.java

4
pom.xml

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>BelegScanner</groupId> <groupId>BelegScanner</groupId>
<artifactId>BelegScanner</artifactId> <artifactId>BelegScanner</artifactId>
<version>0.0.10</version> <version>0.0.11</version>
<name>BelegScanner</name> <name>BelegScanner</name>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -53,7 +53,7 @@
<dependency> <dependency>
<groupId>de.srsoftware</groupId> <groupId>de.srsoftware</groupId>
<artifactId>tools.gui.selectcombobox</artifactId> <artifactId>tools.gui.selectcombobox</artifactId>
<version>0.1.3</version> <version>0.1.7</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>

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

@ -1,9 +1,12 @@
package de.srsoftware.belegscanner.gui; package de.srsoftware.belegscanner.gui;
import java.awt.Color;
import java.awt.FlowLayout; import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints; import java.awt.GridBagConstraints;
import java.awt.GridBagLayout; import java.awt.GridBagLayout;
import java.awt.Insets; import java.awt.Insets;
import java.awt.event.ActionListener;
import java.io.File; import java.io.File;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
@ -15,9 +18,12 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.MatteBorder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 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 PAGES = (dir,name) -> name.toLowerCase().endsWith("pdf") && name.toLowerCase().startsWith("page");
private static FilenameFilter PDFS = (dir,name) -> name.toLowerCase().endsWith("pdf"); private static FilenameFilter PDFS = (dir,name) -> name.toLowerCase().endsWith("pdf");
private static int rowCounter = 0; private static int rowCounter = 0;
private static Font btnFont = new Font("Arial", Font.PLAIN, 28);
public interface PreviewListener{ public interface PreviewListener{
public void show(String filename); public void show(String filename);
@ -55,25 +62,16 @@ public class DocTable extends JPanel{
buttons = new JPanel(); buttons = new JPanel();
buttons.setLayout(new FlowLayout()); buttons.setLayout(new FlowLayout());
JButton folderButton = new JButton("Ordner öffnen"); buttons.add(button("🗀","Ordner öffnen",ev -> openFolder(path)));
folderButton.addActionListener(ev -> openFolder(path)); buttons.add(joinButton = button("⎗","PDFs zusammenführen",ev -> joinDocs(path)));
buttons.add(folderButton); buttons.add(button("🖻","Vorschau",ev -> preview(path)));
buttons.add(button("✓","fertig",ev -> drop(this)));
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);
constraints.gridx = 2; constraints.gridx = 2;
add(buttons,constraints); add(buttons,constraints);
} }
private void drop(Row row) { private void drop(Row row) {
remove(pathLabel); remove(pathLabel);
@ -108,11 +106,18 @@ public class DocTable extends JPanel{
constraints.insets = new Insets(3, 10, 3, 10); constraints.insets = new Insets(3, 10, 3, 10);
constraints.gridy = 0; constraints.gridy = 0;
constraints.gridx = 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; constraints.gridx = 1;
add(new JLabel("Status"),constraints); JLabel status = new JLabel("Status",SwingConstants.CENTER);
status.setBorder(border);
add(status,constraints);
constraints.gridx = 2; constraints.gridx = 2;
add(new JLabel("Aktionen"),constraints); JLabel actions = new JLabel("Aktionen",SwingConstants.CENTER);
actions.setBorder(border);
add(actions,constraints);
previewListeners = new HashSet<>(); previewListeners = new HashSet<>();
} }
@ -125,6 +130,14 @@ public class DocTable extends JPanel{
return this; 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) { public void joinDocs(String path) {
LOG.debug("joinFiles({})",path); LOG.debug("joinFiles({})",path);
rows.get(path).removeJoinButton(); rows.get(path).removeJoinButton();

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

@ -1,6 +1,7 @@
package de.srsoftware.belegscanner.gui; package de.srsoftware.belegscanner.gui;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Point; import java.awt.Point;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@ -15,8 +16,11 @@ import java.util.Vector;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.swing.BorderFactory;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.SwingConstants;
import org.icepdf.ri.common.ComponentKeyBinding; import org.icepdf.ri.common.ComponentKeyBinding;
import org.icepdf.ri.common.SwingController; import org.icepdf.ri.common.SwingController;
@ -69,6 +73,10 @@ public class MainFrame extends JFrame {
private SwingController pdfViewer; private SwingController pdfViewer;
private JLabel fileName;
private boolean isScanning = false;
public MainFrame(Configuration config) { public MainFrame(Configuration config) {
super("BelegScanner"); super("BelegScanner");
this.config = config; this.config = config;
@ -99,21 +107,30 @@ public class MainFrame extends JFrame {
int y = config.getOrCreate(APP_Y, 20); int y = config.getOrCreate(APP_Y, 20);
setLocation(new Point(x, y)); setLocation(new Point(x, y));
checkScanButton();
setPreferredSize(new Dimension(width,height)); setPreferredSize(new Dimension(width,height));
pack(); pack();
setVisible(true); setVisible(true);
} }
private void addFieldsFor(String path) { private void addFieldsFor(String path) {
Vector<String> marks = new Vector<>(); Vector<String> marks = new Vector<>();
Matcher matches = MARKEN.matcher(path); Matcher matches = MARKEN.matcher(path);
while (matches.find()) marks.add(matches.group(1)); while (matches.find()) marks.add(matches.group(1));
toolbar.addFieldsFor(marks); toolbar.addFieldsFor(marks);
}; };
private void checkScanButton() {
toolbar.readyToScanX(!(isScanning || patchedPath==null || patchedPath.isBlank() || patchedPath.contains("$")));
}
private void performScan(String path, Dimension dimension) { private void performScan(String path, Dimension dimension) {
LOG.debug("performScan({})",path); LOG.debug("performScan({})",path);
toolbar.readyToScan(false); setScanning(true);
File folder = new File(path); File folder = new File(path);
if (!folder.exists()) { if (!folder.exists()) {
LOG.warn("Path '{}' does not exist!",path); LOG.warn("Path '{}' does not exist!",path);
@ -148,13 +165,14 @@ public class MainFrame extends JFrame {
if (errorCode != 0) { if (errorCode != 0) {
LOG.error("error code: {} for {}",errorCode,cmd); LOG.error("error code: {} for {}",errorCode,cmd);
docTable.setState(path, "Scannen fehlgeschlagen."); docTable.setState(path, "Scannen fehlgeschlagen.");
toolbar.readyToScan(true); setScanning(false);
return; return;
} }
} catch (InterruptedException | IOException e) { } catch (InterruptedException | IOException e) {
LOG.error("{} terminated: ",builder,e); LOG.error("{} terminated: ",builder,e);
} }
setScanning(false);
String pdf = "page."+timestamp+".pdf"; String pdf = "page."+timestamp+".pdf";
cmd = new Vector<>(); cmd = new Vector<>();
@ -166,12 +184,10 @@ public class MainFrame extends JFrame {
try { try {
Process process = builder.start(); Process process = builder.start();
docTable.setState(path,"Kovertiere zu PDF…"); docTable.setState(path,"Kovertiere zu PDF…");
toolbar.readyToScan(true);
int errorCode = process.waitFor(); int errorCode = process.waitFor();
if (errorCode != 0) { if (errorCode != 0) {
LOG.error("error code: {} for {}",errorCode,cmd); LOG.error("error code: {} for {}",errorCode,cmd);
docTable.setState(path, "Konvertierung fehlgeschlagen."); docTable.setState(path, "Konvertierung fehlgeschlagen.");
toolbar.readyToScan(true);
return; return;
} }
@ -197,7 +213,6 @@ public class MainFrame extends JFrame {
try { try {
Process process = builder.start(); Process process = builder.start();
docTable.setState(path,"Texterkennung…"); docTable.setState(path,"Texterkennung…");
toolbar.readyToScan(true);
int errorCode = process.waitFor(); int errorCode = process.waitFor();
if (errorCode != 0) { if (errorCode != 0) {
LOG.error("error code: {} for {}",errorCode,cmd); LOG.error("error code: {} for {}",errorCode,cmd);
@ -213,8 +228,16 @@ public class MainFrame extends JFrame {
docTable.preview(path); docTable.preview(path);
} }
private void setScanning(boolean scanning) {
isScanning = scanning;
checkScanButton();
}
private JPanel preview() { private JPanel preview() {
// https://stackoverflow.com/a/48248739/1285585 // https://stackoverflow.com/a/48248739/1285585
JPanel pane = new JPanel(new BorderLayout());
pdfViewer = new SwingController(); pdfViewer = new SwingController();
SwingViewBuilder factory = new SwingViewBuilder(pdfViewer); SwingViewBuilder factory = new SwingViewBuilder(pdfViewer);
@ -224,14 +247,21 @@ public class MainFrame extends JFrame {
ComponentKeyBinding.install(pdfViewer, viewerComponentPanel); ComponentKeyBinding.install(pdfViewer, viewerComponentPanel);
// add interactive mouse link annotation support via callback // add interactive mouse link annotation support via callback
pdfViewer.getDocumentViewController().setAnnotationCallback(new org.icepdf.ri.common.MyAnnotationCallback(pdfViewer.getDocumentViewController())); 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) { private void preview(String file) {
pdfViewer.openDocument(file); pdfViewer.openDocument(file);
//pdfViewer.setToolBarVisible(false); //pdfViewer.setToolBarVisible(false);
pdfViewer.setPageFitMode(DocumentViewController.PAGE_FIT_WINDOW_WIDTH, false); pdfViewer.setPageFitMode(DocumentViewController.PAGE_FIT_WINDOW_WIDTH, false);
statusBar.setFile(file); fileName.setText(file);
} }
private void scan(ActionEvent ev) { private void scan(ActionEvent ev) {
@ -313,5 +343,6 @@ public class MainFrame extends JFrame {
addFieldsFor(patchedPath); addFieldsFor(patchedPath);
for (Entry<String, String> entry : fields.entrySet()) patchedPath = patchedPath.replace("$"+entry.getKey(), entry.getValue()); for (Entry<String, String> entry : fields.entrySet()) patchedPath = patchedPath.replace("$"+entry.getKey(), entry.getValue());
statusBar.setPath(patchedPath); statusBar.setPath(patchedPath);
checkScanButton();
} }
} }

14
src/main/java/de/srsoftware/belegscanner/gui/StatusBar.java

@ -1,10 +1,9 @@
package de.srsoftware.belegscanner.gui; package de.srsoftware.belegscanner.gui;
import java.io.File;
import javax.swing.BoxLayout; import javax.swing.BoxLayout;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -15,15 +14,13 @@ public class StatusBar extends JPanel {
private static final long serialVersionUID = 8102800846089594705L; private static final long serialVersionUID = 8102800846089594705L;
private JLabel path; private JLabel path;
private JLabel file;
//private JLabel action; //private JLabel action;
public StatusBar() { public StatusBar() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
//add(action = new JLabel("Bereit."));
add(file = new JLabel());
add(path = new JLabel("Kein Pfad gewält.")); add(path = new JLabel("Kein Pfad gewält."));
path.setBorder(new EmptyBorder(5,5,5,5));
} }
public StatusBar setPath(String path) { public StatusBar setPath(String path) {
@ -31,11 +28,4 @@ public class StatusBar extends JPanel {
this.path.setText(path); this.path.setText(path);
return this; 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;
}
} }

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

@ -7,20 +7,22 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter; import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector; import java.util.Vector;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.swing.Box;
import javax.swing.BoxLayout; import javax.swing.BoxLayout;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
@ -55,14 +57,13 @@ public class Toolbar extends JPanel {
public interface PathListener{ public interface PathListener{
public void setPath(String path); public void setPath(String path);
} }
private static final long serialVersionUID = -5834326573752788233L; private static final long serialVersionUID = -5834326573752788233L;
private static final int OFFSET = 2; 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 Vector<Object> paths = new Vector<>();
private HashMap<String,JPanel> additonalComponents = new HashMap<>(); private HashMap<String,JPanel> additonalComponents = new HashMap<>();
@ -83,16 +84,18 @@ public class Toolbar extends JPanel {
private JTextField width; private JTextField width;
private JTextField height; private JTextField height;
private SelectComboBox catPicker;
public Toolbar(Configuration config) { public Toolbar(Configuration config) {
this.config = config; this.config = config;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(datePicker()); add(datePicker());
add(input("Kategorie",categoryPicker(config))); add(input("Kategorie",catPicker = categoryPicker(config)));
add(input("Pfad",pathPicker = pathPicker())); add(input("Pfad",pathPicker = pathPicker()));
addFormatSelector(); addFormatSelector();
add(scanButton()); 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.setLayout(new BorderLayout());
dummy.setMaximumSize(new Dimension(600, 40)); 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(width = new JTextField(209+""),BorderLayout.CENTER);
dummy.add(new JLabel("px"),BorderLayout.EAST); dummy.add(new JLabel("px"),BorderLayout.EAST);
add(dummy); add(dummy);
@ -110,7 +113,7 @@ public class Toolbar extends JPanel {
dummy.setLayout(new BorderLayout()); dummy.setLayout(new BorderLayout());
dummy.setMaximumSize(new Dimension(600, 40)); 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(height = new JTextField(297+""),BorderLayout.CENTER);
dummy.add(new JLabel("px"),BorderLayout.EAST); dummy.add(new JLabel("px"),BorderLayout.EAST);
add(dummy); add(dummy);
@ -134,9 +137,9 @@ public class Toolbar extends JPanel {
for (String name : marks) { for (String name : marks) {
if (additonalComponents.containsKey(name)) continue; if (additonalComponents.containsKey(name)) continue;
Vector<Object> knownValues = new Vector<>(); SelectComboBox valuePicker = new SelectComboBox(new Vector<>()).onUpdateText(newText -> updateField(name,newText));
SelectComboBox valuePicker = new SelectComboBox(knownValues).onUpdateText(newText -> updateField(name,newText));
JPanel input = input(name, valuePicker); JPanel input = input(name, valuePicker);
input.setBorder(BORDER);
add(input,getComponentCount()-OFFSET); add(input,getComponentCount()-OFFSET);
additonalComponents.put(name, input); 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()); JSONObject elements = config.getOrCreate("app.categories",new JSONObject());
Set<String> cats = elements.keySet().stream().map(Object::toString).map(String::trim).collect(Collectors.toSet()); return new SelectComboBox(elements.keySet())
categories = new Vector<>(cats); .onUpdateText(this::updateCat)
categories.sort((a,b)->a.toString().compareTo(b.toString())); .onDelete(this::dropCategory);
return new SelectComboBox(categories).onUpdateText(this::updateCat);
} }
private Component datePicker() { private Component datePicker() {
@ -189,6 +191,16 @@ public class Toolbar extends JPanel {
return date; 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() { public Date getDate() {
return date.getSelectedDate(); 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.setMaximumSize(new Dimension(600, 40));
component.setToolTipText("Drücken Sie Umschalt + Entf um einen Eintrag zu löschen");
JPanel panel = new JPanel(); JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add(new JLabel(caption+" ")); panel.add(new JLabel(caption+": "));
panel.add(component); panel.add(component);
return panel; return panel;
} }
@ -232,9 +245,8 @@ public class Toolbar extends JPanel {
scanListeners.forEach(l->l.actionPerformed(evt)); scanListeners.forEach(l->l.actionPerformed(evt));
} }
public void readyToScan(boolean val) { public void readyToScanX(boolean val) {
scanButton.setEnabled(val); scanButton.setEnabled(val);
} }
@ -257,10 +269,8 @@ public class Toolbar extends JPanel {
path = prefix+"fields."+fieldName; path = prefix+"fields."+fieldName;
JSONArray arr = config.getOrCreateArray(path); JSONArray arr = config.getOrCreateArray(path);
TreeSet<Object> values = new TreeSet<>();
arr.forEach(elem -> values.add(elem.toString().trim()));
SelectComboBox selector = getSelector(additonalComponents.get(fieldName)); 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"); LOG.debug("Trying to read size");
@ -274,6 +284,17 @@ public class Toolbar extends JPanel {
} else LOG.debug("newCat is empty!"); } 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() { protected void updateDimensions() {
LOG.debug("updateDimensions()"); LOG.debug("updateDimensions()");
try { try {

Loading…
Cancel
Save