/**************************************************************************
OmegaT - Computer Assisted Translation (CAT) tool
with fuzzy matching, translation memory, keyword search,
glossaries, and translation leveraging into updated projects.
Copyright (C) 2016 Aaron Madlon-Kay
Home page: http://www.omegat.org/
Support center: http://groups.yahoo.com/group/OmegaT/
This file is part of OmegaT.
OmegaT is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OmegaT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
package org.omegat.gui.align;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.datatransfer.DataFlavor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CancellationException;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import javax.swing.TransferHandler;
import javax.swing.WindowConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.JTextComponent;
import org.omegat.core.Core;
import org.omegat.core.segmentation.SRX;
import org.omegat.core.segmentation.Segmenter;
import org.omegat.filters2.master.FilterMaster;
import org.omegat.filters2.master.PluginUtils;
import org.omegat.util.Language;
import org.omegat.util.Log;
import org.omegat.util.OStrings;
import org.omegat.util.StringUtil;
import org.omegat.util.gui.LanguageComboBoxRenderer;
import org.omegat.util.gui.StaticUIUtils;
/**
* Controller for align file picker UI
*
* @author Aaron Madlon-Kay
*/
public class AlignFilePickerController {
String sourceFile;
String targetFile;
String sourceDefaultDir;
String targetDefaultDir;
String defaultSaveDir;
List<Language> allLangs = Language.getLanguages();
Language sourceLanguage = allLangs.get(0);
Language targetLanguage = allLangs.get(allLangs.size() - 1);
public void setSourceFile(String sourceFile) {
this.sourceFile = sourceFile;
}
public void setTargetFile(String targetFile) {
this.targetFile = targetFile;
}
public void setSourceLanguage(Language sourceLanguage) {
this.sourceLanguage = sourceLanguage;
}
public void setTargetLanguage(Language targetLanguage) {
this.targetLanguage = targetLanguage;
}
public void setSourceDefaultDir(String sourceDefaultDir) {
this.sourceDefaultDir = sourceDefaultDir;
}
public void setTargetDefaultDir(String targetDefaultDir) {
this.targetDefaultDir = targetDefaultDir;
}
public void setDefaultSaveDir(String defaultSaveDir) {
this.defaultSaveDir = defaultSaveDir;
}
/**
* Display the align tool file picker. The picker is not modal, so this call will return immediately.
*
* @param parent
* Parent window of file picker and align window
*/
@SuppressWarnings("serial")
public void show(final Component parent) {
final JFrame frame = new JFrame(OStrings.getString("ALIGNER_FILEPICKER"));
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
StaticUIUtils.setEscapeClosable(frame);
final AlignFilePicker picker = new AlignFilePicker();
picker.sourceLanguagePicker.setModel(new DefaultComboBoxModel<>(new Vector<>(Language.getLanguages())));
picker.sourceLanguagePicker.setRenderer(new LanguageComboBoxRenderer());
picker.sourceLanguagePicker.setSelectedItem(sourceLanguage);
picker.sourceLanguagePicker.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() != ItemEvent.SELECTED) {
return;
}
if (e.getItem() instanceof String) {
String newVal = (String) e.getItem();
if (Language.verifySingleLangCode(newVal)) {
sourceLanguage = new Language(newVal);
} else {
sourceLanguage = null;
JOptionPane.showMessageDialog(frame,
OStrings.getString("NP_INVALID_SOURCE_LOCALE")
+ OStrings.getString("NP_LOCALE_SUGGESTION"),
OStrings.getString("TF_ERROR"), JOptionPane.ERROR_MESSAGE);
picker.sourceLanguagePicker.requestFocusInWindow();
}
} else if (e.getItem() instanceof Language) {
sourceLanguage = (Language) e.getItem();
} else {
throw new IllegalArgumentException();
}
updatePicker(picker);
}
});
picker.targetLanguagePicker.setModel(new DefaultComboBoxModel<>(new Vector<>(Language.getLanguages())));
picker.targetLanguagePicker.setRenderer(new LanguageComboBoxRenderer());
picker.targetLanguagePicker.setSelectedItem(targetLanguage);
picker.targetLanguagePicker.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() != ItemEvent.SELECTED) {
return;
}
if (e.getItem() instanceof String) {
String newVal = (String) e.getItem();
if (Language.verifySingleLangCode(newVal)) {
targetLanguage = new Language(newVal);
} else {
targetLanguage = null;
JOptionPane.showMessageDialog(frame,
OStrings.getString("NP_INVALID_TARGET_LOCALE")
+ OStrings.getString("NP_LOCALE_SUGGESTION"),
OStrings.getString("TF_ERROR"), JOptionPane.ERROR_MESSAGE);
picker.targetLanguagePicker.requestFocusInWindow();
}
} else if (e.getItem() instanceof Language) {
targetLanguage = (Language) e.getItem();
} else {
throw new IllegalArgumentException();
}
updatePicker(picker);
}
});
picker.sourceChooseFileButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
File file = chooseFile(frame, OStrings.getString("ALIGNER_FILEPICKER_CHOOSE_SOURCE"),
StringUtil.isEmpty(sourceFile) ? sourceDefaultDir : sourceFile);
if (file != null) {
sourceDefaultDir = file.getParent();
targetDefaultDir = targetDefaultDir == null ? sourceDefaultDir : targetDefaultDir;
defaultSaveDir = defaultSaveDir == null ? sourceDefaultDir : defaultSaveDir;
picker.sourceLanguageFileField.setText(file.getAbsolutePath());
}
}
});
picker.targetChooseFileButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
File file = chooseFile(frame, OStrings.getString("ALIGNER_FILEPICKER_CHOOSE_TARGET"),
StringUtil.isEmpty(targetFile) ? targetDefaultDir : targetFile);
if (file != null) {
targetDefaultDir = file.getParent();
sourceDefaultDir = sourceDefaultDir == null ? targetDefaultDir : sourceDefaultDir;
defaultSaveDir = defaultSaveDir == null ? targetDefaultDir : defaultSaveDir;
picker.targetLanguageFileField.setText(file.getAbsolutePath());
}
}
});
picker.sourceLanguageFileField.setText(sourceFile);
picker.sourceLanguageFileField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
update();
}
@Override
public void insertUpdate(DocumentEvent e) {
update();
}
@Override
public void changedUpdate(DocumentEvent e) {
update();
}
private void update() {
sourceFile = picker.sourceLanguageFileField.getText();
updatePicker(picker);
}
});
picker.targetLanguageFileField.setText(targetFile);
picker.targetLanguageFileField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
update();
}
@Override
public void insertUpdate(DocumentEvent e) {
update();
}
@Override
public void changedUpdate(DocumentEvent e) {
update();
}
private void update() {
targetFile = picker.targetLanguageFileField.getText();
updatePicker(picker);
}
});
TransferHandler transferHandler = new TransferHandler() {
@Override
public boolean canImport(TransferSupport support) {
return support.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
}
@Override
public boolean importData(TransferSupport support) {
if (!canImport(support)) {
return false;
}
try {
List<?> list = (List<?>) support.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
List<File> files = getSupportedFiles(list);
if (files.isEmpty()) {
return false;
}
JTextComponent field = (JTextComponent) support.getComponent();
field.setText(files.get(0).getAbsolutePath());
return true;
} catch (Exception e) {
Log.log(e);
return false;
}
}
};
picker.sourceLanguageFileField.setTransferHandler(transferHandler);
picker.targetLanguageFileField.setTransferHandler(transferHandler);
picker.setTransferHandler(new TransferHandler() {
@Override
public boolean canImport(TransferSupport support) {
return support.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
}
@Override
public boolean importData(TransferSupport support) {
if (!canImport(support)) {
return false;
}
try {
List<?> list = (List<?>) support.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
List<File> files = getSupportedFiles(list);
if (files.isEmpty()) {
return false;
} else if (files.size() == 1) {
JTextComponent insertTarget = picker.sourceLanguageFileField;
if (picker.sourceLanguageFileField.getDocument().getLength() != 0
&& picker.targetLanguageFileField.getDocument().getLength() == 0) {
insertTarget = picker.targetLanguageFileField;
}
insertTarget.setText(files.get(0).getAbsolutePath());
} else {
picker.sourceLanguageFileField.setText(files.get(0).getAbsolutePath());
picker.targetLanguageFileField.setText(files.get(1).getAbsolutePath());
}
return true;
} catch (Exception e) {
Log.log(e);
return false;
}
}
});
picker.okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
picker.bottomPanel.remove(picker.messageTextArea);
picker.bottomPanel.add(picker.progressBar, BorderLayout.CENTER);
picker.bottomPanel.revalidate();
new SwingWorker<Aligner, Void>() {
@Override
protected Aligner doInBackground() throws Exception {
Aligner aligner = new Aligner(sourceFile, sourceLanguage, targetFile, targetLanguage);
aligner.loadFiles();
return aligner;
}
@Override
protected void done() {
try {
Aligner aligner = get();
new AlignPanelController(aligner, defaultSaveDir).show(parent);
} catch (CancellationException e) {
// Ignore
} catch (Exception e) {
Log.log(e);
JOptionPane.showMessageDialog(frame, OStrings.getString("ALIGNER_ERROR_LOADING"),
OStrings.getString("ERROR_TITLE"), JOptionPane.ERROR_MESSAGE);
}
frame.dispose();
}
}.execute();
}
});
picker.cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
frame.dispose();
}
});
frame.getRootPane().setDefaultButton(picker.okButton);
updatePicker(picker);
frame.add(picker);
frame.pack();
frame.setLocationRelativeTo(parent);
frame.setVisible(true);
}
private void updatePicker(final AlignFilePicker picker) {
if (sourceFile == null || targetFile == null || sourceLanguage == null || targetLanguage == null) {
picker.messageTextArea.setText(null);
picker.okButton.setEnabled(false);
return;
}
final File srcFile = new File(sourceFile);
final File trgFile = new File(targetFile);
if (!srcFile.isFile() || !trgFile.isFile() || srcFile.equals(trgFile)) {
picker.messageTextArea.setText(null);
picker.okButton.setEnabled(false);
return;
}
new SwingWorker<boolean[], Void>() {
@Override
protected boolean[] doInBackground() throws Exception {
FilterMaster fm = Core.getFilterMaster();
return new boolean[] {
fm.isFileSupported(srcFile, false), fm.isFileSupported(trgFile, false) };
}
@Override
protected void done() {
boolean enabled = false;
String message = null;
try {
boolean[] results = get();
enabled = results[0] && results[1];
if (!results[0] && results[1]) {
message = OStrings.getString("ALIGNER_FILEPICKER_ERROR_ONE_FILE", srcFile.getName());
} else if (results[0] && !results[1]) {
message = OStrings.getString("ALIGNER_FILEPICKER_ERROR_ONE_FILE", trgFile.getName());
} else if (!results[0] && !results[1]) {
message = OStrings.getString("ALIGNER_FILEPICKER_ERROR_BOTH_FILES");
}
} catch (CancellationException e) {
// Ignore
} catch (Exception e) {
Log.log(e);
message = e.getLocalizedMessage();
}
picker.okButton.setEnabled(enabled);
picker.messageTextArea.setText(message);
}
}.execute();
}
private static List<File> getSupportedFiles(List<?> files) {
List<File> result = new ArrayList<File>(files.size());
FilterMaster fm = Core.getFilterMaster();
for (Object o : files) {
File file = (File) o;
if (fm.isFileSupported(file, true)) {
result.add(file);
}
}
return result;
}
static File chooseFile(Component parent, String title, String dir) {
JFileChooser chooser = new JFileChooser(dir);
chooser.setDialogTitle(title);
chooser.setFileFilter(new FileFilter() {
@Override
public String getDescription() {
return OStrings.getString("ALIGNER_FILEPICKER_SUPPORTEDFILES");
}
@Override
public boolean accept(File f) {
return f.isDirectory() || Core.getFilterMaster().isFileSupported(f, true);
}
});
if (chooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
return chooser.getSelectedFile();
}
return null;
}
/**
* Entry point for debugging or standalone use. Optionally accepts four arguments to pre-fill the picker:
* <ol>
* <li>Source language
* <li>Source file path
* <li>Target language
* <li>Target file path
* </ol>
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
System.setProperty("apple.laf.useScreenMenuBar", "true");
PluginUtils.loadPlugins(Collections.<String, String> emptyMap());
Core.setFilterMaster(new FilterMaster(FilterMaster.createDefaultFiltersConfig()));
Core.setSegmenter(new Segmenter(SRX.getDefault()));
AlignFilePickerController picker = new AlignFilePickerController();
if (args.length == 4) {
picker.sourceLanguage = new Language(args[0]);
picker.sourceFile = args[1];
picker.targetLanguage = new Language(args[2]);
picker.targetFile = args[3];
}
picker.show(null);
}
}