summaryrefslogtreecommitdiff
path: root/src/org/unitConverter/converterGUI/UnitConverterGUI.java
diff options
context:
space:
mode:
authorAdrien Hopkins <ahopk127@my.yorku.ca>2021-03-13 16:21:49 -0500
committerAdrien Hopkins <ahopk127@my.yorku.ca>2021-03-13 16:21:49 -0500
commitfe4135a68cfed92ef336eec663e9c42c2c97dcbc (patch)
tree2fcf583265be3c575086f3ce3183a3268c997538 /src/org/unitConverter/converterGUI/UnitConverterGUI.java
parent761ba0b6627df8bc9f6ab41c94f349c84d378609 (diff)
parent184b7cc697ffc2dcbd49cfb3d0fd7b14bdac8803 (diff)
Merge branch 'feature-settings-tab' into develop
Diffstat (limited to 'src/org/unitConverter/converterGUI/UnitConverterGUI.java')
-rw-r--r--src/org/unitConverter/converterGUI/UnitConverterGUI.java1062
1 files changed, 813 insertions, 249 deletions
diff --git a/src/org/unitConverter/converterGUI/UnitConverterGUI.java b/src/org/unitConverter/converterGUI/UnitConverterGUI.java
index 0230728..6ddc4a0 100644
--- a/src/org/unitConverter/converterGUI/UnitConverterGUI.java
+++ b/src/org/unitConverter/converterGUI/UnitConverterGUI.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2018 Adrien Hopkins
+ * Copyright (C) 2018-2021 Adrien Hopkins
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,41 +17,63 @@
package org.unitConverter.converterGUI;
import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
-import java.io.File;
+import java.io.BufferedWriter;
+import java.io.IOException;
import java.math.BigDecimal;
import java.math.MathContext;
+import java.math.RoundingMode;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
+import java.util.NoSuchElementException;
import java.util.Set;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
import javax.swing.JButton;
+import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;
+import javax.swing.border.TitledBorder;
+import org.unitConverter.math.ConditionalExistenceCollections;
import org.unitConverter.math.ObjectProduct;
import org.unitConverter.unit.BaseDimension;
import org.unitConverter.unit.BritishImperial;
import org.unitConverter.unit.LinearUnit;
+import org.unitConverter.unit.LinearUnitValue;
+import org.unitConverter.unit.NameSymbol;
import org.unitConverter.unit.SI;
import org.unitConverter.unit.Unit;
import org.unitConverter.unit.UnitDatabase;
import org.unitConverter.unit.UnitPrefix;
+import org.unitConverter.unit.UnitValue;
/**
* @author Adrien Hopkins
@@ -63,10 +85,22 @@ final class UnitConverterGUI {
* A tab in the View.
*/
private enum Pane {
- UNIT_CONVERTER, EXPRESSION_CONVERTER, UNIT_VIEWER, PREFIX_VIEWER;
+ UNIT_CONVERTER, EXPRESSION_CONVERTER, UNIT_VIEWER, PREFIX_VIEWER, ABOUT,
+ SETTINGS;
}
-
+
private static class Presenter {
+ /** The default place where settings are stored. */
+ private static final String DEFAULT_SETTINGS_FILEPATH = "settings.txt";
+ /** The default place where units are stored. */
+ private static final Path DEFAULT_UNITS_FILE = Path.of("unitsfile.txt");
+ /** The default place where dimensions are stored. */
+ private static final Path DEFAULT_DIMENSION_FILE = Path
+ .of("dimensionfile.txt");
+ /** The default place where exceptions are stored. */
+ private static final Path DEFAULT_EXCEPTIONS_FILE = Path
+ .of("metric_exceptions.txt");
+
/**
* Adds default units and dimensions to a database.
*
@@ -88,33 +122,65 @@ final class UnitConverterGUI {
// nonlinear units - must be loaded manually
database.addUnit("tempCelsius", SI.CELSIUS);
database.addUnit("tempFahrenheit", BritishImperial.FAHRENHEIT);
-
+
// load initial dimensions
database.addDimension("LENGTH", SI.Dimensions.LENGTH);
database.addDimension("MASS", SI.Dimensions.MASS);
database.addDimension("TIME", SI.Dimensions.TIME);
database.addDimension("TEMPERATURE", SI.Dimensions.TEMPERATURE);
}
-
+
+ /**
+ * @return {@code line} with any comments removed.
+ * @since 2021-03-13
+ */
+ private static final String withoutComments(String line) {
+ final int index = line.indexOf('#');
+ return index == -1 ? line : line.substring(index);
+ }
+
/** The presenter's associated view. */
private final View view;
-
+
/** The units known by the program. */
private final UnitDatabase database;
-
+
/** The names of all of the units */
private final List<String> unitNames;
-
+
/** The names of all of the prefixes */
private final List<String> prefixNames;
-
+
/** The names of all of the dimensions */
private final List<String> dimensionNames;
-
+
+ /** Unit names that are ignored by the metric-only/imperial-only filter */
+ private final Set<String> metricExceptions;
+
private final Comparator<String> prefixNameComparator;
-
- private int significantFigures = 6;
-
+
+ /** A boolean remembering whether or not one-way conversion is on */
+ private boolean oneWay = true;
+
+ /** The prefix rule */
+ private DefaultPrefixRepetitionRule prefixRule = null;
+ // conditions for existence of From and To entries
+ // used for one-way conversion
+ private final MutablePredicate<String> fromExistenceCondition = new MutablePredicate<>(
+ s -> true);
+
+ private final MutablePredicate<String> toExistenceCondition = new MutablePredicate<>(
+ s -> true);
+
+ /*
+ * Rounding-related settings. I am using my own system, and not
+ * MathContext, because MathContext does not support decimal place based
+ * or scientific rounding, only significant digit based rounding.
+ */
+ private int precision = 6;
+
+ private RoundingType roundingType = RoundingType.SIGNIFICANT_DIGITS;
+
/**
* Creates the presenter.
*
@@ -124,14 +190,28 @@ final class UnitConverterGUI {
*/
Presenter(final View view) {
this.view = view;
-
+
// load initial units
- this.database = new UnitDatabase();
+ this.database = new UnitDatabase(
+ DefaultPrefixRepetitionRule.NO_RESTRICTION);
Presenter.addDefaults(this.database);
-
- this.database.loadUnitsFile(new File("unitsfile.txt"));
- this.database.loadDimensionFile(new File("dimensionfile.txt"));
-
+
+ this.database.loadUnitsFile(DEFAULT_UNITS_FILE);
+ this.database.loadDimensionFile(DEFAULT_DIMENSION_FILE);
+
+ // load metric exceptions
+ try {
+ this.metricExceptions = Files.readAllLines(DEFAULT_EXCEPTIONS_FILE)
+ .stream().map(Presenter::withoutComments)
+ .filter(s -> !s.isBlank()).collect(Collectors.toSet());
+ } catch (final IOException e) {
+ throw new AssertionError("Loading of metric_exceptions.txt failed.",
+ e);
+ }
+
+ // load settings - requires database to exist
+ this.loadSettings();
+
// a comparator that can be used to compare prefix names
// any name that does not exist is less than a name that does.
// otherwise, they are compared by value
@@ -140,37 +220,43 @@ final class UnitConverterGUI {
return -1;
else if (!Presenter.this.database.containsPrefixName(o2))
return 1;
-
+
final UnitPrefix p1 = Presenter.this.database.getPrefix(o1);
final UnitPrefix p2 = Presenter.this.database.getPrefix(o2);
-
+
if (p1.getMultiplier() < p2.getMultiplier())
return -1;
else if (p1.getMultiplier() > p2.getMultiplier())
return 1;
-
+
return o1.compareTo(o2);
};
-
- this.unitNames = new ArrayList<>(this.database.unitMapPrefixless().keySet());
+
+ this.unitNames = new ArrayList<>(
+ this.database.unitMapPrefixless().keySet());
this.unitNames.sort(null); // sorts it using Comparable
-
+
this.prefixNames = new ArrayList<>(this.database.prefixMap().keySet());
- this.prefixNames.sort(this.prefixNameComparator); // sorts it using my comparator
-
- this.dimensionNames = new DelegateListModel<>(new ArrayList<>(this.database.dimensionMap().keySet()));
+ this.prefixNames.sort(this.prefixNameComparator); // sorts it using my
+ // comparator
+
+ this.dimensionNames = new DelegateListModel<>(
+ new ArrayList<>(this.database.dimensionMap().keySet()));
this.dimensionNames.sort(null); // sorts it using Comparable
-
+
// a Predicate that returns true iff the argument is a full base unit
- final Predicate<Unit> isFullBase = unit -> unit instanceof LinearUnit && ((LinearUnit) unit).isBase();
-
+ final Predicate<Unit> isFullBase = unit -> unit instanceof LinearUnit
+ && ((LinearUnit) unit).isBase();
+
// print out unit counts
- System.out.printf("Successfully loaded %d units with %d unit names (%d base units).%n",
+ System.out.printf(
+ "Successfully loaded %d units with %d unit names (%d base units).%n",
new HashSet<>(this.database.unitMapPrefixless().values()).size(),
this.database.unitMapPrefixless().size(),
- new HashSet<>(this.database.unitMapPrefixless().values()).stream().filter(isFullBase).count());
+ new HashSet<>(this.database.unitMapPrefixless().values())
+ .stream().filter(isFullBase).count());
}
-
+
/**
* Converts in the dimension-based converter
*
@@ -180,7 +266,8 @@ final class UnitConverterGUI {
public final void convertDimensionBased() {
final String fromSelection = this.view.getFromSelection();
if (fromSelection == null) {
- this.view.showErrorDialog("Error", "No unit selected in From field");
+ this.view.showErrorDialog("Error",
+ "No unit selected in From field");
return;
}
final String toSelection = this.view.getToSelection();
@@ -188,30 +275,35 @@ final class UnitConverterGUI {
this.view.showErrorDialog("Error", "No unit selected in To field");
return;
}
-
+
final Unit from = this.database.getUnit(fromSelection);
- final Unit to = this.database.getUnit(toSelection);
-
- final String input = this.view.getDimensionConverterInput();
- if (input.equals("")) {
- this.view.showErrorDialog("Error", "No value to convert entered.");
+ final Unit to = this.database.getUnit(toSelection)
+ .withName(NameSymbol.ofName(toSelection));
+
+ final UnitValue beforeValue;
+ try {
+ beforeValue = UnitValue.of(from,
+ this.view.getDimensionConverterInput());
+ } catch (final ParseException e) {
+ this.view.showErrorDialog("Error",
+ "Error in parsing: " + e.getMessage());
return;
}
- final double beforeValue = Double.parseDouble(input);
- final double value = from.convertTo(to, beforeValue);
-
+ final UnitValue value = beforeValue.convertTo(to);
+
final String output = this.getRoundedString(value);
-
+
this.view.setDimensionConverterOutputText(
- String.format("%s %s = %s %s", input, fromSelection, output, toSelection));
+ String.format("%s = %s", beforeValue, output));
}
-
+
/**
* Runs whenever the convert button is pressed.
*
* <p>
- * Reads and parses a unit expression from the from and to boxes, then converts
- * {@code from} to {@code to}. Any errors are shown in JOptionPanes.
+ * Reads and parses a unit expression from the from and to boxes, then
+ * converts {@code from} to {@code to}. Any errors are shown in
+ * JOptionPanes.
* </p>
*
* @since 2019-01-26
@@ -220,64 +312,79 @@ final class UnitConverterGUI {
public final void convertExpressions() {
final String fromUnitString = this.view.getFromText();
final String toUnitString = this.view.getToText();
-
+
if (fromUnitString.isEmpty()) {
- this.view.showErrorDialog("Parse Error", "Please enter a unit expression in the From: box.");
+ this.view.showErrorDialog("Parse Error",
+ "Please enter a unit expression in the From: box.");
return;
}
if (toUnitString.isEmpty()) {
- this.view.showErrorDialog("Parse Error", "Please enter a unit expression in the To: box.");
+ this.view.showErrorDialog("Parse Error",
+ "Please enter a unit expression in the To: box.");
return;
}
-
- // try to parse from
- final Unit from;
+
+ final LinearUnitValue from;
+ final Unit to;
try {
- from = this.database.getUnitFromExpression(fromUnitString);
- } catch (final IllegalArgumentException e) {
- this.view.showErrorDialog("Parse Error", "Could not recognize text in From entry: " + e.getMessage());
+ from = this.database.evaluateUnitExpression(fromUnitString);
+ } catch (final IllegalArgumentException | NoSuchElementException e) {
+ this.view.showErrorDialog("Parse Error",
+ "Could not recognize text in From entry: " + e.getMessage());
return;
}
-
- final double value;
- // try to parse to
- final Unit to;
try {
- if (this.database.containsUnitName(toUnitString)) {
- // if it's a unit, convert to that
- to = this.database.getUnit(toUnitString);
+ to = this.database.getUnitFromExpression(toUnitString);
+ } catch (final IllegalArgumentException | NoSuchElementException e) {
+ this.view.showErrorDialog("Parse Error",
+ "Could not recognize text in To entry: " + e.getMessage());
+ return;
+ }
+
+ if (to instanceof LinearUnit) {
+ // convert to LinearUnitValue
+ final LinearUnitValue from2;
+ final LinearUnit to2 = ((LinearUnit) to)
+ .withName(NameSymbol.ofName(toUnitString));
+ final boolean useSlash;
+
+ if (from.canConvertTo(to2)) {
+ from2 = from;
+ useSlash = false;
+ } else if (LinearUnitValue.ONE.dividedBy(from).canConvertTo(to2)) {
+ from2 = LinearUnitValue.ONE.dividedBy(from);
+ useSlash = true;
} else {
- to = this.database.getUnitFromExpression(toUnitString);
+ // if I can't convert, leave
+ this.view.showErrorDialog("Conversion Error",
+ String.format("Cannot convert between %s and %s",
+ fromUnitString, toUnitString));
+ return;
}
- } catch (final IllegalArgumentException e) {
- this.view.showErrorDialog("Parse Error", "Could not recognize text in To entry: " + e.getMessage());
+
+ final LinearUnitValue converted = from2.convertTo(to2);
+ this.view.setExpressionConverterOutputText((useSlash ? "1 / " : "")
+ + String.format("%s = %s", fromUnitString,
+ this.getRoundedString(converted, false)));
return;
- }
-
- if (from.canConvertTo(to)) {
- value = from.convertTo(to, 1);
-
- // round value
- final String output = this.getRoundedString(value);
-
- this.view.setExpressionConverterOutputText(
- String.format("%s = %s %s", fromUnitString, output, toUnitString));
- } else if (from instanceof LinearUnit && SI.ONE.dividedBy((LinearUnit) from).canConvertTo(to)) {
- // reciprocal conversion (like seconds to hertz)
- value = SI.ONE.dividedBy((LinearUnit) from).convertTo(to, 1);
-
- // round value
- final String output = this.getRoundedString(value);
-
- this.view.setExpressionConverterOutputText(
- String.format("1 / %s = %s %s", fromUnitString, output, toUnitString));
} else {
- // if I can't convert, leave
- this.view.showErrorDialog("Conversion Error",
- String.format("Cannot convert between %s and %s", fromUnitString, toUnitString));
+ // convert to UnitValue
+ final UnitValue from2 = from.asUnitValue();
+ if (from2.canConvertTo(to)) {
+ final UnitValue converted = from2.convertTo(to);
+
+ this.view
+ .setExpressionConverterOutputText(String.format("%s = %s",
+ fromUnitString, this.getRoundedString(converted)));
+ } else {
+ // if I can't convert, leave
+ this.view.showErrorDialog("Conversion Error",
+ String.format("Cannot convert between %s and %s",
+ fromUnitString, toUnitString));
+ }
}
}
-
+
/**
* @return a list of all of the unit dimensions
* @since 2019-04-13
@@ -286,7 +393,17 @@ final class UnitConverterGUI {
public final List<String> dimensionNameList() {
return this.dimensionNames;
}
-
+
+ /**
+ * @return a list of all the entries in the dimension-based converter's
+ * From box
+ * @since 2020-08-27
+ */
+ public final Set<String> fromEntries() {
+ return ConditionalExistenceCollections.conditionalExistenceSet(
+ this.unitNameSet(), this.fromExistenceCondition);
+ }
+
/**
* @return a comparator to compare prefix names
* @since 2019-04-14
@@ -295,19 +412,54 @@ final class UnitConverterGUI {
public final Comparator<String> getPrefixNameComparator() {
return this.prefixNameComparator;
}
-
+
/**
- * @param value value to round
- * @return string of that value rounded to {@code significantDigits} significant
- * digits.
- * @since 2019-04-14
- * @since v0.2.0
+ * Like {@link LinearUnitValue#toString(boolean)}, but obeys this unit
+ * converter's rounding settings.
+ *
+ * @since 2020-08-04
*/
- private final String getRoundedString(final double value) {
- // round value
- final BigDecimal bigValue = new BigDecimal(value).round(new MathContext(this.significantFigures));
- String output = bigValue.toString();
-
+ private final String getRoundedString(final LinearUnitValue value,
+ boolean showUncertainty) {
+ switch (this.roundingType) {
+ case DECIMAL_PLACES:
+ case SIGNIFICANT_DIGITS:
+ return this.getRoundedString(value.asUnitValue());
+ case SCIENTIFIC:
+ return value.toString(showUncertainty);
+ default:
+ throw new AssertionError("Invalid switch condition.");
+ }
+ }
+
+ /**
+ * Like {@link UnitValue#toString()}, but obeys this unit converter's
+ * rounding settings.
+ *
+ * @since 2020-08-04
+ */
+ private final String getRoundedString(final UnitValue value) {
+ final BigDecimal unrounded = new BigDecimal(value.getValue());
+ final BigDecimal rounded;
+ int precision = this.precision;
+
+ switch (this.roundingType) {
+ case DECIMAL_PLACES:
+ rounded = unrounded.setScale(precision, RoundingMode.HALF_EVEN);
+ break;
+ case SCIENTIFIC:
+ precision = 12;
+ //$FALL-THROUGH$
+ case SIGNIFICANT_DIGITS:
+ rounded = unrounded
+ .round(new MathContext(precision, RoundingMode.HALF_EVEN));
+ break;
+ default:
+ throw new AssertionError("Invalid switch condition.");
+ }
+
+ String output = rounded.toString();
+
// remove trailing zeroes
if (output.contains(".")) {
while (output.endsWith("0")) {
@@ -317,10 +469,74 @@ final class UnitConverterGUI {
output = output.substring(0, output.length() - 1);
}
}
-
- return output;
+
+ return output + " " + value.getUnit().getPrimaryName().get();
}
-
+
+ /**
+ * @return The file where settings are stored;
+ * @since 2020-12-11
+ */
+ private final Path getSettingsFile() {
+ return Path.of(DEFAULT_SETTINGS_FILEPATH);
+ }
+
+ /**
+ * Loads settings from the settings file.
+ *
+ * @since 2021-02-17
+ */
+ public final void loadSettings() {
+ try {
+ // read file line by line
+ final int lineNum = 0;
+ for (final String line : Files
+ .readAllLines(this.getSettingsFile())) {
+ final int equalsIndex = line.indexOf('=');
+ if (equalsIndex == -1)
+ throw new IllegalStateException(
+ "Settings file is malformed at line " + lineNum);
+
+ final String param = line.substring(0, equalsIndex);
+ final String value = line.substring(equalsIndex + 1);
+
+ switch (param) {
+ // set manually to avoid the unnecessary saving of the non-manual
+ // methods
+ case "precision":
+ this.precision = Integer.valueOf(value);
+ break;
+ case "rounding_type":
+ this.roundingType = RoundingType.valueOf(value);
+ break;
+ case "prefix_rule":
+ this.prefixRule = DefaultPrefixRepetitionRule.valueOf(value);
+ this.database.setPrefixRepetitionRule(this.prefixRule);
+ break;
+ case "one_way":
+ this.oneWay = Boolean.valueOf(value);
+ if (this.oneWay) {
+ this.fromExistenceCondition.setPredicate(
+ unitName -> this.metricExceptions.contains(unitName)
+ || !this.database.getUnit(unitName)
+ .isMetric());
+ this.toExistenceCondition.setPredicate(
+ unitName -> this.metricExceptions.contains(unitName)
+ || this.database.getUnit(unitName).isMetric());
+ } else {
+ this.fromExistenceCondition.setPredicate(unitName -> true);
+ this.toExistenceCondition.setPredicate(unitName -> true);
+ }
+ break;
+ default:
+ System.err.printf("Warning: unrecognized setting \"%s\".",
+ param);
+ break;
+ }
+ }
+ } catch (final IOException e) {}
+ }
+
/**
* @return a set of all prefix names in the database
* @since 2019-04-14
@@ -329,7 +545,7 @@ final class UnitConverterGUI {
public final Set<String> prefixNameSet() {
return this.database.prefixMap().keySet();
}
-
+
/**
* Runs whenever a prefix is selected in the viewer.
* <p>
@@ -345,23 +561,107 @@ final class UnitConverterGUI {
return;
else {
final UnitPrefix prefix = this.database.getPrefix(prefixName);
-
- this.view.setPrefixTextBoxText(String.format("%s%nMultiplier: %s", prefixName, prefix.getMultiplier()));
+
+ this.view.setPrefixTextBoxText(String.format("%s%nMultiplier: %s",
+ prefixName, prefix.getMultiplier()));
}
}
-
+
+ /**
+ * Saves the settings to the settings file.
+ *
+ * @since 2021-02-17
+ */
+ public final void saveSettings() {
+ try (BufferedWriter writer = Files
+ .newBufferedWriter(this.getSettingsFile())) {
+ writer.write(String.format("precision=%d\n", this.precision));
+ writer.write(
+ String.format("rounding_type=%s\n", this.roundingType));
+ writer.write(String.format("prefix_rule=%s\n", this.prefixRule));
+ writer.write(String.format("one_way=%s\n", this.oneWay));
+ } catch (final IOException e) {
+ e.printStackTrace();
+ this.view.showErrorDialog("I/O Error",
+ "Error occurred while saving settings: "
+ + e.getLocalizedMessage());
+ }
+ }
+
+ /**
+ * Enables or disables one-way conversion.
+ *
+ * @param oneWay whether one-way conversion should be on (true) or off
+ * (false)
+ * @since 2020-08-27
+ */
+ public final void setOneWay(boolean oneWay) {
+ this.oneWay = oneWay;
+ if (oneWay) {
+ this.fromExistenceCondition.setPredicate(
+ unitName -> this.metricExceptions.contains(unitName)
+ || !this.database.getUnit(unitName).isMetric());
+ this.toExistenceCondition.setPredicate(
+ unitName -> this.metricExceptions.contains(unitName)
+ || this.database.getUnit(unitName).isMetric());
+ } else {
+ this.fromExistenceCondition.setPredicate(unitName -> true);
+ this.toExistenceCondition.setPredicate(unitName -> true);
+ }
+
+ this.saveSettings();
+ }
+
/**
- * @param significantFigures new value of significantFigures
+ * @param precision new value of precision
* @since 2019-01-15
* @since v0.1.0
*/
- public final void setSignificantFigures(final int significantFigures) {
- this.significantFigures = significantFigures;
+ public final void setPrecision(final int precision) {
+ this.precision = precision;
+
+ this.saveSettings();
}
-
+
/**
- * Returns true if and only if the unit represented by {@code unitName} has the
- * dimension represented by {@code dimensionName}.
+ * @param prefixRepetitionRule the prefixRepetitionRule to set
+ * @since 2020-08-26
+ */
+ public void setPrefixRepetitionRule(
+ Predicate<List<UnitPrefix>> prefixRepetitionRule) {
+ if (prefixRepetitionRule instanceof DefaultPrefixRepetitionRule) {
+ this.prefixRule = (DefaultPrefixRepetitionRule) prefixRepetitionRule;
+ } else {
+ this.prefixRule = null;
+ }
+ this.database.setPrefixRepetitionRule(prefixRepetitionRule);
+
+ this.saveSettings();
+ }
+
+ /**
+ * @param roundingType the roundingType to set
+ * @since 2020-07-16
+ */
+ public final void setRoundingType(RoundingType roundingType) {
+ this.roundingType = roundingType;
+
+ this.saveSettings();
+ }
+
+ /**
+ * @return a list of all the entries in the dimension-based converter's To
+ * box
+ * @since 2020-08-27
+ */
+ public final Set<String> toEntries() {
+ return ConditionalExistenceCollections.conditionalExistenceSet(
+ this.unitNameSet(), this.toExistenceCondition);
+ }
+
+ /**
+ * Returns true if and only if the unit represented by {@code unitName}
+ * has the dimension represented by {@code dimensionName}.
*
* @param unitName name of unit to test
* @param dimensionName name of dimension to test
@@ -369,12 +669,14 @@ final class UnitConverterGUI {
* @since 2019-04-13
* @since v0.2.0
*/
- public final boolean unitMatchesDimension(final String unitName, final String dimensionName) {
+ public final boolean unitMatchesDimension(final String unitName,
+ final String dimensionName) {
final Unit unit = this.database.getUnit(unitName);
- final ObjectProduct<BaseDimension> dimension = this.database.getDimension(dimensionName);
+ final ObjectProduct<BaseDimension> dimension = this.database
+ .getDimension(dimensionName);
return unit.getDimension().equals(dimension);
}
-
+
/**
* Runs whenever a unit is selected in the viewer.
* <p>
@@ -390,29 +692,44 @@ final class UnitConverterGUI {
return;
else {
final Unit unit = this.database.getUnit(unitName);
-
+
this.view.setUnitTextBoxText(unit.toString());
}
}
-
+
/**
* @return a set of all of the unit names
* @since 2019-04-14
* @since v0.2.0
*/
- public final Set<String> unitNameSet() {
+ private final Set<String> unitNameSet() {
return this.database.unitMapPrefixless().keySet();
}
}
-
+
+ /**
+ * Different types of rounding.
+ *
+ * Significant digits: Rounds to a number of digits. i.e. with precision 5,
+ * 12345.6789 rounds to 12346. Decimal places: Rounds to a number of digits
+ * after the decimal point, i.e. with precision 5, 12345.6789 rounds to
+ * 12345.67890. Scientific: Rounds based on the number of digits and
+ * operations, following standard scientific rounding.
+ */
+ private static enum RoundingType {
+ SIGNIFICANT_DIGITS, DECIMAL_PLACES, SCIENTIFIC;
+ }
+
private static class View {
+ private static final NumberFormat NUMBER_FORMATTER = new DecimalFormat();
+
/** The view's frame. */
private final JFrame frame;
/** The view's associated presenter. */
private final Presenter presenter;
/** The master pane containing all of the tabs. */
private final JTabbedPane masterPane;
-
+
// DIMENSION-BASED CONVERTER
/** The panel for inputting values in the dimension-based converter */
private final JTextField valueInput;
@@ -422,7 +739,7 @@ final class UnitConverterGUI {
private final SearchBoxList toSearch;
/** The output area in the dimension-based converter */
private final JTextArea dimensionBasedOutput;
-
+
// EXPRESSION-BASED CONVERTER
/** The "From" entry in the conversion panel */
private final JTextField fromEntry;
@@ -430,7 +747,7 @@ final class UnitConverterGUI {
private final JTextField toEntry;
/** The output area in the conversion panel */
private final JTextArea output;
-
+
// UNIT AND PREFIX VIEWERS
/** The searchable list of unit names in the unit viewer */
private final SearchBoxList unitNameList;
@@ -440,7 +757,7 @@ final class UnitConverterGUI {
private final JTextArea unitTextBox;
/** The text box for prefix data in the prefix viewer */
private final JTextArea prefixTextBox;
-
+
/**
* Creates the {@code View}.
*
@@ -451,28 +768,38 @@ final class UnitConverterGUI {
this.presenter = new Presenter(this);
this.frame = new JFrame("Unit Converter");
this.frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
- this.masterPane = new JTabbedPane();
-
+
+ // enable system look and feel
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (ClassNotFoundException | InstantiationException
+ | IllegalAccessException | UnsupportedLookAndFeelException e) {
+ // oh well, just use default theme
+ System.err.println("Failed to enable system look-and-feel.");
+ e.printStackTrace();
+ }
+
// create the components
+ this.masterPane = new JTabbedPane();
this.unitNameList = new SearchBoxList(this.presenter.unitNameSet());
this.prefixNameList = new SearchBoxList(this.presenter.prefixNameSet(),
this.presenter.getPrefixNameComparator(), true);
this.unitTextBox = new JTextArea();
this.prefixTextBox = new JTextArea();
- this.fromSearch = new SearchBoxList(this.presenter.unitNameSet());
- this.toSearch = new SearchBoxList(this.presenter.unitNameSet());
- this.valueInput = new JFormattedTextField(new DecimalFormat("###############0.################"));
+ this.fromSearch = new SearchBoxList(this.presenter.fromEntries());
+ this.toSearch = new SearchBoxList(this.presenter.toEntries());
+ this.valueInput = new JFormattedTextField(NUMBER_FORMATTER);
this.dimensionBasedOutput = new JTextArea(2, 32);
this.fromEntry = new JTextField();
this.toEntry = new JTextField();
this.output = new JTextArea(2, 32);
-
+
// create more components
this.initComponents();
-
+
this.frame.pack();
}
-
+
/**
* @return the currently selected pane.
* @throws AssertionError if no pane (or an invalid pane) is selected
@@ -487,20 +814,30 @@ final class UnitConverterGUI {
return Pane.UNIT_VIEWER;
case 3:
return Pane.PREFIX_VIEWER;
+ case 4:
+ return Pane.ABOUT;
+ case 5:
+ return Pane.SETTINGS;
default:
throw new AssertionError("No selected pane, or invalid pane.");
}
}
-
+
/**
* @return value in dimension-based converter
- * @since 2019-04-13
- * @since v0.2.0
+ * @throws ParseException
+ * @since 2020-07-07
*/
- public String getDimensionConverterInput() {
- return this.valueInput.getText();
+ public double getDimensionConverterInput() throws ParseException {
+ final Number value = NUMBER_FORMATTER.parse(this.valueInput.getText());
+ if (value instanceof Double)
+ return (double) value;
+ else if (value instanceof Long)
+ return ((Long) value).longValue();
+ else
+ throw new AssertionError();
}
-
+
/**
* @return selection in "From" selector in dimension-based converter
* @since 2019-04-13
@@ -509,7 +846,7 @@ final class UnitConverterGUI {
public String getFromSelection() {
return this.fromSearch.getSelectedValue();
}
-
+
/**
* @return text in "From" box in converter panel
* @since 2019-01-15
@@ -518,7 +855,7 @@ final class UnitConverterGUI {
public String getFromText() {
return this.fromEntry.getText();
}
-
+
/**
* @return index of selected prefix in prefix viewer
* @since 2019-01-15
@@ -527,7 +864,7 @@ final class UnitConverterGUI {
public String getPrefixViewerSelection() {
return this.prefixNameList.getSelectedValue();
}
-
+
/**
* @return selection in "To" selector in dimension-based converter
* @since 2019-04-13
@@ -536,7 +873,7 @@ final class UnitConverterGUI {
public String getToSelection() {
return this.toSearch.getSelectedValue();
}
-
+
/**
* @return text in "To" box in converter panel
* @since 2019-01-26
@@ -545,7 +882,7 @@ final class UnitConverterGUI {
public String getToText() {
return this.toEntry.getText();
}
-
+
/**
* @return index of selected unit in unit viewer
* @since 2019-01-15
@@ -554,7 +891,7 @@ final class UnitConverterGUI {
public String getUnitViewerSelection() {
return this.unitNameList.getSelectedValue();
}
-
+
/**
* Starts up the application.
*
@@ -564,7 +901,7 @@ final class UnitConverterGUI {
public final void init() {
this.frame.setVisible(true);
}
-
+
/**
* Initializes the view's components.
*
@@ -574,229 +911,443 @@ final class UnitConverterGUI {
private final void initComponents() {
final JPanel masterPanel = new JPanel();
this.frame.add(masterPanel);
-
+
masterPanel.setLayout(new BorderLayout());
-
+
{ // pane with all of the tabs
masterPanel.add(this.masterPane, BorderLayout.CENTER);
-
+
+ // update stuff
+ this.masterPane.addChangeListener(e -> this.update());
+
{ // a panel for unit conversion using a selector
final JPanel convertUnitPanel = new JPanel();
this.masterPane.addTab("Convert Units", convertUnitPanel);
this.masterPane.setMnemonicAt(0, KeyEvent.VK_U);
-
+
convertUnitPanel.setLayout(new BorderLayout());
-
+
{ // panel for input part
final JPanel inputPanel = new JPanel();
convertUnitPanel.add(inputPanel, BorderLayout.CENTER);
-
+
inputPanel.setLayout(new GridLayout(1, 3));
-
+
final JComboBox<String> dimensionSelector = new JComboBox<>(
- this.presenter.dimensionNameList().toArray(new String[0]));
+ this.presenter.dimensionNameList()
+ .toArray(new String[0]));
dimensionSelector.setSelectedItem("LENGTH");
-
+
// handle dimension filter
- final MutablePredicate<String> dimensionFilter = new MutablePredicate<>(s -> true);
-
+ final MutablePredicate<String> dimensionFilter = new MutablePredicate<>(
+ s -> true);
+
// panel for From things
inputPanel.add(this.fromSearch);
-
+
this.fromSearch.addSearchFilter(dimensionFilter);
-
- { // for dimension selector and arrow that represents conversion
+
+ { // for dimension selector and arrow that represents
+ // conversion
final JPanel inBetweenPanel = new JPanel();
inputPanel.add(inBetweenPanel);
-
+
inBetweenPanel.setLayout(new BorderLayout());
-
+
{ // dimension selector
- inBetweenPanel.add(dimensionSelector, BorderLayout.PAGE_START);
+ inBetweenPanel.add(dimensionSelector,
+ BorderLayout.PAGE_START);
}
-
+
{ // the arrow in the middle
final JLabel arrowLabel = new JLabel("->");
inBetweenPanel.add(arrowLabel, BorderLayout.CENTER);
}
}
-
+
// panel for To things
-
+
inputPanel.add(this.toSearch);
-
+
this.toSearch.addSearchFilter(dimensionFilter);
-
+
// code for dimension filter
dimensionSelector.addItemListener(e -> {
- dimensionFilter.setPredicate(string -> View.this.presenter.unitMatchesDimension(string,
- (String) dimensionSelector.getSelectedItem()));
+ dimensionFilter.setPredicate(string -> View.this.presenter
+ .unitMatchesDimension(string,
+ (String) dimensionSelector.getSelectedItem()));
this.fromSearch.reapplyFilter();
this.toSearch.reapplyFilter();
});
-
- // apply the item listener once because I have a default selection
- dimensionFilter.setPredicate(string -> View.this.presenter.unitMatchesDimension(string,
- (String) dimensionSelector.getSelectedItem()));
+
+ // apply the item listener once because I have a default
+ // selection
+ dimensionFilter.setPredicate(string -> View.this.presenter
+ .unitMatchesDimension(string,
+ (String) dimensionSelector.getSelectedItem()));
this.fromSearch.reapplyFilter();
this.toSearch.reapplyFilter();
}
-
+
{ // panel for submit and output, and also value entry
final JPanel outputPanel = new JPanel();
convertUnitPanel.add(outputPanel, BorderLayout.PAGE_END);
-
+
outputPanel.setLayout(new GridLayout(3, 1));
-
+
{ // unit input
final JPanel valueInputPanel = new JPanel();
outputPanel.add(valueInputPanel);
-
+
valueInputPanel.setLayout(new BorderLayout());
-
+
{ // prompt
- final JLabel valuePrompt = new JLabel("Value to convert: ");
- valueInputPanel.add(valuePrompt, BorderLayout.LINE_START);
+ final JLabel valuePrompt = new JLabel(
+ "Value to convert: ");
+ valueInputPanel.add(valuePrompt,
+ BorderLayout.LINE_START);
}
-
+
{ // value to convert
- valueInputPanel.add(this.valueInput, BorderLayout.CENTER);
+ valueInputPanel.add(this.valueInput,
+ BorderLayout.CENTER);
}
}
-
+
{ // button to convert
final JButton convertButton = new JButton("Convert");
outputPanel.add(convertButton);
-
- convertButton.addActionListener(e -> this.presenter.convertDimensionBased());
+
+ convertButton.addActionListener(
+ e -> this.presenter.convertDimensionBased());
convertButton.setMnemonic(KeyEvent.VK_ENTER);
}
-
+
{ // output of conversion
outputPanel.add(this.dimensionBasedOutput);
this.dimensionBasedOutput.setEditable(false);
}
}
}
-
+
{ // panel for unit conversion using expressions
final JPanel convertExpressionPanel = new JPanel();
- this.masterPane.addTab("Convert Unit Expressions", convertExpressionPanel);
+ this.masterPane.addTab("Convert Unit Expressions",
+ convertExpressionPanel);
this.masterPane.setMnemonicAt(1, KeyEvent.VK_E);
-
- convertExpressionPanel.setLayout(new GridLayout(5, 1));
-
+
+ convertExpressionPanel.setLayout(new GridLayout(4, 1));
+
{ // panel for units to convert from
final JPanel fromPanel = new JPanel();
convertExpressionPanel.add(fromPanel);
-
+
fromPanel.setBorder(BorderFactory.createTitledBorder("From"));
fromPanel.setLayout(new GridLayout(1, 1));
-
+
{ // entry for units
fromPanel.add(this.fromEntry);
}
}
-
+
{ // panel for units to convert to
final JPanel toPanel = new JPanel();
convertExpressionPanel.add(toPanel);
-
+
toPanel.setBorder(BorderFactory.createTitledBorder("To"));
toPanel.setLayout(new GridLayout(1, 1));
-
+
{ // entry for units
toPanel.add(this.toEntry);
}
}
-
+
{ // button to convert
final JButton convertButton = new JButton("Convert");
convertExpressionPanel.add(convertButton);
-
- convertButton.addActionListener(e -> this.presenter.convertExpressions());
+
+ convertButton.addActionListener(
+ e -> this.presenter.convertExpressions());
convertButton.setMnemonic(KeyEvent.VK_ENTER);
}
-
+
{ // output of conversion
final JPanel outputPanel = new JPanel();
convertExpressionPanel.add(outputPanel);
-
- outputPanel.setBorder(BorderFactory.createTitledBorder("Output"));
+
+ outputPanel
+ .setBorder(BorderFactory.createTitledBorder("Output"));
outputPanel.setLayout(new GridLayout(1, 1));
-
+
{ // output
outputPanel.add(this.output);
this.output.setEditable(false);
}
}
-
- { // panel for specifying precision
- final JPanel sigDigPanel = new JPanel();
- convertExpressionPanel.add(sigDigPanel);
-
- sigDigPanel.setBorder(BorderFactory.createTitledBorder("Significant Digits"));
-
- { // slider
- final JSlider sigDigSlider = new JSlider(0, 12);
- sigDigPanel.add(sigDigSlider);
-
- sigDigSlider.setMajorTickSpacing(4);
- sigDigSlider.setMinorTickSpacing(1);
- sigDigSlider.setSnapToTicks(true);
- sigDigSlider.setPaintTicks(true);
- sigDigSlider.setPaintLabels(true);
-
- sigDigSlider.addChangeListener(
- e -> this.presenter.setSignificantFigures(sigDigSlider.getValue()));
- }
- }
}
-
+
{ // panel to look up units
final JPanel unitLookupPanel = new JPanel();
this.masterPane.addTab("Unit Viewer", unitLookupPanel);
this.masterPane.setMnemonicAt(2, KeyEvent.VK_V);
-
+
unitLookupPanel.setLayout(new GridLayout());
-
+
{ // search panel
unitLookupPanel.add(this.unitNameList);
-
- this.unitNameList.getSearchList()
- .addListSelectionListener(e -> this.presenter.unitNameSelected());
+
+ this.unitNameList.getSearchList().addListSelectionListener(
+ e -> this.presenter.unitNameSelected());
}
-
+
{ // the text box for unit's toString
unitLookupPanel.add(this.unitTextBox);
this.unitTextBox.setEditable(false);
this.unitTextBox.setLineWrap(true);
}
}
-
+
{ // panel to look up prefixes
final JPanel prefixLookupPanel = new JPanel();
this.masterPane.addTab("Prefix Viewer", prefixLookupPanel);
this.masterPane.setMnemonicAt(3, KeyEvent.VK_P);
-
+
prefixLookupPanel.setLayout(new GridLayout(1, 2));
-
+
{ // panel for listing and seaching
prefixLookupPanel.add(this.prefixNameList);
-
- this.prefixNameList.getSearchList()
- .addListSelectionListener(e -> this.presenter.prefixSelected());
+
+ this.prefixNameList.getSearchList().addListSelectionListener(
+ e -> this.presenter.prefixSelected());
}
-
+
{ // the text box for prefix's toString
prefixLookupPanel.add(this.prefixTextBox);
this.prefixTextBox.setEditable(false);
this.prefixTextBox.setLineWrap(true);
}
}
+
+ { // Info panel
+ final JPanel infoPanel = new JPanel();
+ 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);
+
+ // get info text
+ final String infoText;
+ try {
+ final Path aboutFile = Path.of("src", "about.txt");
+ infoText = Files.readAllLines(aboutFile).stream()
+ .map(Presenter::withoutComments)
+ .collect(Collectors.joining("\n"));
+ } catch (final IOException e) {
+ throw new AssertionError("I/O exception loading about.txt");
+ }
+ infoTextArea.setText(infoText);
+ }
+
+ { // Settings panel
+ final JPanel settingsPanel = new JPanel();
+ this.masterPane.addTab("\u2699", new JScrollPane(settingsPanel));
+ this.masterPane.setMnemonicAt(5, KeyEvent.VK_S);
+
+ settingsPanel.setLayout(
+ new BoxLayout(settingsPanel, BoxLayout.PAGE_AXIS));
+
+ { // rounding settings
+ final JPanel roundingPanel = new JPanel();
+ settingsPanel.add(roundingPanel);
+ roundingPanel
+ .setBorder(new TitledBorder("Rounding Settings"));
+ roundingPanel.setLayout(new GridBagLayout());
+
+ // rounding rule selection
+ final ButtonGroup roundingRuleButtons = new ButtonGroup();
+
+ final JLabel roundingRuleLabel = new JLabel("Rounding Rule:");
+ roundingPanel.add(roundingRuleLabel, new GridBagBuilder(0, 0)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JRadioButton fixedPrecision = new JRadioButton(
+ "Fixed Precision");
+ if (this.presenter.roundingType == RoundingType.SIGNIFICANT_DIGITS) {
+ fixedPrecision.setSelected(true);
+ }
+ fixedPrecision.addActionListener(e -> this.presenter
+ .setRoundingType(RoundingType.SIGNIFICANT_DIGITS));
+ roundingRuleButtons.add(fixedPrecision);
+ roundingPanel.add(fixedPrecision, new GridBagBuilder(0, 1)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JRadioButton fixedDecimals = new JRadioButton(
+ "Fixed Decimal Places");
+ if (this.presenter.roundingType == RoundingType.DECIMAL_PLACES) {
+ fixedDecimals.setSelected(true);
+ }
+ fixedDecimals.addActionListener(e -> this.presenter
+ .setRoundingType(RoundingType.DECIMAL_PLACES));
+ roundingRuleButtons.add(fixedDecimals);
+ roundingPanel.add(fixedDecimals, new GridBagBuilder(0, 2)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JRadioButton relativePrecision = new JRadioButton(
+ "Scientific Precision");
+ if (this.presenter.roundingType == RoundingType.SCIENTIFIC) {
+ relativePrecision.setSelected(true);
+ }
+ relativePrecision.addActionListener(e -> this.presenter
+ .setRoundingType(RoundingType.SCIENTIFIC));
+ roundingRuleButtons.add(relativePrecision);
+ roundingPanel.add(relativePrecision, new GridBagBuilder(0, 3)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JLabel sliderLabel = new JLabel("Precision:");
+ roundingPanel.add(sliderLabel, new GridBagBuilder(0, 4)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JSlider sigDigSlider = new JSlider(0, 12);
+ roundingPanel.add(sigDigSlider, new GridBagBuilder(0, 5)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ sigDigSlider.setMajorTickSpacing(4);
+ sigDigSlider.setMinorTickSpacing(1);
+ sigDigSlider.setSnapToTicks(true);
+ sigDigSlider.setPaintTicks(true);
+ sigDigSlider.setPaintLabels(true);
+ sigDigSlider.setValue(this.presenter.precision);
+
+ sigDigSlider.addChangeListener(e -> this.presenter
+ .setPrecision(sigDigSlider.getValue()));
+ }
+
+ { // prefix repetition settings
+ final JPanel prefixRepetitionPanel = new JPanel();
+ settingsPanel.add(prefixRepetitionPanel);
+ prefixRepetitionPanel.setBorder(
+ new TitledBorder("Prefix Repetition Settings"));
+ prefixRepetitionPanel.setLayout(new GridBagLayout());
+
+ // prefix rules
+ final ButtonGroup prefixRuleButtons = new ButtonGroup();
+
+ final JRadioButton noRepetition = new JRadioButton(
+ "No Repetition");
+ if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.NO_REPETITION) {
+ noRepetition.setSelected(true);
+ }
+ noRepetition.addActionListener(
+ e -> this.presenter.setPrefixRepetitionRule(
+ DefaultPrefixRepetitionRule.NO_REPETITION));
+ prefixRuleButtons.add(noRepetition);
+ prefixRepetitionPanel.add(noRepetition,
+ new GridBagBuilder(0, 0)
+ .setAnchor(GridBagConstraints.LINE_START)
+ .build());
+
+ final JRadioButton noRestriction = new JRadioButton(
+ "No Restriction");
+ if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.NO_RESTRICTION) {
+ noRestriction.setSelected(true);
+ }
+ noRestriction.addActionListener(
+ e -> this.presenter.setPrefixRepetitionRule(
+ DefaultPrefixRepetitionRule.NO_RESTRICTION));
+ prefixRuleButtons.add(noRestriction);
+ prefixRepetitionPanel.add(noRestriction,
+ new GridBagBuilder(0, 1)
+ .setAnchor(GridBagConstraints.LINE_START)
+ .build());
+
+ final JRadioButton customRepetition = new JRadioButton(
+ "Complex Repetition");
+ if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.COMPLEX_REPETITION) {
+ customRepetition.setSelected(true);
+ }
+ customRepetition.addActionListener(
+ e -> this.presenter.setPrefixRepetitionRule(
+ DefaultPrefixRepetitionRule.COMPLEX_REPETITION));
+ prefixRuleButtons.add(customRepetition);
+ prefixRepetitionPanel.add(customRepetition,
+ new GridBagBuilder(0, 2)
+ .setAnchor(GridBagConstraints.LINE_START)
+ .build());
+ }
+
+ { // search settings
+ final JPanel searchingPanel = new JPanel();
+ settingsPanel.add(searchingPanel);
+ searchingPanel.setBorder(new TitledBorder("Search Settings"));
+ searchingPanel.setLayout(new GridBagLayout());
+
+ // searching rules
+ final ButtonGroup searchRuleButtons = new ButtonGroup();
+
+ final JRadioButton noPrefixes = new JRadioButton(
+ "Never Include Prefixed Units");
+ noPrefixes.setEnabled(false);
+ searchRuleButtons.add(noPrefixes);
+ searchingPanel.add(noPrefixes, new GridBagBuilder(0, 0)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JRadioButton fixedPrefixes = new JRadioButton(
+ "Include Some Prefixes");
+ fixedPrefixes.setEnabled(false);
+ searchRuleButtons.add(fixedPrefixes);
+ searchingPanel.add(fixedPrefixes, new GridBagBuilder(0, 1)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JRadioButton explicitPrefixes = new JRadioButton(
+ "Include Explicit Prefixes");
+ explicitPrefixes.setEnabled(false);
+ searchRuleButtons.add(explicitPrefixes);
+ searchingPanel.add(explicitPrefixes, new GridBagBuilder(0, 2)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JRadioButton alwaysInclude = new JRadioButton(
+ "Include All Single Prefixes");
+ alwaysInclude.setEnabled(false);
+ searchRuleButtons.add(alwaysInclude);
+ searchingPanel.add(alwaysInclude, new GridBagBuilder(0, 3)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+ }
+
+ { // miscellaneous settings
+ final JPanel miscPanel = new JPanel();
+ settingsPanel.add(miscPanel);
+ miscPanel
+ .setBorder(new TitledBorder("Miscellaneous Settings"));
+ miscPanel.setLayout(new GridBagLayout());
+
+ final JCheckBox oneWay = new JCheckBox(
+ "Convert One Way Only");
+ oneWay.setSelected(this.presenter.oneWay);
+ oneWay.addItemListener(
+ e -> this.presenter.setOneWay(e.getStateChange() == 1));
+ miscPanel.add(oneWay, new GridBagBuilder(0, 0)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JCheckBox showAllVariations = new JCheckBox(
+ "Show Symbols in \"Convert Units\"");
+ showAllVariations.setSelected(true);
+ showAllVariations.setEnabled(false);
+ miscPanel.add(showAllVariations, new GridBagBuilder(0, 1)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+
+ final JButton unitFileButton = new JButton(
+ "Manage Unit Data Files");
+ unitFileButton.setEnabled(false);
+ miscPanel.add(unitFileButton, new GridBagBuilder(0, 2)
+ .setAnchor(GridBagConstraints.LINE_START).build());
+ }
+ }
}
}
-
+
/**
* Sets the text in the output of the dimension-based converter.
*
@@ -807,7 +1358,7 @@ final class UnitConverterGUI {
public void setDimensionConverterOutputText(final String text) {
this.dimensionBasedOutput.setText(text);
}
-
+
/**
* Sets the text in the output of the conversion panel.
*
@@ -818,7 +1369,7 @@ final class UnitConverterGUI {
public void setExpressionConverterOutputText(final String text) {
this.output.setText(text);
}
-
+
/**
* Sets the text of the prefix text box in the prefix viewer.
*
@@ -829,7 +1380,7 @@ final class UnitConverterGUI {
public void setPrefixTextBoxText(final String text) {
this.prefixTextBox.setText(text);
}
-
+
/**
* Sets the text of the unit text box in the unit viewer.
*
@@ -840,7 +1391,7 @@ final class UnitConverterGUI {
public void setUnitTextBoxText(final String text) {
this.unitTextBox.setText(text);
}
-
+
/**
* Shows an error dialog.
*
@@ -850,10 +1401,23 @@ final class UnitConverterGUI {
* @since v0.1.0
*/
public void showErrorDialog(final String title, final String message) {
- JOptionPane.showMessageDialog(this.frame, message, title, JOptionPane.ERROR_MESSAGE);
+ JOptionPane.showMessageDialog(this.frame, message, title,
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ public void update() {
+ switch (this.getActivePane()) {
+ case UNIT_CONVERTER:
+ this.fromSearch.updateList();
+ this.toSearch.updateList();
+ break;
+ default:
+ // do nothing, for now
+ break;
+ }
}
}
-
+
public static void main(final String[] args) {
new View().init();
}