diff --git a/gui/pom.xml b/gui/pom.xml
index 64fa5ab6..42474db0 100644
--- a/gui/pom.xml
+++ b/gui/pom.xml
@@ -31,6 +31,18 @@
imageio-tiff
3.4.1
+
+ org.checkerframework
+ checker
+
+
+ org.checkerframework
+ checker-qual
+
+
+ org.checkerframework
+ jdk8
+
junit
junit
@@ -41,6 +53,28 @@
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+ org.checkerframework
+ checker
+ ${checker-framework.version}
+
+
+
+
+ org.checkerframework.checker.nullness.NullnessChecker
+
+
+
+ -Xbootclasspath/p:${annotatedJdk}
+ -Awarns
+
+
+
org.codehaus.mojo
exec-maven-plugin
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/controller/TesseractController.java b/gui/src/main/java/de/vorb/tesseract/gui/controller/TesseractController.java
index d11f7db7..a5ae56f1 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/controller/TesseractController.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/controller/TesseractController.java
@@ -4,24 +4,24 @@
import de.vorb.tesseract.gui.io.BoxFileWriter;
import de.vorb.tesseract.gui.io.PlainTextWriter;
import de.vorb.tesseract.gui.model.ApplicationMode;
-import de.vorb.tesseract.gui.model.BatchExportModel;
-import de.vorb.tesseract.gui.model.BoxFileModel;
+import de.vorb.tesseract.gui.model.BatchExport;
+import de.vorb.tesseract.gui.model.BoxFile;
import de.vorb.tesseract.gui.model.FilteredListModel;
-import de.vorb.tesseract.gui.model.ImageModel;
-import de.vorb.tesseract.gui.model.PageModel;
+import de.vorb.tesseract.gui.model.Image;
+import de.vorb.tesseract.gui.model.Page;
import de.vorb.tesseract.gui.model.PageThumbnail;
import de.vorb.tesseract.gui.model.PreferencesUtil;
-import de.vorb.tesseract.gui.model.ProjectModel;
+import de.vorb.tesseract.gui.model.Project;
import de.vorb.tesseract.gui.model.SymbolListModel;
import de.vorb.tesseract.gui.model.SymbolOrder;
import de.vorb.tesseract.gui.util.DocumentWriter;
-import de.vorb.tesseract.gui.view.BoxFileModelComponent;
+import de.vorb.tesseract.gui.view.BoxFileComponent;
import de.vorb.tesseract.gui.view.EvaluationPane;
import de.vorb.tesseract.gui.view.FeatureDebugger;
import de.vorb.tesseract.gui.view.FilteredTable;
-import de.vorb.tesseract.gui.view.ImageModelComponent;
+import de.vorb.tesseract.gui.view.ImageComponent;
import de.vorb.tesseract.gui.view.MainComponent;
-import de.vorb.tesseract.gui.view.PageModelComponent;
+import de.vorb.tesseract.gui.view.PageComponent;
import de.vorb.tesseract.gui.view.PreprocessingPane;
import de.vorb.tesseract.gui.view.SymbolOverview;
import de.vorb.tesseract.gui.view.TesseractFrame;
@@ -55,6 +55,7 @@
import eu.digitisation.input.Parameters;
import eu.digitisation.input.WarningException;
import eu.digitisation.output.Report;
+import org.checkerframework.checker.nullness.qual.Nullable;
import javax.imageio.ImageIO;
import javax.swing.DefaultListModel;
@@ -91,6 +92,7 @@
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
+import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
@@ -109,6 +111,10 @@
import java.util.TreeMap;
import java.util.prefs.Preferences;
+import static java.nio.file.StandardOpenOption.CREATE;
+import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+import static java.nio.file.StandardOpenOption.WRITE;
+
public class TesseractController extends WindowAdapter implements
ActionListener, ListSelectionListener, Observer, ChangeListener {
@@ -141,13 +147,10 @@ private static void setLookAndFeel() {
}
}
- // constants
private static final String KEY_TRAINING_FILE = "training_file";
private static final String KEY_BOX_FILE = "box_file";
+ private static final OpenOption[] CREATE_OR_REPLACE = {CREATE, WRITE, TRUNCATE_EXISTING};
- public static final Preprocessor DEFAULT_PREPROCESSOR = new DefaultPreprocessor();
-
- // components references
private final TesseractFrame view;
private ApplicationMode mode = ApplicationMode.NONE;
@@ -156,34 +159,33 @@ private static void setLookAndFeel() {
private MainComponent activeComponent;
private final PageRecognitionProducer pageRecognitionProducer;
- private Optional preprocessingWorker = Optional.empty();
+ private PreprocessingWorker preprocessingWorker = null;
// IO workers, timers and tasks
- private Optional thumbnailLoader = Optional.empty();
+ private ThumbnailWorker thumbnailLoader = null;
private final Timer pageSelectionTimer = new Timer("PageSelectionTimer");
- private Optional lastPageSelectionTask = Optional.empty();
+ private TimerTask lastPageSelectionTask = null;
private final Timer thumbnailLoadTimer = new Timer("ThumbnailLoadTimer");
- private Optional lastThumbnailLoadTask = Optional.empty();
+ private TimerTask lastThumbnailLoadTask = null;
private final List tasks = new LinkedList<>();
- // models
- private Optional projectModel = Optional.empty();
- private Optional pageThumbnail = Optional.empty();
+ @Nullable
+ private Project project = null;
+ private PageThumbnail pageThumbnail = null;
private String lastTraineddataFile;
- // preprocessing
private Preprocessor defaultPreprocessor = new DefaultPreprocessor();
private final Map preprocessors = new HashMap<>();
private Set changedPreprocessors = new HashSet<>();
- private Optional recognitionWorker = Optional.empty();
+ private RecognitionWorker recognitionWorker = null;
- public TesseractController() {
+ private TesseractController() {
// create new tesseract frame
view = new TesseractFrame();
featureDebugger = new FeatureDebugger(view);
@@ -358,32 +360,31 @@ public void actionPerformed(ActionEvent evt) {
}
}
- public Optional getPageModel() {
+ @Nullable
+ private Page getPage() {
final MainComponent active = view.getActiveComponent();
- if (active instanceof PageModelComponent) {
- return ((PageModelComponent) active).getPageModel();
+ if (active instanceof PageComponent) {
+ return ((PageComponent) active).getPage();
}
- return Optional.empty();
+ return null;
}
public PageRecognitionProducer getPageRecognitionProducer() {
return pageRecognitionProducer;
}
- public Optional getProjectModel() {
- return projectModel;
+ @Nullable
+ public Project getProject() {
+ return project;
}
- public Optional getSelectedPage() {
+ @Nullable
+ private Path getSelectedPage() {
final PageThumbnail thumbnail = view.getPages().getList().getSelectedValue();
- if (thumbnail == null) {
- return Optional.empty();
- } else {
- return Optional.of(thumbnail.getFile());
- }
+ return Optional.ofNullable(thumbnail).map(PageThumbnail::getFile).orElse(null);
}
public Optional getTrainingFile() {
@@ -405,38 +406,38 @@ private void handleActiveComponentChange() {
if (mode == ApplicationMode.BOX_FILE) {
// if we're in box file mode, everything is simple
if (active == view.getBoxEditor()) {
- view.getBoxEditor().setBoxFileModel(view.getSymbolOverview().getBoxFileModel());
+ view.getBoxEditor().setBoxFile(view.getSymbolOverview().getBoxFile());
} else {
- view.getSymbolOverview().setBoxFileModel(view.getBoxEditor().getBoxFileModel());
+ view.getSymbolOverview().setBoxFile(view.getBoxEditor().getBoxFile());
}
} else if (mode == ApplicationMode.PROJECT) {
// in project mode, it's a bit more complicated
- if (active instanceof ImageModelComponent) {
- if (activeComponent instanceof ImageModelComponent) {
- // ImageModelComponent -> ImageModelComponent
- setImageModel(((ImageModelComponent) activeComponent).getImageModel());
- } else if (activeComponent instanceof PageModelComponent) {
- // PageModelComponent -> ImageModelComponent
- final Optional pm = ((PageModelComponent) activeComponent).getPageModel();
+ if (active instanceof ImageComponent) {
+ if (activeComponent instanceof ImageComponent) {
+ // ImageComponent -> ImageComponent
+ setImage(((ImageComponent) activeComponent).getImage());
+ } else if (activeComponent instanceof PageComponent) {
+ // PageComponent -> ImageComponent
+ final Page pm = ((PageComponent) activeComponent).getPage();
- if (pm.isPresent()) {
- setImageModel(Optional.of(pm.get().getImageModel()));
+ if (pm != null) {
+ setImage(pm.getImage());
} else {
- setImageModel(Optional.empty());
+ setImage(null);
}
} else {
- setImageModel(Optional.empty());
+ setImage(null);
}
- } else if (active instanceof PageModelComponent) {
- if (activeComponent instanceof PageModelComponent) {
- // PageModelComponent -> PageModelComponent
- setPageModel(((PageModelComponent) activeComponent).getPageModel());
- } else if (activeComponent instanceof ImageModelComponent) {
- // ImageModelComponent -> PageModelComponent
- setImageModel(((ImageModelComponent) activeComponent).getImageModel());
+ } else if (active instanceof PageComponent) {
+ if (activeComponent instanceof PageComponent) {
+ // PageComponent -> PageComponent
+ setPage(((PageComponent) activeComponent).getPage());
+ } else if (activeComponent instanceof ImageComponent) {
+ // ImageComponent -> PageComponent
+ setImage(((ImageComponent) activeComponent).getImage());
} else {
- setPageModel(Optional.empty());
+ setPage(null);
}
}
}
@@ -447,19 +448,23 @@ private void handleActiveComponentChange() {
private void handleOpenProjectDirectory() {
if (Desktop.isDesktopSupported()) {
try {
- Desktop.getDesktop().browse(projectModel.get().getProjectDir().toUri());
+ if (project != null) {
+ Desktop.getDesktop().browse(project.getProjectDir().toUri());
+ } else {
+ Dialogs.showError(view, "Exception", "No project directory defined.");
+ }
} catch (IOException e) {
- Dialogs.showError(view, "Exception",
- "Project directory could not be opened.");
+ Dialogs.showError(view, "Exception", "Project directory could not be opened.");
}
}
}
private void handleUseOCRResult() {
- if (getPageModel().isPresent()) {
+ final Page page = getPage();
+ if (page != null) {
final StringWriter ocrResult = new StringWriter();
try {
- new PlainTextWriter(true).write(getPageModel().get().getPage(), ocrResult);
+ new PlainTextWriter(true).write(page.getPage(), ocrResult);
view.getEvaluationPane().getTextAreaTranscript().setText(ocrResult.toString());
} catch (IOException e) {
@@ -473,48 +478,49 @@ private void handleImportTranscriptions() {
new ImportTranscriptionDialog();
importDialog.setVisible(true);
- if (importDialog.isApproved() && projectModel.isPresent()) {
+ if (importDialog.isApproved() && project != null) {
final Path file = importDialog.getTranscriptionFile();
final String sep = importDialog.getPageSeparator();
try {
- Files.createDirectories(projectModel.get().getTranscriptionDir());
+ Files.createDirectories(project.getTranscriptionDir());
view.getProgressBar().setIndeterminate(true);
try (final BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
// for every file
- for (final Path imgFile : projectModel.get().getImageFiles()) {
+ for (final Path imgFile : project.getImageFiles()) {
+
final Path filename = FileNames.replaceExtension(imgFile, "txt").getFileName();
- final Path transcription = projectModel.get().getTranscriptionDir().resolve(filename);
+ final Path transcription = project.getTranscriptionDir().resolve(filename);
+
+ try (final BufferedWriter writer = Files.newBufferedWriter(transcription,
+ StandardCharsets.UTF_8, CREATE_OR_REPLACE)) {
- final BufferedWriter writer = Files.newBufferedWriter(transcription, StandardCharsets.UTF_8);
+ int lines = 0;
- int lines = 0;
+ // read file line by line
+ String line;
+ while ((line = reader.readLine()) != null) {
+ // if the line equals the separator, create the next file
+ if (line.equals(sep)) {
+ break;
+ }
- // read file line by line
- String line;
- while ((line = reader.readLine()) != null) {
- // if the line equals the separator, create the next
- // file
- if (line.equals(sep)) {
- break;
+ lines++;
+ // otherwise write the line to the current file
+ writer.write(line);
+ writer.write('\n');
}
- lines++;
- // otherwise write the line to the current file
- writer.write(line);
- writer.write('\n');
- }
+ // if a transcription file is empty, delete it
+ if (lines == 0) {
+ Files.deleteIfExists(transcription);
+ }
- // if a transcription file is empty, delete it
- if (lines == 0) {
- Files.delete(transcription);
+ writer.write('\n');
}
-
- writer.write('\n');
- writer.close();
}
}
@@ -529,21 +535,21 @@ private void handleImportTranscriptions() {
}
private void handleBatchExport() {
- final Optional export = BatchExportDialog.showBatchExportDialog(this);
+ final Optional export = BatchExportDialog.showBatchExportDialog(this);
if (export.isPresent()) {
- final BatchExecutor batchExec = new BatchExecutor(this, this.getProjectModel().get(), export.get());
+ final Project project = this.getProject();
+ final BatchExecutor batchExec = new BatchExecutor(this, project, export.get());
try {
- final int totalFiles =
- (int) Lists.newArrayList(this.getProjectModel().get().getImageFiles()).stream().count();
+ final int totalFiles = Lists.newArrayList(project.getImageFiles()).size();
final ProgressMonitor progressMonitor = new ProgressMonitor(view, "Processing:", "", 0, totalFiles + 1);
progressMonitor.setProgress(0);
try (final BufferedWriter errorLog = Files.newBufferedWriter(
- export.get().getDestinationDir().resolve("errors.log"),
- StandardCharsets.UTF_8)) {
+ export.get().getDestinationDir().resolve("errors.log"), StandardCharsets.UTF_8,
+ CREATE_OR_REPLACE)) {
batchExec.start(progressMonitor, errorLog);
@@ -557,9 +563,9 @@ private void handleBatchExport() {
private void handleCompareSymbolToPrototype() {
final Symbol selected = view.getSymbolOverview().getSymbolVariantList().getList().getSelectedValue();
- final Optional pm = getPageModel();
- if (pm.isPresent()) {
- final BufferedImage pageImg = pm.get().getImageModel().getPreprocessedImage();
+ final Page pm = getPage();
+ if (pm != null) {
+ final BufferedImage pageImg = pm.getImage().getPreprocessedImage();
final Box symbolBox = selected.getBoundingBox();
final BufferedImage symbolImg = pageImg.getSubimage(
symbolBox.getX(), symbolBox.getY(),
@@ -580,11 +586,11 @@ private void handleGenerateReport() {
return;
}
- final Path sourceFile = getPageModel().get().getImageModel().getSourceFile();
+ final Path sourceFile = getPage().getImage().getSourceFile();
final Path fname = FileNames.replaceExtension(sourceFile, "txt").getFileName();
final Path repName = FileNames.replaceExtension(fname, "html");
- final Path plain = projectModel.get().getOCRDir().resolve(fname);
- final Path report = projectModel.get().getEvaluationDir().resolve(repName);
+ final Path plain = project.getOCRDir().resolve(fname);
+ final Path report = project.getEvaluationDir().resolve(repName);
try {
final Path equivalencesFile = prepareReports();
@@ -607,9 +613,9 @@ private void handleGenerateReport() {
}
public Path prepareReports() throws IOException {
- Files.createDirectories(projectModel.get().getEvaluationDir());
+ Files.createDirectories(project.getEvaluationDir());
- final Path equivalencesFile = projectModel.get().getProjectDir().resolve("character_equivalences.csv");
+ final Path equivalencesFile = project.getProjectDir().resolve("character_equivalences.csv");
if (!Files.exists(equivalencesFile)) {
// copy the default character equivalences to the equivalences file
@@ -634,18 +640,17 @@ public Path prepareReports() throws IOException {
private Optional handleTranscriptionSave() {
try {
- if (projectModel.isPresent() && getPageModel().isPresent()) {
- Files.createDirectories(
- projectModel.get().getTranscriptionDir());
+ final Page page = getPage();
+ if (project != null && page != null) {
+ Files.createDirectories(project.getTranscriptionDir());
- final Path sourceFile =
- getPageModel().get().getImageModel().getSourceFile();
- final Path fileName =
- FileNames.replaceExtension(sourceFile, "txt").getFileName();
+ final Path sourceFile = page.getImage().getSourceFile();
+ final Path fileName = FileNames.replaceExtension(sourceFile, "txt").getFileName();
- final Path transcriptionFile = projectModel.get().getTranscriptionDir().resolve(fileName);
+ final Path transcriptionFile = project.getTranscriptionDir().resolve(fileName);
- try (final Writer writer = Files.newBufferedWriter(transcriptionFile, StandardCharsets.UTF_8)) {
+ try (final Writer writer = Files.newBufferedWriter(transcriptionFile, StandardCharsets.UTF_8,
+ CREATE_OR_REPLACE)) {
final String transcription = view.getEvaluationPane().getTextAreaTranscript().getText();
@@ -668,35 +673,33 @@ private void handleNewProject() {
return;
}
- final Optional result = NewProjectDialog.showDialog(view);
+ final Optional result = NewProjectDialog.showDialog(view);
if (!result.isPresent()) {
return;
}
- setProjectModel(result);
+ setProject(result.get());
- projectModel = result;
- final ProjectModel projectModel = result.get();
+ final Project project = result.get();
final DefaultListModel pages = view.getPages().getListModel();
- final ThumbnailWorker thumbnailLoader = new ThumbnailWorker(projectModel, pages);
+ this.thumbnailLoader = new ThumbnailWorker(project, pages);
thumbnailLoader.execute();
- this.thumbnailLoader = Optional.of(thumbnailLoader);
- final PageListWorker pageListLoader = new PageListWorker(projectModel, pages);
+ final PageListWorker pageListLoader = new PageListWorker(project, pages);
pageListLoader.execute();
setApplicationMode(ApplicationMode.PROJECT);
}
- private void setProjectModel(Optional model) {
- projectModel = model;
+ private void setProject(@Nullable Project project) {
+ this.project = project;
- if (model.isPresent()) {
- view.setTitle(String.format("tesseract4java - %s", model.get().getProjectName()));
+ if (project != null) {
+ view.setTitle(String.format("tesseract4java - %s", project.getName()));
} else {
view.setTitle("tesseract4java");
@@ -756,7 +759,7 @@ public boolean accept(File f) {
PreferencesUtil.getPreferences().put(KEY_BOX_FILE, boxFile.toAbsolutePath().toString());
- setBoxFileModel(Optional.of(new BoxFileModel(boxFile, image, boxes)));
+ setBoxFile(new BoxFile(boxFile, image, boxes));
} catch (IOException | IndexOutOfBoundsException e) {
Dialogs.showError(view, "Error", "Box file could not be opened.");
}
@@ -791,8 +794,7 @@ public boolean accept(File f) {
private void handleSaveProject() {
// TODO fix me
- final JFileChooser fc = new JFileChooser(
- projectModel.get().getProjectDir().toFile());
+ final JFileChooser fc = new JFileChooser(project.getProjectDir().toFile());
fc.setFileFilter(new FileFilter() {
@Override
public String getDescription() {
@@ -812,11 +814,11 @@ public boolean accept(File f) {
}
private void handleSaveBoxFile() {
- final Optional boxFileModel = getBoxFileModel();
+ final BoxFile boxFile = getBoxFile();
- if (boxFileModel.isPresent()) {
+ if (boxFile != null) {
try {
- BoxFileWriter.writeBoxFile(boxFileModel.get());
+ BoxFileWriter.writeBoxFile(boxFile);
Dialogs.showInfo(view, "Saved", "The box file has been saved.");
} catch (IOException e) {
@@ -827,25 +829,25 @@ private void handleSaveBoxFile() {
}
}
- private Optional getBoxFileModel() {
+ @Nullable
+ private BoxFile getBoxFile() {
if (mode == ApplicationMode.NONE) {
- return Optional.empty();
+ return null;
} else if (mode == ApplicationMode.BOX_FILE) {
// first check box editor, then symbol overview
- final Optional model = view.getBoxEditor().getBoxFileModel();
-
- if (model.isPresent()) {
- return model;
- } else {
- return view.getSymbolOverview().getBoxFileModel();
+ final TesseractFrame view = getView();
+ if (view == null) {
+ return null;
}
+ return Optional.ofNullable(view.getBoxEditor().getBoxFile())
+ .orElseGet(() -> view.getSymbolOverview().getBoxFile());
} else {
final MainComponent active = view.getActiveComponent();
- if (active instanceof PageModelComponent) {
- return ((PageModelComponent) active).getBoxFileModel();
+ if (active instanceof PageComponent) {
+ return ((PageComponent) active).getBoxFile();
} else {
- return Optional.empty();
+ return null;
}
}
}
@@ -854,8 +856,8 @@ private boolean handleCloseProject() {
final boolean really = Dialogs.ask(view, "Confirmation", "Do you really want to close this project?");
if (really) {
- setPageModel(Optional.empty());
- setProjectModel(Optional.empty());
+ setPage(null);
+ setProject(null);
setApplicationMode(ApplicationMode.NONE);
}
@@ -867,7 +869,7 @@ private boolean handleCloseBoxFile() {
"Do you really want to close this box file? All unsaved changes will be lost.");
if (really) {
- setBoxFileModel(Optional.empty());
+ setBoxFile(null);
setApplicationMode(ApplicationMode.NONE);
}
@@ -895,7 +897,7 @@ private void handlePageSelection() {
if (!changePage) {
// reselect the old page
- view.getPages().getList().setSelectedValue(pageThumbnail.get(), true);
+ view.getPages().getList().setSelectedValue(pageThumbnail, true);
// don't change the page
return;
}
@@ -903,11 +905,11 @@ private void handlePageSelection() {
view.getSymbolOverview().freeResources();
}
- pageThumbnail = Optional.of(pt);
+ pageThumbnail = pt;
// cancel the last page loading task if it is present
- if (lastPageSelectionTask.isPresent()) {
- lastPageSelectionTask.get().cancel();
+ if (lastPageSelectionTask != null) {
+ lastPageSelectionTask.cancel();
}
// new task
@@ -915,18 +917,16 @@ private void handlePageSelection() {
@Override
public void run() {
// cancel last task
- if (preprocessingWorker.isPresent()) {
- preprocessingWorker.get().cancel(false);
+ if (preprocessingWorker != null) {
+ preprocessingWorker.cancel(false);
}
// create SwingWorker to preprocess page
- final PreprocessingWorker pw = new PreprocessingWorker(
- TesseractController.this,
- getPreprocessor(pt.getFile()), pt.getFile(),
- getProjectModel().get().getPreprocessedDir());
+ final PreprocessingWorker pw = new PreprocessingWorker(TesseractController.this,
+ getPreprocessor(pt.getFile()), pt.getFile(), getProject().getPreprocessedDir());
// save reference
- preprocessingWorker = Optional.of(pw);
+ preprocessingWorker = pw;
view.getProgressBar().setIndeterminate(true);
// execute it
@@ -939,7 +939,7 @@ public void run() {
pageSelectionTimer.schedule(task, 500);
// set as new timer task
- lastPageSelectionTask = Optional.of(task);
+ lastPageSelectionTask = task;
}
private void handleShowSymbolInBoxEditor() {
@@ -965,8 +965,9 @@ private void handleShowSymbolInBoxEditor() {
}
private void handleSymbolGroupSelection() {
- final JList>> selectionList =
- view.getSymbolOverview().getSymbolGroupList().getList();
+ final JList>> selectionList = view.getSymbolOverview()
+ .getSymbolGroupList()
+ .getList();
final int index = selectionList.getSelectedIndex();
if (index == -1) {
@@ -975,13 +976,13 @@ private void handleSymbolGroupSelection() {
final List symbols = selectionList.getModel().getElementAt(index).getValue();
- final Optional bfm = view.getSymbolOverview().getBoxFileModel();
+ final BoxFile boxFile = view.getSymbolOverview().getBoxFile();
- if (!bfm.isPresent()) {
+ if (boxFile == null) {
return;
}
- final SymbolListModel model = new SymbolListModel(bfm.get().getImage());
+ final SymbolListModel model = new SymbolListModel(boxFile.getImage());
symbols.forEach(model::addElement);
// get combo box
@@ -1006,16 +1007,18 @@ private void handleSymbolReordering() {
}
private void handleThumbnailLoading() {
- if (!thumbnailLoader.isPresent()) {
+ if (thumbnailLoader == null) {
return;
}
- final ThumbnailWorker thumbnailLoader = this.thumbnailLoader.get();
+ final ThumbnailWorker thumbnailLoader = this.thumbnailLoader;
tasks.forEach(Task::cancel);
tasks.clear();
- lastThumbnailLoadTask.ifPresent(TimerTask::cancel);
+ if (lastThumbnailLoadTask != null) {
+ lastThumbnailLoadTask.cancel();
+ }
thumbnailLoadTimer.schedule(new TimerTask() {
@Override
@@ -1031,7 +1034,7 @@ public void run() {
for (int i = first; i <= last; i++) {
final PageThumbnail pt = model.getElementAt(i);
- if (pt == null || pt.getThumbnail().isPresent()) {
+ if (pt == null || pt.getThumbnail() != null) {
continue;
}
@@ -1071,18 +1074,18 @@ private void handleTraineddataFileSelection() {
}
private void handlePreprocessorPreview() {
- final Optional selectedPage = getSelectedPage();
+ final Path selectedPage = getSelectedPage();
// if no page is selected, simply ignore it
- if (!selectedPage.isPresent()) {
+ if (selectedPage == null) {
Dialogs.showWarning(view, "No page selection",
"No page has been selected. You need to select a page first.");
return;
}
- final Optional projectModel = getProjectModel();
+ final Project project = getProject();
- if (!projectModel.isPresent()) {
+ if (project == null) {
Dialogs.showWarning(view, "No project",
"No project has been selected. You need to create a project first.");
return;
@@ -1091,15 +1094,14 @@ private void handlePreprocessorPreview() {
final Preprocessor preprocessor =
view.getPreprocessingPane().getPreprocessor();
- if (preprocessingWorker.isPresent()) {
- preprocessingWorker.get().cancel(false);
+ if (preprocessingWorker != null) {
+ preprocessingWorker.cancel(false);
}
- final PreprocessingWorker pw = new PreprocessingWorker(this,
- preprocessor, selectedPage.get(),
- projectModel.get().getProjectDir());
+ final PreprocessingWorker pw = new PreprocessingWorker(this, preprocessor, selectedPage,
+ project.getProjectDir());
- preprocessingWorker = Optional.of(pw);
+ preprocessingWorker = pw;
view.getProgressBar().setIndeterminate(true);
pw.execute();
@@ -1114,11 +1116,11 @@ private void handlePreprocessorChange(boolean allPages) {
defaultPreprocessor = preprocessor;
preprocessors.clear();
- if (getSelectedPage().isPresent()) {
+ if (getSelectedPage() != null) {
handlePreprocessorPreview();
}
- } else if (getSelectedPage().isPresent()) {
- setPreprocessor(getSelectedPage().get(), preprocessor);
+ } else if (getSelectedPage() != null) {
+ setPreprocessor(getSelectedPage(), preprocessor);
handlePreprocessorPreview();
}
@@ -1172,8 +1174,7 @@ public boolean accept(File f) {
if (approved == JFileChooser.APPROVE_OPTION) {
final Path textFile = fc.getSelectedFile().toPath();
- try {
- final BufferedReader reader = Files.newBufferedReader(textFile, StandardCharsets.UTF_8);
+ try (final BufferedReader reader = Files.newBufferedReader(textFile, StandardCharsets.UTF_8)) {
final Map histogram = new TreeMap<>();
@@ -1241,31 +1242,33 @@ private void handleTesseractTrainer() {
trainer.setVisible(true);
}
- public void setPageModel(Optional model) {
- if (projectModel.isPresent() && model.isPresent()) {
+ public void setPage(@Nullable final Page page) {
+
+ Page updatedPage = page;
+ if (project != null && page != null) {
try {
// plain text file name
final Path filename =
- FileNames.replaceExtension(model.get().getImageModel().getSourceFile().getFileName(), "txt");
+ FileNames.replaceExtension(page.getImage().getSourceFile().getFileName(), "txt");
// create ocr directory
- Files.createDirectories(projectModel.get().getOCRDir());
+ Files.createDirectories(project.getOCRDir());
// write the plain text ocr file
- final Path plain = projectModel.get().getOCRDir().resolve(filename);
+ final Path plain = project.getOCRDir().resolve(filename);
final Writer writer = Files.newBufferedWriter(plain, StandardCharsets.UTF_8);
- new PlainTextWriter(true).write(model.get().getPage(), writer);
+ new PlainTextWriter(true).write(page.getPage(), writer);
writer.close();
// read the transcription file
- final Path transcriptionFile = projectModel.get().getTranscriptionDir().resolve(filename);
+ final Path transcriptionFile = project.getTranscriptionDir().resolve(filename);
if (Files.isRegularFile(transcriptionFile)) {
final byte[] bytes = Files.readAllBytes(transcriptionFile);
final String transcription = new String(bytes, StandardCharsets.UTF_8);
- model = Optional.of(model.get().withTranscription(transcription));
+ updatedPage = page.withTranscription(transcription);
}
} catch (IOException e) {
e.printStackTrace();
@@ -1274,35 +1277,34 @@ public void setPageModel(Optional model) {
final MainComponent active = view.getActiveComponent();
- if (active instanceof PageModelComponent) {
- ((PageModelComponent) active).setPageModel(model);
- } else if (active instanceof BoxFileModelComponent) {
- if (model.isPresent()) {
- ((BoxFileModelComponent) active).setBoxFileModel(Optional.of(model.get().toBoxFileModel()));
- } else {
- ((BoxFileModelComponent) active).setBoxFileModel(Optional.empty());
- }
+ if (active instanceof PageComponent) {
+ ((PageComponent) active).setPage(updatedPage);
+ }
+
+ if (active instanceof BoxFileComponent) {
+ final BoxFile boxFile = Optional.ofNullable(updatedPage).map(Page::toBoxFile).orElse(null);
+ ((BoxFileComponent) active).setBoxFile(boxFile);
}
}
- public void setBoxFileModel(Optional model) {
+ private void setBoxFile(@Nullable BoxFile boxFile) {
final MainComponent active = view.getActiveComponent();
- if (active instanceof BoxFileModelComponent) {
- ((BoxFileModelComponent) active).setBoxFileModel(model);
+ if (active instanceof BoxFileComponent) {
+ ((BoxFileComponent) active).setBoxFile(boxFile);
} else {
Dialogs.showWarning(view, "Illegal Action", "Could not set the box file");
}
}
- public void setImageModel(Optional model) {
+ public void setImage(@Nullable Image image) {
view.getProgressBar().setIndeterminate(false);
final MainComponent active = view.getActiveComponent();
- if (active instanceof PageModelComponent) {
- ((PageModelComponent) active).setPageModel(Optional.empty());
+ if (active instanceof PageComponent) {
+ ((PageComponent) active).setPage(null);
- if (recognitionWorker.isPresent()) {
- recognitionWorker.get().cancel(false);
+ if (recognitionWorker != null) {
+ recognitionWorker.cancel(false);
}
final Optional trainingFile = getTrainingFile();
@@ -1310,36 +1312,35 @@ public void setImageModel(Optional model) {
if (!trainingFile.isPresent()) {
Dialogs.showWarning(view, "Warning", "Please select a traineddata file.");
return;
- } else if (!model.isPresent()) {
+ } else if (image == null) {
return;
}
- final RecognitionWorker rw = new RecognitionWorker(this, model.get(), trainingFile.get());
+ final RecognitionWorker rw = new RecognitionWorker(this, image, trainingFile.get());
rw.execute();
- recognitionWorker = Optional.of(rw);
+ recognitionWorker = rw;
return;
- } else if (!(active instanceof ImageModelComponent)) {
+ } else if (!(active instanceof ImageComponent)) {
return;
}
- if (!model.isPresent()) {
- ((ImageModelComponent) active).setImageModel(model);
+ if (image == null) {
+ ((ImageComponent) active).setImage(null);
return;
}
- final Path sourceFile = model.get().getSourceFile();
- final Optional selectedPage = getSelectedPage();
+ final Path sourceFile = image.getSourceFile();
+ final Path selectedPage = getSelectedPage();
- if (!selectedPage.isPresent() || !sourceFile.equals(selectedPage.get())) {
-
- ((ImageModelComponent) active).setImageModel(Optional.empty());
+ if (!sourceFile.equals(selectedPage)) {
+ ((ImageComponent) active).setImage(null);
return;
}
- ((ImageModelComponent) active).setImageModel(model);
+ ((ImageComponent) active).setImage(image);
}
// TODO prototype loading?
@@ -1426,12 +1427,12 @@ public void windowClosing(WindowEvent e) {
pageSelectionTimer.cancel();
thumbnailLoadTimer.cancel();
- if (preprocessingWorker.isPresent()) {
- preprocessingWorker.get().cancel(true);
+ if (preprocessingWorker != null) {
+ preprocessingWorker.cancel(true);
}
- if (recognitionWorker.isPresent()) {
- recognitionWorker.get().cancel(true);
+ if (recognitionWorker != null) {
+ recognitionWorker.cancel(true);
}
view.dispose();
@@ -1448,10 +1449,6 @@ public void windowClosed(WindowEvent evt) {
}
}
- public Preprocessor getDefaultPreprocessor() {
- return defaultPreprocessor;
- }
-
public Preprocessor getPreprocessor(Path sourceFile) {
final Preprocessor preprocessor = preprocessors.get(sourceFile);
@@ -1467,11 +1464,7 @@ public boolean hasPreprocessorChanged(Path sourceFile) {
return changedPreprocessors.contains(sourceFile);
}
- public void setDefaultPreprocessor(Preprocessor preprocessor) {
- defaultPreprocessor = preprocessor;
- }
-
- public void setPreprocessor(Path sourceFile, Preprocessor preprocessor) {
+ private void setPreprocessor(Path sourceFile, Preprocessor preprocessor) {
if (preprocessor.equals(defaultPreprocessor)) {
preprocessors.remove(sourceFile);
} else {
@@ -1479,15 +1472,7 @@ public void setPreprocessor(Path sourceFile, Preprocessor preprocessor) {
}
}
- public void setPreprocessorChanged(Path sourceFile, boolean changed) {
- if (changed) {
- changedPreprocessors.add(sourceFile);
- } else {
- changedPreprocessors.remove(sourceFile);
- }
- }
-
- public void setApplicationMode(ApplicationMode mode) {
+ private void setApplicationMode(ApplicationMode mode) {
this.mode = mode;
final JTabbedPane mainTabs = view.getMainTabs();
@@ -1535,7 +1520,4 @@ public void setApplicationMode(ApplicationMode mode) {
.setVisible(projectEnabled);
}
- public ApplicationMode getApplicationMode() {
- return mode;
- }
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/controller/package-info.java b/gui/src/main/java/de/vorb/tesseract/gui/controller/package-info.java
deleted file mode 100644
index 69889f5a..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/controller/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Controller classes for TesseractGUI.
- *
- * @author Paul Vorbach
- */
-package de.vorb.tesseract.gui.controller;
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/event/package-info.java b/gui/src/main/java/de/vorb/tesseract/gui/event/package-info.java
deleted file mode 100644
index 0969d2ac..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/event/package-info.java
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * @author Paul Vorbach
- */
-/**
- * @author Paul Vorbach
- *
- */
-package de.vorb.tesseract.gui.event;
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/io/BoxFileReader.java b/gui/src/main/java/de/vorb/tesseract/gui/io/BoxFileReader.java
index dacafefc..68eb3733 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/io/BoxFileReader.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/io/BoxFileReader.java
@@ -3,43 +3,48 @@
import de.vorb.tesseract.util.Box;
import de.vorb.tesseract.util.Symbol;
-import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
public final class BoxFileReader {
- private BoxFileReader() {}
+ private BoxFileReader() {
+ }
+
+ private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+");
public static List readBoxFile(Path boxFile, int pageHeight)
throws IOException {
- final List boxes = new LinkedList<>();
- try (final BufferedReader boxReader = Files.newBufferedReader(boxFile, StandardCharsets.UTF_8)) {
- String line;
- while ((line = boxReader.readLine()) != null) {
- final String[] components = line.split("\\s+");
- if (components.length < 5) {
- continue;
- }
+ return Files.lines(boxFile, StandardCharsets.UTF_8)
+ .map(WHITESPACE_PATTERN::split)
+ .filter(components -> components.length >= 5)
+ .map(symbolParser(pageHeight))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
+ private static Function symbolParser(int pageHeight) {
+ return (String[] components) -> {
+ try {
final String text = components[0];
final int x = Integer.parseInt(components[1]);
final int y = Integer.parseInt(components[2]);
final int w = Integer.parseInt(components[3]) - x;
final int h = Integer.parseInt(components[4]) - y;
- boxes.add(new Symbol(text,
- new Box(x, pageHeight - y - h, w, h), 0f));
+ final Box boundingBox = new Box(x, pageHeight - y - h, w, h);
+ return new Symbol(text, boundingBox, 0f);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Could not parse line \"" + String.join(" ", components) + '"', e);
}
- } catch (NumberFormatException e) {
- throw new IOException();
- }
-
- return boxes;
+ };
}
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/io/BoxFileWriter.java b/gui/src/main/java/de/vorb/tesseract/gui/io/BoxFileWriter.java
index 8a72ce0c..ffda1dfe 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/io/BoxFileWriter.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/io/BoxFileWriter.java
@@ -1,6 +1,6 @@
package de.vorb.tesseract.gui.io;
-import de.vorb.tesseract.gui.model.BoxFileModel;
+import de.vorb.tesseract.gui.model.BoxFile;
import de.vorb.tesseract.util.Box;
import de.vorb.tesseract.util.Symbol;
@@ -9,28 +9,31 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
+import static java.nio.file.StandardOpenOption.CREATE;
+import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+import static java.nio.file.StandardOpenOption.WRITE;
+
public final class BoxFileWriter {
- private BoxFileWriter() {}
+ private BoxFileWriter() {
+ }
- public static void writeBoxFile(BoxFileModel model) throws IOException {
- final BufferedWriter boxFileWriter = Files.newBufferedWriter(
- model.getFile(), StandardCharsets.UTF_8);
+ public static void writeBoxFile(BoxFile boxFile) throws IOException {
+ try (final BufferedWriter boxFileWriter = Files.newBufferedWriter(boxFile.getFilePath(),
+ StandardCharsets.UTF_8, CREATE, TRUNCATE_EXISTING, WRITE)) {
- final int pageHeight = model.getImage().getHeight();
+ final int pageHeight = boxFile.getImage().getHeight();
- for (Symbol symbol : model.getBoxes()) {
+ for (Symbol symbol : boxFile.getBoxes()) {
- final Box boundingBox = symbol.getBoundingBox();
- final int x0 = boundingBox.getX();
- final int y0 = pageHeight - boundingBox.getY() - boundingBox.getHeight();
- final int x1 = x0 + boundingBox.getWidth();
- final int y1 = y0 + boundingBox.getHeight();
+ final Box boundingBox = symbol.getBoundingBox();
+ final int x0 = boundingBox.getX();
+ final int y0 = pageHeight - boundingBox.getY() - boundingBox.getHeight();
+ final int x1 = x0 + boundingBox.getWidth();
+ final int y1 = y0 + boundingBox.getHeight();
- boxFileWriter.write(String.format("%s %d %d %d %d 0\n",
- symbol.getText(), x0, y0, x1, y1));
+ boxFileWriter.write(String.format("%s %d %d %d %d 0\n", symbol.getText(), x0, y0, x1, y1));
+ }
}
-
- boxFileWriter.close();
}
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/BatchExportModel.java b/gui/src/main/java/de/vorb/tesseract/gui/model/BatchExport.java
similarity index 93%
rename from gui/src/main/java/de/vorb/tesseract/gui/model/BatchExportModel.java
rename to gui/src/main/java/de/vorb/tesseract/gui/model/BatchExport.java
index 296a607c..a0a2ca80 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/model/BatchExportModel.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/model/BatchExport.java
@@ -2,7 +2,7 @@
import java.nio.file.Path;
-public class BatchExportModel {
+public class BatchExport {
private final Path destinationDir;
private final boolean exportTXT;
@@ -13,7 +13,7 @@ public class BatchExportModel {
private final boolean openDestination;
private final int numThreads;
- public BatchExportModel(Path destinationDir, boolean exportTXT,
+ public BatchExport(Path destinationDir, boolean exportTXT,
boolean exportHTML, boolean exportXML, boolean exportImages,
boolean exportReports, int numThreads, boolean openDestination) {
this.destinationDir = destinationDir;
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/BoxFileModel.java b/gui/src/main/java/de/vorb/tesseract/gui/model/BoxFile.java
similarity index 78%
rename from gui/src/main/java/de/vorb/tesseract/gui/model/BoxFileModel.java
rename to gui/src/main/java/de/vorb/tesseract/gui/model/BoxFile.java
index f1379f70..6d1d87fb 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/model/BoxFileModel.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/model/BoxFile.java
@@ -7,19 +7,19 @@
import java.util.Collections;
import java.util.List;
-public class BoxFileModel {
- private final Path file;
+public class BoxFile {
+ private final Path filePath;
private final BufferedImage image;
private final List boxes;
- public BoxFileModel(Path file, BufferedImage image, List boxes) {
- this.file = file;
+ public BoxFile(Path filePath, BufferedImage image, List boxes) {
+ this.filePath = filePath;
this.image = image;
this.boxes = boxes;
}
- public Path getFile() {
- return file;
+ public Path getFilePath() {
+ return filePath;
}
public BufferedImage getImage() {
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/FilteredListModel.java b/gui/src/main/java/de/vorb/tesseract/gui/model/FilteredListModel.java
index a86d247d..37c18504 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/model/FilteredListModel.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/model/FilteredListModel.java
@@ -2,26 +2,26 @@
import de.vorb.tesseract.gui.util.Filter;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.AbstractListModel;
import javax.swing.ListModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import java.util.ArrayList;
-import java.util.Optional;
public class FilteredListModel extends AbstractListModel {
+
private static final long serialVersionUID = 1L;
private final ListModel source;
private final ArrayList filtered = new ArrayList<>();
- // if filter is absent, all items are shown
- private Optional> filter = Optional.empty();
+ @NonNull
+ private Filter filter = createMatchAllFilter();
- public FilteredListModel(ListModel source) {
- if (source == null) {
- throw new IllegalArgumentException("model was null");
- }
+ public FilteredListModel(@NonNull ListModel source) {
this.source = source;
@@ -45,17 +45,14 @@ public void contentsChanged(ListDataEvent evt) {
}
private void applyFilter() {
- if (filter.isPresent()) {
- final Filter f = filter.get();
- filtered.clear();
-
- // apply filter to every item in source model
- final int sourceSize = source.getSize();
- for (int i = 0; i < sourceSize; ++i) {
- final T item = source.getElementAt(i);
- if (f.accept(item)) {
- filtered.add(item);
- }
+ filtered.clear();
+
+ // apply filter to every item in source model
+ final int sourceSize = source.getSize();
+ for (int i = 0; i < sourceSize; ++i) {
+ final T item = source.getElementAt(i);
+ if (filter.accept(item)) {
+ filtered.add(item);
}
}
@@ -63,34 +60,32 @@ private void applyFilter() {
fireContentsChanged(this, 0, getSize() - 1);
}
- public void setFilter(Optional> filter) {
+ public void setFilter(@NonNull Filter filter) {
this.filter = filter;
applyFilter();
}
+ @Nullable
@Override
public T getElementAt(int index) {
if (index < 0) {
return null;
}
- if (!filter.isPresent()) {
- return source.getElementAt(index);
- }
-
return filtered.get(index);
}
@Override
public int getSize() {
- if (!filter.isPresent()) {
- return source.getSize();
- }
-
return filtered.size();
}
public ListModel getSource() {
return source;
}
+
+ public static Filter createMatchAllFilter() {
+ return item -> true;
+ }
+
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/FilteredTableModel.java b/gui/src/main/java/de/vorb/tesseract/gui/model/FilteredTableModel.java
index 90fbf1e0..2333e62a 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/model/FilteredTableModel.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/model/FilteredTableModel.java
@@ -9,7 +9,7 @@ public abstract class FilteredTableModel extends AbstractTableModel {
private final FilteredListModel source;
- protected FilteredTableModel(FilteredListModel source) {
+ FilteredTableModel(FilteredListModel source) {
this.source = source;
source.addListDataListener(new ListDataListener() {
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/ImageModel.java b/gui/src/main/java/de/vorb/tesseract/gui/model/Image.java
similarity index 90%
rename from gui/src/main/java/de/vorb/tesseract/gui/model/ImageModel.java
rename to gui/src/main/java/de/vorb/tesseract/gui/model/Image.java
index 5d3cbbce..276bfa05 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/model/ImageModel.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/model/Image.java
@@ -3,14 +3,14 @@
import java.awt.image.BufferedImage;
import java.nio.file.Path;
-public class ImageModel {
+public class Image {
private final Path sourceFile;
private final BufferedImage sourceImage;
private final Path preprocessedFile;
private final BufferedImage preprocessedImage;
- public ImageModel(Path sourceFile, BufferedImage sourceImage,
+ public Image(Path sourceFile, BufferedImage sourceImage,
Path preprocessedFile, BufferedImage preprocessedImage) {
this.sourceFile = sourceFile;
this.sourceImage = sourceImage;
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/Page.java b/gui/src/main/java/de/vorb/tesseract/gui/model/Page.java
new file mode 100644
index 00000000..8b1ad655
--- /dev/null
+++ b/gui/src/main/java/de/vorb/tesseract/gui/model/Page.java
@@ -0,0 +1,56 @@
+package de.vorb.tesseract.gui.model;
+
+import de.vorb.tesseract.util.Symbol;
+import de.vorb.util.FileNames;
+
+import java.awt.image.BufferedImage;
+import java.nio.file.Path;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+public class Page {
+
+ private final Image image;
+ private final de.vorb.tesseract.util.Page page;
+ private final String transcription;
+
+ public Page(Image image, de.vorb.tesseract.util.Page page, String string) {
+ this.image = image;
+ this.page = page;
+ this.transcription = string;
+ }
+
+ public de.vorb.tesseract.util.Page getPage() {
+ return page;
+ }
+
+ public Image getImage() {
+ return image;
+ }
+
+ public String getTranscription() {
+ return transcription;
+ }
+
+ public Page withTranscription(String transcription) {
+ if (transcription.equals(this.transcription)) {
+ return this;
+ }
+
+ return new Page(image, page, transcription);
+ }
+
+ public BoxFile toBoxFile() {
+ final Path boxFile = FileNames.replaceExtension(image.getPreprocessedFile(), "box");
+ final BufferedImage image = this.image.getPreprocessedImage();
+
+ final LinkedList boxes = new LinkedList<>();
+ final Iterator symbolIt = page.symbolIterator();
+ while (symbolIt.hasNext()) {
+ boxes.add(symbolIt.next());
+ }
+
+ return new BoxFile(boxFile, image, boxes);
+ }
+
+}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/PageModel.java b/gui/src/main/java/de/vorb/tesseract/gui/model/PageModel.java
deleted file mode 100644
index 80ca9037..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/model/PageModel.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package de.vorb.tesseract.gui.model;
-
-import de.vorb.tesseract.util.Page;
-import de.vorb.tesseract.util.Symbol;
-import de.vorb.util.FileNames;
-
-import java.awt.image.BufferedImage;
-import java.nio.file.Path;
-import java.util.Iterator;
-import java.util.LinkedList;
-
-public class PageModel {
- private final ImageModel imageModel;
- private final Page page;
- private final String transcription;
-
- public PageModel(ImageModel imageModel, Page page, String string) {
- this.imageModel = imageModel;
- this.page = page;
- this.transcription = string;
- }
-
- public Page getPage() {
- return page;
- }
-
- public ImageModel getImageModel() {
- return imageModel;
- }
-
- public String getTranscription() {
- return transcription;
- }
-
- public PageModel withTranscription(String transcription) {
- if (transcription.equals(this.transcription))
- return this;
-
- return new PageModel(imageModel, page, transcription);
- }
-
- public BoxFileModel toBoxFileModel() {
- final Path boxFile = FileNames.replaceExtension(
- imageModel.getPreprocessedFile(), "box");
- final BufferedImage image = imageModel.getPreprocessedImage();
-
- final LinkedList boxes = new LinkedList<>();
- final Iterator symbolIt = page.symbolIterator();
- while (symbolIt.hasNext()) {
- boxes.add(symbolIt.next());
- }
-
- return new BoxFileModel(boxFile, image, boxes);
- }
-}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/PageThumbnail.java b/gui/src/main/java/de/vorb/tesseract/gui/model/PageThumbnail.java
index ed457822..5ef12545 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/model/PageThumbnail.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/model/PageThumbnail.java
@@ -1,60 +1,61 @@
package de.vorb.tesseract.gui.model;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import java.awt.image.BufferedImage;
import java.nio.file.Path;
-import java.util.Optional;
+import java.util.Objects;
public class PageThumbnail {
+
+ @NonNull
private final Path file;
- private Optional thumbnail;
- public PageThumbnail(Path file, Optional thumbnail) {
+ @Nullable
+ private BufferedImage thumbnail;
+
+ public PageThumbnail(@NonNull Path file, @Nullable BufferedImage thumbnail) {
this.file = file;
this.thumbnail = thumbnail;
}
+ @NonNull
public Path getFile() {
return file;
}
- public Optional getThumbnail() {
+ @Nullable
+ public BufferedImage getThumbnail() {
return thumbnail;
}
- public void setThumbnail(Optional thumbnail) {
+ public void setThumbnail(@Nullable BufferedImage thumbnail) {
this.thumbnail = thumbnail;
}
@Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((file == null) ? 0 : file.hashCode());
- result = prime * result
- + ((thumbnail == null) ? 0 : thumbnail.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
+ public boolean equals(Object o) {
+ if (this == o) {
return true;
- if (obj == null)
- return false;
- if (!(obj instanceof PageThumbnail))
+ }
+ if (o == null || getClass() != o.getClass()) {
return false;
- PageThumbnail other = (PageThumbnail) obj;
- if (file == null) {
- if (other.file != null)
- return false;
- } else if (!file.equals(other.file))
- return false;
- if (thumbnail == null) {
- if (other.thumbnail != null)
- return false;
- } else if (!thumbnail.equals(other.thumbnail))
+ }
+
+ final PageThumbnail that = (PageThumbnail) o;
+
+ if (!file.equals(that.file)) {
return false;
- return true;
+ }
+ return Objects.equals(thumbnail, that.thumbnail);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = file.hashCode();
+ result = 31 * result + (thumbnail != null ? thumbnail.hashCode() : 0);
+ return result;
}
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/Project.java b/gui/src/main/java/de/vorb/tesseract/gui/model/Project.java
new file mode 100644
index 00000000..ce70fb02
--- /dev/null
+++ b/gui/src/main/java/de/vorb/tesseract/gui/model/Project.java
@@ -0,0 +1,82 @@
+package de.vorb.tesseract.gui.model;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class Project {
+
+ private static final String PROJECT_DIR = "tesseract-project";
+ private static final String THUMBNAIL_DIR = "tesseract-project/thumbs";
+ private static final String PREPROCESSED_DIR = "tesseract-project/preprocessed";
+ private static final String TRANSCRIPTION_DIR = "tesseract-project/transcriptions";
+ private static final String OCR_DIR = "tesseract-project/ocr";
+ private static final String EVALUATION_DIR = "tesseract-project/evaluation";
+
+ private final String name;
+
+ private final Path imageDir;
+
+ private final DirectoryStream.Filter filter;
+
+ public Project(Path projectDir, boolean includeTiffFiles, boolean includePngFiles, boolean includeJpegFiles) {
+
+ name = projectDir.getFileName().toString();
+
+ this.imageDir = projectDir;
+
+ //noinspection Convert2Lambda
+ this.filter = new DirectoryStream.Filter() {
+ @Override
+ public boolean accept(Path entry) {
+ final String fileName = entry.getFileName().toString();
+
+ if (includePngFiles && fileName.endsWith(".png")) {
+ return true;
+ } else if (includeTiffFiles && (fileName.endsWith(".tif") || fileName.endsWith(".tiff"))) {
+ return true;
+ } else {
+ return includeJpegFiles && (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg"));
+ }
+ }
+ };
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Path getImageDir() {
+ return imageDir;
+ }
+
+ public Path getProjectDir() {
+ return imageDir.resolve(PROJECT_DIR);
+ }
+
+ public Path getThumbnailDir() {
+ return imageDir.resolve(THUMBNAIL_DIR);
+ }
+
+ public Path getPreprocessedDir() {
+ return imageDir.resolve(PREPROCESSED_DIR);
+ }
+
+ public Path getTranscriptionDir() {
+ return imageDir.resolve(TRANSCRIPTION_DIR);
+ }
+
+ public Path getOCRDir() {
+ return imageDir.resolve(OCR_DIR);
+ }
+
+ public Path getEvaluationDir() {
+ return imageDir.resolve(EVALUATION_DIR);
+ }
+
+ public DirectoryStream getImageFiles() throws IOException {
+ return Files.newDirectoryStream(imageDir, filter);
+ }
+
+}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/ProjectModel.java b/gui/src/main/java/de/vorb/tesseract/gui/model/ProjectModel.java
deleted file mode 100644
index b0d6e4f8..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/model/ProjectModel.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package de.vorb.tesseract.gui.model;
-
-import java.io.IOException;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-public class ProjectModel {
- public static final String PROJECT_DIR = "tesseract-project";
- public static final String THUMBNAIL_DIR = "tesseract-project/thumbs";
- public static final String PREPROCESSED_DIR = "tesseract-project/preprocessed";
- public static final String TRANSCRIPTION_DIR = "tesseract-project/transcriptions";
- public static final String OCR_DIR = "tesseract-project/ocr";
- public static final String EVALUATION_DIR = "tesseract-project/evaluation";
-
- private final String projectName;
-
- private final Path imageDir;
-
- private final boolean tiffFiles;
- private final boolean pngFiles;
- private final boolean jpegFiles;
-
- private final DirectoryStream.Filter filter = entry -> {
- final String e = entry.getFileName().toString();
-
- if (png() && e.endsWith(".png")) {
- return true;
- } else if (tiff() && (e.endsWith(".tif") || e.endsWith(".tiff"))) {
- return true;
- } else {
- return jpeg() && (e.endsWith(".jpg") || e.endsWith(".jpeg"));
- }
- };
-
- public ProjectModel(Path projectDir, boolean tiffFiles, boolean pngFiles, boolean jpegFiles) {
- projectName = projectDir.getFileName().toString();
-
- this.imageDir = projectDir;
-
- this.tiffFiles = tiffFiles;
- this.pngFiles = pngFiles;
- this.jpegFiles = jpegFiles;
- }
-
- public String getProjectName() {
- return projectName;
- }
-
- public Path getImageDir() {
- return imageDir;
- }
-
- public Path getProjectDir() {
- return imageDir.resolve(PROJECT_DIR);
- }
-
- public Path getThumbnailDir() {
- return imageDir.resolve(THUMBNAIL_DIR);
- }
-
- public Path getPreprocessedDir() {
- return imageDir.resolve(PREPROCESSED_DIR);
- }
-
- public Path getTranscriptionDir() {
- return imageDir.resolve(TRANSCRIPTION_DIR);
- }
-
- public Path getOCRDir() {
- return imageDir.resolve(OCR_DIR);
- }
-
- public Path getEvaluationDir() {
- return imageDir.resolve(EVALUATION_DIR);
- }
-
- public Iterable getImageFiles() throws IOException {
- return Files.newDirectoryStream(imageDir, filter);
- }
-
- public boolean tiff() {
- return tiffFiles;
- }
-
- public boolean png() {
- return pngFiles;
- }
-
- public boolean jpeg() {
- return jpegFiles;
- }
-}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/model/package-info.java b/gui/src/main/java/de/vorb/tesseract/gui/model/package-info.java
deleted file mode 100644
index 65111624..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/model/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Model classes.
- *
- * @author Paul Vorbach
- */
-package de.vorb.tesseract.gui.model;
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/util/FilterProvider.java b/gui/src/main/java/de/vorb/tesseract/gui/util/FilterProvider.java
index 353a1b69..fb7f7958 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/util/FilterProvider.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/util/FilterProvider.java
@@ -3,5 +3,7 @@
import java.util.Optional;
public interface FilterProvider {
+
Optional> getFilterFor(String filterText);
+
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/BoxEditor.java b/gui/src/main/java/de/vorb/tesseract/gui/view/BoxEditor.java
index 0fbb340a..5c3244c8 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/BoxEditor.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/BoxEditor.java
@@ -1,7 +1,7 @@
package de.vorb.tesseract.gui.view;
-import de.vorb.tesseract.gui.model.BoxFileModel;
-import de.vorb.tesseract.gui.model.PageModel;
+import de.vorb.tesseract.gui.model.BoxFile;
+import de.vorb.tesseract.gui.model.Page;
import de.vorb.tesseract.gui.model.Scale;
import de.vorb.tesseract.gui.model.SingleSelectionModel;
import de.vorb.tesseract.gui.model.SymbolTableModel;
@@ -11,6 +11,8 @@
import de.vorb.tesseract.util.Point;
import de.vorb.tesseract.util.Symbol;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
@@ -27,8 +29,6 @@
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
@@ -47,15 +47,13 @@
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
-import java.util.ArrayList;
import java.util.Iterator;
-import java.util.List;
import java.util.Optional;
import static de.vorb.tesseract.gui.model.Scale.scaled;
import static de.vorb.tesseract.gui.model.Scale.unscaled;
-public class BoxEditor extends JPanel implements BoxFileModelComponent {
+public class BoxEditor extends JPanel implements BoxFileComponent {
private static final long serialVersionUID = 1L;
private static final Dimension DEFAULT_SPINNER_DIMENSION =
@@ -63,12 +61,12 @@ public class BoxEditor extends JPanel implements BoxFileModelComponent {
private final BoxFileRenderer renderer;
- // state
private final Scale scale;
private boolean changed = false;
- private Optional model = Optional.empty();
- private Optional pageModel = Optional.empty();
+ @Nullable
+ private BoxFile boxFile = null;
+ private Page page = null;
private final SingleSelectionModel selectionModel =
new SingleSelectionModel();
@@ -82,58 +80,7 @@ public class BoxEditor extends JPanel implements BoxFileModelComponent {
private final JSpinner spinnerWidth;
private final JSpinner spinnerHeight;
- // events
- private final List changeListeners = new ArrayList<>();
-
- private final PropertyChangeListener spinnerListener =
- new PropertyChangeListener() {
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if (!evt.getPropertyName().startsWith("SPIN")) {
- return;
- }
-
- // don't do anything if no symbol is selected
- final Optional currentSymbol = getSelectedSymbol();
- if (!currentSymbol.isPresent()) {
- return;
- }
-
- final Object source = evt.getSource();
-
- // if the source is one of the JSpinners for x, y, width and
- // height, update the bounding box
- if (source instanceof JSpinner) {
- // get coordinates
- final int x = (int) spinnerX.getValue();
- final int y = (int) spinnerY.getValue();
- final int width = (int) spinnerWidth.getValue();
- final int height = (int) spinnerHeight.getValue();
-
- // update bounding box
- final Box boundingBox = currentSymbol.get().getBoundingBox();
- boundingBox.setX(x);
- boundingBox.setY(y);
- boundingBox.setWidth(width);
- boundingBox.setHeight(height);
-
- // re-render the whole model
- renderer.render(getBoxFileModel(), scale.current());
- }
-
- // propagate table change
- final JTable table = tabSymbols.getTable();
- table.tableChanged(new TableModelEvent(table.getModel(),
- table.getSelectedRow()));
-
- changed = true;
- }
- };
-
- /**
- * Create the panel.
- */
- public BoxEditor(final Scale scale) {
+ BoxEditor(final Scale scale) {
setLayout(new BorderLayout(0, 0));
renderer = new BoxFileRenderer(this);
@@ -190,7 +137,7 @@ public void contentsChanged(ListDataEvent evt) {
private void update() {
long now = System.currentTimeMillis();
if (now - last > 1000) {
- renderer.render(model, scale.current());
+ renderer.render(boxFile, scale.current());
}
last = now;
}
@@ -244,7 +191,7 @@ public void valueChanged(ListSelectionEvent e) {
selectedRow, 0, true);
tabSymbols.getTable().scrollRectToVisible(cell);
- renderer.render(model, scale.current());
+ renderer.render(boxFile, scale.current());
}
});
@@ -256,11 +203,10 @@ public void valueChanged(ListSelectionEvent e) {
JSplitPane splitMain = new JSplitPane();
add(splitMain, BorderLayout.CENTER);
GridBagLayout gbl_toolbar = new GridBagLayout();
- gbl_toolbar.columnWidths = new int[]{0, 56, 15, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 36, 0, 0};
+ gbl_toolbar.columnWidths = new int[]{0, 56, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0};
gbl_toolbar.rowHeights = new int[]{0, 0};
- gbl_toolbar.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0,
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, Double.MIN_VALUE};
+ gbl_toolbar.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
+ Double.MIN_VALUE};
gbl_toolbar.rowWeights = new double[]{0.0, Double.MIN_VALUE};
toolbar.setLayout(gbl_toolbar);
@@ -402,7 +348,7 @@ public void valueChanged(ListSelectionEvent e) {
btnZoomOut.addActionListener(evt -> {
if (scale.hasPrevious()) {
- renderer.render(getBoxFileModel(), scale.previous());
+ renderer.render(getBoxFile(), scale.previous());
}
if (!scale.hasPrevious()) {
@@ -414,7 +360,7 @@ public void valueChanged(ListSelectionEvent e) {
btnZoomIn.addActionListener(evt -> {
if (scale.hasNext()) {
- renderer.render(getBoxFileModel(), scale.next());
+ renderer.render(getBoxFile(), scale.next());
}
if (!scale.hasNext()) {
@@ -452,7 +398,7 @@ public void mouseReleased(MouseEvent e) {
}
private void clicked(MouseEvent e) {
- if (!model.isPresent()) {
+ if (boxFile == null) {
// ignore clicks if no model is present
return;
}
@@ -460,11 +406,9 @@ private void clicked(MouseEvent e) {
final Point p = new Point(unscaled(e.getX(), scale.current()),
unscaled(e.getY(), scale.current()));
- final Iterator it =
- model.get().getBoxes().iterator();
+ final Iterator it = boxFile.getBoxes().iterator();
- final ListSelectionModel sel =
- tabSymbols.getTable().getSelectionModel();
+ final ListSelectionModel sel = tabSymbols.getTable().getSelectionModel();
boolean selection = false;
for (int i = 0; it.hasNext(); i++) {
@@ -485,7 +429,7 @@ private void clicked(MouseEvent e) {
contextMenu.show(e.getComponent(), e.getX(), e.getY());
}
- renderer.render(model, scale.current());
+ renderer.render(boxFile, scale.current());
}
});
@@ -518,6 +462,54 @@ private void clicked(MouseEvent e) {
lblCanvas.scrollRectToVisible(boundingBox.toRectangle());
});
+ // don't do anything if no symbol is selected
+ // if the source is one of the JSpinners for x, y, width and
+ // height, update the bounding box
+ // get coordinates
+ // update bounding box
+ // re-render the whole boxFile
+ // propagate table change
+ final PropertyChangeListener spinnerListener = (PropertyChangeEvent propertyChangeEvent) -> {
+ if (!propertyChangeEvent.getPropertyName().startsWith("SPIN")) {
+ return;
+ }
+
+ // don't do anything if no symbol is selected
+ final Optional currentSymbol = getSelectedSymbol();
+ if (!currentSymbol.isPresent()) {
+ return;
+ }
+
+ final Object source = propertyChangeEvent.getSource();
+
+ // if the source is one of the JSpinners for x, y, width and
+ // height, update the bounding box
+ if (source instanceof JSpinner) {
+ // get coordinates
+ final int x = (int) spinnerX.getValue();
+ final int y = (int) spinnerY.getValue();
+ final int width = (int) spinnerWidth.getValue();
+ final int height = (int) spinnerHeight.getValue();
+
+ // update bounding box
+ final Box boundingBox = currentSymbol.get().getBoundingBox();
+ boundingBox.setX(x);
+ boundingBox.setY(y);
+ boundingBox.setWidth(width);
+ boundingBox.setHeight(height);
+
+ // re-render the whole boxFile
+ renderer.render(getBoxFile(), scale.current());
+ }
+
+ // propagate table change
+ final JTable table1 = tabSymbols.getTable();
+ table1.tableChanged(new TableModelEvent(table1.getModel(),
+ table1.getSelectedRow()));
+
+ changed = true;
+ };
+
spinnerX.addPropertyChangeListener(spinnerListener);
spinnerY.addPropertyChangeListener(spinnerListener);
spinnerWidth.addPropertyChangeListener(spinnerListener);
@@ -525,8 +517,8 @@ private void clicked(MouseEvent e) {
}
@Override
- public void setBoxFileModel(Optional model) {
- this.model = model;
+ public void setBoxFile(@Nullable BoxFile boxFile) {
+ this.boxFile = boxFile;
final SymbolTableModel tabModel =
(SymbolTableModel) tabSymbols.getTable().getModel();
@@ -536,33 +528,27 @@ public void setBoxFileModel(Optional model) {
source.clear();
- if (model.isPresent()) {
+ if (boxFile != null) {
// fill table model and render the page
- model.get().getBoxes().forEach(source::addElement);
+ boxFile.getBoxes().forEach(source::addElement);
}
- renderer.render(model, scale.current());
+ renderer.render(boxFile, scale.current());
}
- @Override
- public void setPageModel(Optional model) {
- if (model.isPresent()) {
- setBoxFileModel(Optional.of(model.get().toBoxFileModel()));
- pageModel = model;
- } else {
- setBoxFileModel(Optional.empty());
- pageModel = model;
- }
+ public void setPage(Page page) {
+ this.page = page;
+ setBoxFile(Optional.ofNullable(page).map(Page::toBoxFile).orElse(null));
}
@Override
- public Optional getBoxFileModel() {
- return model;
+ public @Nullable BoxFile getBoxFile() {
+ return null;
}
@Override
- public Optional getPageModel() {
- return pageModel;
+ public Page getPage() {
+ return page;
}
public JLabel getCanvas() {
@@ -578,7 +564,7 @@ public Component asComponent() {
return this;
}
- public Optional getSelectedSymbol() {
+ private Optional getSelectedSymbol() {
final int index = tabSymbols.getTable().getSelectedRow();
if (index < 0) {
@@ -589,49 +575,13 @@ public Optional getSelectedSymbol() {
.getSymbol(index));
}
- public JTextField getSymbolTextField() {
- return tfSymbol;
- }
-
- public JSpinner getXSpinner() {
- return spinnerX;
- }
-
- public JSpinner getYSpinner() {
- return spinnerY;
- }
-
- public JSpinner getWidthSpinner() {
- return spinnerWidth;
- }
-
- public JSpinner getHeightSpinner() {
- return spinnerHeight;
- }
-
- public void addChangeListener(ChangeListener listener) {
- changeListeners.add(listener);
- }
-
- public void removeChangeListener(ChangeListener listener) {
- changeListeners.remove(listener);
- }
-
public boolean hasChanged() {
return changed;
}
- public void setChanged(boolean b) {
- changed = b;
-
- final ChangeEvent evt = new ChangeEvent(this);
- for (ChangeListener l : changeListeners) {
- l.stateChanged(evt);
- }
- }
-
@Override
public void freeResources() {
lblCanvas.setIcon(null);
}
+
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/BoxFileCanvas.java b/gui/src/main/java/de/vorb/tesseract/gui/view/BoxFileCanvas.java
index 827d5e13..f66363fa 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/BoxFileCanvas.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/BoxFileCanvas.java
@@ -3,19 +3,21 @@
import de.vorb.tesseract.util.Box;
import de.vorb.tesseract.util.Symbol;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.ListModel;
import java.awt.Graphics;
import java.awt.Graphics2D;
-import java.util.Optional;
import static de.vorb.tesseract.gui.model.Scale.scaled;
public class BoxFileCanvas extends Canvas {
+
private static final long serialVersionUID = 1L;
private float scale;
- private Optional> symbols =
- Optional.empty();
+ @Nullable
+ private ListModel symbols = null;
private int selectedIndex = -1;
public BoxFileCanvas() {
@@ -25,8 +27,7 @@ public void setScale(float scale) {
this.scale = scale;
}
- public void setSymbols(Optional> symbols,
- int selectedIndex) {
+ public void setSymbols(@Nullable ListModel symbols, int selectedIndex) {
this.symbols = symbols;
this.selectedIndex = -1;
}
@@ -35,10 +36,10 @@ public void setSymbols(Optional> symbols,
public void paintComponent(Graphics g) {
super.paintComponent(g);
- if (!this.symbols.isPresent())
+ if (symbols == null) {
return;
+ }
- final ListModel symbols = this.symbols.get();
final int size = symbols.getSize();
for (int i = 0; i < size; i++) {
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/BoxFileComponent.java b/gui/src/main/java/de/vorb/tesseract/gui/view/BoxFileComponent.java
new file mode 100644
index 00000000..d37092e6
--- /dev/null
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/BoxFileComponent.java
@@ -0,0 +1,11 @@
+package de.vorb.tesseract.gui.view;
+
+import de.vorb.tesseract.gui.model.BoxFile;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public interface BoxFileComponent extends PageComponent {
+
+ void setBoxFile(@Nullable BoxFile boxFile);
+
+}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/BoxFileModelComponent.java b/gui/src/main/java/de/vorb/tesseract/gui/view/BoxFileModelComponent.java
deleted file mode 100644
index 8b08d69b..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/BoxFileModelComponent.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package de.vorb.tesseract.gui.view;
-
-import de.vorb.tesseract.gui.model.BoxFileModel;
-
-import java.util.Optional;
-
-public interface BoxFileModelComponent extends PageModelComponent {
- void setBoxFileModel(Optional model);
-}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/Canvas.java b/gui/src/main/java/de/vorb/tesseract/gui/view/Canvas.java
index df2d98fc..5674f9d8 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/Canvas.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/Canvas.java
@@ -1,24 +1,26 @@
package de.vorb.tesseract.gui.view;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.JComponent;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
-import java.util.Optional;
public class Canvas extends JComponent {
private static final long serialVersionUID = 1L;
private static final Dimension DIM_EMPTY = new Dimension(0, 0);
- private Optional image = Optional.empty();
+ @Nullable
+ private Image image = null;
- public Canvas() {
+ Canvas() {
}
- public void setImage(Optional image) {
+ public void setImage(@Nullable Image image) {
this.image = image;
}
@@ -26,9 +28,9 @@ public void setImage(Optional image) {
public void paintComponent(Graphics g) {
final Rectangle rect = getVisibleRect();
- if (image.isPresent()) {
+ if (image != null) {
g.setClip(rect.x, rect.y, rect.width, rect.height);
- g.drawImage(image.get(), 0, 0, null);
+ g.drawImage(image, 0, 0, null);
} else {
g.setColor(Color.WHITE);
g.fillRect((int) rect.getX(), (int) rect.getY(),
@@ -38,11 +40,10 @@ public void paintComponent(Graphics g) {
@Override
public Dimension getPreferredSize() {
- if (!image.isPresent()) {
+ if (image == null) {
return DIM_EMPTY;
}
- return new Dimension(image.get().getWidth(null), image.get().getHeight(
- null));
+ return new Dimension(image.getWidth(null), image.getHeight(null));
}
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/EvaluationPane.java b/gui/src/main/java/de/vorb/tesseract/gui/view/EvaluationPane.java
index e662d406..f5dd6033 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/EvaluationPane.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/EvaluationPane.java
@@ -1,10 +1,12 @@
package de.vorb.tesseract.gui.view;
-import de.vorb.tesseract.gui.model.BoxFileModel;
-import de.vorb.tesseract.gui.model.PageModel;
+import de.vorb.tesseract.gui.model.BoxFile;
+import de.vorb.tesseract.gui.model.Page;
import de.vorb.tesseract.gui.model.Scale;
import de.vorb.tesseract.gui.view.renderer.EvaluationPaneRenderer;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
@@ -24,9 +26,9 @@
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.Optional;
-public class EvaluationPane extends JPanel implements PageModelComponent {
+public class EvaluationPane extends JPanel implements PageComponent {
+
private static final long serialVersionUID = 1L;
private static final Insets BUTTON_MARGIN = new Insets(2, 4, 2, 4);
@@ -34,7 +36,8 @@ public class EvaluationPane extends JPanel implements PageModelComponent {
private final Scale scale;
private final EvaluationPaneRenderer renderer;
- private Optional model;
+ @Nullable
+ private Page model;
private final JLabel lblOriginal;
private final JTextArea textAreaTranscript;
private final JButton btnSaveTranscription;
@@ -44,12 +47,7 @@ public class EvaluationPane extends JPanel implements PageModelComponent {
private final JButton btnZoomIn;
private final JButton btnUseOcrResult;
- /**
- * Create the panel.
- *
- * @param scale
- */
- public EvaluationPane(final Scale scale, final String editorFont) {
+ EvaluationPane(final Scale scale, final String editorFont) {
setLayout(new BorderLayout(0, 0));
this.scale = scale;
@@ -134,7 +132,7 @@ public EvaluationPane(final Scale scale, final String editorFont) {
btnZoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (scale.hasPrevious()) {
- renderer.render(getPageModel(), scale.previous());
+ renderer.render(getPage(), scale.previous());
}
if (!scale.hasPrevious()) {
@@ -175,7 +173,7 @@ public void actionPerformed(ActionEvent evt) {
btnZoomIn.addActionListener(evt -> {
if (scale.hasNext()) {
- renderer.render(getPageModel(), scale.next());
+ renderer.render(getPage(), scale.next());
}
if (!scale.hasNext()) {
@@ -212,14 +210,14 @@ public JTextArea getTextAreaTranscript() {
}
@Override
- public void setPageModel(Optional model) {
- this.model = model;
+ public void setPage(@Nullable Page page) {
+ this.model = page;
- renderer.render(model, scale.current());
+ renderer.render(page, scale.current());
}
@Override
- public Optional getPageModel() {
+ public @Nullable Page getPage() {
return model;
}
@@ -229,15 +227,15 @@ public void freeResources() {
}
@Override
- public Optional getBoxFileModel() {
- if (model.isPresent()) {
- return Optional.of(model.get().toBoxFileModel());
+ public @Nullable BoxFile getBoxFile() {
+ if (model != null) {
+ return model.toBoxFile();
} else {
- return Optional.empty();
+ return null;
}
}
- public void setEditorFont(String editorFont) {
+ public void setEditorFont(@Nullable String editorFont) {
textAreaTranscript.setFont(new Font(editorFont, Font.PLAIN, 13));
}
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/FeatureDebugger.java b/gui/src/main/java/de/vorb/tesseract/gui/view/FeatureDebugger.java
index 52142fa1..e5a0c9ca 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/FeatureDebugger.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/FeatureDebugger.java
@@ -5,6 +5,8 @@
import de.vorb.tesseract.util.feat.Feature3D;
import de.vorb.tesseract.util.feat.Feature4D;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JLabel;
@@ -20,29 +22,23 @@
import java.awt.geom.Line2D.Double;
import java.awt.image.BufferedImage;
import java.util.List;
-import java.util.Optional;
public class FeatureDebugger extends JDialog {
+
private static final long serialVersionUID = 1L;
private static final double PI2 = Math.PI + Math.PI;
- private static final double FEATURE_RADIUS = 3.5d;
+ private static final double FEATURE_RADIUS = 3.5;
private static final int WIDTH = 256;
private static final int HEIGHT = 256;
- private final JPanel contentPanel = new JPanel();
- private final BufferedImage canvas = new BufferedImage(WIDTH, HEIGHT,
- BufferedImage.TYPE_INT_RGB);
+ private final BufferedImage canvas = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
private final JLabel lblCanvas;
private List features;
- private Optional prototypes = Optional.empty();
+ @Nullable
+ private IntTemplates prototypes = null;
- /**
- * Create the dialog.
- *
- * @param parent
- */
public FeatureDebugger(Window parent) {
super(parent);
setLocationByPlatform(true);
@@ -50,6 +46,7 @@ public FeatureDebugger(Window parent) {
setModalityType(ModalityType.APPLICATION_MODAL);
getContentPane().setLayout(new BorderLayout());
+ final JPanel contentPanel = new JPanel();
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
contentPanel.setLayout(new BorderLayout(0, 0));
@@ -68,10 +65,6 @@ public void setFeatures(List features) {
redraw();
}
- public void setPrototypes(Optional prototypes) {
- this.prototypes = prototypes;
- }
-
private void redraw() {
final Graphics2D g2d = canvas.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
@@ -81,11 +74,11 @@ private void redraw() {
g2d.clearRect(0, 0, WIDTH, HEIGHT);
final Double line = new Line2D.Double(0d, 0d, 0d, 0d);
- if (prototypes.isPresent()) {
- final List classes = prototypes.get().getClasses();
+ if (prototypes != null) {
+ final List classes = prototypes.getClasses();
for (final Feature4D feat : classes.get(0).getProtoSets().get(0).getProtos()) {
// transform the angle back to radians
- final double angle = feat.getAngle() / 256d * PI2;
+ final double angle = feat.getAngle() / 256.0 * PI2;
final double dx = Math.cos(angle) * feat.getC();
final double dy = Math.sin(angle) * feat.getC();
final double x1 = feat.getA();
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/FilteredList.java b/gui/src/main/java/de/vorb/tesseract/gui/view/FilteredList.java
index 1062fb53..2206a1a7 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/FilteredList.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/FilteredList.java
@@ -71,7 +71,7 @@ private void filter() {
filterField.getTextField().getText();
filteredModel.setFilter(
- filterProvider.getFilterFor(query));
+ filterProvider.getFilterFor(query).orElseGet(FilteredListModel::createMatchAllFilter));
}
});
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/FilteredTable.java b/gui/src/main/java/de/vorb/tesseract/gui/view/FilteredTable.java
index b1e619c4..a8f95a8b 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/FilteredTable.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/FilteredTable.java
@@ -1,5 +1,6 @@
package de.vorb.tesseract.gui.view;
+import de.vorb.tesseract.gui.model.FilteredListModel;
import de.vorb.tesseract.gui.model.FilteredTableModel;
import de.vorb.tesseract.gui.util.FilterProvider;
@@ -16,15 +17,13 @@
import java.awt.SystemColor;
public class FilteredTable extends JPanel {
+
private static final long serialVersionUID = 1L;
private final JTable table;
private final SearchField filterField;
- /**
- * Create the panel.
- */
- public FilteredTable(final FilteredTableModel model,
+ FilteredTable(final FilteredTableModel model,
final FilterProvider filterProvider) {
setLayout(new BorderLayout(0, 0));
@@ -73,7 +72,7 @@ private void filter() {
filterField.getTextField().getText();
filteredModel.getSource().setFilter(
- filterProvider.getFilterFor(query));
+ filterProvider.getFilterFor(query).orElseGet(FilteredListModel::createMatchAllFilter));
}
});
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/ImageComponent.java b/gui/src/main/java/de/vorb/tesseract/gui/view/ImageComponent.java
new file mode 100644
index 00000000..a0b38213
--- /dev/null
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/ImageComponent.java
@@ -0,0 +1,14 @@
+package de.vorb.tesseract.gui.view;
+
+import de.vorb.tesseract.gui.model.Image;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public interface ImageComponent extends MainComponent {
+
+ void setImage(@Nullable Image image);
+
+ @Nullable
+ Image getImage();
+
+}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/ImageModelComponent.java b/gui/src/main/java/de/vorb/tesseract/gui/view/ImageModelComponent.java
deleted file mode 100644
index fcc9d1e4..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/ImageModelComponent.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package de.vorb.tesseract.gui.view;
-
-import de.vorb.tesseract.gui.model.ImageModel;
-
-import java.util.Optional;
-
-public interface ImageModelComponent extends MainComponent {
- void setImageModel(Optional model);
-
- Optional getImageModel();
-}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/PageComponent.java b/gui/src/main/java/de/vorb/tesseract/gui/view/PageComponent.java
new file mode 100644
index 00000000..ff7ef3fc
--- /dev/null
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/PageComponent.java
@@ -0,0 +1,18 @@
+package de.vorb.tesseract.gui.view;
+
+import de.vorb.tesseract.gui.model.BoxFile;
+import de.vorb.tesseract.gui.model.Page;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public interface PageComponent extends MainComponent {
+
+ void setPage(@Nullable Page page);
+
+ @Nullable
+ Page getPage();
+
+ @Nullable
+ BoxFile getBoxFile();
+
+}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/PageListCellRenderer.java b/gui/src/main/java/de/vorb/tesseract/gui/view/PageListCellRenderer.java
index e2c7249b..34419b25 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/PageListCellRenderer.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/PageListCellRenderer.java
@@ -16,10 +16,6 @@
import java.awt.Component;
import java.nio.file.Path;
-/**
- * @author Paul Vorbach
- * @deprecated
- */
public class PageListCellRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 1L;
@@ -32,13 +28,14 @@ public class PageListCellRenderer extends DefaultListCellRenderer {
private static final Border SAFE_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1);
private static final Border DEFAULT_NO_FOCUS_BORDER = new EmptyBorder(1, 1,
1, 1);
- protected static Border noFocusBorder = DEFAULT_NO_FOCUS_BORDER;
+ private static Border noFocusBorder = DEFAULT_NO_FOCUS_BORDER;
private Border getNoFocusBorder() {
Border border = DefaultLookup.getBorder(this, ui, "List.cellNoFocusBorder");
if (System.getSecurityManager() != null) {
- if (border != null)
+ if (border != null) {
return border;
+ }
return SAFE_NO_FOCUS_BORDER;
} else {
if (border != null &&
@@ -50,11 +47,7 @@ private Border getNoFocusBorder() {
}
}
- public Component getListCellRendererComponent(
- JList> list,
- Object value,
- int index,
- boolean isSelected,
+ public Component getListCellRendererComponent(JList> list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
setComponentOrientation(list.getComponentOrientation());
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/PageModelComponent.java b/gui/src/main/java/de/vorb/tesseract/gui/view/PageModelComponent.java
deleted file mode 100644
index f46930e2..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/PageModelComponent.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package de.vorb.tesseract.gui.view;
-
-import de.vorb.tesseract.gui.model.BoxFileModel;
-import de.vorb.tesseract.gui.model.PageModel;
-
-import java.util.Optional;
-
-public interface PageModelComponent extends MainComponent {
- void setPageModel(Optional model);
-
- Optional getPageModel();
-
- Optional getBoxFileModel();
-}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/PageView.java b/gui/src/main/java/de/vorb/tesseract/gui/view/PageView.java
deleted file mode 100644
index d624ae18..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/PageView.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package de.vorb.tesseract.gui.view;
-
-import de.vorb.tesseract.gui.model.PageModel;
-
-import java.util.Optional;
-
-public interface PageView {
- void setPageModel(Optional pageModel);
-
- Optional getPageModel();
-}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/PreprocessingPane.java b/gui/src/main/java/de/vorb/tesseract/gui/view/PreprocessingPane.java
index 47e286bc..3ff8fa21 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/PreprocessingPane.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/PreprocessingPane.java
@@ -1,6 +1,6 @@
package de.vorb.tesseract.gui.view;
-import de.vorb.tesseract.gui.model.ImageModel;
+import de.vorb.tesseract.gui.model.Image;
import de.vorb.tesseract.tools.preprocessing.DefaultPreprocessor;
import de.vorb.tesseract.tools.preprocessing.Preprocessor;
import de.vorb.tesseract.tools.preprocessing.binarization.Binarization;
@@ -39,7 +39,8 @@
import java.util.List;
import java.util.Optional;
-public class PreprocessingPane extends JPanel implements ImageModelComponent {
+public class PreprocessingPane extends JPanel implements ImageComponent {
+
private static final long serialVersionUID = 1L;
private final JComboBox comboBinarization;
@@ -54,12 +55,9 @@ public class PreprocessingPane extends JPanel implements ImageModelComponent {
private final JButton btnApplyToPage;
private final JButton btnApplyToAllPages;
- private Optional imageModel = Optional.empty();
+ private Image imageModel = null;
- /**
- * Create the panel.
- */
- public PreprocessingPane() {
+ PreprocessingPane() {
setBackground(Color.WHITE);
setLayout(new BorderLayout(0, 0));
@@ -234,7 +232,7 @@ public JLabel getPreviewLabel() {
return lblPreview;
}
- public Binarization getBinarization() {
+ private Binarization getBinarization() {
final BinarizationMethod method =
(BinarizationMethod) comboBinarization.getSelectedItem();
@@ -253,7 +251,7 @@ public Binarization getBinarization() {
return binarization;
}
- public List getFilters() {
+ private List getFilters() {
int min = (int) spinnerBlobMinSize.getModel().getValue();
int max = (int) spinnerBlobMaxSize.getModel().getValue();
@@ -303,18 +301,15 @@ public Component asComponent() {
}
@Override
- public void setImageModel(Optional model) {
- imageModel = model;
+ public void setImage(Image image) {
+ imageModel = image;
- if (model.isPresent()) {
- lblPreview.setIcon(new ImageIcon(model.get().getPreprocessedImage()));
- } else {
- lblPreview.setIcon(null);
- }
+ lblPreview.setIcon(
+ Optional.ofNullable(image).map(Image::getPreprocessedImage).map(ImageIcon::new).orElse(null));
}
@Override
- public Optional getImageModel() {
+ public Image getImage() {
return imageModel;
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/RecognitionPane.java b/gui/src/main/java/de/vorb/tesseract/gui/view/RecognitionPane.java
index 1f3197e5..01e3ecba 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/RecognitionPane.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/RecognitionPane.java
@@ -1,7 +1,7 @@
package de.vorb.tesseract.gui.view;
-import de.vorb.tesseract.gui.model.BoxFileModel;
-import de.vorb.tesseract.gui.model.PageModel;
+import de.vorb.tesseract.gui.model.BoxFile;
+import de.vorb.tesseract.gui.model.Page;
import de.vorb.tesseract.gui.model.Scale;
import de.vorb.tesseract.gui.view.renderer.RecognitionRenderer;
import de.vorb.tesseract.util.AlternativeChoice;
@@ -9,11 +9,12 @@
import de.vorb.tesseract.util.Symbol;
import de.vorb.tesseract.util.Word;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
-import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
@@ -27,7 +28,6 @@
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
-import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
@@ -39,7 +39,7 @@
import java.util.Timer;
import java.util.TimerTask;
-public class RecognitionPane extends JPanel implements PageModelComponent {
+public class RecognitionPane extends JPanel implements PageComponent {
private static final long serialVersionUID = 1L;
private static final int SCROLL_UNITS = 12;
@@ -57,7 +57,8 @@ public class RecognitionPane extends JPanel implements PageModelComponent {
private final JCheckBox cbLineNumbers;
private final JCheckBox cbBaselines;
- private Optional model = Optional.empty();
+ @Nullable
+ private Page page = null;
private final Timer delayer = new Timer(true);
private JButton btZoomOut;
@@ -301,7 +302,7 @@ public void itemStateChanged(ItemEvent ev) {
RecognitionPane.class.getResource("/icons/zoom_out.png")));
btZoomOut.addActionListener(ev -> {
if (scale.hasPrevious()) {
- renderer.render(getPageModel(), scale.previous());
+ renderer.render(getPage(), scale.previous());
}
if (!scale.hasPrevious()) {
@@ -323,7 +324,7 @@ public void itemStateChanged(ItemEvent ev) {
RecognitionPane.class.getResource("/icons/zoom_in.png")));
btZoomIn.addActionListener(ev -> {
if (scale.hasNext()) {
- renderer.render(getPageModel(), scale.next());
+ renderer.render(getPage(), scale.next());
}
if (!scale.hasPrevious()) {
@@ -358,25 +359,14 @@ public void itemStateChanged(ItemEvent ev) {
}
private Optional findSymbolAt(int x, int y) {
- if (!model.isPresent()) {
+ if (page == null) {
return Optional.empty();
}
- final Iterator symbolIt =
- model.get().getPage().symbolIterator();
+ final Iterator symbolIt = page.getPage().symbolIterator();
while (symbolIt.hasNext()) {
final Symbol symb = symbolIt.next();
- final de.vorb.tesseract.util.Box bbox = symb.getBoundingBox();
-
- final int scaledX0 = Scale.scaled(bbox.getX(), scale.current());
- final int scaledY0 = Scale.scaled(bbox.getY(), scale.current());
- final int scaledX1 = scaledX0
- + Scale.scaled(bbox.getWidth(), scale.current());
- final int scaledY1 = scaledY0
- + Scale.scaled(bbox.getHeight(), scale.current());
-
- if (x >= scaledX0 && x <= scaledX1 && y >= scaledY0
- && y <= scaledY1) {
+ if (boundingBoxContainsPoint(symb.getBoundingBox(), x, y)) {
return Optional.of(symb);
}
}
@@ -385,26 +375,15 @@ private Optional findSymbolAt(int x, int y) {
}
private Optional findWordAt(int x, int y) {
- if (!model.isPresent()) {
+ if (page == null) {
return Optional.empty();
}
- final Iterator wordIt =
- model.get().getPage().wordIterator();
+ final Iterator wordIt = page.getPage().wordIterator();
while (wordIt.hasNext()) {
final Word word = wordIt.next();
- final de.vorb.tesseract.util.Box bbox = word.getBoundingBox();
-
- final int scaledX0 = Scale.scaled(bbox.getX(), scale.current());
- final int scaledY0 = Scale.scaled(bbox.getY(), scale.current());
- final int scaledX1 = scaledX0
- + Scale.scaled(bbox.getWidth(), scale.current());
- final int scaledY1 = scaledY0
- + Scale.scaled(bbox.getHeight(), scale.current());
-
- if (x >= scaledX0 && x <= scaledX1 && y >= scaledY0
- && y <= scaledY1) {
+ if (boundingBoxContainsPoint(word.getBoundingBox(), x, y)) {
return Optional.of(word);
}
}
@@ -412,12 +391,24 @@ private Optional findWordAt(int x, int y) {
return Optional.empty();
}
- public Optional getPageModel() {
- return model;
+ private boolean boundingBoxContainsPoint(de.vorb.tesseract.util.Box boundingBox, int x, int y) {
+
+ final int scaledX0 = Scale.scaled(boundingBox.getX(), scale.current());
+ final int scaledY0 = Scale.scaled(boundingBox.getY(), scale.current());
+ final int scaledX1 = scaledX0 + Scale.scaled(boundingBox.getWidth(), scale.current());
+ final int scaledY1 = scaledY0 + Scale.scaled(boundingBox.getHeight(), scale.current());
+
+ return x >= scaledX0 && x <= scaledX1 && y >= scaledY0 && y <= scaledY1;
+ }
+
+ @Override
+ public @Nullable Page getPage() {
+ return page;
}
- public void setPageModel(Optional page) {
- model = page;
+ @Override
+ public void setPage(@Nullable Page page) {
+ this.page = page;
render();
}
@@ -428,7 +419,7 @@ public void render() {
delayer.schedule(new TimerTask() {
@Override
public void run() {
- renderer.render(model, scale.current());
+ renderer.render(page, scale.current());
}
}, 200);
}
@@ -445,11 +436,11 @@ public void freeResources() {
}
@Override
- public Optional getBoxFileModel() {
- if (model.isPresent()) {
- return Optional.of(model.get().toBoxFileModel());
+ public @Nullable BoxFile getBoxFile() {
+ if (page != null) {
+ return page.toBoxFile();
} else {
- return Optional.empty();
+ return null;
}
}
@@ -485,7 +476,7 @@ public JCheckBox getParagraphs() {
return cbParagraphs;
}
- public void setRenderingFont(String renderingFont) {
+ public void setRenderingFont(@Nullable String renderingFont) {
renderer.setRenderingFont(renderingFont);
}
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/SymbolOverview.java b/gui/src/main/java/de/vorb/tesseract/gui/view/SymbolOverview.java
index 2d766f73..e58b3471 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/SymbolOverview.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/SymbolOverview.java
@@ -1,11 +1,12 @@
package de.vorb.tesseract.gui.view;
-import de.vorb.tesseract.gui.event.SymbolLinkListener;
-import de.vorb.tesseract.gui.model.BoxFileModel;
-import de.vorb.tesseract.gui.model.PageModel;
+import de.vorb.tesseract.gui.model.BoxFile;
+import de.vorb.tesseract.gui.model.Page;
import de.vorb.tesseract.gui.view.renderer.SymbolVariantListCellRenderer;
import de.vorb.tesseract.util.Symbol;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JPanel;
@@ -13,40 +14,30 @@
import java.awt.BorderLayout;
import java.awt.Component;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
-public class SymbolOverview extends JPanel implements BoxFileModelComponent {
+public class SymbolOverview extends JPanel implements BoxFileComponent {
+
private static final long serialVersionUID = 1L;
private final SymbolGroupList glyphSelectionPane;
private final SymbolVariantList glyphListPane;
- private Optional model = Optional.empty();
- private Optional pageModel = Optional.empty();
+ @Nullable
+ private BoxFile boxFile = null;
+ private Page page = null;
- private final LinkedList listeners = new LinkedList<>();
-
- public static final Comparator>> SYMBOL_GROUP_COMP =
- (o1, o2) -> o2.getValue().size() - o1.getValue().size();
-
- public static final Comparator SYMBOL_COMP = (o1, o2) -> {
- if (o2.getConfidence() >= o1.getConfidence()) {
- return 1;
- }
-
- return -1;
- };
+ private static final Comparator>> SYMBOL_GROUP_COMP =
+ Comparator.comparingInt(symbolGroup -> symbolGroup.getValue().size());
/**
* Create the panel.
*/
- public SymbolOverview() {
+ SymbolOverview() {
super();
setLayout(new BorderLayout(0, 0));
@@ -60,18 +51,14 @@ public SymbolOverview() {
splitPane.setRightComponent(glyphListPane);
}
- public void addSymbolLinkListener(SymbolLinkListener listener) {
- listeners.add(listener);
- }
-
@Override
public Component asComponent() {
return this;
}
@Override
- public Optional getBoxFileModel() {
- return model;
+ public @Nullable BoxFile getBoxFile() {
+ return boxFile;
}
public SymbolGroupList getSymbolGroupList() {
@@ -83,12 +70,11 @@ public SymbolVariantList getSymbolVariantList() {
}
@Override
- public void setBoxFileModel(Optional model) {
- this.model = model;
+ public void setBoxFile(@Nullable BoxFile boxFile) {
+ this.boxFile = boxFile;
- if (!model.isPresent()) {
- glyphSelectionPane.getList().setModel(
- new DefaultListModel<>());
+ if (boxFile == null) {
+ glyphSelectionPane.getList().setModel(new DefaultListModel<>());
glyphListPane.getList().setModel(new DefaultListModel<>());
return;
}
@@ -98,8 +84,6 @@ public void setBoxFileModel(Optional model) {
final HashMap> glyphs = new HashMap<>();
- final BoxFileModel boxFile = model.get();
-
getSymbolVariantList().getList().setModel(
new DefaultListModel<>());
@@ -121,7 +105,7 @@ public void setBoxFileModel(Optional model) {
final ArrayList>> entries = new ArrayList<>(
glyphs.entrySet());
- Collections.sort(entries, SYMBOL_GROUP_COMP);
+ entries.sort(SYMBOL_GROUP_COMP);
final DefaultListModel>> listModel =
new DefaultListModel<>();
@@ -132,26 +116,20 @@ public void setBoxFileModel(Optional model) {
}
@Override
- public void setPageModel(Optional model) {
- if (model.isPresent()) {
- setBoxFileModel(Optional.of(model.get().toBoxFileModel()));
- pageModel = model;
- } else {
- setBoxFileModel(Optional.empty());
- pageModel = model;
- }
+ public void setPage(Page page) {
+ this.page = page;
+ setBoxFile(Optional.ofNullable(page).map(Page::toBoxFile).orElse(null));
}
@Override
- public Optional getPageModel() {
- return pageModel;
+ public @Nullable Page getPage() {
+ return page;
}
@Override
public void freeResources() {
- getSymbolGroupList().getList().setModel(
- new DefaultListModel<>());
- getSymbolVariantList().getList().setModel(
- new DefaultListModel<>());
+ getSymbolGroupList().getList().setModel(new DefaultListModel<>());
+ getSymbolVariantList().getList().setModel(new DefaultListModel<>());
}
+
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/TesseractFrame.java b/gui/src/main/java/de/vorb/tesseract/gui/view/TesseractFrame.java
index 6ee2b806..55a422f5 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/TesseractFrame.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/TesseractFrame.java
@@ -9,6 +9,8 @@
import de.vorb.tesseract.gui.view.i18n.Labels;
import de.vorb.tesseract.gui.view.renderer.PageListCellRenderer;
+import org.checkerframework.checker.nullness.qual.NonNull;
+
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
@@ -45,7 +47,9 @@
* Swing component that allows to compare the results of Tesseract.
*/
public class TesseractFrame extends JFrame {
+
private static final long serialVersionUID = 1L;
+
private final FilteredList listPages;
private final FilteredList listTrainingFiles;
private final PreprocessingPane preprocessingPane;
@@ -224,8 +228,7 @@ public TesseractFrame() {
mnBatchExport = new JMenuItem("Batch Export...");
mnBatchExport.setEnabled(false);
- mnBatchExport.setIcon(new ImageIcon(
- TesseractFrame.class.getResource("/icons/book_next.png")));
+ mnBatchExport.setIcon(new ImageIcon(TesseractFrame.class.getResource("/icons/book_next.png")));
mnBatchExport.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E,
InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK));
mnFile.add(mnBatchExport);
@@ -242,8 +245,7 @@ public TesseractFrame() {
menuBar.add(mnEdit);
mnPreferences = new JMenuItem("Preferences");
- mnPreferences.setIcon(new ImageIcon(
- TesseractFrame.class.getResource("/icons/cog.png")));
+ mnPreferences.setIcon(new ImageIcon(TesseractFrame.class.getResource("/icons/cog.png")));
mnEdit.add(mnPreferences);
mnTools = new JMenu("Tools");
@@ -256,16 +258,15 @@ public TesseractFrame() {
mnTools.add(mnInspectUnicharset);
mnTesseractTrainer = new JMenuItem("Tesseract Trainer...");
- mnTesseractTrainer.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T,
- InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK));
+ mnTesseractTrainer.setAccelerator(
+ KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK));
mnTools.add(mnTesseractTrainer);
final JMenu mnHelp = new JMenu(
Labels.getLabel(getLocale(), "menu_help"));
menuBar.add(mnHelp);
- final JMenuItem mntmAbout = new JMenuItem(Labels.getLabel(getLocale(),
- "menu_about"));
+ final JMenuItem mntmAbout = new JMenuItem(Labels.getLabel(getLocale(), "menu_about"));
mntmAbout.setIcon(new ImageIcon(
TesseractFrame.class.getResource("/icons/information.png")));
mntmAbout.addActionListener(e -> JOptionPane.showMessageDialog(TesseractFrame.this,
@@ -304,10 +305,10 @@ public TesseractFrame() {
gbc_lblScaleFactor.gridy = 0;
panel.add(lblScaleFactor, gbc_lblScaleFactor);
- GridBagConstraints gbc_pbRegognitionProgress = new GridBagConstraints();
- gbc_pbRegognitionProgress.gridx = 3;
- gbc_pbRegognitionProgress.gridy = 0;
- panel.add(pbLoadPage, gbc_pbRegognitionProgress);
+ GridBagConstraints gbc_pbRecognitionProgress = new GridBagConstraints();
+ gbc_pbRecognitionProgress.gridx = 3;
+ gbc_pbRecognitionProgress.gridy = 0;
+ panel.add(pbLoadPage, gbc_pbRecognitionProgress);
getContentPane().add(spMain, BorderLayout.CENTER);
tabsMain = new JTabbedPane();
@@ -424,7 +425,7 @@ public JLabel getScaleLabel() {
return lblScaleFactor;
}
- public SymbolOverview getSymbolOverview() {
+ public @NonNull SymbolOverview getSymbolOverview() {
return glyphOverview;
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/BatchExportDialog.java b/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/BatchExportDialog.java
index 10a31d66..17b5081f 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/BatchExportDialog.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/BatchExportDialog.java
@@ -1,7 +1,7 @@
package de.vorb.tesseract.gui.view.dialogs;
import de.vorb.tesseract.gui.controller.TesseractController;
-import de.vorb.tesseract.gui.model.BatchExportModel;
+import de.vorb.tesseract.gui.model.BatchExport;
import javax.swing.BoxLayout;
import javax.swing.JButton;
@@ -56,7 +56,7 @@ public class BatchExportDialog extends JDialog implements ActionListener {
private final TesseractController controller;
- private BatchExportModel exportModel = null;
+ private BatchExport exportModel = null;
private JCheckBox chckbxExportImages;
private JLabel lblExport;
private JCheckBox chckbxXml;
@@ -259,7 +259,7 @@ public JTextField getDestinationDirectoryTextField() {
return tfDestinationDir;
}
- public static Optional showBatchExportDialog(
+ public static Optional showBatchExportDialog(
TesseractController controller) {
final BatchExportDialog dialog = new BatchExportDialog(controller);
dialog.setVisible(true);
@@ -272,8 +272,7 @@ public void actionPerformed(ActionEvent evt) {
if (evt.getSource() == btnCancel) {
this.dispose();
} else if (evt.getSource() == btnDestinationDir) {
- final JFileChooser dirChooser = new JFileChooser(
- controller.getProjectModel().get().getProjectDir().toFile());
+ final JFileChooser dirChooser = new JFileChooser(controller.getProject().getProjectDir().toFile());
dirChooser.setDialogTitle("Choose Destination Directory");
dirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
final int result = dirChooser.showOpenDialog(controller.getView());
@@ -303,7 +302,7 @@ public void actionPerformed(ActionEvent evt) {
final boolean openDestination = chckbxOpenDestination.isSelected();
final int numThreads = (Integer) spinnerWorkerThreads.getValue();
- exportModel = new BatchExportModel(
+ exportModel = new BatchExport(
destinationDir, exportTXT, exportHTML, exportXML,
exportImages, exportReports, numThreads,
openDestination);
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/Dialogs.java b/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/Dialogs.java
index 8f88bb42..4c26db77 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/Dialogs.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/Dialogs.java
@@ -1,33 +1,31 @@
package de.vorb.tesseract.gui.view.dialogs;
+import com.drew.lang.annotations.NotNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.JOptionPane;
import java.awt.Component;
public final class Dialogs {
- private Dialogs() {}
+ private Dialogs() {
+ }
- public static void showInfo(Component parent, String title,
- String message) {
- JOptionPane.showMessageDialog(parent, message, title,
- JOptionPane.INFORMATION_MESSAGE);
+ public static void showInfo(@Nullable Component parent, @NotNull String title, @NotNull String message) {
+ JOptionPane.showMessageDialog(parent, message, title, JOptionPane.INFORMATION_MESSAGE);
}
- public static void showWarning(Component parent, String title,
- String message) {
- JOptionPane.showMessageDialog(parent, message, title,
- JOptionPane.WARNING_MESSAGE);
+ public static void showWarning(@Nullable Component parent, @NotNull String title, @NotNull String message) {
+ JOptionPane.showMessageDialog(parent, message, title, JOptionPane.WARNING_MESSAGE);
}
- public static void showError(Component parent, String title,
- String message) {
- JOptionPane.showMessageDialog(parent, message, title,
- JOptionPane.ERROR_MESSAGE);
+ public static void showError(@Nullable Component parent, @NotNull String title, @NotNull String message) {
+ JOptionPane.showMessageDialog(parent, message, title, JOptionPane.ERROR_MESSAGE);
}
- public static boolean ask(Component parent, String title, String question) {
- int result = JOptionPane.showConfirmDialog(parent, question, title,
- JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
+ public static boolean ask(@Nullable Component parent, @NotNull String title, @NotNull String question) {
+ final int result = JOptionPane.showConfirmDialog(parent, question, title, JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.QUESTION_MESSAGE);
return result == JOptionPane.OK_OPTION;
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/NewProjectDialog.java b/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/NewProjectDialog.java
index 6bcdbf69..50efdddc 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/NewProjectDialog.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/dialogs/NewProjectDialog.java
@@ -1,6 +1,6 @@
package de.vorb.tesseract.gui.view.dialogs;
-import de.vorb.tesseract.gui.model.ProjectModel;
+import de.vorb.tesseract.gui.model.Project;
import javax.swing.JButton;
import javax.swing.JCheckBox;
@@ -53,7 +53,7 @@ public class NewProjectDialog extends JDialog implements ActionListener,
private final JButton btnCreate;
private final JButton btnCancel;
- private Optional result = Optional.empty();
+ private Optional result = Optional.empty();
/**
* Create the dialog.
@@ -208,7 +208,7 @@ public void actionPerformed(ActionEvent evt) {
// set result if settings are valid
if (isStateValid()) {
Path dir = Paths.get(tfPath.getText());
- this.result = Optional.of(new ProjectModel(dir,
+ this.result = Optional.of(new Project(dir,
cbTiff.isSelected(), cbPng.isSelected(),
cbJpeg.isSelected()));
}
@@ -258,7 +258,7 @@ private Preferences getPreferences() {
return Preferences.userNodeForPackage(getClass());
}
- public static Optional showDialog(Window parent) {
+ public static Optional showDialog(Window parent) {
final NewProjectDialog dialog = new NewProjectDialog(parent);
dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/i18n/package-info.java b/gui/src/main/java/de/vorb/tesseract/gui/view/i18n/package-info.java
deleted file mode 100644
index 6d2298a5..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/i18n/package-info.java
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * @author Paul Vorbach
- */
-/**
- * @author Paul Vorbach
- *
- */
-package de.vorb.tesseract.gui.view.i18n;
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/package-info.java b/gui/src/main/java/de/vorb/tesseract/gui/view/package-info.java
deleted file mode 100644
index d44e9281..00000000
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * @author Paul Vorbach
- */
-package de.vorb.tesseract.gui.view;
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/BoxFileRenderer.java b/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/BoxFileRenderer.java
index a701c2c9..2c023bc3 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/BoxFileRenderer.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/BoxFileRenderer.java
@@ -1,19 +1,20 @@
package de.vorb.tesseract.gui.view.renderer;
-import de.vorb.tesseract.gui.model.BoxFileModel;
+import de.vorb.tesseract.gui.model.BoxFile;
import de.vorb.tesseract.gui.view.BoxEditor;
import de.vorb.tesseract.gui.view.Colors;
import de.vorb.tesseract.gui.view.Strokes;
import de.vorb.tesseract.util.Box;
import de.vorb.tesseract.util.Symbol;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.ListModel;
import javax.swing.SwingWorker;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
-import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
@@ -22,17 +23,18 @@
public class BoxFileRenderer {
private final BoxEditor boxEditor;
+ @Nullable
private SwingWorker renderWorker;
public BoxFileRenderer(BoxEditor boxEditor) {
this.boxEditor = boxEditor;
}
- public void render(final Optional model, final float scale) {
- if (!model.isPresent()) {
+ public void render(@Nullable final BoxFile boxFile, final float scale) {
+ if (boxFile == null) {
// remove image, if no page model is given and free resources
final Icon icon = boxEditor.getCanvas().getIcon();
- if (icon != null && icon instanceof ImageIcon) {
+ if (icon instanceof ImageIcon) {
((ImageIcon) icon).getImage().flush();
}
@@ -43,9 +45,8 @@ public void render(final Optional model, final float scale) {
return;
}
- // TODO add a version of render() that takes two rectangles and a new
- // box and updates the necessary area only
- final BufferedImage image = model.get().getImage();
+ // TODO add a version of render() that takes two rectangles and a new box and updates the necessary area only
+ final BufferedImage image = boxFile.getImage();
// calculate image dimensions
final int w = image.getWidth();
@@ -83,7 +84,7 @@ public void render(final Optional model, final float scale) {
// worker that renders the boxes to a new buffered image
renderWorker = new SwingWorker() {
@Override
- protected BufferedImage doInBackground() throws Exception {
+ protected BufferedImage doInBackground() {
final BufferedImage rendered = new BufferedImage(scaledW,
scaledH, BufferedImage.TYPE_INT_RGB);
@@ -94,8 +95,7 @@ protected BufferedImage doInBackground() throws Exception {
g2d.setStroke(Strokes.NORMAL);
// draw the scaled image
- g2d.drawImage(image, 0, 0, scaledW, scaledH, 0, 0,
- w - 1, h - 1, null);
+ g2d.drawImage(image, 0, 0, scaledW, scaledH, 0, 0, w - 1, h - 1, null);
for (final Symbol symbol : symbols) {
final boolean isSelected = symbol == selectedSymbol;
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/EvaluationPaneRenderer.java b/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/EvaluationPaneRenderer.java
index c2551d8c..73516f9c 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/EvaluationPaneRenderer.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/EvaluationPaneRenderer.java
@@ -1,15 +1,17 @@
package de.vorb.tesseract.gui.view.renderer;
-import de.vorb.tesseract.gui.model.PageModel;
+import de.vorb.tesseract.gui.model.Page;
import de.vorb.tesseract.gui.model.Scale;
import de.vorb.tesseract.gui.view.EvaluationPane;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.ImageIcon;
import java.awt.Image;
import java.awt.image.BufferedImage;
-import java.util.Optional;
public class EvaluationPaneRenderer implements PageRenderer {
+
private final EvaluationPane evaluationPane;
public EvaluationPaneRenderer(EvaluationPane evaluationPane) {
@@ -17,28 +19,25 @@ public EvaluationPaneRenderer(EvaluationPane evaluationPane) {
}
@Override
- public void render(Optional pageModel, float scale) {
- final boolean modelPresent = pageModel.isPresent();
+ public void render(@Nullable Page page, float scale) {
+ final boolean modelPresent = page != null;
evaluationPane.getSaveTranscriptionButton().setEnabled(modelPresent);
evaluationPane.getGenerateReportButton().setEnabled(modelPresent);
evaluationPane.getTextAreaTranscript().setEnabled(modelPresent);
if (modelPresent) {
- final BufferedImage img =
- pageModel.get().getImageModel().getSourceImage();
+ final BufferedImage img = page.getImage().getSourceImage();
final int w = Scale.scaled(img.getWidth(), scale);
final int h = Scale.scaled(img.getHeight(), scale);
- evaluationPane.getOriginal().setIcon(
- new ImageIcon(img.getScaledInstance(w, h,
- Image.SCALE_SMOOTH)));
- evaluationPane.getTextAreaTranscript().setText(
- pageModel.get().getTranscription());
+ evaluationPane.getOriginal().setIcon(new ImageIcon(img.getScaledInstance(w, h, Image.SCALE_SMOOTH)));
+ evaluationPane.getTextAreaTranscript().setText(page.getTranscription());
} else {
evaluationPane.getOriginal().setIcon(null);
evaluationPane.getTextAreaTranscript().setText("");
}
}
+
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/PageListCellRenderer.java b/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/PageListCellRenderer.java
index 43169957..697ea61d 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/PageListCellRenderer.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/PageListCellRenderer.java
@@ -11,16 +11,14 @@
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
-import java.util.Optional;
-public class PageListCellRenderer extends JLabel implements
- ListCellRenderer {
+public class PageListCellRenderer extends JLabel implements ListCellRenderer {
private static final long serialVersionUID = 1L;
private static final ImageIcon ICON_PLACEHOLDER = new ImageIcon(
PageListCellRenderer.class.getResource("/page_loading.png"));
- public static final Color COLOR_SELECT = new Color(0x4477FF);
+ private static final Color COLOR_SELECT = new Color(0x4477FF);
public PageListCellRenderer() {
setOpaque(true);
@@ -40,8 +38,7 @@ public Component getListCellRendererComponent(
int index, boolean isSelected, boolean cellHasFocus) {
String filename = value.getFile().getFileName().toString();
if (filename.length() > 32) {
- filename = filename.substring(0, 10) + "..."
- + filename.substring(filename.length() - 16);
+ filename = filename.substring(0, 10) + "..." + filename.substring(filename.length() - 16);
}
setText(filename);
@@ -54,10 +51,9 @@ public Component getListCellRendererComponent(
setForeground(Color.BLACK);
}
- final Optional opt = value.getThumbnail();
+ final BufferedImage thumbnail = value.getThumbnail();
- if (opt.isPresent()) {
- final BufferedImage thumbnail = opt.get();
+ if (thumbnail != null) {
final Graphics2D g2d = (Graphics2D) thumbnail.getGraphics();
// set color
@@ -71,8 +67,7 @@ public Component getListCellRendererComponent(
g2d.setColor(Color.BLACK);
}
- g2d.drawRect(0, 0, thumbnail.getWidth() - 1,
- thumbnail.getHeight() - 1);
+ g2d.drawRect(0, 0, thumbnail.getWidth() - 1, thumbnail.getHeight() - 1);
g2d.dispose();
setIcon(new ImageIcon(thumbnail));
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/PageRenderer.java b/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/PageRenderer.java
index cd2267bf..72617582 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/PageRenderer.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/PageRenderer.java
@@ -1,21 +1,11 @@
package de.vorb.tesseract.gui.view.renderer;
-import de.vorb.tesseract.gui.model.PageModel;
+import de.vorb.tesseract.gui.model.Page;
-import java.util.Optional;
+import org.checkerframework.checker.nullness.qual.Nullable;
-/**
- * Page renderer.
- *
- * @author Paul Vorbach
- */
public interface PageRenderer {
- /**
- * Renders the information of a page on an optionally given background.
- *
- * @param pageModel page model to render
- * @param scale scaling factor
- */
- void render(final Optional pageModel, final float scale);
+ void render(@Nullable final Page page, final float scale);
+
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/RecognitionRenderer.java b/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/RecognitionRenderer.java
index cd01fb06..7c026011 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/RecognitionRenderer.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/view/renderer/RecognitionRenderer.java
@@ -1,6 +1,6 @@
package de.vorb.tesseract.gui.view.renderer;
-import de.vorb.tesseract.gui.model.PageModel;
+import de.vorb.tesseract.gui.model.Page;
import de.vorb.tesseract.gui.view.Colors;
import de.vorb.tesseract.gui.view.RecognitionPane;
import de.vorb.tesseract.util.Baseline;
@@ -8,11 +8,12 @@
import de.vorb.tesseract.util.Box;
import de.vorb.tesseract.util.FontAttributes;
import de.vorb.tesseract.util.Line;
-import de.vorb.tesseract.util.Page;
import de.vorb.tesseract.util.Paragraph;
import de.vorb.tesseract.util.Symbol;
import de.vorb.tesseract.util.Word;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import javax.swing.ImageIcon;
import javax.swing.SwingWorker;
import java.awt.Color;
@@ -21,7 +22,6 @@
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.Iterator;
-import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import static de.vorb.tesseract.gui.model.Scale.scaled;
@@ -33,12 +33,19 @@ public class RecognitionRenderer implements PageRenderer {
private static final Font FONT_LINE_NUMBERS = new Font("Dialog", Font.PLAIN, DEFAULT_FONT_SIZE);
private final RecognitionPane recognitionPane;
+
+ @Nullable
private SwingWorker renderWorker;
- private PageModel lastPageModel = null;
+ @Nullable
+ private Page lastPage = null;
+
+ @Nullable
private BufferedImage original = null;
+
+ @Nullable
private BufferedImage recognition = null;
- private float minimumConfidence = 0;
+
private float lastScale;
private final AtomicReference fontNormal = new AtomicReference<>();
@@ -52,28 +59,21 @@ public RecognitionRenderer(RecognitionPane pane, String renderingFont) {
setRenderingFont(renderingFont);
}
- public void setRenderingFont(String renderingFont) {
- final String selectedFontFamily = renderingFont;
-
- fontNormal.set(new Font(selectedFontFamily, Font.PLAIN, DEFAULT_FONT_SIZE));
- fontBold.set(new Font(selectedFontFamily, Font.BOLD, DEFAULT_FONT_SIZE));
- fontItalic.set(new Font(selectedFontFamily, Font.ITALIC, DEFAULT_FONT_SIZE));
- fontBoldItalic.set(new Font(selectedFontFamily, Font.BOLD | Font.ITALIC, DEFAULT_FONT_SIZE));
- }
-
- public void setMinimumConfidence(float min) {
- this.minimumConfidence = min;
+ public void setRenderingFont(@Nullable String renderingFont) {
+ fontNormal.set(new Font(renderingFont, Font.PLAIN, DEFAULT_FONT_SIZE));
+ fontBold.set(new Font(renderingFont, Font.BOLD, DEFAULT_FONT_SIZE));
+ fontItalic.set(new Font(renderingFont, Font.ITALIC, DEFAULT_FONT_SIZE));
+ fontBoldItalic.set(new Font(renderingFont, Font.BOLD | Font.ITALIC, DEFAULT_FONT_SIZE));
}
@Override
- public void render(Optional pageModel, final float scale) {
- if (renderWorker != null && !renderWorker.isCancelled()
- && !renderWorker.isDone()) {
+ public void render(@Nullable Page page, final float scale) {
+ if (renderWorker != null && !renderWorker.isCancelled() && !renderWorker.isDone()) {
renderWorker.cancel(true);
}
// if no page model is present, remove the images and render worker
- if (!pageModel.isPresent()) {
+ if (page == null) {
renderWorker = null;
recognitionPane.getCanvasOriginal().setIcon(null);
@@ -85,18 +85,17 @@ public void render(Optional pageModel, final float scale) {
return;
}
- final Page page = pageModel.get().getPage();
- final BufferedImage preprocessed =
- pageModel.get().getImageModel().getPreprocessedImage();
+ final de.vorb.tesseract.util.Page internalPage = page.getPage();
+ final BufferedImage preprocessed = page.getImage().getPreprocessedImage();
final int width = preprocessed.getWidth();
final int height = preprocessed.getHeight();
final int scaledWidth;
final int scaledHeight;
- if (lastPageModel != pageModel.get() || lastScale != scale) {
+ if (lastPage != page || lastScale != scale) {
// prepare the images if the model has changed
- lastPageModel = pageModel.get();
+ lastPage = page;
lastScale = scale;
// calculate the width and height of the scene
@@ -114,12 +113,6 @@ public void render(Optional pageModel, final float scale) {
scaledHeight = original.getHeight();
}
- // set the base fonts
- final Font baseFontNormal;
- final Font baseFontItalic;
- final Font baseFontBold;
- final Font baseFontBoldItalic;
-
final boolean showWordBoxes = recognitionPane.getWordBoxes().isSelected();
final boolean showSymbolBoxes = recognitionPane.getSymbolBoxes().isSelected();
final boolean showLineNumbers = recognitionPane.getLineNumbers().isSelected();
@@ -137,8 +130,7 @@ private void drawLineNumber(final Line line, final int lineNumber) {
final String num = String.valueOf(lineNumber);
final int x = scaled(20, scale);
- final int y = scaled(box.getY() + box.getHeight()
- - line.getBaseline().getYOffset(), scale);
+ final int y = scaled(box.getY() + box.getHeight() - line.getBaseline().getYOffset(), scale);
origGfx.setFont(FONT_LINE_NUMBERS);
origGfx.setPaint(Colors.LINE_NUMBER);
@@ -149,7 +141,7 @@ private void drawLineNumber(final Line line, final int lineNumber) {
recogGfx.drawString(num, x, y);
}
- private void drawWord(final Line line, final Word word) {
+ private void drawWord(final Word word) {
// bounding box
final Box box = word.getBoundingBox();
@@ -181,7 +173,7 @@ private void drawWord(final Line line, final Word word) {
final int scH = scaled(bH, scale);
// text coordinates
- final int tx = scX;
+ @SuppressWarnings("UnnecessaryLocalVariable") final int tx = scX;
final int ty = scaled(bY + bH - word.getBaseline().getYOffset(), scale);
// set font
@@ -190,7 +182,7 @@ private void drawWord(final Line line, final Word word) {
font = fontNormal.get().deriveFont(scFontSize);
} else if (italic && !bold) {
font = fontItalic.get().deriveFont(scFontSize);
- } else if (bold && !italic) {
+ } else if (!italic) {
font = fontBold.get().deriveFont(scFontSize);
} else {
font = fontBoldItalic.get().deriveFont(scFontSize);
@@ -205,7 +197,7 @@ private void drawWord(final Line line, final Word word) {
if (showWordBoxes) {
origGfx.drawRect(scX, scY, scW, scH);
recogGfx.drawRect(scX, scY, scW, scH);
- } else if (showSymbolBoxes) {
+ } else {
for (final Symbol sym : word.getSymbols()) {
final Box symbolBoundingBox = sym.getBoundingBox();
@@ -258,7 +250,7 @@ private void drawWord(final Line line, final Word word) {
}
@Override
- protected Void doInBackground() throws Exception {
+ protected Void doInBackground() {
// init graphics contexts
origGfx = original.createGraphics();
recogGfx = recognition.createGraphics();
@@ -277,7 +269,7 @@ protected Void doInBackground() throws Exception {
if (showBlocks) {
origGfx.setPaint(Colors.BLOCK);
recogGfx.setPaint(Colors.BLOCK);
- final Iterator blocks = page.blockIterator();
+ final Iterator blocks = internalPage.blockIterator();
while (blocks.hasNext()) {
final Block block = blocks.next();
final Box boundingBox = block.getBoundingBox();
@@ -295,7 +287,7 @@ protected Void doInBackground() throws Exception {
if (showParagraphs) {
origGfx.setPaint(Colors.PARAGRAPH);
recogGfx.setPaint(Colors.PARAGRAPH);
- final Iterator paragraphs = page.paragraphIterator();
+ final Iterator paragraphs = internalPage.paragraphIterator();
while (paragraphs.hasNext()) {
final Paragraph paragraph = paragraphs.next();
final Box boundingBox = paragraph.getBoundingBox();
@@ -311,7 +303,7 @@ protected Void doInBackground() throws Exception {
}
int lineNumber = 1;
- final Iterator lines = page.lineIterator();
+ final Iterator lines = internalPage.lineIterator();
while (lines.hasNext()) {
final Line line = lines.next();
if (scale >= 0.5f && showLineNumbers) {
@@ -323,7 +315,7 @@ protected Void doInBackground() throws Exception {
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
for (final Word word : line.getWords()) {
- drawWord(line, word);
+ drawWord(word);
}
lineNumber++;
@@ -336,8 +328,7 @@ protected Void doInBackground() throws Exception {
protected void done() {
try {
recognitionPane.getCanvasOriginal().setIcon(new ImageIcon(original));
- recognitionPane.getCanvasRecognition().setIcon(
- new ImageIcon(recognition));
+ recognitionPane.getCanvasRecognition().setIcon(new ImageIcon(recognition));
} catch (Exception e) {
} finally {
System.gc();
@@ -348,7 +339,4 @@ protected void done() {
renderWorker.execute();
}
- public void freeResources() {
- lastPageModel = null;
- }
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/work/BatchExecutor.java b/gui/src/main/java/de/vorb/tesseract/gui/work/BatchExecutor.java
index 58ca49e8..94552041 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/work/BatchExecutor.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/work/BatchExecutor.java
@@ -1,8 +1,8 @@
package de.vorb.tesseract.gui.work;
import de.vorb.tesseract.gui.controller.TesseractController;
-import de.vorb.tesseract.gui.model.BatchExportModel;
-import de.vorb.tesseract.gui.model.ProjectModel;
+import de.vorb.tesseract.gui.model.BatchExport;
+import de.vorb.tesseract.gui.model.Project;
import de.vorb.tesseract.gui.util.DocumentWriter;
import de.vorb.tesseract.gui.view.dialogs.Dialogs;
import de.vorb.tesseract.tools.preprocessing.Preprocessor;
@@ -12,6 +12,7 @@
import eu.digitisation.input.Parameters;
import eu.digitisation.input.WarningException;
import eu.digitisation.output.Report;
+import org.checkerframework.checker.nullness.qual.NonNull;
import javax.swing.ProgressMonitor;
import javax.swing.SwingUtilities;
@@ -37,21 +38,22 @@
import java.util.concurrent.atomic.AtomicInteger;
public class BatchExecutor {
+
private final TesseractController controller;
- private final ProjectModel project;
- private final BatchExportModel export;
+ private final Project project;
+ private final BatchExport batchExport;
- public BatchExecutor(TesseractController controller, ProjectModel project,
- BatchExportModel export) {
+ public BatchExecutor(@NonNull TesseractController controller, @NonNull Project project,
+ @NonNull BatchExport batchExport) {
this.controller = controller;
this.project = project;
- this.export = export;
+ this.batchExport = batchExport;
}
public void start(final ProgressMonitor progressMonitor,
final Writer errorLog) throws IOException, InterruptedException {
- final int numThreads = export.getNumThreads();
+ final int numThreads = batchExport.getNumThreads();
final ExecutorService threadPool =
Executors.newFixedThreadPool(numThreads);
@@ -76,7 +78,7 @@ public void start(final ProgressMonitor progressMonitor,
Files.createDirectories(project.getEvaluationDir());
Files.createDirectories(project.getTranscriptionDir());
Files.createDirectories(project.getOCRDir());
- Files.createDirectories(export.getDestinationDir());
+ Files.createDirectories(batchExport.getDestinationDir());
// holds progress count
final AtomicInteger progress = new AtomicInteger(0);
@@ -96,7 +98,7 @@ public void start(final ProgressMonitor progressMonitor,
controller.hasPreprocessorChanged(sourceFile);
final OCRTask task = new OCRTask(sourceFile,
- project, export, preprocessor, recognizers,
+ project, batchExport, preprocessor, recognizers,
hasPreprocessorChanged, equivalencesFile, progressMonitor,
progress, errorLog, errors);
@@ -109,8 +111,9 @@ public boolean cancel(boolean mayInterruptIfRunning) {
int cancelled = 0;
for (Future> future : futures) {
- if (future.cancel(mayInterruptIfRunning))
+ if (future.cancel(mayInterruptIfRunning)) {
cancelled++;
+ }
}
return cancelled > 0;
@@ -207,7 +210,7 @@ public Void call() throws IOException {
} catch (InterruptedException | ExecutionException e) {
} finally {
all = null;
- if (export.exportReports()) {
+ if (batchExport.exportReports()) {
progressMonitor.setNote("Final report");
// create a single report for all transcriptions
DirectoryStream transcriptions;
@@ -224,7 +227,7 @@ public Void call() throws IOException {
final Report report = new Report(batch, params);
- final Path projectReport = export.getDestinationDir()
+ final Path projectReport = batchExport.getDestinationDir()
.resolve("project.report.html");
// write report html
@@ -232,7 +235,7 @@ public Void call() throws IOException {
// write report csv
final BufferedWriter csv = Files.newBufferedWriter(
- export.getDestinationDir().resolve(
+ batchExport.getDestinationDir().resolve(
"project.report.csv"),
StandardCharsets.UTF_8);
csv.write(report.getStats().asCSV("\n", ",").toString());
@@ -246,10 +249,10 @@ public Void call() throws IOException {
}
}
- if (export.openDestination()) {
+ if (batchExport.openDestination()) {
try {
Desktop.getDesktop().browse(
- export.getDestinationDir().toUri());
+ batchExport.getDestinationDir().toUri());
} catch (IOException e) {
errors.incrementAndGet();
@@ -279,7 +282,7 @@ public Void call() throws IOException {
if (investigate) {
try {
Desktop.getDesktop().open(
- export.getDestinationDir().resolve(
+ batchExport.getDestinationDir().resolve(
"errors.log").toFile());
} catch (IOException e) {
Dialogs.showError(controller.getView(),
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/work/OCRTask.java b/gui/src/main/java/de/vorb/tesseract/gui/work/OCRTask.java
index 48ae8616..3ce19fbe 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/work/OCRTask.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/work/OCRTask.java
@@ -1,8 +1,8 @@
package de.vorb.tesseract.gui.work;
import de.vorb.tesseract.gui.io.PlainTextWriter;
-import de.vorb.tesseract.gui.model.BatchExportModel;
-import de.vorb.tesseract.gui.model.ProjectModel;
+import de.vorb.tesseract.gui.model.BatchExport;
+import de.vorb.tesseract.gui.model.Project;
import de.vorb.tesseract.gui.util.DocumentWriter;
import de.vorb.tesseract.tools.preprocessing.Preprocessor;
import de.vorb.tesseract.tools.recognition.PageRecognitionConsumer;
@@ -33,8 +33,8 @@
public class OCRTask implements Callable {
private final Path sourceFile;
- private final ProjectModel project;
- private final BatchExportModel export;
+ private final Project project;
+ private final BatchExport export;
private final Preprocessor preprocessor;
private final LinkedBlockingQueue recognizers;
private final boolean hasPreprocessorChanged;
@@ -46,12 +46,10 @@ public class OCRTask implements Callable {
private final Writer errorLog;
private final AtomicInteger errors;
- public OCRTask(Path sourceFile, ProjectModel project,
- BatchExportModel export, Preprocessor preprocessor,
- LinkedBlockingQueue recognizers,
- boolean hasPreprocessorChanged, Path equivalencesFile,
- ProgressMonitor progressMonitor, AtomicInteger progress,
- Writer errorLog, AtomicInteger errors) {
+ OCRTask(Path sourceFile, Project project, BatchExport export, Preprocessor preprocessor,
+ LinkedBlockingQueue recognizers, boolean hasPreprocessorChanged,
+ Path equivalencesFile, ProgressMonitor progressMonitor, AtomicInteger progress, Writer errorLog,
+ AtomicInteger errors) {
this.sourceFile = sourceFile;
this.project = project;
this.export = export;
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/work/PageListWorker.java b/gui/src/main/java/de/vorb/tesseract/gui/work/PageListWorker.java
index 30bf4d7a..e95e75af 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/work/PageListWorker.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/work/PageListWorker.java
@@ -1,22 +1,20 @@
package de.vorb.tesseract.gui.work;
import de.vorb.tesseract.gui.model.PageThumbnail;
-import de.vorb.tesseract.gui.model.ProjectModel;
+import de.vorb.tesseract.gui.model.Project;
import javax.swing.DefaultListModel;
import javax.swing.SwingWorker;
-import java.awt.image.BufferedImage;
import java.nio.file.Path;
import java.util.List;
-import java.util.Optional;
public class PageListWorker extends SwingWorker {
- private final ProjectModel projectModel;
+ private final Project project;
private final DefaultListModel pages;
- public PageListWorker(final ProjectModel projectModel,
+ public PageListWorker(final Project project,
DefaultListModel pages) {
- this.projectModel = projectModel;
+ this.project = project;
this.pages = pages;
pages.clear();
@@ -24,12 +22,9 @@ public PageListWorker(final ProjectModel projectModel,
@Override
protected Void doInBackground() throws Exception {
- // no thumbnail
- final Optional thumbnail = Optional.empty();
-
// publish a placeholder (no thumbnail) for every image file
- for (final Path file : projectModel.getImageFiles()) {
- publish(new PageThumbnail(file, thumbnail));
+ for (final Path file : project.getImageFiles()) {
+ publish(new PageThumbnail(file, null));
}
return null;
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/work/PageRecognitionProducer.java b/gui/src/main/java/de/vorb/tesseract/gui/work/PageRecognitionProducer.java
index 11acc9a1..c1a6d527 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/work/PageRecognitionProducer.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/work/PageRecognitionProducer.java
@@ -22,17 +22,16 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
-import java.util.Optional;
public class PageRecognitionProducer extends RecognitionProducer {
+
private final Path tessdataDir;
- private Optional lastPix = Optional.empty();
+ private lept.PIX lastPix = null;
private final TesseractController controller;
private final HashMap variables = new HashMap<>();
- public PageRecognitionProducer(TesseractController controller,
- Path tessdataDir, String trainingFile) {
+ public PageRecognitionProducer(TesseractController controller, Path tessdataDir, String trainingFile) {
super(trainingFile);
this.controller = controller;
@@ -76,34 +75,34 @@ public void reset() throws IOException {
}
@Override
- public void close() throws IOException {
+ public void close() {
tesseract.TessBaseAPIDelete(getHandle());
}
- public void loadImage(Path imageFile) {
- if (lastPix.isPresent()) {
+ void loadImage(Path imageFile) {
+ if (lastPix != null) {
// destroy old pix
- lept.pixDestroy(lastPix.get());
+ lept.pixDestroy(lastPix);
}
final lept.PIX pix = lept.pixRead(imageFile.toString());
tesseract.TessBaseAPISetImage2(getHandle(), pix);
- lastPix = Optional.of(pix);
+ lastPix = pix;
}
- public Optional getImage() {
+ public lept.PIX getImage() {
return lastPix;
}
- public Optional getThresholdedImage() {
- return Optional.ofNullable(tesseract.TessBaseAPIGetThresholdedImage(getHandle()));
+ public lept.PIX getThresholdedImage() {
+ return tesseract.TessBaseAPIGetThresholdedImage(getHandle());
}
public List getFeaturesForSymbol(BufferedImage symbol) {
- if (!lastPix.isPresent()) {
- return new LinkedList<>();
+ if (lastPix == null) {
+ return Collections.emptyList();
}
final int padding = 5;
@@ -122,12 +121,11 @@ public List getFeaturesForSymbol(BufferedImage symbol) {
g2d.dispose();
// FIXME
- if (!controller.getProjectModel().isPresent()) {
+ if (controller.getProject() == null) {
return Collections.emptyList();
}
- final String symbolFile = controller.getProjectModel().get().getProjectDir().resolve(
- "symbol.png").toString();
+ final String symbolFile = controller.getProject().getProjectDir().resolve("symbol.png").toString();
try {
ImageIO.write(symbolWithPadding, "PNG", new File(symbolFile));
} catch (IOException e) {
@@ -166,7 +164,4 @@ public List getFeaturesForSymbol(BufferedImage symbol) {
}
}
- public void setVariable(String key, String value) {
- variables.put(key, value);
- }
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/work/PreprocessingWorker.java b/gui/src/main/java/de/vorb/tesseract/gui/work/PreprocessingWorker.java
index eee4912c..8bbbb66b 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/work/PreprocessingWorker.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/work/PreprocessingWorker.java
@@ -1,27 +1,28 @@
package de.vorb.tesseract.gui.work;
import de.vorb.tesseract.gui.controller.TesseractController;
-import de.vorb.tesseract.gui.model.ImageModel;
+import de.vorb.tesseract.gui.model.Image;
import de.vorb.tesseract.tools.preprocessing.Preprocessor;
import de.vorb.util.FileNames;
+import org.checkerframework.checker.nullness.qual.NonNull;
+
import javax.imageio.ImageIO;
import javax.swing.SwingWorker;
import java.awt.image.BufferedImage;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
-public class PreprocessingWorker extends SwingWorker {
+public class PreprocessingWorker extends SwingWorker {
private final TesseractController controller;
private final Preprocessor preprocessor;
private final Path sourceFile;
private final Path destinationDir;
public PreprocessingWorker(TesseractController controller,
- Preprocessor preprocessor, Path sourceFile, Path destinationDir) {
+ Preprocessor preprocessor, Path sourceFile, @NonNull Path destinationDir) {
this.controller = controller;
this.preprocessor = preprocessor;
this.sourceFile = sourceFile;
@@ -29,7 +30,7 @@ public PreprocessingWorker(TesseractController controller,
}
@Override
- protected ImageModel doInBackground() throws Exception {
+ protected Image doInBackground() throws Exception {
Files.createDirectories(destinationDir);
final Path destFile = destinationDir.resolve(FileNames.replaceExtension(
@@ -40,15 +41,14 @@ protected ImageModel doInBackground() throws Exception {
final BufferedImage preprocessedImg = preprocessor.process(sourceImg);
ImageIO.write(preprocessedImg, "PNG", destFile.toFile());
- return new ImageModel(sourceFile, sourceImg, destFile, preprocessedImg);
+ return new Image(sourceFile, sourceImg, destFile, preprocessedImg);
}
@Override
protected void done() {
try {
- controller.setImageModel(Optional.of(get()));
- } catch (InterruptedException | ExecutionException
- | CancellationException e) {
+ controller.setImage(get());
+ } catch (InterruptedException | ExecutionException | CancellationException e) {
} finally {
controller.getView().getProgressBar().setIndeterminate(false);
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/work/RecognitionWorker.java b/gui/src/main/java/de/vorb/tesseract/gui/work/RecognitionWorker.java
index afcfe1cf..9543c1d9 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/work/RecognitionWorker.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/work/RecognitionWorker.java
@@ -1,40 +1,38 @@
package de.vorb.tesseract.gui.work;
import de.vorb.tesseract.gui.controller.TesseractController;
-import de.vorb.tesseract.gui.model.ImageModel;
-import de.vorb.tesseract.gui.model.PageModel;
+import de.vorb.tesseract.gui.model.Image;
+import de.vorb.tesseract.gui.model.Page;
import de.vorb.tesseract.gui.view.dialogs.Dialogs;
import de.vorb.tesseract.tools.recognition.PageRecognitionConsumer;
import de.vorb.tesseract.util.Block;
-import de.vorb.tesseract.util.Page;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
-import java.util.Optional;
import java.util.concurrent.ExecutionException;
-public class RecognitionWorker extends SwingWorker {
+public class RecognitionWorker extends SwingWorker {
private final TesseractController controller;
- private final ImageModel imageModel;
+ private final Image image;
private final String trainingFile;
private final PageRecognitionProducer producer;
public RecognitionWorker(TesseractController controller,
- ImageModel imageModel, String trainingFile) {
+ Image image, String trainingFile) {
this.controller = controller;
- this.imageModel = imageModel;
+ this.image = image;
this.trainingFile = trainingFile;
this.producer = controller.getPageRecognitionProducer();
}
@Override
- protected PageModel doInBackground() throws Exception {
+ protected Page doInBackground() throws Exception {
// set the progress bar state to indeterminate
SwingUtilities.invokeLater(() -> {
- controller.setPageModel(Optional.empty());
+ controller.setPage(null);
controller.getView().getProgressBar().setIndeterminate(true);
});
@@ -44,12 +42,12 @@ protected PageModel doInBackground() throws Exception {
producer.reset();
- producer.loadImage(imageModel.getPreprocessedFile());
+ producer.loadImage(image.getPreprocessedFile());
final List blocks = new ArrayList<>(1);
// Get images
- final BufferedImage image = imageModel.getPreprocessedImage();
+ final BufferedImage image = this.image.getPreprocessedImage();
producer.recognize(new PageRecognitionConsumer(blocks) {
@Override
@@ -58,22 +56,22 @@ public boolean isCancelled() {
}
});
- final Page page = new Page(imageModel.getPreprocessedFile(),
+ final de.vorb.tesseract.util.Page page = new de.vorb.tesseract.util.Page(this.image.getPreprocessedFile(),
image.getWidth(), image.getHeight(), 300, blocks);
- return new PageModel(imageModel, page, "");
+ return new Page(this.image, page, "");
}
@Override
protected void done() {
try {
- controller.setPageModel(Optional.of(get()));
+ controller.setPage(get());
} catch (ExecutionException e) {
e.printStackTrace();
final String message = "The image could not be recognized";
- controller.setPageModel(Optional.empty());
+ controller.setPage(null);
Dialogs.showError(controller.getView(), "Error during recognition",
message);
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/work/RecognitionWriter.java b/gui/src/main/java/de/vorb/tesseract/gui/work/RecognitionWriter.java
index 82da1208..9b3f7df3 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/work/RecognitionWriter.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/work/RecognitionWriter.java
@@ -6,5 +6,7 @@
import java.io.Writer;
public interface RecognitionWriter {
+
void write(Page page, Writer writer) throws IOException;
+
}
diff --git a/gui/src/main/java/de/vorb/tesseract/gui/work/ThumbnailWorker.java b/gui/src/main/java/de/vorb/tesseract/gui/work/ThumbnailWorker.java
index c39a9e8f..184fd7f2 100644
--- a/gui/src/main/java/de/vorb/tesseract/gui/work/ThumbnailWorker.java
+++ b/gui/src/main/java/de/vorb/tesseract/gui/work/ThumbnailWorker.java
@@ -1,7 +1,7 @@
package de.vorb.tesseract.gui.work;
import de.vorb.tesseract.gui.model.PageThumbnail;
-import de.vorb.tesseract.gui.model.ProjectModel;
+import de.vorb.tesseract.gui.model.Project;
import javax.imageio.ImageIO;
import javax.swing.DefaultListModel;
@@ -11,13 +11,12 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
-import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class ThumbnailWorker extends
SwingWorker {
- private final ProjectModel projectModel;
+ private final Project project;
private final DefaultListModel pages;
private final Queue tasks = new ConcurrentLinkedQueue<>();
@@ -37,9 +36,9 @@ public void cancel() {
}
}
- public ThumbnailWorker(final ProjectModel project,
+ public ThumbnailWorker(final Project project,
DefaultListModel pages) {
- this.projectModel = project;
+ this.project = project;
this.pages = pages;
}
@@ -49,7 +48,7 @@ public void submitTask(Task task) {
@Override
protected Void doInBackground() throws Exception {
- final Path thumbsDir = projectModel.getThumbnailDir();
+ final Path thumbsDir = project.getThumbnailDir();
// mkdir -p thumbsDir
Files.createDirectories(thumbsDir);
@@ -96,12 +95,11 @@ protected Void doInBackground() throws Exception {
// release system resources used by this image
img.flush();
- // write the thumnail to disk
+ // write the thumbnail to disk
ImageIO.write(thumb, "PNG", thumbFile.toFile());
}
- publish(new Task(task.index, new PageThumbnail(imageFile,
- Optional.of(thumb))));
+ publish(new Task(task.index, new PageThumbnail(imageFile, thumb)));
} else {
Thread.sleep(500L);
}
diff --git a/ocrevalUAtion/pom.xml b/ocrevalUAtion/pom.xml
index e12af5dd..91286e93 100644
--- a/ocrevalUAtion/pom.xml
+++ b/ocrevalUAtion/pom.xml
@@ -37,7 +37,6 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.1
1.6
1.6
diff --git a/pom.xml b/pom.xml
index 3045b965..88091582 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,8 +17,15 @@
UTF-8
- 1.8
- 1.8
+
+
+ ${org.checkerframework:jdk8:jar}
+
+ 2.9.0
+
+ 3.1.1
+ 3.8.1
+ 1.12.0
@@ -33,6 +40,21 @@
ocrevalUAtion
${project.version}
+
+ org.checkerframework
+ checker
+ ${checker-framework.version}
+
+
+ org.checkerframework
+ checker-qual
+ ${checker-framework.version}
+
+
+ org.checkerframework
+ jdk8
+ ${checker-framework.version}
+
@@ -41,7 +63,7 @@
com.amashchenko.maven.plugin
gitflow-maven-plugin
- 1.12.0
+ ${gitflow-maven-plugin.version}
1
true
@@ -51,6 +73,35 @@
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ ${maven-dependency-plugin.version}
+
+
+
+ properties
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ 1.8
+ 1.8
+
+ 10000
+ 10000
+
+
+
+
+
diff --git a/tools/pom.xml b/tools/pom.xml
index 6b619154..efeaf83c 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -36,6 +36,18 @@
de.vorb.tesseract
ocrevalUAtion
+
+ org.checkerframework
+ checker
+
+
+ org.checkerframework
+ checker-qual
+
+
+ org.checkerframework
+ jdk8
+
junit
junit
@@ -44,6 +56,33 @@
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+ org.checkerframework
+ checker
+ ${checker-framework.version}
+
+
+
+
+ org.checkerframework.checker.nullness.NullnessChecker
+
+
+
+ -Xbootclasspath/p:${annotatedJdk}
+ -Awarns
+
+
+
+
+
+
central
diff --git a/tools/src/main/java/de/vorb/tesseract/tools/package-info.java b/tools/src/main/java/de/vorb/tesseract/tools/package-info.java
deleted file mode 100644
index 65644a9c..00000000
--- a/tools/src/main/java/de/vorb/tesseract/tools/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Tesseract.
- *
- * @author Paul Vorbach
- */
-package de.vorb.tesseract.tools;
-
diff --git a/tools/src/main/java/de/vorb/tesseract/tools/preprocessing/package-info.java b/tools/src/main/java/de/vorb/tesseract/tools/preprocessing/package-info.java
deleted file mode 100644
index 4f95cb07..00000000
--- a/tools/src/main/java/de/vorb/tesseract/tools/preprocessing/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Pre-processing tools.
- *
- * @author Paul Vorbach
- */
-package de.vorb.tesseract.tools.preprocessing;
diff --git a/tools/src/main/java/de/vorb/tesseract/tools/recognition/package-info.java b/tools/src/main/java/de/vorb/tesseract/tools/recognition/package-info.java
deleted file mode 100644
index 8eb8d9ef..00000000
--- a/tools/src/main/java/de/vorb/tesseract/tools/recognition/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Recognition related tools.
- *
- * @author Paul Vorbach
- */
-package de.vorb.tesseract.tools.recognition;
diff --git a/tools/src/main/java/de/vorb/tesseract/tools/training/package-info.java b/tools/src/main/java/de/vorb/tesseract/tools/training/package-info.java
deleted file mode 100644
index e83f6fcf..00000000
--- a/tools/src/main/java/de/vorb/tesseract/tools/training/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Tesseract training.
- *
- * @author Paul Vorbach
- */
-package de.vorb.tesseract.tools.training;
-
diff --git a/tools/src/main/java/de/vorb/tesseract/util/package-info.java b/tools/src/main/java/de/vorb/tesseract/util/package-info.java
deleted file mode 100644
index d7c06fb6..00000000
--- a/tools/src/main/java/de/vorb/tesseract/util/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Utilities for the Tesseract tools.
- *
- * @author Paul Vorbach
- */
-package de.vorb.tesseract.util;
-
diff --git a/tools/src/main/java/de/vorb/util/package-info.java b/tools/src/main/java/de/vorb/util/package-info.java
deleted file mode 100644
index 74b7f08f..00000000
--- a/tools/src/main/java/de/vorb/util/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Common utilities.
- *
- * @author Paul Vorbach
- */
-package de.vorb.util;
-