From 07c86e02be29aa3d3d878adce62c5c0a9a458e47 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 26 Feb 2022 09:53:24 -0500 Subject: Implemented unit conversion, with a few problems TabbedView now displays its units, but with their toString method which shows their definition in addition to their name --- src/main/java/sevenUnits/unit/LinearUnit.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src/main/java/sevenUnits/unit/LinearUnit.java') diff --git a/src/main/java/sevenUnits/unit/LinearUnit.java b/src/main/java/sevenUnits/unit/LinearUnit.java index 25c2e2e..deefc9a 100644 --- a/src/main/java/sevenUnits/unit/LinearUnit.java +++ b/src/main/java/sevenUnits/unit/LinearUnit.java @@ -19,6 +19,7 @@ package sevenUnits.unit; import java.util.Objects; import sevenUnits.utils.DecimalComparison; +import sevenUnits.utils.NameSymbol; import sevenUnits.utils.ObjectProduct; import sevenUnits.utils.UncertainDouble; -- cgit v1.2.3 From c5b209d48ef38b733e3fd8fd8ef86ae13a552821 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Thu, 10 Mar 2022 06:55:59 -0500 Subject: Simplified toString of common unit classes --- CHANGELOG.org | 1 + src/main/java/sevenUnits/unit/LinearUnit.java | 20 ++++-------- src/main/java/sevenUnits/unit/Unit.java | 36 +++++++++++++++++----- .../java/sevenUnits/utils/NamedObjectProduct.java | 6 +++- src/main/java/sevenUnitsGUI/TabbedView.java | 2 +- 5 files changed, 41 insertions(+), 24 deletions(-) (limited to 'src/main/java/sevenUnits/unit/LinearUnit.java') diff --git a/CHANGELOG.org b/CHANGELOG.org index 681fead..7c53032 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -9,6 +9,7 @@ - Rewrote the GUI code internally using an MVP model to make it easier to maintain and improve - BaseDimension is now Nameable. As a consequence, its name and symbol return Optional instead of String, even though they will always succeed. - The UnitDatabase's units and dimensions are now always named + - The toString method of the common unit classes is now simpler. Alternate toString functions that describe the full unit are provided. - Tweaked the look of the unit and expression conversion sections of the view ** v0.3.2 - [2021-12-02 Thu] *** Added diff --git a/src/main/java/sevenUnits/unit/LinearUnit.java b/src/main/java/sevenUnits/unit/LinearUnit.java index deefc9a..3a28261 100644 --- a/src/main/java/sevenUnits/unit/LinearUnit.java +++ b/src/main/java/sevenUnits/unit/LinearUnit.java @@ -370,6 +370,12 @@ public final class LinearUnit extends Unit { this.getConversionFactor() * multiplier.getConversionFactor()); } + @Override + public String toDefinitionString() { + return Double.toString(this.conversionFactor) + " " + + this.getBase().toString(BaseUnit::getShortName); + } + /** * Returns this unit but to an exponent. * @@ -383,20 +389,6 @@ public final class LinearUnit extends Unit { Math.pow(this.conversionFactor, exponent)); } - /** - * @return a string providing a definition of this unit - * @since 2019-10-21 - */ - @Override - public String toString() { - return this.getPrimaryName().orElse("Unnamed unit") - + (this.getSymbol().isPresent() - ? String.format(" (%s)", this.getSymbol().get()) - : "") - + ", " + Double.toString(this.conversionFactor) + " * " - + this.getBase().toString(u -> u.getSymbol().get()); - } - @Override public LinearUnit withName(final NameSymbol ns) { return valueOf(this.getBase(), this.getConversionFactor(), ns); diff --git a/src/main/java/sevenUnits/unit/Unit.java b/src/main/java/sevenUnits/unit/Unit.java index 9866e9c..b80ccbd 100644 --- a/src/main/java/sevenUnits/unit/Unit.java +++ b/src/main/java/sevenUnits/unit/Unit.java @@ -24,6 +24,7 @@ import java.util.function.DoubleUnaryOperator; import sevenUnits.utils.DecimalComparison; import sevenUnits.utils.NameSymbol; import sevenUnits.utils.Nameable; +import sevenUnits.utils.NamedObjectProduct; import sevenUnits.utils.ObjectProduct; /** @@ -349,16 +350,35 @@ public abstract class Unit implements Nameable { .equals(Math.log10(linear.getConversionFactor()) % 1.0, 0); } + /** + * @return a string representing this unit's definition + * @since 2022-03-10 + */ + public String toDefinitionString() { + if (this.unitBase instanceof NamedObjectProduct) + return "derived from " + + ((NamedObjectProduct) this.unitBase).getName(); + else + return "derived from " + + this.getBase().toString(BaseUnit::getShortName); + } + + /** + * @return a string containing both this unit's name and its definition + * @since 2022-03-10 + */ + public final String toFullString() { + return this.toString() + " (" + this.toDefinitionString() + ")"; + } + @Override public String toString() { - return this.getPrimaryName().orElse("Unnamed unit") - + (this.getSymbol().isPresent() - ? String.format(" (%s)", this.getSymbol().get()) - : "") - + ", derived from " - + this.getBase().toString(u -> u.getSymbol().get()) - + (this.getOtherNames().isEmpty() ? "" - : ", also called " + String.join(", ", this.getOtherNames())); + if (this.nameSymbol.getPrimaryName().isPresent() + && this.nameSymbol.getSymbol().isPresent()) + return this.nameSymbol.getPrimaryName().orElseThrow() + " (" + + this.nameSymbol.getSymbol().orElseThrow() + ")"; + else + return this.getName(); } /** diff --git a/src/main/java/sevenUnits/utils/NamedObjectProduct.java b/src/main/java/sevenUnits/utils/NamedObjectProduct.java index 9c3079c..89b2fad 100644 --- a/src/main/java/sevenUnits/utils/NamedObjectProduct.java +++ b/src/main/java/sevenUnits/utils/NamedObjectProduct.java @@ -40,8 +40,12 @@ public class NamedObjectProduct extends ObjectProduct return this.nameSymbol; } + public final String toDefinitionString() { + return super.toString(); + } + @Override public String toString() { - return this.nameSymbol.toString() + ", " + super.toString(); + return this.nameSymbol.toString(); } } diff --git a/src/main/java/sevenUnitsGUI/TabbedView.java b/src/main/java/sevenUnitsGUI/TabbedView.java index 1d40087..0461cb6 100644 --- a/src/main/java/sevenUnitsGUI/TabbedView.java +++ b/src/main/java/sevenUnitsGUI/TabbedView.java @@ -71,7 +71,7 @@ import sevenUnits.utils.ObjectProduct; */ final class TabbedView implements ExpressionConversionView, UnitConversionView { /** - * A List-like view of a JComboBox's items + * A Set-like view of a JComboBox's items * * @param type of item in list * -- cgit v1.2.3 From 855cdf83b91bd3061662e563db6656408cc24a12 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 16 Apr 2022 17:00:52 -0500 Subject: Implemented the unit & prefix viewers --- CHANGELOG.org | 2 +- src/main/java/sevenUnits/unit/LinearUnit.java | 5 +- src/main/java/sevenUnits/unit/UnitDatabase.java | 4 +- src/main/java/sevenUnits/utils/ObjectProduct.java | 7 +- src/main/java/sevenUnitsGUI/Presenter.java | 98 ++++++++++++++++++++--- src/main/java/sevenUnitsGUI/TabbedView.java | 15 ++-- src/main/java/sevenUnitsGUI/ViewBot.java | 29 ++++--- src/test/java/sevenUnitsGUI/PresenterTest.java | 11 ++- 8 files changed, 133 insertions(+), 38 deletions(-) (limited to 'src/main/java/sevenUnits/unit/LinearUnit.java') diff --git a/CHANGELOG.org b/CHANGELOG.org index 7c53032..61d9333 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -8,7 +8,7 @@ *** Changed - Rewrote the GUI code internally using an MVP model to make it easier to maintain and improve - BaseDimension is now Nameable. As a consequence, its name and symbol return Optional instead of String, even though they will always succeed. - - The UnitDatabase's units and dimensions are now always named + - The UnitDatabase's units, prefixes and dimensions are now always named - The toString method of the common unit classes is now simpler. Alternate toString functions that describe the full unit are provided. - Tweaked the look of the unit and expression conversion sections of the view ** v0.3.2 - [2021-12-02 Thu] diff --git a/src/main/java/sevenUnits/unit/LinearUnit.java b/src/main/java/sevenUnits/unit/LinearUnit.java index 3a28261..103b7f6 100644 --- a/src/main/java/sevenUnits/unit/LinearUnit.java +++ b/src/main/java/sevenUnits/unit/LinearUnit.java @@ -372,8 +372,9 @@ public final class LinearUnit extends Unit { @Override public String toDefinitionString() { - return Double.toString(this.conversionFactor) + " " - + this.getBase().toString(BaseUnit::getShortName); + return Double.toString(this.conversionFactor) + + (this.getBase().equals(ObjectProduct.empty()) ? "" + : " " + this.getBase().toString(BaseUnit::getShortName)); } /** diff --git a/src/main/java/sevenUnits/unit/UnitDatabase.java b/src/main/java/sevenUnits/unit/UnitDatabase.java index 5591d7d..7b02ac7 100644 --- a/src/main/java/sevenUnits/unit/UnitDatabase.java +++ b/src/main/java/sevenUnits/unit/UnitDatabase.java @@ -1458,7 +1458,9 @@ public final class UnitDatabase { System.err.printf("Parsing error on line %d:%n", lineCounter); throw e; } - this.addPrefix(name.substring(0, name.length() - 1), prefix); + final String prefixName = name.substring(0, name.length() - 1); + this.addPrefix(prefixName, + prefix.withName(NameSymbol.ofName(prefixName))); } else { // it's a unit, get the unit final Unit unit; diff --git a/src/main/java/sevenUnits/utils/ObjectProduct.java b/src/main/java/sevenUnits/utils/ObjectProduct.java index 110bdc1..66bb773 100644 --- a/src/main/java/sevenUnits/utils/ObjectProduct.java +++ b/src/main/java/sevenUnits/utils/ObjectProduct.java @@ -257,9 +257,10 @@ public class ObjectProduct implements Nameable { /** * Converts this product to a string using the objects' - * {@link Object#toString()} method. If objects have a long toString - * representation, it is recommended to use {@link #toString(Function)} - * instead to shorten the returned string. + * {@link Object#toString()} method (or {@link Nameable#getShortName} if + * available). If objects have a long toString representation, it is + * recommended to use {@link #toString(Function)} instead to shorten the + * returned string. * *

* {@inheritDoc} diff --git a/src/main/java/sevenUnitsGUI/Presenter.java b/src/main/java/sevenUnitsGUI/Presenter.java index 5c8ce53..981af21 100644 --- a/src/main/java/sevenUnitsGUI/Presenter.java +++ b/src/main/java/sevenUnitsGUI/Presenter.java @@ -33,13 +33,17 @@ import java.util.stream.Collectors; import sevenUnits.ProgramInfo; import sevenUnits.unit.BaseDimension; +import sevenUnits.unit.BaseUnit; import sevenUnits.unit.BritishImperial; +import sevenUnits.unit.LinearUnit; import sevenUnits.unit.LinearUnitValue; import sevenUnits.unit.Metric; import sevenUnits.unit.Unit; import sevenUnits.unit.UnitDatabase; import sevenUnits.unit.UnitPrefix; +import sevenUnits.unit.UnitType; import sevenUnits.unit.UnitValue; +import sevenUnits.utils.Nameable; import sevenUnits.utils.ObjectProduct; import sevenUnits.utils.UncertainDouble; @@ -382,6 +386,21 @@ public final class Presenter { return this.showDuplicateUnits; } + /** + * Gets a name for this dimension using the database + * + * @param dimension dimension to name + * @return name of dimension + * @since 2022-04-16 + */ + final String getDimensionName(ObjectProduct dimension) { + // find this dimension in the database and get its name + // if it isn't there, use the dimension's toString instead + return this.database.dimensionMap().values().stream() + .filter(d -> d.equals(dimension)).findAny().map(Nameable::getName) + .orElse(dimension.toString(Nameable::getName)); + } + /** * @return the rule that is used by this presenter to convert numbers into * strings @@ -402,14 +421,25 @@ public final class Presenter { } /** - * @return true iff the One-Way Conversion feature is available (views that - * show units as a list will have metric units removed from the From - * unit list and imperial/USC units removed from the To unit list) - * - * @since 2022-03-30 + * @return type of unit {@code u} + * @since 2022-04-16 */ - public boolean oneWayConversionEnabled() { - return this.oneWayConversionEnabled; + private final UnitType getUnitType(Unit u) { + // determine if u is an exception + final var primaryName = u.getPrimaryName(); + final var symbol = u.getSymbol(); + final boolean isException = primaryName.isPresent() + && this.metricExceptions.contains(primaryName.orElseThrow()) + || symbol.isPresent() + && this.metricExceptions.contains(symbol.orElseThrow()); + + // determine unit type + if (isException) + return UnitType.SEMI_METRIC; + else if (u.isMetric()) + return UnitType.METRIC; + else + return UnitType.NON_METRIC; } /** @@ -421,6 +451,17 @@ public final class Presenter { */ void loadSettings(Path settingsFile) {} + /** + * @return true iff the One-Way Conversion feature is available (views that + * show units as a list will have metric units removed from the From + * unit list and imperial/USC units removed from the To unit list) + * + * @since 2022-03-30 + */ + public boolean oneWayConversionEnabled() { + return this.oneWayConversionEnabled; + } + /** * Completes creation of the presenter. This part of the initialization * depends on the view's functions, so it cannot be run if the components @@ -434,9 +475,24 @@ public final class Presenter { final UnitConversionView ucview = (UnitConversionView) this.view; ucview.setDimensionNames(this.database.dimensionMap().keySet()); } + + // load units & prefixes into viewers + this.view.setViewableUnitNames( + this.database.unitMapPrefixless(this.showDuplicateUnits).keySet()); + this.view.setViewablePrefixNames(this.database.prefixMap().keySet()); } - void prefixSelected() {} + void prefixSelected() { + final Optional selectedPrefixName = this.view + .getViewedPrefixName(); + final Optional selectedPrefix = selectedPrefixName + .map(name -> this.database.containsPrefixName(name) + ? this.database.getPrefix(name) + : null); + selectedPrefix + .ifPresent(prefix -> this.view.showPrefix(prefix.getNameSymbol(), + String.valueOf(prefix.getMultiplier()))); + } /** * Saves the presenter's settings to the user settings file. @@ -487,13 +543,37 @@ public final class Presenter { this.updateView(); } + /** + * Shows a unit in the unit viewer + * + * @param u unit to show + * @since 2022-04-16 + */ + private final void showUnit(Unit u) { + final var nameSymbol = u.getNameSymbol(); + final boolean isBase = u instanceof BaseUnit + || u instanceof LinearUnit && ((LinearUnit) u).isBase(); + final var definition = isBase ? "(Base unit)" : u.toDefinitionString(); + final var dimensionString = this.getDimensionName(u.getDimension()); + final var unitType = this.getUnitType(u); + this.view.showUnit(nameSymbol, definition, dimensionString, unitType); + } + /** * Runs whenever a unit name is selected in the unit viewer. Gets the * description of a unit and displays it. * * @since 2022-04-10 */ - void unitNameSelected() {} + void unitNameSelected() { + // get selected unit, if it's there and valid + final Optional selectedUnitName = this.view.getViewedUnitName(); + final Optional selectedUnit = selectedUnitName + .map(unitName -> this.database.containsUnitName(unitName) + ? this.database.getUnit(unitName) + : null); + selectedUnit.ifPresent(this::showUnit); + } /** * Updates the view's From and To units, if it has some diff --git a/src/main/java/sevenUnitsGUI/TabbedView.java b/src/main/java/sevenUnitsGUI/TabbedView.java index fd48965..d0eb32f 100644 --- a/src/main/java/sevenUnitsGUI/TabbedView.java +++ b/src/main/java/sevenUnitsGUI/TabbedView.java @@ -578,12 +578,12 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { @Override public Optional getViewedPrefixName() { - throw new UnsupportedOperationException("Not implemented yet"); + return this.prefixNameList.getSelectedValue(); } @Override public Optional getViewedUnitName() { - throw new UnsupportedOperationException("Not implemented yet"); + return this.unitNameList.getSelectedValue(); } @Override @@ -606,12 +606,12 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { @Override public void setViewablePrefixNames(Set prefixNames) { - throw new UnsupportedOperationException("Not implemented yet"); + this.prefixNameList.setItems(prefixNames); } @Override public void setViewableUnitNames(Set unitNames) { - throw new UnsupportedOperationException("Not implemented yet"); + this.unitNameList.setItems(unitNames); } @Override @@ -628,13 +628,16 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { @Override public void showPrefix(NameSymbol name, String multiplierString) { - throw new UnsupportedOperationException("Not implemented yet"); + this.prefixTextBox.setText( + String.format("%s%nMultiplier: %s", name, multiplierString)); } @Override public void showUnit(NameSymbol name, String definition, String dimensionName, UnitType type) { - throw new UnsupportedOperationException("Not implemented yet"); + this.unitTextBox.setText( + String.format("%s%nDefinition: %s%nDimension: %s%nType: %s", name, + definition, dimensionName, type)); } @Override diff --git a/src/main/java/sevenUnitsGUI/ViewBot.java b/src/main/java/sevenUnitsGUI/ViewBot.java index 988d1bc..dd9869d 100644 --- a/src/main/java/sevenUnitsGUI/ViewBot.java +++ b/src/main/java/sevenUnitsGUI/ViewBot.java @@ -216,6 +216,11 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { /** The units available in the To selection */ private Set toUnits; + /** The selected unit in the unit viewer */ + private Optional unitViewerSelection; + /** The selected unit in the prefix viewer */ + private Optional prefixViewerSelection; + /** Saved outputs of all unit conversions */ private final List unitConversions; /** Saved outputs of all unit expressions */ @@ -314,12 +319,12 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { @Override public Optional getViewedPrefixName() { - throw new UnsupportedOperationException("Not implemented yet"); + return this.prefixViewerSelection; } @Override public Optional getViewedUnitName() { - throw new UnsupportedOperationException("Not implemented yet"); + return this.unitViewerSelection; } /** @@ -423,26 +428,24 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { @Override public void setViewablePrefixNames(Set prefixNames) { - throw new UnsupportedOperationException("Not implemented yet"); + // do nothing, ViewBot supports selecting any prefix } @Override public void setViewableUnitNames(Set unitNames) { - throw new UnsupportedOperationException("Not implemented yet"); + // do nothing, ViewBot supports selecting any unit } - public void setViewedPrefixName( - @SuppressWarnings("unused") Optional viewedPrefixName) { - throw new UnsupportedOperationException("Not implemented yet"); + public void setViewedPrefixName(Optional viewedPrefixName) { + this.prefixViewerSelection = viewedPrefixName; } public void setViewedPrefixName(String viewedPrefixName) { this.setViewedPrefixName(Optional.of(viewedPrefixName)); } - public void setViewedUnitName( - @SuppressWarnings("unused") Optional viewedUnitName) { - throw new UnsupportedOperationException("Not implemented yet"); + public void setViewedUnitName(Optional viewedUnitName) { + this.unitViewerSelection = viewedUnitName; } public void setViewedUnitName(String viewedUnitName) { @@ -462,13 +465,15 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { @Override public void showPrefix(NameSymbol name, String multiplierString) { - throw new UnsupportedOperationException("Not implemented yet"); + this.prefixViewingRecords + .add(new PrefixViewingRecord(name, multiplierString)); } @Override public void showUnit(NameSymbol name, String definition, String dimensionName, UnitType type) { - throw new UnsupportedOperationException("Not implemented yet"); + this.unitViewingRecords + .add(new UnitViewingRecord(name, definition, dimensionName, type)); } @Override diff --git a/src/test/java/sevenUnitsGUI/PresenterTest.java b/src/test/java/sevenUnitsGUI/PresenterTest.java index 85ebe09..8446a90 100644 --- a/src/test/java/sevenUnitsGUI/PresenterTest.java +++ b/src/test/java/sevenUnitsGUI/PresenterTest.java @@ -212,7 +212,8 @@ public final class PresenterTest { presenter.prefixSelected(); // just in case // get correct values - final var expectedNameSymbol = Metric.KILO.getNameSymbol(); + final var expectedNameSymbol = presenter.database.getPrefix("kilo") + .getNameSymbol(); final var expectedMultiplierString = String .valueOf(Metric.KILO.getMultiplier()); @@ -298,9 +299,11 @@ public final class PresenterTest { // automatically // get correct values - final var expectedNameSymbol = Metric.METRE.getNameSymbol(); - final var expectedDefinition = Metric.METRE.toDefinitionString(); - final var expectedDimensionName = Metric.METRE.getDimension().getName(); + final var expectedNameSymbol = presenter.database.getUnit("metre") + .getNameSymbol(); + final var expectedDefinition = "(Base unit)"; + final var expectedDimensionName = presenter + .getDimensionName(Metric.METRE.getDimension()); final var expectedUnitType = UnitType.METRIC; // test for correctness -- cgit v1.2.3