summaryrefslogtreecommitdiff
path: root/src/main/java/sevenUnitsGUI/TabbedView.java
diff options
context:
space:
mode:
authorAdrien Hopkins <adrien.p.hopkins@gmail.com>2025-02-23 20:38:54 -0500
committerAdrien Hopkins <adrien.p.hopkins@gmail.com>2025-02-23 20:38:54 -0500
commit9f85e0c201f64b5de646c4d66323424bcb3a279d (patch)
tree92609c64a7c96fcdd0f20b63bca9c6effe8dd97d /src/main/java/sevenUnitsGUI/TabbedView.java
parenta9485b187844cad900bc43c0651406c51a7295c1 (diff)
parent9c358d708ba4988648d7b19ccb842f076ec4c354 (diff)
Merge branch 'i18n' into develop
This merge adds the internationalization features, the final required feature for 7Units version 1.0.0.
Diffstat (limited to 'src/main/java/sevenUnitsGUI/TabbedView.java')
-rw-r--r--src/main/java/sevenUnitsGUI/TabbedView.java168
1 files changed, 126 insertions, 42 deletions
diff --git a/src/main/java/sevenUnitsGUI/TabbedView.java b/src/main/java/sevenUnitsGUI/TabbedView.java
index 6542541..9850aac 100644
--- a/src/main/java/sevenUnitsGUI/TabbedView.java
+++ b/src/main/java/sevenUnitsGUI/TabbedView.java
@@ -24,13 +24,16 @@ import java.awt.event.ItemEvent;
import java.awt.event.KeyEvent;
import java.util.AbstractSet;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
+import java.util.function.Consumer;
import java.util.function.Function;
import javax.swing.BorderFactory;
@@ -195,10 +198,14 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
/** The text box for prefix data in the prefix viewer */
private final JTextArea prefixTextBox;
- // SETTINGS STUFF
+ // INFO & SETTINGS STUFF
+ final JTextArea infoTextArea;
+ private final JComboBox<String> localeSelector;
private StandardRoundingType roundingType;
private int precision;
+ private final Map<String, Consumer<String>> localizedTextSetters;
+
/**
* Creates the view and makes it visible to the user
*
@@ -218,16 +225,20 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
// initialize important components
this.presenter = new Presenter(this);
- this.frame = new JFrame("7Units " + ProgramInfo.VERSION);
+ this.frame = new JFrame("7Units (Unlocalized)");
this.frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// master components (those that contain everything else within them)
this.masterPane = new JTabbedPane();
this.frame.add(this.masterPane);
+ this.localizedTextSetters = new HashMap<>();
+
// ============ UNIT CONVERSION TAB ============
final JPanel convertUnitPanel = new JPanel();
this.masterPane.addTab("Convert Units", convertUnitPanel);
+ this.localizedTextSetters.put("tv.convert_units.title",
+ txt -> this.masterPane.setTitleAt(0, txt));
this.masterPane.setMnemonicAt(0, KeyEvent.VK_U);
convertUnitPanel.setLayout(new BorderLayout());
@@ -263,7 +274,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
outputPanel.setLayout(new BorderLayout());
outputPanel.setBorder(new EmptyBorder(3, 6, 6, 6));
- final JLabel valuePrompt = new JLabel("Value to convert: ");
+ final JLabel valuePrompt = new JLabel();
+ this.localizedTextSetters.put("tv.convert_units.value_prompt",
+ valuePrompt::setText);
outputPanel.add(valuePrompt, BorderLayout.LINE_START);
this.valueInput = new JTextField();
@@ -271,6 +284,8 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
// conversion button
this.convertUnitButton = new JButton("Convert");
+ this.localizedTextSetters.put("tv.convert_units.convert_btn",
+ this.convertUnitButton::setText);
outputPanel.add(this.convertUnitButton, BorderLayout.LINE_END);
this.convertUnitButton
.addActionListener(e -> this.presenter.convertUnits());
@@ -286,20 +301,26 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
final JPanel convertExpressionPanel = new JPanel();
this.masterPane.addTab("Convert Unit Expressions",
convertExpressionPanel);
+ this.localizedTextSetters.put("tv.convert_expressions.title",
+ txt -> this.masterPane.setTitleAt(1, txt));
this.masterPane.setMnemonicAt(1, KeyEvent.VK_E);
convertExpressionPanel.setLayout(new GridLayout(4, 1));
// from and to expressions
this.fromEntry = new JTextField();
convertExpressionPanel.add(this.fromEntry);
- this.fromEntry.setBorder(BorderFactory.createTitledBorder("From"));
+ this.localizedTextSetters.put("tv.convert_expressions.from",
+ txt -> this.fromEntry.setBorder(BorderFactory.createTitledBorder(txt)));
this.toEntry = new JTextField();
convertExpressionPanel.add(this.toEntry);
- this.toEntry.setBorder(BorderFactory.createTitledBorder("To"));
+ this.localizedTextSetters.put("tv.convert_expressions.to",
+ txt -> this.toEntry.setBorder(BorderFactory.createTitledBorder(txt)));
// button to convert
- this.convertExpressionButton = new JButton("Convert");
+ this.convertExpressionButton = new JButton();
+ this.localizedTextSetters.put("tv.convert_expressions.convert_btn",
+ this.convertExpressionButton::setText);
convertExpressionPanel.add(this.convertExpressionButton);
this.convertExpressionButton
@@ -309,13 +330,15 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
// output of conversion
this.expressionOutput = new JTextArea(2, 32);
convertExpressionPanel.add(this.expressionOutput);
- this.expressionOutput
- .setBorder(BorderFactory.createTitledBorder("Output"));
+ this.localizedTextSetters.put("tv.convert_expressions.output",
+ txt -> this.expressionOutput.setBorder(BorderFactory.createTitledBorder(txt)));
this.expressionOutput.setEditable(false);
// =========== UNIT VIEWER ===========
final JPanel unitLookupPanel = new JPanel();
this.masterPane.addTab("Unit Viewer", unitLookupPanel);
+ this.localizedTextSetters.put("tv.unit_viewer.title",
+ txt -> this.masterPane.setTitleAt(2, txt));
this.masterPane.setMnemonicAt(2, KeyEvent.VK_V);
unitLookupPanel.setLayout(new GridLayout());
@@ -333,6 +356,8 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
// ============ PREFIX VIEWER =============
final JPanel prefixLookupPanel = new JPanel();
this.masterPane.addTab("Prefix Viewer", prefixLookupPanel);
+ this.localizedTextSetters.put("tv.prefix_viewer.title",
+ txt -> this.masterPane.setTitleAt(3, txt));
this.masterPane.setMnemonicAt(3, KeyEvent.VK_P);
prefixLookupPanel.setLayout(new GridLayout(1, 2));
@@ -353,19 +378,20 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
this.masterPane.addTab("\uD83D\uDEC8", // info (i) character
new JScrollPane(infoPanel));
- final JTextArea infoTextArea = new JTextArea();
- infoTextArea.setEditable(false);
- infoTextArea.setOpaque(false);
- infoPanel.add(infoTextArea);
- infoTextArea.setText(this.presenter.getAboutText());
+ this.infoTextArea = new JTextArea();
+ this.infoTextArea.setEditable(false);
+ this.infoTextArea.setOpaque(false);
+ infoPanel.add(this.infoTextArea);
// ============ SETTINGS PANEL ============
+ this.localeSelector = new JComboBox<>();
this.masterPane.addTab("\u2699",
new JScrollPane(this.createSettingsPanel()));
this.masterPane.setMnemonicAt(5, KeyEvent.VK_S);
// ============ FINALIZE CREATION OF VIEW ============
this.presenter.postViewInitialize();
+ this.updateText();
this.frame.pack();
this.frame.setVisible(true);
}
@@ -386,7 +412,8 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
{
final JPanel roundingPanel = new JPanel();
settingsPanel.add(roundingPanel);
- roundingPanel.setBorder(new TitledBorder("Rounding Settings"));
+ this.localizedTextSetters.put("tv.settings.rounding.title",
+ txt -> roundingPanel.setBorder(new TitledBorder(txt)));
roundingPanel.setLayout(new GridBagLayout());
// rounding rule selection
@@ -396,13 +423,17 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
"Presenter loaded non-standard rounding rule"));
this.precision = this.getPresenterPrecision().orElse(6);
- final JLabel roundingRuleLabel = new JLabel("Rounding Rule:");
+ final JLabel roundingRuleLabel = new JLabel();
+ this.localizedTextSetters.put("tv.settings.rounding.rule",
+ roundingRuleLabel::setText);
roundingPanel.add(roundingRuleLabel, new GridBagBuilder(0, 0)
.setAnchor(GridBagConstraints.LINE_START).build());
// sigDigSlider needs to be first so that the rounding-type buttons can
// show and hide it
- final JLabel sliderLabel = new JLabel("Precision:");
+ final JLabel sliderLabel = new JLabel();
+ this.localizedTextSetters.put("tv.settings.rounding.precision",
+ sliderLabel::setText);
sliderLabel.setVisible(
this.roundingType != StandardRoundingType.UNCERTAINTY);
roundingPanel.add(sliderLabel, new GridBagBuilder(0, 4)
@@ -428,8 +459,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
});
// significant digit rounding
- final JRadioButton fixedPrecision = new JRadioButton(
- "Fixed Precision");
+ final JRadioButton fixedPrecision = new JRadioButton();
+ this.localizedTextSetters.put("tv.settings.rounding.fixed_sigfig",
+ fixedPrecision::setText);
if (this.roundingType == StandardRoundingType.SIGNIFICANT_DIGITS) {
fixedPrecision.setSelected(true);
}
@@ -444,8 +476,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
.setAnchor(GridBagConstraints.LINE_START).build());
// decimal place rounding
- final JRadioButton fixedDecimals = new JRadioButton(
- "Fixed Decimal Places");
+ final JRadioButton fixedDecimals = new JRadioButton();
+ this.localizedTextSetters.put("tv.settings.rounding.fixed_places",
+ fixedDecimals::setText);
if (this.roundingType == StandardRoundingType.DECIMAL_PLACES) {
fixedDecimals.setSelected(true);
}
@@ -460,8 +493,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
.setAnchor(GridBagConstraints.LINE_START).build());
// scientific rounding
- final JRadioButton relativePrecision = new JRadioButton(
- "Uncertainty-Based Rounding");
+ final JRadioButton relativePrecision = new JRadioButton();
+ this.localizedTextSetters.put("tv.settings.rounding.uncertainty",
+ relativePrecision::setText);
if (this.roundingType == StandardRoundingType.UNCERTAINTY) {
relativePrecision.setSelected(true);
}
@@ -480,8 +514,8 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
{
final JPanel prefixRepetitionPanel = new JPanel();
settingsPanel.add(prefixRepetitionPanel);
- prefixRepetitionPanel
- .setBorder(new TitledBorder("Prefix Repetition Settings"));
+ this.localizedTextSetters.put("tv.settings.repetition.title",
+ txt -> prefixRepetitionPanel.setBorder(new TitledBorder(txt)));
prefixRepetitionPanel.setLayout(new GridBagLayout());
final var prefixRule = this.getPresenterPrefixRule()
@@ -491,7 +525,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
// prefix rules
final ButtonGroup prefixRuleButtons = new ButtonGroup();
- final JRadioButton noRepetition = new JRadioButton("No Repetition");
+ final JRadioButton noRepetition = new JRadioButton();
+ this.localizedTextSetters.put("tv.settings.repetition.no",
+ noRepetition::setText);
if (prefixRule == DefaultPrefixRepetitionRule.NO_REPETITION) {
noRepetition.setSelected(true);
}
@@ -504,7 +540,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
prefixRepetitionPanel.add(noRepetition, new GridBagBuilder(0, 0)
.setAnchor(GridBagConstraints.LINE_START).build());
- final JRadioButton noRestriction = new JRadioButton("No Restriction");
+ final JRadioButton noRestriction = new JRadioButton();
+ this.localizedTextSetters.put("tv.settings.repetition.any",
+ noRestriction::setText);
if (prefixRule == DefaultPrefixRepetitionRule.NO_RESTRICTION) {
noRestriction.setSelected(true);
}
@@ -517,8 +555,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
prefixRepetitionPanel.add(noRestriction, new GridBagBuilder(0, 1)
.setAnchor(GridBagConstraints.LINE_START).build());
- final JRadioButton customRepetition = new JRadioButton(
- "Complex Repetition");
+ final JRadioButton customRepetition = new JRadioButton();
+ this.localizedTextSetters.put("tv.settings.repetition.complex",
+ customRepetition::setText);
if (prefixRule == DefaultPrefixRepetitionRule.COMPLEX_REPETITION) {
customRepetition.setSelected(true);
}
@@ -536,7 +575,8 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
{
final JPanel searchingPanel = new JPanel();
settingsPanel.add(searchingPanel);
- searchingPanel.setBorder(new TitledBorder("Search Settings"));
+ this.localizedTextSetters.put("tv.settings.search.title",
+ txt -> searchingPanel.setBorder(new TitledBorder(txt)));
searchingPanel.setLayout(new GridBagLayout());
// searching rules
@@ -544,8 +584,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
final var searchRule = this.presenter.getSearchRule();
- final JRadioButton noPrefixes = new JRadioButton(
- "Never Include Prefixed Units");
+ final JRadioButton noPrefixes = new JRadioButton();
+ this.localizedTextSetters.put("tv.settings.search.no_prefixes",
+ noPrefixes::setText);
noPrefixes.addActionListener(e -> {
this.presenter.setSearchRule(PrefixSearchRule.NO_PREFIXES);
this.presenter.updateView();
@@ -555,8 +596,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
searchingPanel.add(noPrefixes, new GridBagBuilder(0, 0)
.setAnchor(GridBagConstraints.LINE_START).build());
- final JRadioButton commonPrefixes = new JRadioButton(
- "Include Common Prefixes");
+ final JRadioButton commonPrefixes = new JRadioButton();
+ this.localizedTextSetters.put("tv.settings.search.common_prefixes",
+ commonPrefixes::setText);
commonPrefixes.addActionListener(e -> {
this.presenter.setSearchRule(PrefixSearchRule.COMMON_PREFIXES);
this.presenter.updateView();
@@ -566,8 +608,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
searchingPanel.add(commonPrefixes, new GridBagBuilder(0, 1)
.setAnchor(GridBagConstraints.LINE_START).build());
- final JRadioButton alwaysInclude = new JRadioButton(
- "Include All Single Prefixes");
+ final JRadioButton alwaysInclude = new JRadioButton();
+ this.localizedTextSetters.put("tv.settings.search.all_prefixes",
+ alwaysInclude::setText);
alwaysInclude.addActionListener(e -> {
this.presenter
.setSearchRule(this.presenter.getUniversalSearchRule());
@@ -596,30 +639,62 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
settingsPanel.add(miscPanel);
miscPanel.setLayout(new GridBagLayout());
- final JCheckBox oneWay = new JCheckBox("Convert One Way Only");
+ final JCheckBox oneWay = new JCheckBox();
+ this.localizedTextSetters.put("tv.settings.oneway", oneWay::setText);
oneWay.setSelected(this.presenter.oneWayConversionEnabled());
oneWay.addItemListener(e -> {
this.presenter.setOneWayConversionEnabled(
e.getStateChange() == ItemEvent.SELECTED);
this.presenter.saveSettings();
});
- miscPanel.add(oneWay, new GridBagBuilder(0, 0)
+ miscPanel.add(oneWay, new GridBagBuilder(0, 0, 2, 1)
.setAnchor(GridBagConstraints.LINE_START).build());
- final JCheckBox showAllVariations = new JCheckBox(
- "Show Duplicate Units & Prefixes");
+ final JCheckBox showAllVariations = new JCheckBox();
+ this.localizedTextSetters.put("tv.settings.show_duplicate",
+ showAllVariations::setText);
showAllVariations.setSelected(this.presenter.duplicatesShown());
showAllVariations.addItemListener(e -> {
this.presenter
.setShowDuplicates(e.getStateChange() == ItemEvent.SELECTED);
this.presenter.saveSettings();
});
- miscPanel.add(showAllVariations, new GridBagBuilder(0, 1)
+ miscPanel.add(showAllVariations, new GridBagBuilder(0, 1, 2, 1)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JCheckBox useDefaultFiles = new JCheckBox();
+ this.localizedTextSetters.put("tv.settings.use_default_files",
+ useDefaultFiles::setText);
+ useDefaultFiles.setSelected(this.presenter.usingDefaultDatafiles());
+ useDefaultFiles.addItemListener(e -> {
+ this.presenter
+ .setUseDefaultDatafiles(e.getStateChange() == ItemEvent.SELECTED);
+ this.presenter.saveSettings();
+ });
+ miscPanel.add(useDefaultFiles, new GridBagBuilder(0, 2, 2, 1)
.setAnchor(GridBagConstraints.LINE_START).build());
- final JButton unitFileButton = new JButton("Manage Unit Data Files");
+ final JLabel localeLabel = new JLabel();
+ this.localizedTextSetters.put("tv.settings.locale",
+ localeLabel::setText);
+ miscPanel.add(localeLabel, new GridBagBuilder(0, 3, 1, 1)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ this.presenter.getAvailableLocales().stream().sorted()
+ .forEachOrdered(this.localeSelector::addItem);
+ this.localeSelector.setSelectedItem(this.presenter.getUserLocale());
+ this.localeSelector.addItemListener(e -> {
+ this.presenter.setUserLocale((String) e.getItem());
+ this.presenter.saveSettings();
+ });
+ miscPanel.add(localeSelector, new GridBagBuilder(1, 3, 1, 1)
+ .setAnchor(GridBagConstraints.LINE_END).build());
+
+ final JButton unitFileButton = new JButton();
+ this.localizedTextSetters.put("tv.settings.unitfiles.button",
+ unitFileButton::setText);
unitFileButton.setEnabled(false);
- miscPanel.add(unitFileButton, new GridBagBuilder(0, 2)
+ miscPanel.add(unitFileButton, new GridBagBuilder(0, 4, 2, 1)
.setAnchor(GridBagConstraints.LINE_START).build());
}
@@ -827,4 +902,13 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
this.presenter.setNumberDisplayRule(roundingRule);
this.presenter.saveSettings();
}
+
+ @Override
+ public void updateText() {
+ this.frame.setTitle(this.presenter.getLocalizedText("tv.title")
+ .replace("[v]", ProgramInfo.VERSION.toString()));
+ this.infoTextArea.setText(this.presenter.getAboutText());
+ this.localizedTextSetters.forEach((id, action) ->
+ action.accept(this.presenter.getLocalizedText(id)));
+ }
}