Skip to content
Snippets Groups Projects
Commit 79755216 authored by Yonatan's avatar Yonatan
Browse files

MVC Refactor

parent 05f0b300
No related branches found
No related tags found
No related merge requests found
package es.yonatan.tfg.frontend;
import es.yonatan.tfg.frontend.controller.ClientController;
import es.yonatan.tfg.frontend.model.Model;
import es.yonatan.tfg.frontend.view.MainView;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
var restClient = new RESTClient();
new MainWindow(restClient);
public static void main(String[] args) {
var model = new Model();
var view = new MainView();
var controller = new ClientController(model, view);
view.setupViews();
view.setVisible(true);
}
}
\ No newline at end of file
package es.yonatan.tfg.frontend;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.function.Consumer;
public class RESTClient {
public void translate(String serverUrl, File imageFile, String targetLang, String srcLang, double confidenceLevel, boolean debug, Consumer<String> responseListener) {
try {
var image = ImageIO.read(imageFile);
HttpURLConnection connection = (HttpURLConnection) new URL(serverUrl).openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
String jsonParameter = String.format(Locale.US, """
{
"imageData": "%s",
"options": {
"targetLang": "%s",
%s
"confidenceLevel": %.2f,
"debug": %b
}
}
""", Util.encodeBase64(image), targetLang, srcLang == null || srcLang.isEmpty() ? "" : "\"srcLang\": \"%s\",".formatted(srcLang), confidenceLevel, debug);
connection.setRequestProperty("Content-Type", "application/json");
byte[] postData = jsonParameter.getBytes(StandardCharsets.UTF_8);
connection.getOutputStream().write(postData);
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
connection.disconnect();
responseListener.accept(response.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
package es.yonatan.tfg.frontend.controller;
import com.google.gson.Gson;
import es.yonatan.tfg.frontend.model.Model;
import es.yonatan.tfg.frontend.util.Util;
import es.yonatan.tfg.frontend.view.MainView;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class ClientController {
private final Model model;
private final MainView view;
public ClientController(Model model, MainView view) {
this.model = model;
this.view = view;
view.setController(this);
}
public void pickImage() {
var fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setMultiSelectionEnabled(false);
fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
@Override
public boolean accept(java.io.File f) {
return f.isDirectory() || f.getName().endsWith(".png") || f.getName().endsWith(".jpg");
}
@Override
public String getDescription() {
return "Archivos de imagen";
}
});
var result = fileChooser.showOpenDialog(null);
if (result == JFileChooser.APPROVE_OPTION) {
model.setImageFile(fileChooser.getSelectedFile());
view.setFileLabel(model.getImageFile().getAbsolutePath());
view.setTranslateButtonEnabled(true);
}
}
public void save() {
var fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChooser.setMultiSelectionEnabled(false);
var saveFolder = fileChooser.showSaveDialog(null);
if (saveFolder == JFileChooser.APPROVE_OPTION) {
var savePath = fileChooser.getSelectedFile().getAbsolutePath();
var imageFile = new File(savePath + "/%s - translated.png".formatted(model.getImageFile().getName()));
var textFile = new File(savePath + "/%s - original transcript.txt".formatted(model.getImageFile().getName()));
var translatedFile = new File(savePath + "/%s - translated transcript.txt".formatted(model.getImageFile().getName()));
try {
ImageIO.write(Util.decodeBase64((String) model.getResult().get("imageData")), "png", imageFile);
Files.write(textFile.toPath(), ((String) model.getResult().get("srcTranscript")).getBytes());
Files.write(translatedFile.toPath(), ((String) model.getResult().get("translatedTranscript")).getBytes());
if (model.isDebug()) {
var debugPath = savePath + "/%s - ".formatted(model.getImageFile().getName());
var stepNames = new String[]{"Grayscale", "Binarization", "Bounding boxes", "Text mask"};
@SuppressWarnings("unchecked") var debugImages = ((java.util.List<String>) model.getResult().getOrDefault("debugImages", new ArrayList<String>()));
for (var i = 0; i < debugImages.size(); i++) {
var debugFile = new File(debugPath + stepNames[i] + ".png");
ImageIO.write(Util.decodeBase64(debugImages.get(i)), "png", debugFile);
}
}
Desktop.getDesktop().open(new File(savePath));
} catch (IOException e2) {
e2.printStackTrace();
}
model.setImageFile(null);
view.setFileLabel("Ningún archivo seleccionado");
view.setSaveButtonEnabled(false);
}
}
public void translate() {
try {
var image = ImageIO.read(model.getImageFile());
HttpURLConnection connection = (HttpURLConnection) new URL(model.getServerUrl()).openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
String jsonParameter = String.format(Locale.US, """
{
"imageData": "%s",
"options": {
"targetLang": "%s",
%s
"confidenceLevel": %.2f,
"debug": %b
}
}
""", Util.encodeBase64(image), model.getTargetLang(), model.getSrcLang() == null || model.getSrcLang().isEmpty() ? "" : "\"srcLang\": \"%s\",".formatted(model.getSrcLang()), model.getConfidenceLevel(), model.isDebug());
connection.setRequestProperty("Content-Type", "application/json");
byte[] postData = jsonParameter.getBytes(StandardCharsets.UTF_8);
connection.getOutputStream().write(postData);
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
connection.disconnect();
var result = new Gson().<Map<String, Object>>fromJson(response.toString(), HashMap.class);
model.setResult(result);
if (!((boolean) result.getOrDefault("success", false))) {
JOptionPane.showMessageDialog(null, result.get("message"), "Error", JOptionPane.ERROR_MESSAGE);
} else {
view.setTranslateButtonEnabled(false);
view.setSaveButtonEnabled(true);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void updateData() {
model.setServerUrl(view.getUrl());
var srcLang = view.getSrcLang();
model.setSrcLang(srcLang.toLowerCase().contains("detectar") ? null : srcLang);
model.setTargetLang(view.getTargetLang());
model.setConfidenceLevel(view.getConfidenceLevel());
model.setDebug(view.isDebugMode());
}
}
package es.yonatan.tfg.frontend.model;
import java.io.File;
import java.util.Map;
public class Model {
private String serverUrl;
private String targetLang;
private String srcLang;
private double confidenceLevel;
private boolean debug;
private File imageFile;
private Map<String, Object> result;
public Model() {
this.serverUrl = "http://localhost:8080/translate";
this.targetLang = "en";
this.srcLang = "";
this.confidenceLevel = 0.8;
this.debug = false;
this.result = null;
}
public String getServerUrl() {
return serverUrl;
}
public void setServerUrl(String serverUrl) {
this.serverUrl = serverUrl;
}
public String getTargetLang() {
return targetLang;
}
public void setTargetLang(String targetLang) {
this.targetLang = targetLang;
}
public String getSrcLang() {
return srcLang;
}
public void setSrcLang(String srcLang) {
this.srcLang = srcLang;
}
public double getConfidenceLevel() {
return confidenceLevel;
}
public void setConfidenceLevel(double confidenceLevel) {
this.confidenceLevel = confidenceLevel;
}
public boolean isDebug() {
return debug;
}
public void setDebug(boolean debug) {
this.debug = debug;
}
public File getImageFile() {
return imageFile;
}
public void setImageFile(File imageFile) {
this.imageFile = imageFile;
}
public Map<String, Object> getResult() {
return result;
}
public void setResult(Map<String, Object> result) {
this.result = result;
}
}
package es.yonatan.tfg.frontend;
package es.yonatan.tfg.frontend.util;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
......
package es.yonatan.tfg.frontend;
package es.yonatan.tfg.frontend.view;
import com.google.gson.Gson;
import netscape.javascript.JSObject;
import es.yonatan.tfg.frontend.controller.ClientController;
import es.yonatan.tfg.frontend.model.Model;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class MainWindow extends JFrame {
public class MainView extends JFrame {
private File selectedFile;
private ClientController controller;
private JButton translateButton;
private JButton saveButton;
private JLabel fileLabel;
private JTextField urlField;
private JComboBox<String> srcLang;
private JComboBox<String> targetLang;
private JSpinner confidenceLevel;
private JCheckBox debugMode;
public MainView() {
public MainWindow(RESTClient restClient) {
setTitle("TFG Yonatan Rodríguez Martín Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(800, 600);
......@@ -30,7 +32,9 @@ public class MainWindow extends JFrame {
IllegalAccessException e) {
e.printStackTrace();
}
}
public void setupViews() {
var panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
......@@ -40,7 +44,7 @@ public class MainWindow extends JFrame {
topPanel.add(new JLabel("URL del servidor: "));
var urlField = new JTextField("http://localhost:8080/translate");
urlField = new JTextField("http://localhost:8080/translate");
urlField.setPreferredSize(new Dimension(200, 26));
topPanel.add(urlField);
......@@ -59,7 +63,7 @@ public class MainWindow extends JFrame {
label1.setAlignmentX(SwingConstants.LEADING);
panel1.add(label1);
panel1.add(Box.createVerticalStrut(5));
var srcLang = new JComboBox<>(new String[]{"Detectar idioma", "es", "en"});
srcLang = new JComboBox<>(new String[]{"Detectar idioma", "es", "en"});
panel1.add(srcLang);
optionsPanel.add(panel1);
......@@ -71,7 +75,7 @@ public class MainWindow extends JFrame {
label2.setAlignmentX(SwingConstants.LEADING);
panel2.add(label2);
panel2.add(Box.createVerticalStrut(5));
var targetLang = new JComboBox<>(new String[]{"es", "en"});
targetLang = new JComboBox<>(new String[]{"es", "en"});
panel2.add(targetLang);
optionsPanel.add(panel2);
......@@ -83,7 +87,7 @@ public class MainWindow extends JFrame {
label3.setAlignmentX(SwingConstants.LEADING);
panel3.add(label3);
panel3.add(Box.createVerticalStrut(5));
var confidenceLevel = new JSpinner(new SpinnerNumberModel(80, 0, 100, 5));
confidenceLevel = new JSpinner(new SpinnerNumberModel(80, 0, 100, 5));
panel3.add(confidenceLevel);
optionsPanel.add(panel3);
......@@ -99,7 +103,7 @@ public class MainWindow extends JFrame {
panel4.add(fileChooserButton);
var fileLabel = new JLabel("Ningún archivo seleccionado");
fileLabel = new JLabel("Ningún archivo seleccionado");
panel4.add(Box.createHorizontalStrut(5));
panel4.add(fileLabel);
......@@ -108,7 +112,7 @@ public class MainWindow extends JFrame {
centerPanel.add(Box.createVerticalStrut(10));
var debugMode = new JCheckBox("Incluir pasos intermedios");
debugMode = new JCheckBox("Incluir pasos intermedios");
debugMode.setAlignmentX(SwingConstants.WEST);
centerPanel.add(debugMode);
......@@ -121,110 +125,73 @@ public class MainWindow extends JFrame {
var progressBar = new JProgressBar();
progressBar.setPreferredSize(new Dimension(200, 20));
var saveButton = new JButton("Guardar");
saveButton = new JButton("Guardar");
saveButton.setEnabled(false);
saveButton.addActionListener(e -> {
controller.save();
progressBar.setValue(0);
});
var translateButton = new JButton("Traducir");
translateButton = new JButton("Traducir");
translateButton.setEnabled(false);
translateButton.addActionListener(e -> {
progressBar.setValue(100);
if (srcLang.getSelectedItem() == null || targetLang.getSelectedItem() == null) return;
var url = urlField.getText();
var image = selectedFile;
var src = ((String) srcLang.getSelectedItem()).toLowerCase().contains("detectar") ? null : (String) srcLang.getSelectedItem();
var target = (String) targetLang.getSelectedItem();
var confidence = (Integer) confidenceLevel.getValue() / 100f;
var debug = debugMode.isSelected();
controller.updateData();
restClient.translate(url, image, target, src, confidence, debug, res -> {
var result = new Gson().<Map<String, Object>>fromJson(res, HashMap.class);
controller.translate();
});
if (!((boolean) result.getOrDefault("success", false))) {
JOptionPane.showMessageDialog(this, result.get("message"), "Error", JOptionPane.ERROR_MESSAGE);
} else {
translateButton.setEnabled(false);
saveButton.setEnabled(true);
saveButton.addActionListener(e1 -> {
var fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChooser.setMultiSelectionEnabled(false);
var saveFolder = fileChooser.showSaveDialog(this);
if (saveFolder == JFileChooser.APPROVE_OPTION) {
var savePath = fileChooser.getSelectedFile().getAbsolutePath();
var imageFile = new File(savePath + "/%s - translated.png".formatted(selectedFile.getName()));
var textFile = new File(savePath + "/%s - original transcript.txt".formatted(selectedFile.getName()));
var translatedFile = new File(savePath + "/%s - translated transcript.txt".formatted(selectedFile.getName()));
bottomPanel.add(translateButton);
try {
ImageIO.write(Util.decodeBase64((String) result.get("imageData")), "png", imageFile);
Files.write(textFile.toPath(), ((String) result.get("srcTranscript")).getBytes());
Files.write(translatedFile.toPath(), ((String) result.get("translatedTranscript")).getBytes());
fileChooserButton.addActionListener(e -> controller.pickImage());
if (debug) {
var debugPath = savePath + "/%s - ".formatted(selectedFile.getName());
bottomPanel.add(saveButton);
bottomPanel.add(progressBar);
var stepNames = new String[]{"Grayscale", "Binarization", "Bounding boxes", "Text mask"};
panel.add(bottomPanel, BorderLayout.SOUTH);
@SuppressWarnings("unchecked") var debugImages = ((java.util.List<String>) result.getOrDefault("debugImages", new ArrayList<String>()));
setContentPane(panel);
for (var i = 0; i < debugImages.size(); i++) {
var debugFile = new File(debugPath + stepNames[i] + ".png");
ImageIO.write(Util.decodeBase64(debugImages.get(i)), "png", debugFile);
}
pack();
setVisible(true);
}
Desktop.getDesktop().open(new File(savePath));
} catch (IOException e2) {
e2.printStackTrace();
public void setController(ClientController controller) {
this.controller = controller;
}
selectedFile = null;
fileLabel.setText("Ningún archivo seleccionado");
saveButton.setEnabled(false);
progressBar.setValue(0);
public void setTranslateButtonEnabled(boolean enabled) {
translateButton.setEnabled(enabled);
}
});
}
});
});
bottomPanel.add(translateButton);
fileChooserButton.addActionListener(e -> {
var fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setMultiSelectionEnabled(false);
fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
@Override
public boolean accept(java.io.File f) {
return f.isDirectory() || f.getName().endsWith(".png") || f.getName().endsWith(".jpg");
public void setSaveButtonEnabled(boolean enabled) {
saveButton.setEnabled(enabled);
}
@Override
public String getDescription() {
return "Archivos de imagen";
public void setFileLabel(String text) {
fileLabel.setText(text);
}
});
var result = fileChooser.showOpenDialog(this);
if (result == JFileChooser.APPROVE_OPTION) {
selectedFile = fileChooser.getSelectedFile();
fileLabel.setText(selectedFile.getAbsolutePath());
translateButton.setEnabled(true);
public String getUrl() {
return urlField.getText();
}
});
bottomPanel.add(saveButton);
bottomPanel.add(progressBar);
public String getSrcLang() {
return (String) srcLang.getSelectedItem();
}
panel.add(bottomPanel, BorderLayout.SOUTH);
public String getTargetLang() {
return (String) targetLang.getSelectedItem();
}
setContentPane(panel);
public double getConfidenceLevel() {
return (int) confidenceLevel.getValue() / 100d;
}
pack();
setVisible(true);
public boolean isDebugMode() {
return debugMode.isSelected();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment