Added translate from tengwar to english.

This commit is contained in:
Andrew Lalis 2017-05-02 11:27:29 +02:00
parent b894c67900
commit 8a71899904
2 changed files with 174 additions and 39 deletions

View File

@ -17,6 +17,7 @@ import java.util.ArrayList;
public class Window { public class Window {
//List of files that can be imported.
public static final List<String> OPEN_FILE_EXTENSIONS = new ArrayList<>(); public static final List<String> OPEN_FILE_EXTENSIONS = new ArrayList<>();
static { static {
@ -39,18 +40,16 @@ public class Window {
private boolean isLive = false; private boolean isLive = false;
public Window() { Window() {
//Load the font into the system.
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Font tengwar_annatar = null;
try { try {
tengwar_annatar = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getClassLoader().getResourceAsStream("resources/tngan.ttf")); ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, this.getClass().getClassLoader().getResourceAsStream("resources/tngan.ttf")));
} catch (FontFormatException e) { } catch (FontFormatException e) {
e.printStackTrace(); System.err.println("Font format exception!");
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); System.err.println("IOException!");
} }
ge.registerFont(tengwar_annatar);
//Explicit translation from english to tengwar. //Explicit translation from english to tengwar.
toTengwarButton.addActionListener(new ActionListener() { toTengwarButton.addActionListener(new ActionListener() {
@ -59,6 +58,7 @@ public class Window {
tengwarTextArea.setText(Translator.translateToTengwar(inputTextArea.getText())); tengwarTextArea.setText(Translator.translateToTengwar(inputTextArea.getText()));
} }
}); });
//Clear both text areas. //Clear both text areas.
clearButton.addActionListener(new ActionListener() { clearButton.addActionListener(new ActionListener() {
@Override @Override
@ -67,10 +67,12 @@ public class Window {
inputTextArea.setText(null); inputTextArea.setText(null);
} }
}); });
//Translate tengwar to english. //Translate tengwar to english.
toEnglishButton.addActionListener(new ActionListener() { toEnglishButton.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
inputTextArea.setText(Translator.translateToEnglish(tengwarTextArea.getText()));
} }
}); });
} }
@ -101,20 +103,31 @@ public class Window {
this.inputTextArea.requestFocus(); this.inputTextArea.requestFocus();
} }
public JPanel getMainPanel(){ JPanel getMainPanel(){
return this.mainPanel; return this.mainPanel;
} }
/**
* If the english text is changed, and live is selected, then update the tengwar text.
*/
private void onEnglishTextChanged(){ private void onEnglishTextChanged(){
if (isLive) if (isLive && inputTextArea.hasFocus())
tengwarTextArea.setText(Translator.translateToTengwar(inputTextArea.getText())); tengwarTextArea.setText(Translator.translateToTengwar(inputTextArea.getText()));
} }
/**
* If tengwar text is changed, and live is selected, then update the english text.
*/
private void onTengwarTextChanged(){
if (isLive && tengwarTextArea.hasFocus())
inputTextArea.setText(Translator.translateToEnglish(tengwarTextArea.getText()));
}
/** /**
* Toggle the live button and disable translate buttons if needed. * Toggle the live button and disable translate buttons if needed.
* @param e event generated by the check box. * @param e event generated by the check box.
*/ */
public void onLiveToggled(ActionEvent e){ void onLiveToggled(ActionEvent e){
if (((JCheckBoxMenuItem) e.getSource()).getState()){ if (((JCheckBoxMenuItem) e.getSource()).getState()){
//Deactivate buttons, set live to true. //Deactivate buttons, set live to true.
toTengwarButton.setEnabled(false); toTengwarButton.setEnabled(false);
@ -131,7 +144,7 @@ public class Window {
/** /**
* What to do if the user clicks the 'import' button. * What to do if the user clicks the 'import' button.
*/ */
public void onImportClicked(){ void onImportClicked(){
JFileChooser fileChooser = new JFileChooser(System.getProperty("user.documents")); JFileChooser fileChooser = new JFileChooser(System.getProperty("user.documents"));
fileChooser.setFileFilter(new FileFilter() { fileChooser.setFileFilter(new FileFilter() {
@Override @Override
@ -171,7 +184,7 @@ public class Window {
/** /**
* What to do when the user wants to save their document. * What to do when the user wants to save their document.
*/ */
public void onSaveClicked(){ void onSaveClicked(){
JFileChooser fileChooser = new JFileChooser(System.getProperty("user.documents")); JFileChooser fileChooser = new JFileChooser(System.getProperty("user.documents"));
int result = fileChooser.showSaveDialog(this.mainPanel); int result = fileChooser.showSaveDialog(this.mainPanel);
if (result == JFileChooser.APPROVE_OPTION){ if (result == JFileChooser.APPROVE_OPTION){
@ -186,7 +199,7 @@ public class Window {
/** /**
* Attempt to open the pdf in the browser. * Attempt to open the pdf in the browser.
*/ */
public void onEnglishModeAboutClicked(){ void onEnglishModeAboutClicked(){
if (Desktop.isDesktopSupported()){ if (Desktop.isDesktopSupported()){
try{ try{
Desktop.getDesktop().browse(new URI("https://github.com/andrewlalis/TengwarTranslator/blob/master/src/resources/EnglishOneToOneTengwarV2-1.pdf")); Desktop.getDesktop().browse(new URI("https://github.com/andrewlalis/TengwarTranslator/blob/master/src/resources/EnglishOneToOneTengwarV2-1.pdf"));
@ -199,7 +212,7 @@ public class Window {
/** /**
* Attempt to open Tengwar wikipedia page. * Attempt to open Tengwar wikipedia page.
*/ */
public void onTengwarAboutClicked(){ void onTengwarAboutClicked(){
if (Desktop.isDesktopSupported()){ if (Desktop.isDesktopSupported()){
try{ try{
Desktop.getDesktop().browse(new URI("https://en.wikipedia.org/wiki/Tengwar")); Desktop.getDesktop().browse(new URI("https://en.wikipedia.org/wiki/Tengwar"));
@ -212,7 +225,7 @@ public class Window {
/** /**
* Attempt to open my github page. * Attempt to open my github page.
*/ */
public void onAboutMeClicked(){ void onAboutMeClicked(){
if (Desktop.isDesktopSupported()){ if (Desktop.isDesktopSupported()){
try{ try{
Desktop.getDesktop().browse(new URI("https://github.com/andrewlalis")); Desktop.getDesktop().browse(new URI("https://github.com/andrewlalis"));

View File

@ -1,28 +1,12 @@
package net.agspace.translate; package net.agspace.translate;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* Created by Andrew's Computer on 23-Apr-17. * Created by Andrew's Computer on 23-Apr-17.
*/ */
public class Translator { public class Translator {
private enum CHAR_TYPE {
CONSONANT,
COMPOUND,
ALTERNATE,
VOWEL,
NUMBER,
CARRIER,
PUNCTUATION,
BAR,
S_CURL,
UNKNOWN,
}
//Consonant variables. //Consonant variables.
private static final char B = 'w'; private static final char B = 'w';
private static final char C = 'c'; private static final char C = 'c';
@ -184,7 +168,6 @@ public class Translator {
alternateChars.put('s', S_ALT); alternateChars.put('s', S_ALT);
alternateChars.put('z', Z_ALT); alternateChars.put('z', Z_ALT);
alternateChars.put('w', W_ALT); alternateChars.put('w', W_ALT);
//alternateChars.put('r', R_ALT); R alt is used if followed by a vowel.
alternateChars.put('y', Y_ALT); alternateChars.put('y', Y_ALT);
} }
@ -372,6 +355,92 @@ public class Translator {
return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'); return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u');
} }
/**
* Determines if a tengwar character is a vowel.
* @param c tengwar char to check.
* @return true if vowel, false if not.
*/
private static boolean isVowelTengwar(char c){
for (Character[] ch : vowelChars.values()){
for (char cha : ch){
if (cha == c)
return true;
}
}
return false;
}
/**
* Returns the english vowel representation of a tengwar vowel.
* @param tengwarVowel The tengwar vowel to decipher.
* @return english vowel char.
*/
private static char getEnglishVowel(char tengwarVowel){
if (!isVowelTengwar(tengwarVowel)){
return 0;
}
for (Character[] ch : vowelChars.values()){
for (char cha : ch){
if (cha == tengwarVowel) {
return getKeyByValue(vowelChars, ch);
}
}
}
return 0;
}
/**
* Determines if a tengwar char is a silent E.
* @param tengwarChar the tengwar char to evaluate.
* @return True if it is a silent E, false otherwise.
*/
private static boolean isSilentE(char tengwarChar){
return tengwarChar == E_UNDER_1
|| tengwarChar == E_UNDER_2
|| tengwarChar == E_UNDER_3
|| tengwarChar == E_UNDER_4
|| tengwarChar == E_LAMBE;
}
/**
* Returns a character or string that is a literal translation from tengwar.
* @param tengwarChar the tengwar char to translate.
* @return english representation of the tengwar.
*/
private static String getEnglishLiteral(char tengwarChar){
if (consonantChars.containsValue(tengwarChar)){
return getKeyByValue(consonantChars, tengwarChar).toString();
} else if (compoundChars.containsValue(tengwarChar)){
return getKeyByValue(compoundChars, tengwarChar);
} else if (alternateChars.containsValue(tengwarChar)) {
return getKeyByValue(alternateChars, tengwarChar).toString();
} else if (tengwarChar == R_ALT){
return "r";
} else if (numberChars.containsValue(tengwarChar)){
return getKeyByValue(numberChars, tengwarChar).toString();
} else if (punctuationChars.containsValue(tengwarChar)){
return getKeyByValue(punctuationChars, tengwarChar).toString();
}
return null;
}
/**
* Returns the key for a specified value in a 1 to 1 map.
* @param map The 1 to 1 map to use.
* @param value Value to return the key of.
* @param <T> Key type of the map.
* @param <E> Value type of the map.
* @return Key associated with value.
*/
private static <T, E> T getKeyByValue(Map<T, E> map, E value) {
for (Map.Entry<T, E> entry : map.entrySet()) {
if (Objects.equals(value, entry.getValue())) {
return entry.getKey();
}
}
return null;
}
/** /**
* Translate an english string to tengwar. * Translate an english string to tengwar.
* @param englishString english string. * @param englishString english string.
@ -380,19 +449,14 @@ public class Translator {
public static String translateToTengwar(String englishString){ public static String translateToTengwar(String englishString){
StringBuilder result = new StringBuilder(englishString.length()); StringBuilder result = new StringBuilder(englishString.length());
String input = englishString.toLowerCase().trim(); String input = englishString.toLowerCase().trim();
for (int i = 0; i < input.length(); i++){ for (int i = 0; i < input.length(); i++){
//Attempt to get previous, current, and next char. //Attempt to get previous, current, and next char.
char currentChar = input.charAt(i); char currentChar = input.charAt(i);
char previousChar = 0;
char nextChar = 0; char nextChar = 0;
try{
previousChar = input.charAt(i-1);
} catch (IndexOutOfBoundsException e){
}
try{ try{
nextChar = input.charAt(i+1); nextChar = input.charAt(i+1);
} catch (IndexOutOfBoundsException e){ } catch (IndexOutOfBoundsException e){
//Do nothing, since this may happen.
} }
//Test if the current char is a vowel. //Test if the current char is a vowel.
if (isVowel(currentChar)){ if (isVowel(currentChar)){
@ -429,6 +493,7 @@ public class Translator {
} }
result.append(tengwarCharToBeAdded); result.append(tengwarCharToBeAdded);
result.append(getAppropriateVowel(tengwarCharToBeAdded, currentChar)); result.append(getAppropriateVowel(tengwarCharToBeAdded, currentChar));
//Bar gets added after the vowel.
if (needsBar) if (needsBar)
result.append(bars.get(barSizes.get(tengwarCharToBeAdded))); result.append(bars.get(barSizes.get(tengwarCharToBeAdded)));
i++; i++;
@ -483,4 +548,61 @@ public class Translator {
} }
return result.toString(); return result.toString();
} }
/**
* Translates a tengwar string to english.
* @param tengwarString tengwar string.
* @return english string.
*/
public static String translateToEnglish(String tengwarString){
StringBuilder result = new StringBuilder(tengwarString.length()+tengwarString.length()/2);
for (int i = 0; i < tengwarString.length(); i++){
char currentChar = tengwarString.charAt(i);
char nextChar = 0;
char secondNextChar = 0;
try{
nextChar = tengwarString.charAt(i+1);
} catch (IndexOutOfBoundsException e){
//Do nothing, this is fine.
}
try{
secondNextChar = tengwarString.charAt(i+2);
} catch (IndexOutOfBoundsException e){
//Do nothing, this is fine.
}
String currentLiteral = getEnglishLiteral(currentChar);
System.out.println("At: "+i+" Literal: "+currentLiteral);
//Check if the current character is a literal translation.
if (currentLiteral != null){
//Check if the next character is a vowel that should be placed before a character.
if (isVowelTengwar(nextChar) && !isSilentE(nextChar)){
result.append(getEnglishVowel(nextChar));
result.append(currentLiteral);
i++;
//Check for a double-bar, and then add whatever the current char is.
if (bars.contains(secondNextChar)){
result.append(currentLiteral);
i++;
}
} else if (bars.contains(nextChar)){
result.append(currentLiteral);
i++;
} else {
//Just append the current literal, no skipping.
result.append(currentLiteral);
}
} else {
//Current character is not a literal translation, so it is an E_UNDER, or carrier.
if (carriers.contains(currentChar)){
//If carrier, append the following vowel.
result.append(getEnglishVowel(nextChar));
i++;
} else if (isSilentE(currentChar)) {
result.append('e');
}
}
}
return result.toString();
}
} }