From 8ff06e8e5661645c00656c40d15c8d13db665b57 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Fri, 25 Jan 2019 19:09:47 -0500 Subject: Added code from the previous implementation of the Unit Converter It includes: - a units database to store units - unit prefix classes - a unit converter GUI that accepts some unit math NOTE: A lot of this code will be edited in the near future. --- .../converterGUI/DelegateListModel.java | 228 ++++++++ .../converterGUI/FilterComparator.java | 72 +++ src/unitConverter/converterGUI/GridBagBuilder.java | 432 +++++++++++++++ .../converterGUI/UnitConverterGUI.java | 586 +++++++++++++++++++++ src/unitConverter/converterGUI/package-info.java | 23 + 5 files changed, 1341 insertions(+) create mode 100755 src/unitConverter/converterGUI/DelegateListModel.java create mode 100755 src/unitConverter/converterGUI/FilterComparator.java create mode 100755 src/unitConverter/converterGUI/GridBagBuilder.java create mode 100755 src/unitConverter/converterGUI/UnitConverterGUI.java create mode 100644 src/unitConverter/converterGUI/package-info.java (limited to 'src/unitConverter/converterGUI') diff --git a/src/unitConverter/converterGUI/DelegateListModel.java b/src/unitConverter/converterGUI/DelegateListModel.java new file mode 100755 index 0000000..42bc0dc --- /dev/null +++ b/src/unitConverter/converterGUI/DelegateListModel.java @@ -0,0 +1,228 @@ +/** + * Copyright (C) 2018 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package unitConverter.converterGUI; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +import javax.swing.AbstractListModel; + +/** + * A list model that delegates to a list. + *

+ * It is recommended to use the delegate methods in DelegateListModel instead of the delegated list's methods because + * the delegate methods handle updating the list. + *

+ * + * @author Adrien Hopkins + * @since 2019-01-14 + */ +final class DelegateListModel extends AbstractListModel implements List { + /** + * @since 2019-01-14 + */ + private static final long serialVersionUID = 8985494428224810045L; + + /** + * The list that this model is a delegate to. + * + * @since 2019-01-14 + */ + private final List delegate; + + /** + * Creates the {@code DelegateListModel}. + * + * @param delegate + * list to delegate + * @since 2019-01-14 + */ + public DelegateListModel(final List delegate) { + this.delegate = delegate; + } + + @Override + public boolean add(final E element) { + final int index = this.delegate.size(); + final boolean success = this.delegate.add(element); + this.fireIntervalAdded(this, index, index); + return success; + } + + @Override + public void add(final int index, final E element) { + this.delegate.add(index, element); + this.fireIntervalAdded(this, index, index); + } + + @Override + public boolean addAll(final Collection c) { + boolean changed = false; + for (final E e : c) { + if (this.add(e)) { + changed = true; + } + } + return changed; + } + + @Override + public boolean addAll(final int index, final Collection c) { + for (final E e : c) { + this.add(index, e); + } + return !c.isEmpty(); // Since this is a list, it will always change if c has elements. + } + + @Override + public void clear() { + final int oldSize = this.delegate.size(); + this.delegate.clear(); + if (oldSize >= 1) { + this.fireIntervalRemoved(this, 0, oldSize - 1); + } + } + + @Override + public boolean contains(final Object elem) { + return this.delegate.contains(elem); + } + + @Override + public boolean containsAll(final Collection c) { + for (final Object e : c) { + if (!c.contains(e)) + return false; + } + return true; + } + + @Override + public E get(final int index) { + return this.delegate.get(index); + } + + @Override + public E getElementAt(final int index) { + return this.delegate.get(index); + } + + @Override + public int getSize() { + return this.delegate.size(); + } + + @Override + public int indexOf(final Object elem) { + return this.delegate.indexOf(elem); + } + + @Override + public boolean isEmpty() { + return this.delegate.isEmpty(); + } + + @Override + public Iterator iterator() { + return this.delegate.iterator(); + } + + @Override + public int lastIndexOf(final Object elem) { + return this.delegate.lastIndexOf(elem); + } + + @Override + public ListIterator listIterator() { + return this.delegate.listIterator(); + } + + @Override + public ListIterator listIterator(final int index) { + return this.delegate.listIterator(index); + } + + @Override + public E remove(final int index) { + final E returnValue = this.delegate.get(index); + this.delegate.remove(index); + this.fireIntervalRemoved(this, index, index); + return returnValue; + } + + @Override + public boolean remove(final Object o) { + final int index = this.delegate.indexOf(o); + final boolean returnValue = this.delegate.remove(o); + this.fireIntervalRemoved(this, index, index); + return returnValue; + } + + @Override + public boolean removeAll(final Collection c) { + boolean changed = false; + for (final Object e : c) { + if (this.remove(e)) { + changed = true; + } + } + return changed; + } + + @Override + public boolean retainAll(final Collection c) { + final int oldSize = this.size(); + final boolean returnValue = this.delegate.retainAll(c); + this.fireIntervalRemoved(this, this.size(), oldSize - 1); + return returnValue; + } + + @Override + public E set(final int index, final E element) { + final E returnValue = this.delegate.get(index); + this.delegate.set(index, element); + this.fireContentsChanged(this, index, index); + return returnValue; + } + + @Override + public int size() { + return this.delegate.size(); + } + + @Override + public List subList(final int fromIndex, final int toIndex) { + return this.delegate.subList(fromIndex, toIndex); + } + + @Override + public Object[] toArray() { + return this.delegate.toArray(); + } + + @Override + public T[] toArray(final T[] a) { + return this.delegate.toArray(a); + } + + @Override + public String toString() { + return this.delegate.toString(); + } +} diff --git a/src/unitConverter/converterGUI/FilterComparator.java b/src/unitConverter/converterGUI/FilterComparator.java new file mode 100755 index 0000000..ab25f2f --- /dev/null +++ b/src/unitConverter/converterGUI/FilterComparator.java @@ -0,0 +1,72 @@ +/** + * Copyright (C) 2018 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package unitConverter.converterGUI; + +import java.util.Comparator; + +/** + * @author Adrien Hopkins + * @since 2019-01-15 + */ +public final class FilterComparator implements Comparator { + + private final String filter; + private final Comparator comparator; + + /** + * Creates the {@code FilterComparator}. + * + * @param filter + * @since 2019-01-15 + */ + public FilterComparator(final String filter) { + this(filter, null); + } + + /** + * Creates the {@code FilterComparator}. + * + * @param filter + * @param comparator + * @since 2019-01-15 + */ + public FilterComparator(final String filter, final Comparator comparator) { + this.filter = filter; + this.comparator = comparator; + } + + @Override + public int compare(final String arg0, final String arg1) { + // elements that start with the filter always go first + if (arg0.startsWith(this.filter) && !arg1.startsWith(this.filter)) + return -1; + else if (!arg0.startsWith(this.filter) && arg1.startsWith(this.filter)) + return 1; + + // elements that contain the filter but don't start with them go next + if (arg0.contains(this.filter) && !arg1.contains(this.filter)) + return -1; + else if (!arg0.contains(this.filter) && !arg1.contains(this.filter)) + return 1; + + // other elements go last + if (this.comparator == null) + return arg0.compareTo(arg1); + else + return this.comparator.compare(arg0, arg1); + } +} diff --git a/src/unitConverter/converterGUI/GridBagBuilder.java b/src/unitConverter/converterGUI/GridBagBuilder.java new file mode 100755 index 0000000..7a0615a --- /dev/null +++ b/src/unitConverter/converterGUI/GridBagBuilder.java @@ -0,0 +1,432 @@ +/** + * Copyright (C) 2018 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package unitConverter.converterGUI; + +import java.awt.GridBagConstraints; +import java.awt.Insets; + +/** + * @author Adrien Hopkins + * @since 2018-11-30 + */ +final class GridBagBuilder { + /** + * Specifies the cell containing the leading edge of the component's display area, where the first cell in a row has + * gridx=0. The leading edge of a component's display area is its left edge for a horizontal, + * left-to-right container and its right edge for a horizontal, right-to-left container. The value + * RELATIVE specifies that the component be placed immediately following the component that was added + * to the container just before this component was added. + *

+ * The default value is RELATIVE. gridx should be a non-negative value. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#gridy + * @see java.awt.ComponentOrientation + */ + private final int gridx; + + /** + * Specifies the cell at the top of the component's display area, where the topmost cell has gridy=0. + * The value RELATIVE specifies that the component be placed just below the component that was added to + * the container just before this component was added. + *

+ * The default value is RELATIVE. gridy should be a non-negative value. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#gridx + */ + private final int gridy; + + /** + * Specifies the number of cells in a row for the component's display area. + *

+ * Use REMAINDER to specify that the component's display area will be from gridx to the + * last cell in the row. Use RELATIVE to specify that the component's display area will be from + * gridx to the next to the last one in its row. + *

+ * gridwidth should be non-negative and the default value is 1. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#gridheight + */ + private final int gridwidth; + + /** + * Specifies the number of cells in a column for the component's display area. + *

+ * Use REMAINDER to specify that the component's display area will be from gridy to the + * last cell in the column. Use RELATIVE to specify that the component's display area will be from + * gridy to the next to the last one in its column. + *

+ * gridheight should be a non-negative value and the default value is 1. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#gridwidth + */ + private final int gridheight; + + /** + * Specifies how to distribute extra horizontal space. + *

+ * The grid bag layout manager calculates the weight of a column to be the maximum weightx of all the + * components in a column. If the resulting layout is smaller horizontally than the area it needs to fill, the extra + * space is distributed to each column in proportion to its weight. A column that has a weight of zero receives no + * extra space. + *

+ * If all the weights are zero, all the extra space appears between the grids of the cell and the left and right + * edges. + *

+ * The default value of this field is 0. weightx should be a non-negative value. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#weighty + */ + private double weightx; + + /** + * Specifies how to distribute extra vertical space. + *

+ * The grid bag layout manager calculates the weight of a row to be the maximum weighty of all the + * components in a row. If the resulting layout is smaller vertically than the area it needs to fill, the extra + * space is distributed to each row in proportion to its weight. A row that has a weight of zero receives no extra + * space. + *

+ * If all the weights are zero, all the extra space appears between the grids of the cell and the top and bottom + * edges. + *

+ * The default value of this field is 0. weighty should be a non-negative value. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#weightx + */ + private double weighty; + + /** + * This field is used when the component is smaller than its display area. It determines where, within the display + * area, to place the component. + *

+ * There are three kinds of possible values: orientation relative, baseline relative and absolute. Orientation + * relative values are interpreted relative to the container's component orientation property, baseline relative + * values are interpreted relative to the baseline and absolute values are not. The absolute values are: + * CENTER, NORTH, NORTHEAST, EAST, SOUTHEAST, + * SOUTH, SOUTHWEST, WEST, and NORTHWEST. The orientation + * relative values are: PAGE_START, PAGE_END, LINE_START, + * LINE_END, FIRST_LINE_START, FIRST_LINE_END, LAST_LINE_START + * and LAST_LINE_END. The baseline relative values are: BASELINE, + * BASELINE_LEADING, BASELINE_TRAILING, ABOVE_BASELINE, + * ABOVE_BASELINE_LEADING, ABOVE_BASELINE_TRAILING, BELOW_BASELINE, + * BELOW_BASELINE_LEADING, and BELOW_BASELINE_TRAILING. The default value is + * CENTER. + * + * @serial + * @see #clone() + * @see java.awt.ComponentOrientation + */ + private int anchor; + + /** + * This field is used when the component's display area is larger than the component's requested size. It determines + * whether to resize the component, and if so, how. + *

+ * The following values are valid for fill: + * + *

    + *
  • NONE: Do not resize the component. + *
  • HORIZONTAL: Make the component wide enough to fill its display area horizontally, but do not + * change its height. + *
  • VERTICAL: Make the component tall enough to fill its display area vertically, but do not change + * its width. + *
  • BOTH: Make the component fill its display area entirely. + *
+ *

+ * The default value is NONE. + * + * @serial + * @see #clone() + */ + private int fill; + + /** + * This field specifies the external padding of the component, the minimum amount of space between the component and + * the edges of its display area. + *

+ * The default value is new Insets(0, 0, 0, 0). + * + * @serial + * @see #clone() + */ + private Insets insets; + + /** + * This field specifies the internal padding of the component, how much space to add to the minimum width of the + * component. The width of the component is at least its minimum width plus ipadx pixels. + *

+ * The default value is 0. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#ipady + */ + private int ipadx; + + /** + * This field specifies the internal padding, that is, how much space to add to the minimum height of the component. + * The height of the component is at least its minimum height plus ipady pixels. + *

+ * The default value is 0. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#ipadx + */ + private int ipady; + + /** + * @param gridx + * x position + * @param gridy + * y position + * @since 2018-11-30 + */ + public GridBagBuilder(final int gridx, final int gridy) { + this(gridx, gridy, 1, 1); + } + + /** + * @param gridx + * x position + * @param gridy + * y position + * @param gridwidth + * number of cells occupied horizontally + * @param gridheight + * number of cells occupied vertically + * @since 2018-11-30 + */ + public GridBagBuilder(final int gridx, final int gridy, final int gridwidth, final int gridheight) { + this(gridx, gridy, gridwidth, gridheight, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, + new Insets(0, 0, 0, 0), 0, 0); + } + + /** + * @param gridx + * x position + * @param gridy + * y position + * @param gridwidth + * number of cells occupied horizontally + * @param gridheight + * number of cells occupied vertically + * @param weightx + * @param weighty + * @param anchor + * @param fill + * @param insets + * @param ipadx + * @param ipady + * @since 2018-11-30 + */ + private GridBagBuilder(final int gridx, final int gridy, final int gridwidth, final int gridheight, + final double weightx, final double weighty, final int anchor, final int fill, final Insets insets, + final int ipadx, final int ipady) { + super(); + this.gridx = gridx; + this.gridy = gridy; + this.gridwidth = gridwidth; + this.gridheight = gridheight; + this.weightx = weightx; + this.weighty = weighty; + this.anchor = anchor; + this.fill = fill; + this.insets = (Insets) insets.clone(); + this.ipadx = ipadx; + this.ipady = ipady; + } + + /** + * @return {@code GridBagConstraints} created by this builder + * @since 2018-11-30 + */ + public GridBagConstraints build() { + return new GridBagConstraints(this.gridx, this.gridy, this.gridwidth, this.gridheight, this.weightx, + this.weighty, this.anchor, this.fill, this.insets, this.ipadx, this.ipady); + } + + /** + * @return anchor + * @since 2018-11-30 + */ + public int getAnchor() { + return this.anchor; + } + + /** + * @return fill + * @since 2018-11-30 + */ + public int getFill() { + return this.fill; + } + + /** + * @return gridheight + * @since 2018-11-30 + */ + public int getGridheight() { + return this.gridheight; + } + + /** + * @return gridwidth + * @since 2018-11-30 + */ + public int getGridwidth() { + return this.gridwidth; + } + + /** + * @return gridx + * @since 2018-11-30 + */ + public int getGridx() { + return this.gridx; + } + + /** + * @return gridy + * @since 2018-11-30 + */ + public int getGridy() { + return this.gridy; + } + + /** + * @return insets + * @since 2018-11-30 + */ + public Insets getInsets() { + return this.insets; + } + + /** + * @return ipadx + * @since 2018-11-30 + */ + public int getIpadx() { + return this.ipadx; + } + + /** + * @return ipady + * @since 2018-11-30 + */ + public int getIpady() { + return this.ipady; + } + + /** + * @return weightx + * @since 2018-11-30 + */ + public double getWeightx() { + return this.weightx; + } + + /** + * @return weighty + * @since 2018-11-30 + */ + public double getWeighty() { + return this.weighty; + } + + /** + * @param anchor + * anchor to set + * @since 2018-11-30 + */ + public GridBagBuilder setAnchor(final int anchor) { + this.anchor = anchor; + return this; + } + + /** + * @param fill + * fill to set + * @since 2018-11-30 + */ + public GridBagBuilder setFill(final int fill) { + this.fill = fill; + return this; + } + + /** + * @param insets + * insets to set + * @since 2018-11-30 + */ + public GridBagBuilder setInsets(final Insets insets) { + this.insets = insets; + return this; + } + + /** + * @param ipadx + * ipadx to set + * @since 2018-11-30 + */ + public GridBagBuilder setIpadx(final int ipadx) { + this.ipadx = ipadx; + return this; + } + + /** + * @param ipady + * ipady to set + * @since 2018-11-30 + */ + public GridBagBuilder setIpady(final int ipady) { + this.ipady = ipady; + return this; + } + + /** + * @param weightx + * weightx to set + * @since 2018-11-30 + */ + public GridBagBuilder setWeightx(final double weightx) { + this.weightx = weightx; + return this; + } + + /** + * @param weighty + * weighty to set + * @since 2018-11-30 + */ + public GridBagBuilder setWeighty(final double weighty) { + this.weighty = weighty; + return this; + } +} diff --git a/src/unitConverter/converterGUI/UnitConverterGUI.java b/src/unitConverter/converterGUI/UnitConverterGUI.java new file mode 100755 index 0000000..0068312 --- /dev/null +++ b/src/unitConverter/converterGUI/UnitConverterGUI.java @@ -0,0 +1,586 @@ +/** + * Copyright (C) 2018 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package unitConverter.converterGUI; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.io.File; +import java.math.BigDecimal; +import java.math.MathContext; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.function.Predicate; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSlider; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; + +import unitConverter.UnitsDatabase; +import unitConverter.dimension.StandardDimensions; +import unitConverter.dimension.UnitDimension; +import unitConverter.unit.AbstractUnit; +import unitConverter.unit.NonlinearUnits; +import unitConverter.unit.SI; +import unitConverter.unit.Unit; +import unitConverter.unit.UnitPrefix; + +/** + * @author Adrien Hopkins + * @since 2018-12-27 + */ +final class UnitConverterGUI { + private static class Presenter { + /** The presenter's associated view. */ + private final View view; + + /** The units known by the program. */ + private final UnitsDatabase units; + + /** The names of all of the units */ + private final List unitNames; + + /** The names of all of the units, but filtered */ + private final DelegateListModel unitNamesFiltered; + + /** The names of all of the prefixes */ + private final List prefixNames; + + /** The names of all of the prefixes */ + private final DelegateListModel prefixNamesFiltered; + + private final Comparator prefixNameComparator; + + private int significantFigures = 6; + + /** + * Creates the presenter. + * + * @param view + * presenter's associated view + * @since 2018-12-27 + */ + Presenter(final View view) { + this.view = view; + + // load initial units + this.units = new UnitsDatabase(); + this.units.addUnit("metre", SI.METRE); + this.units.addUnit("kilogram", SI.KILOGRAM); + this.units.addUnit("gram", SI.KILOGRAM.dividedBy(1000)); + this.units.addUnit("second", SI.SECOND); + this.units.addUnit("ampere", SI.AMPERE); + this.units.addUnit("kelvin", SI.KELVIN); + this.units.addUnit("mole", SI.MOLE); + this.units.addUnit("candela", SI.CANDELA); + this.units.addUnit("bit", SI.SI.getBaseUnit(StandardDimensions.INFORMATION)); + this.units.addUnit("unit", SI.SI.getBaseUnit(UnitDimension.EMPTY)); + // nonlinear units - must be loaded manually + this.units.addUnit("tempCelsius", NonlinearUnits.CELSIUS); + this.units.addUnit("tempFahrenheit", NonlinearUnits.FAHRENHEIT); + + this.units.addAllFromFile(new File("unitsfile.txt")); + + // 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 + this.prefixNameComparator = (o1, o2) -> { + if (!Presenter.this.units.containsPrefixName(o1)) + return -1; + else if (!Presenter.this.units.containsPrefixName(o2)) + return 1; + + final UnitPrefix p1 = Presenter.this.units.getPrefix(o1); + final UnitPrefix p2 = Presenter.this.units.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.units.prefixlessUnitNameSet()); + this.unitNames.sort(null); // sorts it using Comparable + + this.unitNamesFiltered = new DelegateListModel<>(new ArrayList<>(this.units.prefixlessUnitNameSet())); + this.unitNamesFiltered.sort(null); // sorts it using Comparable + + this.prefixNames = new ArrayList<>(this.units.prefixNameSet()); + this.prefixNames.sort(this.prefixNameComparator); // sorts it using my comparator + + this.prefixNamesFiltered = new DelegateListModel<>(new ArrayList<>(this.units.prefixNameSet())); + this.prefixNamesFiltered.sort(this.prefixNameComparator); // sorts it using my comparator + + System.out.printf("Successfully loaded %d units (%d base units)", AbstractUnit.getUnitCount(), + AbstractUnit.getBaseUnitCount()); + } + + public final void convert() { + final String fromUnitString = this.view.getFromText(); + final String toUnitString = this.view.getToText(); + + // try to parse from + final Unit from; + try { + from = this.units.getUnitFromExpression(fromUnitString); + } catch (final IllegalArgumentException 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 { + to = this.units.getUnitFromExpression(toUnitString); + } catch (final IllegalArgumentException e) { + this.view.showErrorDialog("Parse Error", "Could not recognize text in To entry: " + e.getMessage()); + return; + } + + // if I can't convert, leave + if (!from.canConvertTo(to)) { + this.view.showErrorDialog("Conversion Error", + String.format("Cannot convert between %s and %s", fromUnitString, toUnitString)); + return; + } + + value = to.convertFromBase(from.convertToBase(1)); + + // round value + final BigDecimal bigValue = new BigDecimal(value).round(new MathContext(this.significantFigures)); + String output = bigValue.toString(); + + // remove trailing zeroes + if (output.contains(".")) { + while (output.endsWith("0")) { + output = output.substring(0, output.length() - 1); + } + if (output.endsWith(".")) { + output = output.substring(0, output.length() - 1); + } + } + + this.view.setOutputText(String.format("%s = %s %s", fromUnitString, output, toUnitString)); + } + + /** + * Filters the filtered model for units + * + * @param filter + * filter to use + * @since 2019-01-15 + */ + private final void filterFilteredPrefixModel(final Predicate filter) { + this.prefixNamesFiltered.clear(); + for (final String prefixName : this.prefixNames) { + if (filter.test(prefixName)) { + this.prefixNamesFiltered.add(prefixName); + } + } + } + + /** + * Filters the filtered model for units + * + * @param filter + * filter to use + * @since 2019-01-15 + */ + private final void filterFilteredUnitModel(final Predicate filter) { + this.unitNamesFiltered.clear(); + for (final String unitName : this.unitNames) { + if (filter.test(unitName)) { + this.unitNamesFiltered.add(unitName); + } + } + } + + /** + * @return a list model of all of the unit keys + * @since 2019-01-14 + */ + public final ListModel keyListModel() { + return this.unitNamesFiltered; + } + + public final void prefixFilterUpdated() { + final String filter = this.view.getPrefixFilterText(); + if (filter.equals("")) { + this.filterFilteredPrefixModel(t -> true); + } else { + this.filterFilteredPrefixModel(t -> t.contains(filter)); + } + this.prefixNamesFiltered.sort(new FilterComparator(filter)); + } + + /** + * @return a list model of all fo the prefix names + * @since 2019-01-15 + */ + public final ListModel prefixNameListModel() { + return this.prefixNamesFiltered; + } + + public final void prefixSelected() { + final int index = this.view.getPrefixListSelection(); + if (index == -1) + return; + else { + final String prefixName = this.prefixNamesFiltered.get(index); + final UnitPrefix prefix = this.units.getPrefix(prefixName); + + this.view.setPrefixTextBoxText(String.format("%s%nMultiplier: %s", prefixName, prefix.getMultiplier())); + } + } + + /** + * @param significantFigures + * new value of significantFigures + * @since 2019-01-15 + */ + public final void setSignificantFigures(final int significantFigures) { + this.significantFigures = significantFigures; + } + + public final void unitFilterUpdated() { + final String filter = this.view.getUnitFilterText(); + if (filter.equals("")) { + this.filterFilteredUnitModel(t -> true); + } else { + this.filterFilteredUnitModel(t -> t.contains(filter)); + } + this.unitNamesFiltered.sort(new FilterComparator(filter)); + } + + /** + * + * @since 2019-01-15 + */ + public void unitNameSelected() { + final int index = this.view.getUnitListSelection(); + if (index == -1) + return; + else { + final String unitName = this.unitNamesFiltered.get(index); + final Unit unit = this.units.getUnit(unitName); + + this.view.setUnitTextBoxText(unit.toString()); + } + } + } + + private static class View { + /** The view's frame. */ + private final JFrame frame; + /** The view's associated presenter. */ + private final Presenter presenter; + + private final JList unitNameList; + private final JList prefixNameList; + private final JTextField unitFilterEntry; + private final JTextArea unitTextBox; + private final JTextField prefixFilterEntry; + private final JTextArea prefixTextBox; + private final JTextField fromEntry; + private final JTextField toEntry; + private final JTextArea output; + + /** + * Creates the {@code View}. + * + * @since 2019-01-14 + */ + public View() { + this.presenter = new Presenter(this); + this.frame = new JFrame("Unit Converter"); + this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + this.unitNameList = new JList<>(this.presenter.keyListModel()); + this.prefixNameList = new JList<>(this.presenter.prefixNameListModel()); + this.unitFilterEntry = new JTextField(); + this.unitTextBox = new JTextArea(); + this.prefixFilterEntry = new JTextField(); + this.prefixTextBox = new JTextArea(); + this.fromEntry = new JTextField(); + this.toEntry = new JTextField(); + this.output = new JTextArea(2, 32); + + this.initComponents(); + + this.frame.pack(); + } + + public String getFromText() { + return this.fromEntry.getText(); + } + + /** + * @return text in prefix filter + * @since 2019-01-15 + */ + public String getPrefixFilterText() { + return this.prefixFilterEntry.getText(); + } + + /** + * @return index of selected prefix + * @since 2019-01-15 + */ + public int getPrefixListSelection() { + return this.prefixNameList.getSelectedIndex(); + } + + public String getToText() { + return this.toEntry.getText(); + } + + /** + * @return text in unit filter + * @see javax.swing.text.JTextComponent#getText() + */ + public String getUnitFilterText() { + return this.unitFilterEntry.getText(); + } + + /** + * @return index of selected unit + * @since 2019-01-15 + */ + public int getUnitListSelection() { + return this.unitNameList.getSelectedIndex(); + } + + /** + * Starts up the application. + * + * @since 2018-12-27 + */ + public final void init() { + this.frame.setVisible(true); + } + + /** + * Initializes the view's components. + * + * @since 2018-12-27 + */ + private final void initComponents() { + final JPanel masterPanel = new JPanel(); + this.frame.add(masterPanel); + + masterPanel.setLayout(new BorderLayout()); + + { // pane with all of the tabs + final JTabbedPane masterPane = new JTabbedPane(); + masterPanel.add(masterPane, BorderLayout.CENTER); + + { // panel for unit conversion + final JPanel convertPanel = new JPanel(); + masterPane.addTab("Convert Units", convertPanel); + + convertPanel.setLayout(new GridLayout(5, 1)); + + { // panel for units to convert from + final JPanel fromPanel = new JPanel(); + convertPanel.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(); + convertPanel.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!"); + convertPanel.add(convertButton); + + convertButton.addActionListener(e -> this.presenter.convert()); + } + + { // output of conversion + final JPanel outputPanel = new JPanel(); + convertPanel.add(outputPanel); + + outputPanel.setBorder(BorderFactory.createTitledBorder("Output")); + outputPanel.setLayout(new GridLayout(1, 1)); + + { // output + outputPanel.add(this.output); + this.output.setEditable(false); + } + } + + { + final JPanel sigDigPanel = new JPanel(); + convertPanel.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(); + masterPane.addTab("Unit Viewer", unitLookupPanel); + + unitLookupPanel.setLayout(new GridLayout()); + + { // panel for listing and searching + final JPanel listPanel = new JPanel(); + unitLookupPanel.add(listPanel); + + listPanel.setLayout(new BorderLayout()); + + { + listPanel.add(this.unitFilterEntry, BorderLayout.PAGE_START); + this.unitFilterEntry.addCaretListener(e -> this.presenter.unitFilterUpdated()); + } + + { // a list of units + listPanel.add(new JScrollPane(this.unitNameList), BorderLayout.CENTER); + this.unitNameList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // temp + this.unitNameList.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(); + masterPane.addTab("Prefix Viewer", prefixLookupPanel); + + prefixLookupPanel.setLayout(new GridLayout(1, 2)); + + { + final JPanel prefixListPanel = new JPanel(); + prefixLookupPanel.add(prefixListPanel); + + prefixListPanel.setLayout(new BorderLayout()); + + { + prefixListPanel.add(this.prefixFilterEntry, BorderLayout.PAGE_START); + this.prefixFilterEntry.addCaretListener(e -> this.presenter.prefixFilterUpdated()); + } + + { // a list of prefixes + prefixListPanel.add(new JScrollPane(this.prefixNameList), BorderLayout.CENTER); + this.prefixNameList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // temp + this.prefixNameList.addListSelectionListener(e -> { + this.presenter.prefixSelected(); + }); + } + } + + { // the text box for prefix's toString + prefixLookupPanel.add(this.prefixTextBox); + this.unitTextBox.setEditable(false); + } + } + } + } + + public void setOutputText(final String text) { + this.output.setText(text); + } + + /** + * Sets the text of the prefix text box. + * + * @param text + * text to set + * @since 2019-01-15 + */ + public void setPrefixTextBoxText(final String text) { + this.prefixTextBox.setText(text); + } + + /** + * Sets the text of the unit text box. + * + * @param t + * text to set + * @see javax.swing.text.JTextComponent#setText(java.lang.String) + */ + public void setUnitTextBoxText(final String t) { + this.unitTextBox.setText(t); + } + + /** + * Shows an error dialog. + * + * @param title + * title of dialog + * @param message + * message in dialog + * @since 2019-01-14 + */ + public void showErrorDialog(final String title, final String message) { + JOptionPane.showMessageDialog(this.frame, message, title, JOptionPane.ERROR_MESSAGE); + } + } + + public static void main(final String[] args) { + new View().init(); + } +} diff --git a/src/unitConverter/converterGUI/package-info.java b/src/unitConverter/converterGUI/package-info.java new file mode 100644 index 0000000..9f7fa57 --- /dev/null +++ b/src/unitConverter/converterGUI/package-info.java @@ -0,0 +1,23 @@ +/** + * Copyright (C) 2019 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +/** + * All classes that work to convert units. + * + * @author Adrien Hopkins + * @since 2019-01-25 + */ +package unitConverter.converterGUI; \ No newline at end of file -- cgit v1.2.3 From da01eec8c59477da649767f3ed72c98fe1bbb301 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 26 Jan 2019 14:07:29 -0500 Subject: Added more @since tags, edited some documentation There is now a @since tag for version as well as date. --- src/unitConverter/UnitsDatabase.java | 35 +++++--- .../converterGUI/DelegateListModel.java | 4 + .../converterGUI/FilterComparator.java | 25 +++++- src/unitConverter/converterGUI/GridBagBuilder.java | 47 +++++++++++ .../converterGUI/UnitConverterGUI.java | 95 ++++++++++++++++++++-- src/unitConverter/dimension/BaseDimension.java | 5 +- .../dimension/OtherBaseDimension.java | 2 + src/unitConverter/dimension/SIBaseDimension.java | 2 + .../dimension/StandardDimensions.java | 1 + src/unitConverter/dimension/UnitDimension.java | 11 +++ src/unitConverter/dimension/UnitDimensionTest.java | 21 +++++ src/unitConverter/unit/AbstractUnit.java | 14 +++- src/unitConverter/unit/BaseUnit.java | 11 ++- src/unitConverter/unit/DefaultUnitPrefix.java | 3 + src/unitConverter/unit/LinearUnit.java | 14 +++- src/unitConverter/unit/NonlinearUnits.java | 1 + src/unitConverter/unit/SI.java | 2 + src/unitConverter/unit/SIPrefix.java | 5 ++ src/unitConverter/unit/Unit.java | 7 ++ src/unitConverter/unit/UnitPrefix.java | 2 + src/unitConverter/unit/UnitSystem.java | 5 +- src/unitConverter/unit/UnitTest.java | 2 +- 22 files changed, 288 insertions(+), 26 deletions(-) (limited to 'src/unitConverter/converterGUI') diff --git a/src/unitConverter/UnitsDatabase.java b/src/unitConverter/UnitsDatabase.java index d479917..4816db1 100755 --- a/src/unitConverter/UnitsDatabase.java +++ b/src/unitConverter/UnitsDatabase.java @@ -41,12 +41,14 @@ import unitConverter.unit.UnitPrefix; * * @author Adrien Hopkins * @since 2019-01-07 + * @since v0.1.0 */ public final class UnitsDatabase { /** * The units in this system. * * @since 2019-01-07 + * @since v0.1.0 */ private final Map units; @@ -54,6 +56,7 @@ public final class UnitsDatabase { * The unit prefixes in this system. * * @since 2019-01-14 + * @since v0.1.0 */ private final Map prefixes; @@ -61,6 +64,7 @@ public final class UnitsDatabase { * Creates the {@code UnitsDatabase}. * * @since 2019-01-10 + * @since v0.1.0 */ public UnitsDatabase() { this.units = new HashMap<>(); @@ -90,6 +94,7 @@ public final class UnitsDatabase { * @throws NullPointerException * if file is null * @since 2019-01-13 + * @since v0.1.0 */ public void addAllFromFile(final File file) { Objects.requireNonNull(file, "file must not be null."); @@ -128,7 +133,7 @@ public final class UnitsDatabase { if (name.endsWith("-")) { final UnitPrefix prefix; try { - prefix = this.getPrefixFromExpression(expression, name.substring(0, name.length() - 1)); + prefix = this.getPrefixFromExpression(expression); } catch (final IllegalArgumentException e) { System.err.printf("Parsing error on line %d:%n", lineCounter); throw e; @@ -168,6 +173,7 @@ public final class UnitsDatabase { * @throws NullPointerException * if name or unit is null * @since 2019-01-14 + * @since v0.1.0 */ public void addPrefix(final String name, final UnitPrefix prefix) { this.prefixes.put(Objects.requireNonNull(name, "name must not be null."), @@ -184,6 +190,7 @@ public final class UnitsDatabase { * @throws NullPointerException * if unit is null * @since 2019-01-10 + * @since v0.1.0 */ public void addUnit(final String name, final Unit unit) { this.units.put(name, Objects.requireNonNull(unit, "unit must not be null.")); @@ -196,6 +203,7 @@ public final class UnitsDatabase { * name to test * @return if database contains name * @since 2019-01-13 + * @since v0.1.0 */ public boolean containsPrefixlessUnitName(final String name) { return this.units.containsKey(name); @@ -208,6 +216,7 @@ public final class UnitsDatabase { * name to test * @return if database contains name * @since 2019-01-13 + * @since v0.1.0 */ public boolean containsPrefixName(final String name) { return this.prefixes.containsKey(name); @@ -220,6 +229,7 @@ public final class UnitsDatabase { * name to test * @return if database contains name * @since 2019-01-13 + * @since v0.1.0 */ public boolean containsUnitName(final String name) { // check for prefixes @@ -238,13 +248,14 @@ public final class UnitsDatabase { * prefix's name * @return prefix * @since 2019-01-10 + * @since v0.1.0 */ public UnitPrefix getPrefix(final String name) { return this.prefixes.get(name); } /** - * Gets a unit prefix from a prefix expression and a name + * Gets a unit prefix from a prefix expression *

* Currently, prefix expressions are much simpler than unit expressions: They are either a number or the name of * another prefix @@ -252,18 +263,16 @@ public final class UnitsDatabase { * * @param expression * expression to input - * @param name - * name of prefix if a new prefix is created * @return prefix * @throws IllegalArgumentException * if expression cannot be parsed * @throws NullPointerException * if any argument is null * @since 2019-01-14 + * @since v0.1.0 */ - public UnitPrefix getPrefixFromExpression(final String expression, final String name) { + public UnitPrefix getPrefixFromExpression(final String expression) { Objects.requireNonNull(expression, "expression must not be null."); - Objects.requireNonNull(name, "name must not be null."); try { return new DefaultUnitPrefix(Double.parseDouble(expression)); @@ -301,6 +310,7 @@ public final class UnitsDatabase { * unit's name * @return unit * @since 2019-01-10 + * @since v0.1.0 */ public Unit getPrefixlessUnit(final String name) { return this.units.get(name); @@ -313,6 +323,7 @@ public final class UnitsDatabase { * unit's name * @return unit * @since 2019-01-10 + * @since v0.1.0 */ public Unit getUnit(final String name) { if (name.contains("^")) { @@ -377,21 +388,19 @@ public final class UnitsDatabase { *

  • The name of a unit, which multiplies or divides the result based on preceding operators
  • *
  • The operators '*' and '/', which multiply and divide (note that just putting two units or values next to each * other is equivalent to multiplication)
  • + *
  • The operator '^' which exponentiates. Exponents must be integers.
  • *
  • A number which is multiplied or divided
  • * * This method only works with linear units. - *

    - * If the expression contains just the name of a unit, returns that unit without changing name or symbol. This - * exists for the creation of aliases. - *

    * - * @param line - * line to parse + * @param expression + * expression to parse * @throws IllegalArgumentException * if the expression cannot be parsed * @throws NullPointerException * if any argument is null * @since 2019-01-07 + * @since v0.1.0 */ public Unit getUnitFromExpression(final String expression) { Objects.requireNonNull(expression, "expression must not be null."); @@ -558,6 +567,7 @@ public final class UnitsDatabase { /** * @return an immutable set of all of the unit names in this database, ignoring prefixes * @since 2019-01-14 + * @since v0.1.0 */ public Set prefixlessUnitNameSet() { return Collections.unmodifiableSet(this.units.keySet()); @@ -566,6 +576,7 @@ public final class UnitsDatabase { /** * @return an immutable set of all of the prefix names in this database * @since 2019-01-14 + * @since v0.1.0 */ public Set prefixNameSet() { return Collections.unmodifiableSet(this.prefixes.keySet()); diff --git a/src/unitConverter/converterGUI/DelegateListModel.java b/src/unitConverter/converterGUI/DelegateListModel.java index 42bc0dc..0e9b342 100755 --- a/src/unitConverter/converterGUI/DelegateListModel.java +++ b/src/unitConverter/converterGUI/DelegateListModel.java @@ -32,10 +32,12 @@ import javax.swing.AbstractListModel; * * @author Adrien Hopkins * @since 2019-01-14 + * @since v0.1.0 */ final class DelegateListModel extends AbstractListModel implements List { /** * @since 2019-01-14 + * @since v0.1.0 */ private static final long serialVersionUID = 8985494428224810045L; @@ -43,6 +45,7 @@ final class DelegateListModel extends AbstractListModel implements List * The list that this model is a delegate to. * * @since 2019-01-14 + * @since v0.1.0 */ private final List delegate; @@ -52,6 +55,7 @@ final class DelegateListModel extends AbstractListModel implements List * @param delegate * list to delegate * @since 2019-01-14 + * @since v0.1.0 */ public DelegateListModel(final List delegate) { this.delegate = delegate; diff --git a/src/unitConverter/converterGUI/FilterComparator.java b/src/unitConverter/converterGUI/FilterComparator.java index ab25f2f..27ec3ab 100755 --- a/src/unitConverter/converterGUI/FilterComparator.java +++ b/src/unitConverter/converterGUI/FilterComparator.java @@ -17,14 +17,29 @@ package unitConverter.converterGUI; import java.util.Comparator; +import java.util.Objects; /** + * A comparator that compares strings using a filter. + * * @author Adrien Hopkins * @since 2019-01-15 + * @since v0.1.0 */ public final class FilterComparator implements Comparator { - + /** + * The filter that the comparator is filtered by. + * + * @since 2019-01-15 + * @since v0.1.0 + */ private final String filter; + /** + * The comparator to use if the arguments are otherwise equal. + * + * @since 2019-01-15 + * @since v0.1.0 + */ private final Comparator comparator; /** @@ -32,6 +47,7 @@ public final class FilterComparator implements Comparator { * * @param filter * @since 2019-01-15 + * @since v0.1.0 */ public FilterComparator(final String filter) { this(filter, null); @@ -41,11 +57,16 @@ public final class FilterComparator implements Comparator { * Creates the {@code FilterComparator}. * * @param filter + * string to filter by * @param comparator + * comparator to fall back to if all else fails, null is compareTo. * @since 2019-01-15 + * @since v0.1.0 + * @throws NullPointerException + * if filter is null */ public FilterComparator(final String filter, final Comparator comparator) { - this.filter = filter; + this.filter = Objects.requireNonNull(filter, "filter must not be null."); this.comparator = comparator; } diff --git a/src/unitConverter/converterGUI/GridBagBuilder.java b/src/unitConverter/converterGUI/GridBagBuilder.java index 7a0615a..e036677 100755 --- a/src/unitConverter/converterGUI/GridBagBuilder.java +++ b/src/unitConverter/converterGUI/GridBagBuilder.java @@ -20,11 +20,16 @@ import java.awt.GridBagConstraints; import java.awt.Insets; /** + * A builder for Java's {@link java.awt.GridBagConstraints} class. + * * @author Adrien Hopkins * @since 2018-11-30 + * @since v0.1.0 */ final class GridBagBuilder { /** + * The built {@code GridBagConstraints}'s {@code gridx} property. + *

    * Specifies the cell containing the leading edge of the component's display area, where the first cell in a row has * gridx=0. The leading edge of a component's display area is its left edge for a horizontal, * left-to-right container and its right edge for a horizontal, right-to-left container. The value @@ -41,6 +46,8 @@ final class GridBagBuilder { private final int gridx; /** + * The built {@code GridBagConstraints}'s {@code gridy} property. + *

    * Specifies the cell at the top of the component's display area, where the topmost cell has gridy=0. * The value RELATIVE specifies that the component be placed just below the component that was added to * the container just before this component was added. @@ -54,6 +61,8 @@ final class GridBagBuilder { private final int gridy; /** + * The built {@code GridBagConstraints}'s {@code gridwidth} property. + *

    * Specifies the number of cells in a row for the component's display area. *

    * Use REMAINDER to specify that the component's display area will be from gridx to the @@ -69,6 +78,8 @@ final class GridBagBuilder { private final int gridwidth; /** + * The built {@code GridBagConstraints}'s {@code gridheight} property. + *

    * Specifies the number of cells in a column for the component's display area. *

    * Use REMAINDER to specify that the component's display area will be from gridy to the @@ -84,6 +95,8 @@ final class GridBagBuilder { private final int gridheight; /** + * The built {@code GridBagConstraints}'s {@code weightx} property. + *

    * Specifies how to distribute extra horizontal space. *

    * The grid bag layout manager calculates the weight of a column to be the maximum weightx of all the @@ -103,6 +116,8 @@ final class GridBagBuilder { private double weightx; /** + * The built {@code GridBagConstraints}'s {@code weighty} property. + *

    * Specifies how to distribute extra vertical space. *

    * The grid bag layout manager calculates the weight of a row to be the maximum weighty of all the @@ -122,6 +137,8 @@ final class GridBagBuilder { private double weighty; /** + * The built {@code GridBagConstraints}'s {@code anchor} property. + *

    * This field is used when the component is smaller than its display area. It determines where, within the display * area, to place the component. *

    @@ -145,6 +162,8 @@ final class GridBagBuilder { private int anchor; /** + * The built {@code GridBagConstraints}'s {@code fill} property. + *

    * This field is used when the component's display area is larger than the component's requested size. It determines * whether to resize the component, and if so, how. *

    @@ -167,6 +186,8 @@ final class GridBagBuilder { private int fill; /** + * The built {@code GridBagConstraints}'s {@code insets} property. + *

    * This field specifies the external padding of the component, the minimum amount of space between the component and * the edges of its display area. *

    @@ -178,6 +199,8 @@ final class GridBagBuilder { private Insets insets; /** + * The built {@code GridBagConstraints}'s {@code ipadx} property. + *

    * This field specifies the internal padding of the component, how much space to add to the minimum width of the * component. The width of the component is at least its minimum width plus ipadx pixels. *

    @@ -190,6 +213,8 @@ final class GridBagBuilder { private int ipadx; /** + * The built {@code GridBagConstraints}'s {@code ipady} property. + *

    * This field specifies the internal padding, that is, how much space to add to the minimum height of the component. * The height of the component is at least its minimum height plus ipady pixels. *

    @@ -207,6 +232,7 @@ final class GridBagBuilder { * @param gridy * y position * @since 2018-11-30 + * @since v0.1.0 */ public GridBagBuilder(final int gridx, final int gridy) { this(gridx, gridy, 1, 1); @@ -222,6 +248,7 @@ final class GridBagBuilder { * @param gridheight * number of cells occupied vertically * @since 2018-11-30 + * @since v0.1.0 */ public GridBagBuilder(final int gridx, final int gridy, final int gridwidth, final int gridheight) { this(gridx, gridy, gridwidth, gridheight, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, @@ -245,6 +272,7 @@ final class GridBagBuilder { * @param ipadx * @param ipady * @since 2018-11-30 + * @since v0.1.0 */ private GridBagBuilder(final int gridx, final int gridy, final int gridwidth, final int gridheight, final double weightx, final double weighty, final int anchor, final int fill, final Insets insets, @@ -266,6 +294,7 @@ final class GridBagBuilder { /** * @return {@code GridBagConstraints} created by this builder * @since 2018-11-30 + * @since v0.1.0 */ public GridBagConstraints build() { return new GridBagConstraints(this.gridx, this.gridy, this.gridwidth, this.gridheight, this.weightx, @@ -275,6 +304,7 @@ final class GridBagBuilder { /** * @return anchor * @since 2018-11-30 + * @since v0.1.0 */ public int getAnchor() { return this.anchor; @@ -283,6 +313,7 @@ final class GridBagBuilder { /** * @return fill * @since 2018-11-30 + * @since v0.1.0 */ public int getFill() { return this.fill; @@ -291,6 +322,7 @@ final class GridBagBuilder { /** * @return gridheight * @since 2018-11-30 + * @since v0.1.0 */ public int getGridheight() { return this.gridheight; @@ -299,6 +331,7 @@ final class GridBagBuilder { /** * @return gridwidth * @since 2018-11-30 + * @since v0.1.0 */ public int getGridwidth() { return this.gridwidth; @@ -307,6 +340,7 @@ final class GridBagBuilder { /** * @return gridx * @since 2018-11-30 + * @since v0.1.0 */ public int getGridx() { return this.gridx; @@ -315,6 +349,7 @@ final class GridBagBuilder { /** * @return gridy * @since 2018-11-30 + * @since v0.1.0 */ public int getGridy() { return this.gridy; @@ -323,6 +358,7 @@ final class GridBagBuilder { /** * @return insets * @since 2018-11-30 + * @since v0.1.0 */ public Insets getInsets() { return this.insets; @@ -331,6 +367,7 @@ final class GridBagBuilder { /** * @return ipadx * @since 2018-11-30 + * @since v0.1.0 */ public int getIpadx() { return this.ipadx; @@ -339,6 +376,7 @@ final class GridBagBuilder { /** * @return ipady * @since 2018-11-30 + * @since v0.1.0 */ public int getIpady() { return this.ipady; @@ -347,6 +385,7 @@ final class GridBagBuilder { /** * @return weightx * @since 2018-11-30 + * @since v0.1.0 */ public double getWeightx() { return this.weightx; @@ -355,6 +394,7 @@ final class GridBagBuilder { /** * @return weighty * @since 2018-11-30 + * @since v0.1.0 */ public double getWeighty() { return this.weighty; @@ -364,6 +404,7 @@ final class GridBagBuilder { * @param anchor * anchor to set * @since 2018-11-30 + * @since v0.1.0 */ public GridBagBuilder setAnchor(final int anchor) { this.anchor = anchor; @@ -374,6 +415,7 @@ final class GridBagBuilder { * @param fill * fill to set * @since 2018-11-30 + * @since v0.1.0 */ public GridBagBuilder setFill(final int fill) { this.fill = fill; @@ -384,6 +426,7 @@ final class GridBagBuilder { * @param insets * insets to set * @since 2018-11-30 + * @since v0.1.0 */ public GridBagBuilder setInsets(final Insets insets) { this.insets = insets; @@ -394,6 +437,7 @@ final class GridBagBuilder { * @param ipadx * ipadx to set * @since 2018-11-30 + * @since v0.1.0 */ public GridBagBuilder setIpadx(final int ipadx) { this.ipadx = ipadx; @@ -404,6 +448,7 @@ final class GridBagBuilder { * @param ipady * ipady to set * @since 2018-11-30 + * @since v0.1.0 */ public GridBagBuilder setIpady(final int ipady) { this.ipady = ipady; @@ -414,6 +459,7 @@ final class GridBagBuilder { * @param weightx * weightx to set * @since 2018-11-30 + * @since v0.1.0 */ public GridBagBuilder setWeightx(final double weightx) { this.weightx = weightx; @@ -424,6 +470,7 @@ final class GridBagBuilder { * @param weighty * weighty to set * @since 2018-11-30 + * @since v0.1.0 */ public GridBagBuilder setWeighty(final double weighty) { this.weighty = weighty; diff --git a/src/unitConverter/converterGUI/UnitConverterGUI.java b/src/unitConverter/converterGUI/UnitConverterGUI.java index 0068312..b54e0da 100755 --- a/src/unitConverter/converterGUI/UnitConverterGUI.java +++ b/src/unitConverter/converterGUI/UnitConverterGUI.java @@ -52,6 +52,7 @@ import unitConverter.unit.UnitPrefix; /** * @author Adrien Hopkins * @since 2018-12-27 + * @since v0.1.0 */ final class UnitConverterGUI { private static class Presenter { @@ -83,6 +84,7 @@ final class UnitConverterGUI { * @param view * presenter's associated view * @since 2018-12-27 + * @since v0.1.0 */ Presenter(final View view) { this.view = view; @@ -141,6 +143,17 @@ final class UnitConverterGUI { AbstractUnit.getBaseUnitCount()); } + /** + * Runs whenever the convert button is pressed. + * + *

    + * 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. + *

    + * + * @since 2019-01-26 + * @since v0.1.0 + */ public final void convert() { final String fromUnitString = this.view.getFromText(); final String toUnitString = this.view.getToText(); @@ -196,6 +209,7 @@ final class UnitConverterGUI { * @param filter * filter to use * @since 2019-01-15 + * @since v0.1.0 */ private final void filterFilteredPrefixModel(final Predicate filter) { this.prefixNamesFiltered.clear(); @@ -212,6 +226,7 @@ final class UnitConverterGUI { * @param filter * filter to use * @since 2019-01-15 + * @since v0.1.0 */ private final void filterFilteredUnitModel(final Predicate filter) { this.unitNamesFiltered.clear(); @@ -225,11 +240,21 @@ final class UnitConverterGUI { /** * @return a list model of all of the unit keys * @since 2019-01-14 + * @since v0.1.0 */ public final ListModel keyListModel() { return this.unitNamesFiltered; } + /** + * Runs whenever the prefix filter is changed. + *

    + * Filters the prefix list then sorts it using a {@code FilterComparator}. + *

    + * + * @since 2019-01-15 + * @since v0.1.0 + */ public final void prefixFilterUpdated() { final String filter = this.view.getPrefixFilterText(); if (filter.equals("")) { @@ -241,13 +266,22 @@ final class UnitConverterGUI { } /** - * @return a list model of all fo the prefix names + * @return a list model of all of the prefix names * @since 2019-01-15 */ public final ListModel prefixNameListModel() { return this.prefixNamesFiltered; } + /** + * Runs whenever a prefix is selected in the viewer. + *

    + * Shows its information in the text box to the right. + *

    + * + * @since 2019-01-15 + * @since v0.1.0 + */ public final void prefixSelected() { final int index = this.view.getPrefixListSelection(); if (index == -1) @@ -269,6 +303,15 @@ final class UnitConverterGUI { this.significantFigures = significantFigures; } + /** + * Runs whenever the unit filter is changed. + *

    + * Filters the unit list then sorts it using a {@code FilterComparator}. + *

    + * + * @since 2019-01-15 + * @since v0.1.0 + */ public final void unitFilterUpdated() { final String filter = this.view.getUnitFilterText(); if (filter.equals("")) { @@ -280,8 +323,13 @@ final class UnitConverterGUI { } /** + * Runs whenever a unit is selected in the viewer. + *

    + * Shows its information in the text box to the right. + *

    * * @since 2019-01-15 + * @since v0.1.0 */ public void unitNameSelected() { final int index = this.view.getUnitListSelection(); @@ -302,26 +350,37 @@ final class UnitConverterGUI { /** The view's associated presenter. */ private final Presenter presenter; + /** The list of unit names in the unit viewer */ private final JList unitNameList; + /** The list of prefix names in the prefix viewer */ private final JList prefixNameList; + /** The unit search box in the unit viewer */ private final JTextField unitFilterEntry; + /** The text box for unit data in the unit viewer */ private final JTextArea unitTextBox; + /** The prefix search box in the prefix viewer */ private final JTextField prefixFilterEntry; + /** The text box for prefix data in the prefix viewer */ private final JTextArea prefixTextBox; + /** The "From" entry in the conversion panel */ private final JTextField fromEntry; + /** The "To" entry in the conversion panel */ private final JTextField toEntry; + /** The output area in the conversion panel */ private final JTextArea output; /** * Creates the {@code View}. * * @since 2019-01-14 + * @since v0.1.0 */ public View() { this.presenter = new Presenter(this); this.frame = new JFrame("Unit Converter"); this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + // create the components this.unitNameList = new JList<>(this.presenter.keyListModel()); this.prefixNameList = new JList<>(this.presenter.prefixNameListModel()); this.unitFilterEntry = new JTextField(); @@ -332,11 +391,17 @@ final class UnitConverterGUI { this.toEntry = new JTextField(); this.output = new JTextArea(2, 32); + // create more components this.initComponents(); this.frame.pack(); } + /** + * @return text in "From" box in converter panel + * @since 2019-01-15 + * @since v0.1.0 + */ public String getFromText() { return this.fromEntry.getText(); } @@ -344,6 +409,7 @@ final class UnitConverterGUI { /** * @return text in prefix filter * @since 2019-01-15 + * @since v0.1.0 */ public String getPrefixFilterText() { return this.prefixFilterEntry.getText(); @@ -352,11 +418,17 @@ final class UnitConverterGUI { /** * @return index of selected prefix * @since 2019-01-15 + * @since v0.1.0 */ public int getPrefixListSelection() { return this.prefixNameList.getSelectedIndex(); } + /** + * @return text in "To" box in converter panel + * @since 2019-01-26 + * @since v0.1.0 + */ public String getToText() { return this.toEntry.getText(); } @@ -372,6 +444,7 @@ final class UnitConverterGUI { /** * @return index of selected unit * @since 2019-01-15 + * @since v0.1.0 */ public int getUnitListSelection() { return this.unitNameList.getSelectedIndex(); @@ -381,6 +454,7 @@ final class UnitConverterGUI { * Starts up the application. * * @since 2018-12-27 + * @since v0.1.0 */ public final void init() { this.frame.setVisible(true); @@ -390,6 +464,7 @@ final class UnitConverterGUI { * Initializes the view's components. * * @since 2018-12-27 + * @since v0.1.0 */ private final void initComponents() { final JPanel masterPanel = new JPanel(); @@ -451,7 +526,7 @@ final class UnitConverterGUI { } } - { + { // panel for specifying precision final JPanel sigDigPanel = new JPanel(); convertPanel.add(sigDigPanel); @@ -485,7 +560,7 @@ final class UnitConverterGUI { listPanel.setLayout(new BorderLayout()); - { + { // unit search box listPanel.add(this.unitFilterEntry, BorderLayout.PAGE_START); this.unitFilterEntry.addCaretListener(e -> this.presenter.unitFilterUpdated()); } @@ -512,13 +587,13 @@ final class UnitConverterGUI { prefixLookupPanel.setLayout(new GridLayout(1, 2)); - { + { // panel for listing and seaching final JPanel prefixListPanel = new JPanel(); prefixLookupPanel.add(prefixListPanel); prefixListPanel.setLayout(new BorderLayout()); - { + { // prefix search box prefixListPanel.add(this.prefixFilterEntry, BorderLayout.PAGE_START); this.prefixFilterEntry.addCaretListener(e -> this.presenter.prefixFilterUpdated()); } @@ -540,6 +615,14 @@ final class UnitConverterGUI { } } + /** + * Sets the text in the output of the conversion panel. + * + * @param text + * text to set + * @since 2019-01-15 + * @since v0.1.0 + */ public void setOutputText(final String text) { this.output.setText(text); } @@ -550,6 +633,7 @@ final class UnitConverterGUI { * @param text * text to set * @since 2019-01-15 + * @since v0.1.0 */ public void setPrefixTextBoxText(final String text) { this.prefixTextBox.setText(text); @@ -574,6 +658,7 @@ final class UnitConverterGUI { * @param message * message in dialog * @since 2019-01-14 + * @since v0.1.0 */ public void showErrorDialog(final String title, final String message) { JOptionPane.showMessageDialog(this.frame, message, title, JOptionPane.ERROR_MESSAGE); diff --git a/src/unitConverter/dimension/BaseDimension.java b/src/unitConverter/dimension/BaseDimension.java index 6a727a9..0c09dce 100755 --- a/src/unitConverter/dimension/BaseDimension.java +++ b/src/unitConverter/dimension/BaseDimension.java @@ -21,17 +21,20 @@ package unitConverter.dimension; * * @author Adrien Hopkins * @since 2018-12-22 + * @since v0.1.0 */ public interface BaseDimension { /** * @return the dimension's name - * @since 2019-01-25 + * @since 2018-12-22 + * @since v0.1.0 */ String getName(); /** * @return a short string (usually one character) that represents this base dimension * @since 2018-12-22 + * @since v0.1.0 */ String getSymbol(); } diff --git a/src/unitConverter/dimension/OtherBaseDimension.java b/src/unitConverter/dimension/OtherBaseDimension.java index 2ab19b3..8c6d25d 100755 --- a/src/unitConverter/dimension/OtherBaseDimension.java +++ b/src/unitConverter/dimension/OtherBaseDimension.java @@ -23,6 +23,7 @@ import java.util.Objects; * * @author Adrien Hopkins * @since 2019-01-14 + * @since v0.1.0 */ public enum OtherBaseDimension implements BaseDimension { INFORMATION("Info"), CURRENCY("$$"); @@ -36,6 +37,7 @@ public enum OtherBaseDimension implements BaseDimension { * @param symbol * dimension's symbol * @since 2018-12-11 + * @since v0.1.0 */ private OtherBaseDimension(final String symbol) { this.symbol = Objects.requireNonNull(symbol, "symbol must not be null."); diff --git a/src/unitConverter/dimension/SIBaseDimension.java b/src/unitConverter/dimension/SIBaseDimension.java index b731b00..928d8d6 100755 --- a/src/unitConverter/dimension/SIBaseDimension.java +++ b/src/unitConverter/dimension/SIBaseDimension.java @@ -23,6 +23,7 @@ import java.util.Objects; * * @author Adrien Hopkins * @since 2018-12-11 + * @since v0.1.0 */ public enum SIBaseDimension implements BaseDimension { LENGTH("L"), MASS("M"), TIME("T"), ELECTRIC_CURRENT("I"), TEMPERATURE("\u0398"), // u0398 is the theta symbol @@ -37,6 +38,7 @@ public enum SIBaseDimension implements BaseDimension { * @param symbol * dimension's symbol * @since 2018-12-11 + * @since v0.1.0 */ private SIBaseDimension(final String symbol) { this.symbol = Objects.requireNonNull(symbol, "symbol must not be null."); diff --git a/src/unitConverter/dimension/StandardDimensions.java b/src/unitConverter/dimension/StandardDimensions.java index c830f00..b3edb7d 100755 --- a/src/unitConverter/dimension/StandardDimensions.java +++ b/src/unitConverter/dimension/StandardDimensions.java @@ -21,6 +21,7 @@ package unitConverter.dimension; * * @author Adrien Hopkins * @since 2018-12-11 + * @since v0.1.0 */ public final class StandardDimensions { // base dimensions diff --git a/src/unitConverter/dimension/UnitDimension.java b/src/unitConverter/dimension/UnitDimension.java index ba2a750..40e5bbc 100755 --- a/src/unitConverter/dimension/UnitDimension.java +++ b/src/unitConverter/dimension/UnitDimension.java @@ -29,12 +29,14 @@ import java.util.Set; * * @author Adrien Hopkins * @since 2018-12-11 + * @since v0.1.0 */ public final class UnitDimension { /** * The unit dimension where every exponent is zero * * @since 2018-12-12 + * @since v0.1.0 */ public static final UnitDimension EMPTY = new UnitDimension(new HashMap<>()); @@ -45,6 +47,7 @@ public final class UnitDimension { * dimension to get * @return unit dimension * @since 2018-12-11 + * @since v0.1.0 */ public static final UnitDimension getBase(final BaseDimension dimension) { final Map map = new HashMap<>(); @@ -56,6 +59,7 @@ public final class UnitDimension { * The base dimensions that make up this dimension. * * @since 2018-12-11 + * @since v0.1.0 */ final Map exponents; @@ -65,6 +69,7 @@ public final class UnitDimension { * @param exponents * base dimensions that make up this dimension * @since 2018-12-11 + * @since v0.1.0 */ private UnitDimension(final Map exponents) { this.exponents = new HashMap<>(exponents); @@ -77,6 +82,7 @@ public final class UnitDimension { * other dimension * @return quotient of two dimensions * @since 2018-12-11 + * @since v0.1.0 */ public UnitDimension dividedBy(final UnitDimension other) { final Map map = new HashMap<>(this.exponents); @@ -119,6 +125,7 @@ public final class UnitDimension { /** * @return a set of all of the base dimensions with non-zero exponents that make up this dimension. * @since 2018-12-12 + * @since v0.1.0 */ public final Set getBaseSet() { final Set dimensions = new HashSet<>(); @@ -140,6 +147,7 @@ public final class UnitDimension { * dimension to check * @return exponent for that dimension * @since 2018-12-12 + * @since v0.1.0 */ public int getExponent(final BaseDimension dimension) { return this.exponents.getOrDefault(dimension, 0); @@ -153,6 +161,7 @@ public final class UnitDimension { /** * @return true if this dimension is a base, i.e. it has one exponent of one and no other nonzero exponents * @since 2019-01-15 + * @since v0.1.0 */ public boolean isBase() { int oneCount = 0; @@ -174,6 +183,7 @@ public final class UnitDimension { * other dimension * @return product of two dimensions * @since 2018-12-11 + * @since v0.1.0 */ public UnitDimension times(final UnitDimension other) { final Map map = new HashMap<>(this.exponents); @@ -196,6 +206,7 @@ public final class UnitDimension { * exponent * @return result of exponientation * @since 2019-01-15 + * @since v0.1.0 */ public UnitDimension toExponent(final int exp) { final Map map = new HashMap<>(this.exponents); diff --git a/src/unitConverter/dimension/UnitDimensionTest.java b/src/unitConverter/dimension/UnitDimensionTest.java index 603320b..86db1b8 100755 --- a/src/unitConverter/dimension/UnitDimensionTest.java +++ b/src/unitConverter/dimension/UnitDimensionTest.java @@ -30,22 +30,43 @@ import static unitConverter.dimension.StandardDimensions.VOLUME; import org.junit.jupiter.api.Test; /** + * Tests for {@link UnitDimension}. + * * @author Adrien Hopkins * @since 2018-12-12 + * @since v0.1.0 */ class UnitDimensionTest { + /** + * Tests {@link UnitDimension#equals} + * + * @since 2018-12-12 + * @since v0.1.0 + */ @Test void testEquals() { assertEquals(LENGTH, LENGTH); assertFalse(LENGTH.equals(QUANTITY)); } + /** + * Tests {@code UnitDimension}'s exponentiation + * + * @since 2019-01-15 + * @since v0.1.0 + */ @Test void testExponents() { assertEquals(1, LENGTH.getExponent(SIBaseDimension.LENGTH)); assertEquals(3, VOLUME.getExponent(SIBaseDimension.LENGTH)); } + /** + * Tests {@code UnitDimension}'s multiplication and division. + * + * @since 2018-12-12 + * @since v0.1.0 + */ @Test void testMultiplicationAndDivision() { assertEquals(AREA, LENGTH.times(LENGTH)); diff --git a/src/unitConverter/unit/AbstractUnit.java b/src/unitConverter/unit/AbstractUnit.java index d3d6dbd..24814e8 100644 --- a/src/unitConverter/unit/AbstractUnit.java +++ b/src/unitConverter/unit/AbstractUnit.java @@ -24,13 +24,15 @@ import unitConverter.dimension.UnitDimension; * The default abstract implementation of the {@code Unit} interface. * * @author Adrien Hopkins - * @since 2019-01-25 + * @since 2018-12-22 + * @since v0.1.0 */ public abstract class AbstractUnit implements Unit { /** * The number of units created, including base units. * * @since 2019-01-02 + * @since v0.1.0 */ private static long unitCount = 0; @@ -38,12 +40,14 @@ public abstract class AbstractUnit implements Unit { * The number of base units created. * * @since 2019-01-02 + * @since v0.1.0 */ private static long baseUnitCount = 0; /** * @return number of base units created * @since 2019-01-02 + * @since v0.1.0 */ public static final long getBaseUnitCount() { return baseUnitCount; @@ -52,6 +56,7 @@ public abstract class AbstractUnit implements Unit { /** * @return number of units created * @since 2019-01-02 + * @since v0.1.0 */ public static final long getUnitCount() { return unitCount; @@ -61,6 +66,7 @@ public abstract class AbstractUnit implements Unit { * Increments the number of base units. * * @since 2019-01-15 + * @since v0.1.0 */ public static final void incrementBaseUnitCounter() { baseUnitCount++; @@ -70,6 +76,7 @@ public abstract class AbstractUnit implements Unit { * Increments the number of units. * * @since 2019-01-15 + * @since v0.1.0 */ public static final void incrementUnitCounter() { unitCount++; @@ -79,6 +86,7 @@ public abstract class AbstractUnit implements Unit { * The dimension, or what the unit measures. * * @since 2018-12-22 + * @since v0.1.0 */ private final UnitDimension dimension; @@ -87,6 +95,7 @@ public abstract class AbstractUnit implements Unit { * unit. * * @since 2018-12-22 + * @since v0.1.0 */ private final BaseUnit base; @@ -94,6 +103,7 @@ public abstract class AbstractUnit implements Unit { * The system that this unit is a part of. * * @since 2018-12-23 + * @since v0.1.0 */ private final UnitSystem system; @@ -105,6 +115,7 @@ public abstract class AbstractUnit implements Unit { * @throws NullPointerException * if name, symbol or base is null * @since 2018-12-22 + * @since v0.1.0 */ public AbstractUnit(final BaseUnit base) { this.base = Objects.requireNonNull(base, "base must not be null."); @@ -125,6 +136,7 @@ public abstract class AbstractUnit implements Unit { * @throws NullPointerException * if name, symbol or dimension is null * @since 2018-12-23 + * @since v0.1.0 */ AbstractUnit(final UnitDimension dimension, final UnitSystem system) { // try to set this as a base unit diff --git a/src/unitConverter/unit/BaseUnit.java b/src/unitConverter/unit/BaseUnit.java index 204b1cd..d4a1e9c 100755 --- a/src/unitConverter/unit/BaseUnit.java +++ b/src/unitConverter/unit/BaseUnit.java @@ -26,12 +26,14 @@ import unitConverter.dimension.UnitDimension; * * @author Adrien Hopkins * @since 2018-12-23 + * @since v0.1.0 */ public final class BaseUnit extends AbstractUnit { /** * Is this unit a full base (i.e. m, s, ... but not N, J, ...) * * @since 2019-01-15 + * @since v0.1.0 */ private final boolean isFullBase; @@ -47,6 +49,7 @@ public final class BaseUnit extends AbstractUnit { * @param symbol * symbol of unit * @since 2018-12-23 + * @since v0.1.0 */ BaseUnit(final UnitDimension dimension, final UnitSystem system) { super(dimension, system); @@ -56,6 +59,7 @@ public final class BaseUnit extends AbstractUnit { /** * @return this unit as a {@code LinearUnit} * @since 2019-01-25 + * @since v0.1.0 */ public LinearUnit asLinearUnit() { return this.times(1); @@ -82,6 +86,7 @@ public final class BaseUnit extends AbstractUnit { * @throws NullPointerException * if other is null * @since 2018-12-22 + * @since v0.1.0 */ public BaseUnit dividedBy(final BaseUnit other) { Objects.requireNonNull(other, "other must not be null."); @@ -97,6 +102,7 @@ public final class BaseUnit extends AbstractUnit { * amount to divide by * @return quotient * @since 2018-12-23 + * @since v0.1.0 */ public LinearUnit dividedBy(final double divisor) { return new LinearUnit(this, 1 / divisor); @@ -113,6 +119,7 @@ public final class BaseUnit extends AbstractUnit { * @throws NullPointerException * if other is null * @since 2018-12-22 + * @since v0.1.0 */ public BaseUnit times(final BaseUnit other) { Objects.requireNonNull(other, "other must not be null."); @@ -127,7 +134,8 @@ public final class BaseUnit extends AbstractUnit { * @param multiplier * amount to multiply by * @return product - * @since 2018-12-23B + * @since 2018-12-23 + * @since v0.1.0 */ public LinearUnit times(final double multiplier) { return new LinearUnit(this, multiplier); @@ -140,6 +148,7 @@ public final class BaseUnit extends AbstractUnit { * exponent * @return result of exponentiation * @since 2019-01-15 + * @since v0.1.0 */ public BaseUnit toExponent(final int exponent) { return this.getSystem().getBaseUnit(this.getDimension().toExponent(exponent)); diff --git a/src/unitConverter/unit/DefaultUnitPrefix.java b/src/unitConverter/unit/DefaultUnitPrefix.java index 1cce413..d19161b 100755 --- a/src/unitConverter/unit/DefaultUnitPrefix.java +++ b/src/unitConverter/unit/DefaultUnitPrefix.java @@ -19,8 +19,11 @@ package unitConverter.unit; import java.util.Objects; /** + * The default implementation of {@code UnitPrefix}, which contains a multiplier and nothing else. + * * @author Adrien Hopkins * @since 2019-01-14 + * @since v0.1.0 */ public final class DefaultUnitPrefix implements UnitPrefix { private final double multiplier; diff --git a/src/unitConverter/unit/LinearUnit.java b/src/unitConverter/unit/LinearUnit.java index e2c9eb2..6514ff4 100644 --- a/src/unitConverter/unit/LinearUnit.java +++ b/src/unitConverter/unit/LinearUnit.java @@ -24,13 +24,15 @@ import unitConverter.dimension.UnitDimension; * A unit that is equal to a certain number multiplied by its base. * * @author Adrien Hopkins - * @since 2019-01-25 + * @since 2018-12-22 + * @since v0.1.0 */ public final class LinearUnit extends AbstractUnit { /** * The value of one of this unit in this unit's base unit * * @since 2018-12-22 + * @since v0.1.0 */ private final double conversionFactor; @@ -43,6 +45,7 @@ public final class LinearUnit extends AbstractUnit { * @param conversionFactor * value of one of this unit in its base * @since 2018-12-23 + * @since v0.1.0 */ LinearUnit(final BaseUnit base, final double conversionFactor) { super(base); @@ -57,6 +60,7 @@ public final class LinearUnit extends AbstractUnit { * @param system * system unit is part of * @since 2019-01-25 + * @since v0.1.0 */ LinearUnit(final UnitDimension dimension, final UnitSystem system, final double conversionFactor) { super(dimension, system); @@ -80,6 +84,7 @@ public final class LinearUnit extends AbstractUnit { * scalar to divide by * @return quotient * @since 2018-12-23 + * @since v0.1.0 */ public LinearUnit dividedBy(final double divisor) { return new LinearUnit(this.getBase(), this.getConversionFactor() / divisor); @@ -94,6 +99,7 @@ public final class LinearUnit extends AbstractUnit { * @throws NullPointerException * if other is null * @since 2018-12-22 + * @since v0.1.0 */ public LinearUnit dividedBy(final LinearUnit other) { Objects.requireNonNull(other, "other must not be null"); @@ -103,7 +109,8 @@ public final class LinearUnit extends AbstractUnit { /** * @return conversionFactor - * @since 2019-01-25 + * @since 2018-12-22 + * @since v0.1.0 */ public final double getConversionFactor() { return this.conversionFactor; @@ -116,6 +123,7 @@ public final class LinearUnit extends AbstractUnit { * scalar to multiply by * @return product * @since 2018-12-23 + * @since v0.1.0 */ public LinearUnit times(final double multiplier) { return new LinearUnit(this.getBase(), this.getConversionFactor() * multiplier); @@ -130,6 +138,7 @@ public final class LinearUnit extends AbstractUnit { * @throws NullPointerException * if other is null * @since 2018-12-22 + * @since v0.1.0 */ public LinearUnit times(final LinearUnit other) { Objects.requireNonNull(other, "other must not be null"); @@ -144,6 +153,7 @@ public final class LinearUnit extends AbstractUnit { * exponent to exponientate unit to * @return exponientated unit * @since 2019-01-15 + * @since v0.1.0 */ public LinearUnit toExponent(final int exponent) { return new LinearUnit(this.getBase().toExponent(exponent), Math.pow(this.conversionFactor, exponent)); diff --git a/src/unitConverter/unit/NonlinearUnits.java b/src/unitConverter/unit/NonlinearUnits.java index f7e257c..ec1874c 100755 --- a/src/unitConverter/unit/NonlinearUnits.java +++ b/src/unitConverter/unit/NonlinearUnits.java @@ -21,6 +21,7 @@ package unitConverter.unit; * * @author Adrien Hopkins * @since 2019-01-14 + * @since v0.1.0 */ public final class NonlinearUnits { public static final Unit CELSIUS = new AbstractUnit(SI.KELVIN) { diff --git a/src/unitConverter/unit/SI.java b/src/unitConverter/unit/SI.java index cda42e7..54eb4c5 100644 --- a/src/unitConverter/unit/SI.java +++ b/src/unitConverter/unit/SI.java @@ -28,6 +28,7 @@ import unitConverter.dimension.UnitDimension; * * @author Adrien Hopkins * @since 2018-12-23 + * @since v0.1.0 */ public enum SI implements UnitSystem { SI; @@ -36,6 +37,7 @@ public enum SI implements UnitSystem { * This system's base units. * * @since 2019-01-25 + * @since v0.1.0 */ private static final Set baseUnits = new HashSet<>(); diff --git a/src/unitConverter/unit/SIPrefix.java b/src/unitConverter/unit/SIPrefix.java index 39f1a8c..54625fb 100755 --- a/src/unitConverter/unit/SIPrefix.java +++ b/src/unitConverter/unit/SIPrefix.java @@ -17,8 +17,11 @@ package unitConverter.unit; /** + * The SI prefixes. + * * @author Adrien Hopkins * @since 2019-01-14 + * @since v0.1.0 */ public enum SIPrefix implements UnitPrefix { DECA(10), HECTO(100), KILO(1e3), MEGA(1e6), GIGA(1e9), TERA(1e12), PETA(1e15), EXA(1e18), ZETTA(1e21), YOTTA( @@ -33,6 +36,7 @@ public enum SIPrefix implements UnitPrefix { * @param multiplier * prefix's multiplier * @since 2019-01-14 + * @since v0.1.0 */ private SIPrefix(final double multiplier) { this.multiplier = multiplier; @@ -41,6 +45,7 @@ public enum SIPrefix implements UnitPrefix { /** * @return value * @since 2019-01-14 + * @since v0.1.0 */ @Override public final double getMultiplier() { diff --git a/src/unitConverter/unit/Unit.java b/src/unitConverter/unit/Unit.java index 9e1375a..54f1423 100755 --- a/src/unitConverter/unit/Unit.java +++ b/src/unitConverter/unit/Unit.java @@ -25,6 +25,7 @@ import unitConverter.dimension.UnitDimension; * * @author Adrien Hopkins * @since 2018-12-22 + * @since v0.1.0 */ public interface Unit { /** @@ -34,6 +35,7 @@ public interface Unit { * unit to test with * @return true if the units are compatible * @since 2019-01-13 + * @since v0.1.0 */ default boolean canConvertTo(final Unit other) { return Objects.equals(this.getBase(), other.getBase()); @@ -53,6 +55,7 @@ public interface Unit { * value expressed in base unit * @return value expressed in this unit * @since 2018-12-22 + * @since v0.1.0 */ double convertFromBase(double value); @@ -70,6 +73,7 @@ public interface Unit { * value expressed in this unit * @return value expressed in base unit * @since 2018-12-22 + * @since v0.1.0 */ double convertToBase(double value); @@ -86,18 +90,21 @@ public interface Unit { * * @return base unit associated with this unit * @since 2018-12-22 + * @since v0.1.0 */ BaseUnit getBase(); /** * @return dimension measured by this unit * @since 2018-12-22 + * @since v0.1.0 */ UnitDimension getDimension(); /** * @return system that this unit is a part of * @since 2018-12-23 + * @since v0.1.0 */ UnitSystem getSystem(); } diff --git a/src/unitConverter/unit/UnitPrefix.java b/src/unitConverter/unit/UnitPrefix.java index cb50fd9..a0c1b7c 100755 --- a/src/unitConverter/unit/UnitPrefix.java +++ b/src/unitConverter/unit/UnitPrefix.java @@ -21,11 +21,13 @@ package unitConverter.unit; * * @author Adrien Hopkins * @since 2019-01-14 + * @since v0.1.0 */ public interface UnitPrefix { /** * @return this prefix's multiplier * @since 2019-01-14 + * @since v0.1.0 */ double getMultiplier(); } diff --git a/src/unitConverter/unit/UnitSystem.java b/src/unitConverter/unit/UnitSystem.java index d641832..ce8c249 100755 --- a/src/unitConverter/unit/UnitSystem.java +++ b/src/unitConverter/unit/UnitSystem.java @@ -25,6 +25,7 @@ import unitConverter.dimension.UnitDimension; * * @author Adrien Hopkins * @since 2018-12-23 + * @since v0.1.0 */ public interface UnitSystem { /** @@ -36,6 +37,7 @@ public interface UnitSystem { * @throws NullPointerException * if dimension is null * @since 2019-01-25 + * @since v0.1.0 */ default BaseUnit getBaseUnit(final UnitDimension dimension) { Objects.requireNonNull(dimension, "dimension must not be null."); @@ -44,7 +46,8 @@ public interface UnitSystem { /** * @return name of system - * @since 2019-01-25 + * @since 2018-12-23 + * @since v0.1.0 */ String getName(); } diff --git a/src/unitConverter/unit/UnitTest.java b/src/unitConverter/unit/UnitTest.java index 7e16123..c3237eb 100755 --- a/src/unitConverter/unit/UnitTest.java +++ b/src/unitConverter/unit/UnitTest.java @@ -26,7 +26,7 @@ import unitConverter.dimension.StandardDimensions; * Testing the various Unit classes * * @author Adrien Hopkins - * @since 2019-01-26 + * @since 2018-12-22 */ class UnitTest { @Test -- cgit v1.2.3