Skip to content

Commit

Permalink
Completes user-selected language implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
edimoral committed Mar 10, 2024
1 parent 2b82846 commit b3c5f7b
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 27 deletions.
22 changes: 11 additions & 11 deletions src/main/java/jpass/ui/EntryDetailsTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ public class EntryDetailsTable extends JTable {
private static final DateTimeFormatter FORMATTER
= DateUtils.createFormatter(Configuration.getInstance().get("date.format", "yyyy-MM-dd"));

private enum DetailType {
TITLE(getLocalizedMessages().getString(VIEW_WINDOW_TITLE), Entry::getTitle),
URL(getLocalizedMessages().getString(VIEW_WINDOW_URL), Entry::getUrl),
USER(getLocalizedMessages().getString(VIEW_WINDOW_USER), Entry::getUser),
MODIFIED(getLocalizedMessages().getString(VIEW_WINDOW_MODIFIED), entry -> DateUtils.formatIsoDateTime(entry.getLastModification(), FORMATTER)),
CREATED(getLocalizedMessages().getString(VIEW_WINDOW_CREATED), entry -> DateUtils.formatIsoDateTime(entry.getCreationDate(), FORMATTER));
public enum DetailType {
TITLE(VIEW_WINDOW_TITLE, Entry::getTitle),
URL(VIEW_WINDOW_URL, Entry::getUrl),
USER(VIEW_WINDOW_USER, Entry::getUser),
MODIFIED(VIEW_WINDOW_MODIFIED, entry -> DateUtils.formatIsoDateTime(entry.getLastModification(), FORMATTER)),
CREATED(VIEW_WINDOW_CREATED, entry -> DateUtils.formatIsoDateTime(entry.getCreationDate(), FORMATTER));

private final String description;
private final Function<Entry, String> valueMapper;
Expand Down Expand Up @@ -111,7 +111,7 @@ public EntryDetailsTable() {
}

tableModel = new DefaultTableModel();
detailsToDisplay.forEach(detail -> tableModel.addColumn(detail.getDescription()));
detailsToDisplay.forEach(detail -> tableModel.addColumn(getLocalizedMessages().getString(detail.getDescription())));
setModel(tableModel);
getTableHeader().setReorderingAllowed(false);
addMouseListener(new TableListener());
Expand All @@ -135,6 +135,10 @@ public Component prepareRenderer(TableCellRenderer renderer, int row, int column
return component;
}

public List<DetailType> getDetailsToDisplay() {
return detailsToDisplay;
}

public void clear() {
tableModel.setRowCount(0);
}
Expand All @@ -144,8 +148,4 @@ public void addRow(Entry entry) {
.map(detail -> detail.getValue(entry))
.toArray(Object[]::new));
}

public int rowCount() {
return tableModel.getRowCount();
}
}
136 changes: 121 additions & 15 deletions src/main/java/jpass/ui/JPassFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import jpass.xml.bind.Entry;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
Expand All @@ -46,12 +47,14 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JTable;
Expand All @@ -63,6 +66,7 @@
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.table.TableColumn;

import static jpass.ui.MessageDialog.NO_OPTION;
import static jpass.ui.MessageDialog.YES_NO_CANCEL_OPTION;
Expand All @@ -80,6 +84,8 @@
import static jpass.util.Constants.LANGUAGE_ES_MX;
import static jpass.util.Constants.LANGUAGE_HU_HU;
import static jpass.util.Constants.LANGUAGE_IT_IT;
import static jpass.util.Constants.LANGUAGE_LANGUAGE_SETTING;
import static jpass.util.Constants.PANEL_FIND;
import static jpass.util.Constants.PANEL_SAVE_MODIFIED_QUESTION_MESSAGE;
import static jpass.util.Constants.SETTINGS_MENU;
import static jpass.util.Constants.SETTINGS_MENU_LANGUAGE;
Expand Down Expand Up @@ -117,9 +123,10 @@ public final class JPassFrame extends JFrame {
private final EntryDetailsTable entryDetailsTable;
private final DataModel model = DataModel.getInstance();
private final StatusPanel statusPanel;
private static String currentLanguage;
private volatile boolean processing = false;

private JPassFrame(String fileName, Locale locale) {
private JPassFrame(String fileName) {
try {
setIconImages(Stream.of(16, 20, 32, 40, 64, 80, 128, 160)
.map(size -> getIcon("jpass", size, size).getImage())
Expand All @@ -129,8 +136,8 @@ private JPassFrame(String fileName, Locale locale) {
}

setSupportedLanguages();
setLocalizedMessages(locale);
UIManager.put("FileChooser.cancelButtonText", localizedMessages.getString(BUTTON_MESSAGE_CANCEL));
setLocalizedMessages(Locale.forLanguageTag(getCurrentLanguage()));
UIManager.put(FILE_CHOOSER_CANCEL_BUTTON_TEXT, localizedMessages.getString(BUTTON_MESSAGE_CANCEL));

this.toolBar = new JToolBar();
this.toolBar.setFloatable(false);
Expand Down Expand Up @@ -207,8 +214,11 @@ private JPassFrame(String fileName, Locale locale) {

SUPPORTED_LANGUAGES.forEach((key, value) -> {
JMenuItem language = new JMenuItem(localizedMessages.getString(key));
if (Objects.equals(getCurrentLanguage(), value)) {
language.setIcon(getIcon("check_mark"));
}
language.setActionCommand(key);
language.addActionListener(e -> refreshComponentsWithLanguage(e.getActionCommand()));
language.addActionListener(e -> refreshComponentsWithLanguageSelected(e.getActionCommand()));
languageMenu.add(language);
});
settingsMenu.add(languageMenu);
Expand Down Expand Up @@ -247,7 +257,7 @@ private JPassFrame(String fileName, Locale locale) {

setJMenuBar(this.jpassMenuBar);
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
setSize(450, 400);
setSize(490, 400);
setMinimumSize(new Dimension(420, 200));
addWindowListener(new CloseListener());
setLocationRelativeTo(null);
Expand All @@ -264,8 +274,13 @@ public static JPassFrame getInstance() {

public static synchronized JPassFrame getInstance(String fileName) {
if (instance == null) {
String languageTag = Configuration.getInstance().get("language.languageSetting", "en-US");
instance = new JPassFrame(fileName, Locale.forLanguageTag(languageTag));
String languageTag = Configuration.getInstance().get(LANGUAGE_LANGUAGE_SETTING, null);
if (null == languageTag) {
languageTag = "en-US"; //Defaulting to en-US
Configuration.getInstance().set(LANGUAGE_LANGUAGE_SETTING, languageTag);
}
setCurrentLanguage(languageTag);
instance = new JPassFrame(fileName);
}
return instance;
}
Expand Down Expand Up @@ -345,9 +360,18 @@ public void refreshAll() {
refreshEntryTitleList(null);
}

private void refreshComponentsWithLanguage(String actionCommand) {
Locale locale = Locale.forLanguageTag(getSupportedLanguages().get(actionCommand));
setLocalizedMessages(locale);
/**
* Refresh UI components with new translated strings from language selected
*
* @param actionCommand key to differentiate a component
*/
private void refreshComponentsWithLanguageSelected(String actionCommand) {
String newLanguage = getSupportedLanguages().get(actionCommand);
if (Objects.equals(getCurrentLanguage(), newLanguage)) {
return;
}
setCurrentLanguage(newLanguage);
setLocalizedMessages(Locale.forLanguageTag(newLanguage));

UIManager.put(FILE_CHOOSER_CANCEL_BUTTON_TEXT, localizedMessages.getString(BUTTON_MESSAGE_CANCEL));

Expand All @@ -362,19 +386,36 @@ private void refreshComponentsWithLanguage(String actionCommand) {
updateMenuComponents(toolsMenu);
updateMenuComponents(settingsMenu);
updateMenuComponents(helpMenu);
//updateMenuComponents(toolBar);
updateToolbarComponents(toolBar);

refreshEntryTitleList(null);
updateJPopupMenu(popup);
getSearchPanel().setLabelText(String.format("%s: ", getLocalizedMessages().getString(PANEL_FIND)));

updateTable();

Configuration.getInstance().set(LANGUAGE_LANGUAGE_SETTING, newLanguage);
MessageDialog.showInformationMessage(this, "Language has been changed");
}

/**
* Updates JMenu components and its children with new translated strings
*
* @param menu to update
*/
private void updateMenuComponents(JMenu menu) {
for (int i = 0; i < menu.getItemCount(); i++) {
JMenuItem item = menu.getItem(i);
if (null != item) {
if (null != item.getActionCommand()) {
item.setText(localizedMessages.getString(item.getActionCommand()));
String actionCommand = item.getActionCommand();
if (null != actionCommand) {
item.setText(localizedMessages.getString(actionCommand));

if (getSupportedLanguages().containsKey(actionCommand)) {
item.setIcon(null);
if (Objects.equals(getSupportedLanguages().get(actionCommand), getCurrentLanguage())) {
item.setIcon(getIcon("check_mark"));
}
}
}

if (item instanceof JMenu) {
Expand All @@ -384,6 +425,44 @@ private void updateMenuComponents(JMenu menu) {
}
}

/**
* Updates JPopupMenu components with new translated strings
* @param jPopupMenu
*/
private void updateJPopupMenu(JPopupMenu jPopupMenu) {
for (Component comp : jPopupMenu.getComponents()) {
if (comp instanceof JMenuItem) {
JMenuItem item = (JMenuItem) comp;
item.setText(localizedMessages.getString(item.getActionCommand()));
}
}
}

/**
* Updates JToolBar components with new translated strings
* @param toolBar
*/
private void updateToolbarComponents(JToolBar toolBar) {
for (Component comp : toolBar.getComponents()) {
if (comp instanceof JButton) {
JButton jButton = (JButton) comp;
jButton.setToolTipText(localizedMessages.getString(jButton.getActionCommand()));
}
}
}

/**
* Updates main JTable columns headers with new translated strings
*/
private void updateTable() {
for (int i = 0; i < getEntryTitleTable().getColumnModel().getColumnCount(); i++) {
TableColumn column = getEntryTitleTable().getColumnModel().getColumn(i);
column.setHeaderValue(getLocalizedMessages().getString(entryDetailsTable.getDetailsToDisplay().get(i).getDescription()));
}
getEntryTitleTable().getTableHeader().repaint();
refreshEntryTitleList(null);
}

/**
* Exits the application.
*/
Expand Down Expand Up @@ -434,6 +513,15 @@ public static void setLocalizedMessages(Locale locale) {
JPassFrame.localizedMessages = ResourceBundle.getBundle("resources.languages.languages", locale);
}

/**
* Sets the current language for the program
*
* @param newLanguage
*/
private static void setCurrentLanguage(String newLanguage) {
currentLanguage = newLanguage;
}

/**
* Gets the processing state of this frame.
*
Expand All @@ -444,7 +532,7 @@ public boolean isProcessing() {
}

/**
* Get search panel.
* Gets search panel.
*
* @return the search panel
*/
Expand All @@ -461,13 +549,31 @@ public static ResourceBundle getLocalizedMessages() {
return localizedMessages;
}

/**
* Gets current language selected
*
* @return currentLanguage
*/
private static String getCurrentLanguage() {
return currentLanguage;
}

/**
* Set supported languages currently
*
*/
private static void setSupportedLanguages() {
SUPPORTED_LANGUAGES.put(LANGUAGE_EN_US, "en-US");
SUPPORTED_LANGUAGES.put(LANGUAGE_ES_MX, "es-MX");
SUPPORTED_LANGUAGES.put(LANGUAGE_HU_HU, "hu-HU");
SUPPORTED_LANGUAGES.put(LANGUAGE_IT_IT, "it-IT");
}

/**
* Gets supported languages
*
* @return Map of supported languages
*/
private static Map<String, String> getSupportedLanguages() {
return SUPPORTED_LANGUAGES;
}
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/jpass/ui/SearchPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ public void actionPerformed(ActionEvent e) {
}
}

/**
* Sets text for label
* @param text of the label
*/
public void setLabelText(String text) {
this.label.setText(text);
}

/**
* Get search criteria.
*
Expand Down
19 changes: 18 additions & 1 deletion src/main/java/jpass/util/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand All @@ -44,7 +47,7 @@ public final class Configuration {

private static final Logger LOG = Logger.getLogger(Configuration.class.getName());
private static Configuration instance;
private Properties properties = new Properties();
private final Properties properties = new Properties();

private Configuration() {
try {
Expand Down Expand Up @@ -98,6 +101,20 @@ public String get(String key, String defaultValue) {
return properties.getProperty(key, defaultValue);
}

public void set(String key, String value) {
properties.setProperty(key, value);
saveProperties();
}

private void saveProperties() {
File filePath = new File(getConfigurationFolderPath(), "jpass.properties");
try (OutputStream os = Files.newOutputStream(filePath.toPath())) {
properties.store(os, "Configuration properties");
} catch (IOException e) {
LOG.log(Level.WARNING, "Could not save configuration to file.", e);
}
}

public String[] getArray(String key, String[] defaultValue) {
String prop = properties.getProperty(key);
if (prop != null) {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/jpass/util/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ private Constants() {
public static final String PANEL_SAVE_MODIFIED_QUESTION_MESSAGE = "panel.saveModifiedQuestionMessage";
public static final String PANEL_UNENCRYPTED_DATA_WARNING_MESSAGE = "panel.unencryptedDataWarningMessage";

public static final String LANGUAGE_LANGUAGE_SETTING = "language.languageSetting";
public static final String LANGUAGE_EN_US = "language.en.us";
public static final String LANGUAGE_ES_MX = "language.es.mx";
public static final String LANGUAGE_HU_HU = "language.hu.hu";
Expand Down

0 comments on commit b3c5f7b

Please sign in to comment.