Development #2

Merged
andrewlalis merged 3 commits from development into master 2017-05-04 06:13:38 +00:00
4 changed files with 209 additions and 111 deletions

View File

@ -15,6 +15,8 @@ Since Tengwar is inherently a phonetic script, converting english to Tengwar wou
![Tengwar](https://puu.sh/vtyfi/598ad704e1.png "Tengwar Characters")
To translate from Tengwar back to English is much simpler, but because Tengwar characters do use capitalization, the resulting string of text will be in only lower-case letters.
### To-Do List
* Implement s-curls.

View File

@ -4,10 +4,8 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
/**
* @author Andrew Lalis
@ -15,8 +13,8 @@ import java.io.IOException;
*/
public class Main {
public static final String TITLE = "Tengwar Typewriter";
public static final String ICON_PATH = "resources/icon.png";
private static final String TITLE = "Tengwar Typewriter";
private static final String ICON_PATH = "resources/icon.png";
public static void main(String[] args){
JFrame f = new JFrame(TITLE);
@ -31,31 +29,16 @@ public class Main {
JMenu fileMenu = new JMenu("File");
//Save Item.
JMenuItem saveItem = new JMenuItem("Save");
saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
saveItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
window.onSaveClicked();
}
});
saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
saveItem.addActionListener(e -> window.onSaveClicked());
fileMenu.add(saveItem);
//Import Item.
JMenuItem importItem = new JMenuItem("Import");
importItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
window.onImportClicked();
}
});
importItem.addActionListener(e -> window.onImportClicked());
fileMenu.add(importItem);
//Exit Item.
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
f.dispose();
}
});
exitItem.addActionListener(e -> f.dispose());
fileMenu.add(exitItem);
menuBar.add(fileMenu);
//Edit menu.
@ -63,49 +46,29 @@ public class Main {
//Live checkbox
JCheckBoxMenuItem liveCheckBox = new JCheckBoxMenuItem("Live");
liveCheckBox.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, ActionEvent.CTRL_MASK));
liveCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
window.onLiveToggled(e);
}
});
liveCheckBox.addActionListener(e -> window.onLiveToggled(e));
editMenu.add(liveCheckBox);
menuBar.add(editMenu);
//About Menu.
JMenu aboutMenu = new JMenu("About");
//Tengwar Item.
JMenuItem tengwarItem = new JMenuItem("Tengwar");
tengwarItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
window.onTengwarAboutClicked();
}
});
tengwarItem.addActionListener(e -> window.onTengwarAboutClicked());
aboutMenu.add(tengwarItem);
//English Mode.
JMenuItem englishModeItem = new JMenuItem("English Mode");
englishModeItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
window.onEnglishModeAboutClicked();
}
});
englishModeItem.addActionListener(e -> window.onEnglishModeAboutClicked());
aboutMenu.add(englishModeItem);
//About the author.
JMenuItem aboutMeItem = new JMenuItem("About the Author");
aboutMeItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
window.onAboutMeClicked();
}
});
aboutMeItem.addActionListener(e -> window.onAboutMeClicked());
aboutMenu.add(aboutMeItem);
menuBar.add(aboutMenu);
f.setJMenuBar(menuBar);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {

View File

@ -11,13 +11,13 @@ import java.awt.event.*;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.List;
import java.util.ArrayList;
public class Window {
public static final List<String> OPEN_FILE_EXTENSIONS = new ArrayList<>();
//List of files that can be imported.
private static final List<String> OPEN_FILE_EXTENSIONS = new ArrayList<>();
static {
OPEN_FILE_EXTENSIONS.add("txt");
@ -39,40 +39,28 @@ public class Window {
private boolean isLive = false;
public Window() {
Window() {
//Load the font into the system.
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Font tengwar_annatar = null;
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) {
e.printStackTrace();
System.err.println("Font format exception!");
} catch (IOException e) {
e.printStackTrace();
System.err.println("IOException!");
}
ge.registerFont(tengwar_annatar);
//Explicit translation from english to tengwar.
toTengwarButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tengwarTextArea.setText(Translator.translateToTengwar(inputTextArea.getText()));
}
});
toTengwarButton.addActionListener(e -> tengwarTextArea.setText(Translator.translateToTengwar(inputTextArea.getText())));
//Clear both text areas.
clearButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
clearButton.addActionListener(e -> {
tengwarTextArea.setText(null);
inputTextArea.setText(null);
}
});
//Translate tengwar to english.
toEnglishButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
}
});
toEnglishButton.addActionListener(e -> inputTextArea.setText(Translator.translateToEnglish(tengwarTextArea.getText())));
}
private void createUIComponents() {
@ -95,26 +83,53 @@ public class Window {
}
});
this.tengwarTextArea = new JTextArea();
tengwarTextArea.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
onTengwarTextChanged();
}
@Override
public void removeUpdate(DocumentEvent e) {
onTengwarTextChanged();
}
@Override
public void changedUpdate(DocumentEvent e) {
onTengwarTextChanged();
}
});
this.toTengwarButton = new JButton();
this.toEnglishButton = new JButton();
this.clearButton = new JButton();
this.inputTextArea.requestFocus();
}
public JPanel getMainPanel(){
JPanel getMainPanel(){
return this.mainPanel;
}
/**
* If the english text is changed, and live is selected, then update the tengwar text.
*/
private void onEnglishTextChanged(){
if (isLive)
if (isLive && inputTextArea.hasFocus())
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.
* @param e event generated by the check box.
*/
public void onLiveToggled(ActionEvent e){
void onLiveToggled(ActionEvent e){
if (((JCheckBoxMenuItem) e.getSource()).getState()){
//Deactivate buttons, set live to true.
toTengwarButton.setEnabled(false);
@ -131,7 +146,7 @@ public class Window {
/**
* What to do if the user clicks the 'import' button.
*/
public void onImportClicked(){
void onImportClicked(){
JFileChooser fileChooser = new JFileChooser(System.getProperty("user.documents"));
fileChooser.setFileFilter(new FileFilter() {
@Override
@ -139,10 +154,7 @@ public class Window {
if (f.isDirectory())
return true;
String extension = Utils.getExtension(f);
if (extension != null)
return OPEN_FILE_EXTENSIONS.contains(extension.toLowerCase());
else
return false;
return extension != null && OPEN_FILE_EXTENSIONS.contains(extension.toLowerCase());
}
@Override
@ -171,7 +183,7 @@ public class Window {
/**
* What to do when the user wants to save their document.
*/
public void onSaveClicked(){
void onSaveClicked(){
JFileChooser fileChooser = new JFileChooser(System.getProperty("user.documents"));
int result = fileChooser.showSaveDialog(this.mainPanel);
if (result == JFileChooser.APPROVE_OPTION){
@ -186,7 +198,7 @@ public class Window {
/**
* Attempt to open the pdf in the browser.
*/
public void onEnglishModeAboutClicked(){
void onEnglishModeAboutClicked(){
if (Desktop.isDesktopSupported()){
try{
Desktop.getDesktop().browse(new URI("https://github.com/andrewlalis/TengwarTranslator/blob/master/src/resources/EnglishOneToOneTengwarV2-1.pdf"));
@ -199,7 +211,7 @@ public class Window {
/**
* Attempt to open Tengwar wikipedia page.
*/
public void onTengwarAboutClicked(){
void onTengwarAboutClicked(){
if (Desktop.isDesktopSupported()){
try{
Desktop.getDesktop().browse(new URI("https://en.wikipedia.org/wiki/Tengwar"));
@ -212,7 +224,7 @@ public class Window {
/**
* Attempt to open my github page.
*/
public void onAboutMeClicked(){
void onAboutMeClicked(){
if (Desktop.isDesktopSupported()){
try{
Desktop.getDesktop().browse(new URI("https://github.com/andrewlalis"));

View File

@ -1,28 +1,12 @@
package net.agspace.translate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* Created by Andrew's Computer on 23-Apr-17.
*/
public class Translator {
private enum CHAR_TYPE {
CONSONANT,
COMPOUND,
ALTERNATE,
VOWEL,
NUMBER,
CARRIER,
PUNCTUATION,
BAR,
S_CURL,
UNKNOWN,
}
//Consonant variables.
private static final char B = 'w';
private static final char C = 'c';
@ -184,7 +168,6 @@ public class Translator {
alternateChars.put('s', S_ALT);
alternateChars.put('z', Z_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);
}
@ -372,6 +355,92 @@ public class Translator {
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.
* @param englishString english string.
@ -380,19 +449,14 @@ public class Translator {
public static String translateToTengwar(String englishString){
StringBuilder result = new StringBuilder(englishString.length());
String input = englishString.toLowerCase().trim();
for (int i = 0; i < input.length(); i++){
//Attempt to get previous, current, and next char.
char currentChar = input.charAt(i);
char previousChar = 0;
char nextChar = 0;
try{
previousChar = input.charAt(i-1);
} catch (IndexOutOfBoundsException e){
}
try{
nextChar = input.charAt(i+1);
} catch (IndexOutOfBoundsException e){
//Do nothing, since this may happen.
}
//Test if the current char is a vowel.
if (isVowel(currentChar)){
@ -429,6 +493,7 @@ public class Translator {
}
result.append(tengwarCharToBeAdded);
result.append(getAppropriateVowel(tengwarCharToBeAdded, currentChar));
//Bar gets added after the vowel.
if (needsBar)
result.append(bars.get(barSizes.get(tengwarCharToBeAdded)));
i++;
@ -483,4 +548,60 @@ public class Translator {
}
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);
//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();
}
}