package magic.ui.dialog.prefs;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import magic.data.GeneralConfig;
import magic.translate.MText;
import magic.exception.DesktopNotSupportedException;
import magic.ui.ScreenController;
import magic.ui.WikiPage;
import magic.ui.helpers.DesktopHelper;
import magic.utility.MagicFileSystem;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
class TranslationPanel extends JPanel {
// translatable strings.
private static final String _S1 = "Edit";
private static final String _S2 = "Delete the <b>%s</b> translation file?";
private static final String _S3 = "Delete translation file";
private static final String _S4 = "Delete";
private static final String _S5 = "eg. français, español, Deutsch, etc.";
private static final String _S6 = "New Translation File";
private static final String _S7 = "A translation file with this name already exists.";
private static final String _S8 = "Invalid filename!";
private static final String _S9 = "Failed to create translation file.\n%s";
private static final String _S10 = "Could not open translation file.\n%s";
private static final String _S11 = "Could not locate JAR.\n%s";
private static final String _S12 = "New translation";
private static final String _S13 = "Could not open file in default 'txt' editor.\n%s";
private static final String _S14 = "File Explorer";
private static final String _S15 = "Yes";
private static final String _S16 = "No";
private static final String _S17 = "Help";
private final JComboBox<String> languageCombo = new JComboBox<>();
private final JButton menuButton = new JButton();
private final JPopupMenu popupMenu = new JPopupMenu();
private final JMenuItem newMenuItem = new JMenuItem();
private final JMenuItem editMenuItem = new JMenuItem();
private final JMenuItem deleteMenuItem = new JMenuItem();
TranslationPanel() {
setupMenuButton();
setupNewMenuItem();
setupEditMenuItem();
setupDeleteMenuItem();
popupMenu.addSeparator();
setupExplorerMenuItem();
popupMenu.addSeparator();
setupHelpMenuItem();
setupComboBox();
setLayout(new MigLayout("insets 0, gap 0"));
add(languageCombo, "w 200!");
add(menuButton, "w 26!, h 26!");
}
private void setupHelpMenuItem() {
final JMenuItem menu = new JMenuItem(new AbstractAction(MText.get(MText.get(_S17))) {
@Override
public void actionPerformed(ActionEvent e) {
WikiPage.show(WikiPage.TRANSLATING);
}
});
popupMenu.add(menu);
}
private void setupExplorerMenuItem() {
final JMenuItem itemReload = new JMenuItem(new AbstractAction(MText.get(_S14)) {
@Override
public void actionPerformed(ActionEvent e) {
try {
getParent().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
doOpenTranslationsFolder();
} catch (IOException ex) {
ScreenController.showWarningMessage(ex.getMessage());
} finally {
getParent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
});
popupMenu.add(itemReload);
}
private void showPopupMenu() {
popupMenu.show(this, menuButton.getX(), menuButton.getY() + menuButton.getHeight());
}
private void setupMenuButton() {
menuButton.setText("...");
menuButton.setFont(menuButton.getFont().deriveFont(Font.BOLD));
menuButton.setFocusable(false);
menuButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(final ActionEvent e) {
showPopupMenu();
}
});
}
private void setupComboBox() {
refreshLanguageCombo();
languageCombo.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
setStateOfActionButtons();
}
});
languageCombo.setFocusable(false);
}
private void setStateOfActionButtons() {
final boolean isEnglish = languageCombo.getSelectedIndex() == 0;
final boolean isActive = getSelectedLanguage().equals(GeneralConfig.getInstance().getTranslation());
editMenuItem.setEnabled(!isEnglish);
deleteMenuItem.setEnabled(!isEnglish && !isActive);
}
private void doEditTranslationFile() throws URISyntaxException, UnsupportedEncodingException, IOException {
final String lang = (String) languageCombo.getSelectedItem();
final File langFile = MagicFileSystem.getDataPath(
MagicFileSystem.DataPath.TRANSLATIONS).resolve(lang + ".txt").toFile();
if (langFile.exists() == false) {
throw new FileNotFoundException(langFile.getAbsolutePath());
}
// 1. Build strings map from UI.
final Map<Long, String> latestStrings = MText.getUiStringsMap();
// 2. load map of escaped strings from translation file.
final Map<Long, String> langStrings = MText.getEscapedStringsMap(langFile);
// 3. remove entries from 2. missing in 1.
final Set<Long> latestKeys = latestStrings.keySet();
final Set<Long> langKeys = langStrings.keySet();
langKeys.retainAll(latestKeys);
// 4. append remaining entries in 2. to end of 1.
latestKeys.removeAll(langKeys);
latestStrings.putAll(langStrings);
// 5. save 1. by overwriting existing translation file.
MText.createTranslationFile(langFile, latestStrings);
// 6. open file in default txt editor.
try {
DesktopHelper.openFileInDefaultOsEditor(langFile);
} catch (IOException | DesktopNotSupportedException ex) {
ScreenController.showWarningMessage(MText.get(_S13, ex));
}
}
private void doOpenTranslationsFolder() throws IOException {
final Path folder = MagicFileSystem.getDataPath(MagicFileSystem.DataPath.TRANSLATIONS);
DesktopHelper.openDirectory(folder.toString());
}
private void setupEditMenuItem() {
editMenuItem.setAction(new AbstractAction(MText.get(_S1)) {
@Override
public void actionPerformed(ActionEvent e) {
getParent().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
doEditTranslationFile();
} catch (URISyntaxException | IOException ex) {
ScreenController.showWarningMessage(ex.getMessage());
} finally {
getParent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
});
editMenuItem.setEnabled(false);
popupMenu.add(editMenuItem);
}
private void doDeleteTranslationFile() {
final String lang = (String) languageCombo.getSelectedItem();
final File langFile = MagicFileSystem.getDataPath(MagicFileSystem.DataPath.TRANSLATIONS).resolve(lang + ".txt").toFile();
if (langFile.exists()) {
if (JOptionPane.showOptionDialog(ScreenController.getFrame(),
String.format("<html>%s</html>", MText.get(_S2, lang)),
MText.get(_S3),
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
new String[]{MText.get(_S15), MText.get(_S16)},
MText.get(_S16)
) == JOptionPane.YES_OPTION) {
langFile.delete();
refreshLanguageCombo();
}
}
}
private void setupDeleteMenuItem() {
deleteMenuItem.setAction(new AbstractAction(MText.get(_S4)) {
@Override
public void actionPerformed(ActionEvent e) {
getParent().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
doDeleteTranslationFile();
getParent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
});
deleteMenuItem.setEnabled(false);
popupMenu.add(deleteMenuItem);
}
private void doAddNewTranslationFile() {
try {
final String text = JOptionPane.showInputDialog(null, MText.get(_S5), MText.get(_S6), JOptionPane.QUESTION_MESSAGE);
if (text != null) {
final String language = text.trim();
if (language.isEmpty() == false && language.equalsIgnoreCase("English") == false) {
File langFile = MagicFileSystem.getDataPath(MagicFileSystem.DataPath.TRANSLATIONS).resolve(language + ".txt").toFile();
if (langFile.exists()) {
ScreenController.showWarningMessage(MText.get(_S7));
return;
}
MText.createTranslationFIle(langFile);
DesktopHelper.openFileInDefaultOsEditor(langFile);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
refreshLanguageCombo();
languageCombo.setSelectedItem(language);
}
});
} else {
ScreenController.showWarningMessage(MText.get(_S8));
}
}
} catch (FileNotFoundException ex) {
ScreenController.showWarningMessage(MText.get(_S9, ex));
} catch (IOException | DesktopNotSupportedException ex) {
ScreenController.showWarningMessage(MText.get(_S10, ex));
} catch (URISyntaxException ex) {
ScreenController.showWarningMessage(MText.get(_S11, ex));
}
}
private void setupNewMenuItem() {
newMenuItem.setAction(new AbstractAction(MText.get(_S12)) {
@Override
public void actionPerformed(ActionEvent e) {
getParent().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
doAddNewTranslationFile();
getParent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
});
popupMenu.add(newMenuItem);
}
public void refreshLanguageCombo() {
final List<String> languages = MagicFileSystem.getTranslationFilenames();
languages.add(0, "English");
languageCombo.setModel(new DefaultComboBoxModel<>(languages.toArray(new String[0])));
languageCombo.setSelectedItem(GeneralConfig.getInstance().getTranslation());
setStateOfActionButtons();
}
@Override
public void setToolTipText(String text) {
super.setToolTipText(text);
languageCombo.setToolTipText(text);
}
@Override
public synchronized void addMouseListener(MouseListener aListener) {
languageCombo.addMouseListener(aListener);
}
String getSelectedLanguage() {
return languageCombo.getSelectedIndex() == 0 ? "" : (String) languageCombo.getSelectedItem();
}
}