diff options
Diffstat (limited to 'src/main/java/sevenUnitsGUI')
-rw-r--r-- | src/main/java/sevenUnitsGUI/DefaultPrefixRepetitionRule.java | 10 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/DelegateListModel.java | 14 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/ExpressionConversionView.java | 4 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/FilterComparator.java | 14 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/GridBagBuilder.java | 205 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/Main.java | 4 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/PrefixSearchRule.java | 26 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/Presenter.java | 190 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/SearchBoxList.java | 72 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/StandardDisplayRules.java | 58 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/TabbedView.java | 204 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/UnitConversionRecord.java | 24 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/UnitConversionView.java | 20 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/View.java | 16 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/ViewBot.java | 126 |
15 files changed, 503 insertions, 484 deletions
diff --git a/src/main/java/sevenUnitsGUI/DefaultPrefixRepetitionRule.java b/src/main/java/sevenUnitsGUI/DefaultPrefixRepetitionRule.java index b56356d..1fb2709 100644 --- a/src/main/java/sevenUnitsGUI/DefaultPrefixRepetitionRule.java +++ b/src/main/java/sevenUnitsGUI/DefaultPrefixRepetitionRule.java @@ -45,16 +45,16 @@ public enum DefaultPrefixRepetitionRule implements Predicate<List<UnitPrefix>> { } else { magnifying = false; } - + // if the first prefix is non-metric (including binary prefixes), // assume we are using non-metric prefixes // non-metric prefixes are allowed, but can't be repeated. if (!Metric.DECIMAL_PREFIXES.contains(prefixes.get(0))) return NO_REPETITION.test(prefixes); - + int part = 0; // 0=yotta/yoctos, 1=kilo-zetta/milli-zepto, // 2=deka,hecto,deci,centi - + for (final UnitPrefix prefix : prefixes) { // check that the current prefix is metric and appropriately // magnifying/reducing @@ -62,7 +62,7 @@ public enum DefaultPrefixRepetitionRule implements Predicate<List<UnitPrefix>> { return false; if (magnifying != prefix.getMultiplier() > 1) return false; - + // check if the current prefix is correct // since part is set *after* this check, part designates the state // of the *previous* prefix @@ -79,7 +79,7 @@ public enum DefaultPrefixRepetitionRule implements Predicate<List<UnitPrefix>> { // deka/hecto must be the last prefix, so this is always invalid return false; } - + // set part if (Metric.YOTTA.equals(prefix) || Metric.YOCTO.equals(prefix)) { part = 0; diff --git a/src/main/java/sevenUnitsGUI/DelegateListModel.java b/src/main/java/sevenUnitsGUI/DelegateListModel.java index 5938b59..798383b 100644 --- a/src/main/java/sevenUnitsGUI/DelegateListModel.java +++ b/src/main/java/sevenUnitsGUI/DelegateListModel.java @@ -27,15 +27,17 @@ import javax.swing.AbstractListModel; /** * A list model that delegates to a list. * <p> - * 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. + * 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. * </p> * * @author Adrien Hopkins * @since 2019-01-14 * @since v0.1.0 */ -final class DelegateListModel<E> extends AbstractListModel<E> implements List<E> { +final class DelegateListModel<E> extends AbstractListModel<E> + implements List<E> { /** * @since 2019-01-14 * @since v0.1.0 @@ -62,8 +64,7 @@ final class DelegateListModel<E> extends AbstractListModel<E> implements List<E> /** * Creates the {@code DelegateListModel}. * - * @param delegate - * list to delegate + * @param delegate list to delegate * @since 2019-01-14 * @since v0.1.0 */ @@ -101,7 +102,8 @@ final class DelegateListModel<E> extends AbstractListModel<E> implements List<E> 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. + return !c.isEmpty(); // Since this is a list, it will always change if c + // has elements. } @Override diff --git a/src/main/java/sevenUnitsGUI/ExpressionConversionView.java b/src/main/java/sevenUnitsGUI/ExpressionConversionView.java index 5c39788..882c995 100644 --- a/src/main/java/sevenUnitsGUI/ExpressionConversionView.java +++ b/src/main/java/sevenUnitsGUI/ExpressionConversionView.java @@ -30,14 +30,14 @@ public interface ExpressionConversionView extends View { * @since 2021-12-15 */ String getFromExpression(); - + /** * @return unit expression to convert <em>to</em> * @since v0.4.0 * @since 2021-12-15 */ String getToExpression(); - + /** * Shows the output of an expression conversion to the user. * diff --git a/src/main/java/sevenUnitsGUI/FilterComparator.java b/src/main/java/sevenUnitsGUI/FilterComparator.java index c0a67e8..484a98f 100644 --- a/src/main/java/sevenUnitsGUI/FilterComparator.java +++ b/src/main/java/sevenUnitsGUI/FilterComparator.java @@ -50,7 +50,7 @@ final class FilterComparator<T> implements Comparator<T> { * @since v0.2.0 */ private final boolean caseSensitive; - + /** * Creates the {@code FilterComparator}. * @@ -61,7 +61,7 @@ final class FilterComparator<T> implements Comparator<T> { public FilterComparator(final String filter) { this(filter, null); } - + /** * Creates the {@code FilterComparator}. * @@ -76,7 +76,7 @@ final class FilterComparator<T> implements Comparator<T> { final Comparator<T> comparator) { this(filter, comparator, false); } - + /** * Creates the {@code FilterComparator}. * @@ -95,7 +95,7 @@ final class FilterComparator<T> implements Comparator<T> { this.comparator = comparator; this.caseSensitive = caseSensitive; } - + /** * Compares two objects according to whether or not they match a filter. * Objects whose string representation starts with the filter's text go @@ -114,19 +114,19 @@ final class FilterComparator<T> implements Comparator<T> { str0 = arg0.toString().toLowerCase(); str1 = arg1.toString().toLowerCase(); } - + // elements that start with the filter always go first if (str0.startsWith(this.filter) && !str1.startsWith(this.filter)) return -1; else if (!str0.startsWith(this.filter) && str1.startsWith(this.filter)) return 1; - + // elements that contain the filter but don't start with them go next if (str0.contains(this.filter) && !str1.contains(this.filter)) return -1; else if (!str0.contains(this.filter) && !str1.contains(this.filter)) return 1; - + // other elements go last if (this.comparator == null) return str0.compareTo(str1); diff --git a/src/main/java/sevenUnitsGUI/GridBagBuilder.java b/src/main/java/sevenUnitsGUI/GridBagBuilder.java index 32e94d7..fdbaee7 100644 --- a/src/main/java/sevenUnitsGUI/GridBagBuilder.java +++ b/src/main/java/sevenUnitsGUI/GridBagBuilder.java @@ -30,13 +30,16 @@ final class GridBagBuilder { /** * The built {@code GridBagConstraints}'s {@code gridx} property. * <p> - * Specifies the cell containing the leading edge of the component's display area, where the first cell in a row has - * <code>gridx=0</code>. 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 - * <code>RELATIVE</code> specifies that the component be placed immediately following the component that was added - * to the container just before this component was added. + * Specifies the cell containing the leading edge of the component's display + * area, where the first cell in a row has <code>gridx=0</code>. 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 <code>RELATIVE</code> specifies that the component be + * placed immediately following the component that was added to the container + * just before this component was added. * <p> - * The default value is <code>RELATIVE</code>. <code>gridx</code> should be a non-negative value. + * The default value is <code>RELATIVE</code>. <code>gridx</code> should be a + * non-negative value. * * @serial * @see #clone() @@ -48,11 +51,13 @@ final class GridBagBuilder { /** * The built {@code GridBagConstraints}'s {@code gridy} property. * <p> - * Specifies the cell at the top of the component's display area, where the topmost cell has <code>gridy=0</code>. - * The value <code>RELATIVE</code> specifies that the component be placed just below the component that was added to - * the container just before this component was added. + * Specifies the cell at the top of the component's display area, where the + * topmost cell has <code>gridy=0</code>. The value <code>RELATIVE</code> + * specifies that the component be placed just below the component that was + * added to the container just before this component was added. * <p> - * The default value is <code>RELATIVE</code>. <code>gridy</code> should be a non-negative value. + * The default value is <code>RELATIVE</code>. <code>gridy</code> should be a + * non-negative value. * * @serial * @see #clone() @@ -65,9 +70,10 @@ final class GridBagBuilder { * <p> * Specifies the number of cells in a row for the component's display area. * <p> - * Use <code>REMAINDER</code> to specify that the component's display area will be from <code>gridx</code> to the - * last cell in the row. Use <code>RELATIVE</code> to specify that the component's display area will be from - * <code>gridx</code> to the next to the last one in its row. + * Use <code>REMAINDER</code> to specify that the component's display area + * will be from <code>gridx</code> to the last cell in the row. Use + * <code>RELATIVE</code> to specify that the component's display area will be + * from <code>gridx</code> to the next to the last one in its row. * <p> * <code>gridwidth</code> should be non-negative and the default value is 1. * @@ -80,13 +86,16 @@ final class GridBagBuilder { /** * The built {@code GridBagConstraints}'s {@code gridheight} property. * <p> - * Specifies the number of cells in a column for the component's display area. + * Specifies the number of cells in a column for the component's display + * area. * <p> - * Use <code>REMAINDER</code> to specify that the component's display area will be from <code>gridy</code> to the - * last cell in the column. Use <code>RELATIVE</code> to specify that the component's display area will be from - * <code>gridy</code> to the next to the last one in its column. + * Use <code>REMAINDER</code> to specify that the component's display area + * will be from <code>gridy</code> to the last cell in the column. Use + * <code>RELATIVE</code> to specify that the component's display area will be + * from <code>gridy</code> to the next to the last one in its column. * <p> - * <code>gridheight</code> should be a non-negative value and the default value is 1. + * <code>gridheight</code> should be a non-negative value and the default + * value is 1. * * @serial * @see #clone() @@ -99,15 +108,17 @@ final class GridBagBuilder { * <p> * Specifies how to distribute extra horizontal space. * <p> - * The grid bag layout manager calculates the weight of a column to be the maximum <code>weightx</code> 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. + * The grid bag layout manager calculates the weight of a column to be the + * maximum <code>weightx</code> 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. * <p> - * If all the weights are zero, all the extra space appears between the grids of the cell and the left and right - * edges. + * If all the weights are zero, all the extra space appears between the grids + * of the cell and the left and right edges. * <p> - * The default value of this field is <code>0</code>. <code>weightx</code> should be a non-negative value. + * The default value of this field is <code>0</code>. <code>weightx</code> + * should be a non-negative value. * * @serial * @see #clone() @@ -120,15 +131,17 @@ final class GridBagBuilder { * <p> * Specifies how to distribute extra vertical space. * <p> - * The grid bag layout manager calculates the weight of a row to be the maximum <code>weighty</code> 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. + * The grid bag layout manager calculates the weight of a row to be the + * maximum <code>weighty</code> 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. * <p> - * If all the weights are zero, all the extra space appears between the grids of the cell and the top and bottom - * edges. + * If all the weights are zero, all the extra space appears between the grids + * of the cell and the top and bottom edges. * <p> - * The default value of this field is <code>0</code>. <code>weighty</code> should be a non-negative value. + * The default value of this field is <code>0</code>. <code>weighty</code> + * should be a non-negative value. * * @serial * @see #clone() @@ -139,20 +152,26 @@ final class GridBagBuilder { /** * The built {@code GridBagConstraints}'s {@code anchor} property. * <p> - * This field is used when the component is smaller than its display area. It determines where, within the display - * area, to place the component. + * This field is used when the component is smaller than its display area. It + * determines where, within the display area, to place the component. * <p> - * 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: - * <code>CENTER</code>, <code>NORTH</code>, <code>NORTHEAST</code>, <code>EAST</code>, <code>SOUTHEAST</code>, - * <code>SOUTH</code>, <code>SOUTHWEST</code>, <code>WEST</code>, and <code>NORTHWEST</code>. The orientation - * relative values are: <code>PAGE_START</code>, <code>PAGE_END</code>, <code>LINE_START</code>, - * <code>LINE_END</code>, <code>FIRST_LINE_START</code>, <code>FIRST_LINE_END</code>, <code>LAST_LINE_START</code> - * and <code>LAST_LINE_END</code>. The baseline relative values are: <code>BASELINE</code>, - * <code>BASELINE_LEADING</code>, <code>BASELINE_TRAILING</code>, <code>ABOVE_BASELINE</code>, - * <code>ABOVE_BASELINE_LEADING</code>, <code>ABOVE_BASELINE_TRAILING</code>, <code>BELOW_BASELINE</code>, - * <code>BELOW_BASELINE_LEADING</code>, and <code>BELOW_BASELINE_TRAILING</code>. The default value is + * 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: <code>CENTER</code>, + * <code>NORTH</code>, <code>NORTHEAST</code>, <code>EAST</code>, + * <code>SOUTHEAST</code>, <code>SOUTH</code>, <code>SOUTHWEST</code>, + * <code>WEST</code>, and <code>NORTHWEST</code>. The orientation relative + * values are: <code>PAGE_START</code>, <code>PAGE_END</code>, + * <code>LINE_START</code>, <code>LINE_END</code>, + * <code>FIRST_LINE_START</code>, <code>FIRST_LINE_END</code>, + * <code>LAST_LINE_START</code> and <code>LAST_LINE_END</code>. The baseline + * relative values are: <code>BASELINE</code>, <code>BASELINE_LEADING</code>, + * <code>BASELINE_TRAILING</code>, <code>ABOVE_BASELINE</code>, + * <code>ABOVE_BASELINE_LEADING</code>, <code>ABOVE_BASELINE_TRAILING</code>, + * <code>BELOW_BASELINE</code>, <code>BELOW_BASELINE_LEADING</code>, and + * <code>BELOW_BASELINE_TRAILING</code>. The default value is * <code>CENTER</code>. * * @serial @@ -164,17 +183,18 @@ final class GridBagBuilder { /** * The built {@code GridBagConstraints}'s {@code fill} property. * <p> - * 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. + * 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. * <p> * The following values are valid for <code>fill</code>: * * <ul> * <li><code>NONE</code>: Do not resize the component. - * <li><code>HORIZONTAL</code>: Make the component wide enough to fill its display area horizontally, but do not - * change its height. - * <li><code>VERTICAL</code>: Make the component tall enough to fill its display area vertically, but do not change - * its width. + * <li><code>HORIZONTAL</code>: Make the component wide enough to fill its + * display area horizontally, but do not change its height. + * <li><code>VERTICAL</code>: Make the component tall enough to fill its + * display area vertically, but do not change its width. * <li><code>BOTH</code>: Make the component fill its display area entirely. * </ul> * <p> @@ -188,8 +208,8 @@ final class GridBagBuilder { /** * The built {@code GridBagConstraints}'s {@code insets} property. * <p> - * This field specifies the external padding of the component, the minimum amount of space between the component and - * the edges of its display area. + * This field specifies the external padding of the component, the minimum + * amount of space between the component and the edges of its display area. * <p> * The default value is <code>new Insets(0, 0, 0, 0)</code>. * @@ -201,8 +221,9 @@ final class GridBagBuilder { /** * The built {@code GridBagConstraints}'s {@code ipadx} property. * <p> - * 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 <code>ipadx</code> pixels. + * 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 <code>ipadx</code> pixels. * <p> * The default value is <code>0</code>. * @@ -215,8 +236,9 @@ final class GridBagBuilder { /** * The built {@code GridBagConstraints}'s {@code ipady} property. * <p> - * 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 <code>ipady</code> pixels. + * 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 <code>ipady</code> pixels. * <p> * The default value is 0. * @@ -227,10 +249,8 @@ final class GridBagBuilder { private int ipady; /** - * @param gridx - * x position - * @param gridy - * y position + * @param gridx x position + * @param gridy y position * @since 2018-11-30 * @since v0.1.0 */ @@ -239,31 +259,25 @@ final class GridBagBuilder { } /** - * @param gridx - * x position - * @param gridy - * y position - * @param gridwidth - * number of cells occupied horizontally - * @param gridheight - * number of cells occupied vertically + * @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 * @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, + 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 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 @@ -274,9 +288,10 @@ final class GridBagBuilder { * @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, - final int ipadx, final int ipady) { + 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; @@ -297,8 +312,9 @@ final class GridBagBuilder { * @since v0.1.0 */ 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 new GridBagConstraints(this.gridx, this.gridy, this.gridwidth, + this.gridheight, this.weightx, this.weighty, this.anchor, this.fill, + this.insets, this.ipadx, this.ipady); } /** @@ -401,8 +417,7 @@ final class GridBagBuilder { } /** - * @param anchor - * anchor to set + * @param anchor anchor to set * @since 2018-11-30 * @since v0.1.0 */ @@ -412,8 +427,7 @@ final class GridBagBuilder { } /** - * @param fill - * fill to set + * @param fill fill to set * @since 2018-11-30 * @since v0.1.0 */ @@ -423,8 +437,7 @@ final class GridBagBuilder { } /** - * @param insets - * insets to set + * @param insets insets to set * @since 2018-11-30 * @since v0.1.0 */ @@ -434,8 +447,7 @@ final class GridBagBuilder { } /** - * @param ipadx - * ipadx to set + * @param ipadx ipadx to set * @since 2018-11-30 * @since v0.1.0 */ @@ -445,8 +457,7 @@ final class GridBagBuilder { } /** - * @param ipady - * ipady to set + * @param ipady ipady to set * @since 2018-11-30 * @since v0.1.0 */ @@ -456,8 +467,7 @@ final class GridBagBuilder { } /** - * @param weightx - * weightx to set + * @param weightx weightx to set * @since 2018-11-30 * @since v0.1.0 */ @@ -467,8 +477,7 @@ final class GridBagBuilder { } /** - * @param weighty - * weighty to set + * @param weighty weighty to set * @since 2018-11-30 * @since v0.1.0 */ diff --git a/src/main/java/sevenUnitsGUI/Main.java b/src/main/java/sevenUnitsGUI/Main.java index 998b373..ff61b3b 100644 --- a/src/main/java/sevenUnitsGUI/Main.java +++ b/src/main/java/sevenUnitsGUI/Main.java @@ -23,7 +23,7 @@ package sevenUnitsGUI; * @since 2022-04-19 */ public final class Main { - + /** * The main method that starts 7Units * @@ -34,5 +34,5 @@ public final class Main { public static void main(String[] args) { View.createTabbedView(); } - + } diff --git a/src/main/java/sevenUnitsGUI/PrefixSearchRule.java b/src/main/java/sevenUnitsGUI/PrefixSearchRule.java index a5034c9..69f09e6 100644 --- a/src/main/java/sevenUnitsGUI/PrefixSearchRule.java +++ b/src/main/java/sevenUnitsGUI/PrefixSearchRule.java @@ -46,7 +46,7 @@ public final class PrefixSearchRule implements */ public static final PrefixSearchRule NO_PREFIXES = getUniversalRule( Set.of()); - + /** * A rule that gives every unit a common set of prefixes. * @@ -54,7 +54,7 @@ public final class PrefixSearchRule implements */ public static final PrefixSearchRule COMMON_PREFIXES = getCoherentOnlyRule( Set.of(Metric.MILLI, Metric.KILO)); - + /** * A rule that gives every unit all metric prefixes. * @@ -62,7 +62,7 @@ public final class PrefixSearchRule implements */ public static final PrefixSearchRule ALL_METRIC_PREFIXES = getCoherentOnlyRule( Metric.ALL_PREFIXES); - + /** * Gets a rule that applies the provided prefixes to coherent units only (as * defined by {@link LinearUnit#isCoherent}), except the kilogram @@ -78,7 +78,7 @@ public final class PrefixSearchRule implements return new PrefixSearchRule(prefixes, u -> u.isCoherent() && !u.getName().equals("kilogram")); } - + /** * Gets a rule that applies the provided prefixes to all units. * @@ -91,17 +91,17 @@ public final class PrefixSearchRule implements Set<UnitPrefix> prefixes) { return new PrefixSearchRule(prefixes, u -> true); } - + /** * The set of prefixes that will be applied to the unit. */ private final Set<UnitPrefix> prefixes; - + /** * Determines which units are given prefixes. */ private final Predicate<LinearUnit> prefixableUnitRule; - + /** * @param prefixes prefixes to add to units * @param prefixableUnitRule function that determines which units get @@ -114,7 +114,7 @@ public final class PrefixSearchRule implements this.prefixes = Collections.unmodifiableSet(new HashSet<>(prefixes)); this.prefixableUnitRule = prefixableUnitRule; } - + @Override public Map<String, LinearUnit> apply(Entry<String, LinearUnit> t) { final Map<String, LinearUnit> outputUnits = new HashMap<>(); @@ -129,7 +129,7 @@ public final class PrefixSearchRule implements } return Collections.unmodifiableMap(outputUnits); } - + @Override public boolean equals(Object obj) { if (this == obj) @@ -140,7 +140,7 @@ public final class PrefixSearchRule implements return Objects.equals(this.prefixableUnitRule, other.prefixableUnitRule) && Objects.equals(this.prefixes, other.prefixes); } - + /** * @return rule that determines which units get prefixes * @since v0.4.0 @@ -149,7 +149,7 @@ public final class PrefixSearchRule implements public Predicate<LinearUnit> getPrefixableUnitRule() { return this.prefixableUnitRule; } - + /** * @return the prefixes that are applied by this rule * @since v0.4.0 @@ -158,12 +158,12 @@ public final class PrefixSearchRule implements public Set<UnitPrefix> getPrefixes() { return this.prefixes; } - + @Override public int hashCode() { return Objects.hash(this.prefixableUnitRule, this.prefixes); } - + @Override public String toString() { return "Apply the following prefixes: " + this.prefixes; diff --git a/src/main/java/sevenUnitsGUI/Presenter.java b/src/main/java/sevenUnitsGUI/Presenter.java index b129d95..eba8438 100644 --- a/src/main/java/sevenUnitsGUI/Presenter.java +++ b/src/main/java/sevenUnitsGUI/Presenter.java @@ -61,17 +61,18 @@ import sevenUnitsGUI.StandardDisplayRules.UncertaintyBased; */ public final class Presenter { /** - * The place where settings are stored. - * Both this path and its parent directory may not exist. + * The place where settings are stored. Both this path and its parent + * directory may not exist. */ - private static final Path CONFIG_FILE = userConfigDir().resolve("SevenUnits").resolve("config.txt"); + private static final Path CONFIG_FILE = userConfigDir().resolve("SevenUnits") + .resolve("config.txt"); /** The default place where units are stored. */ private static final String DEFAULT_UNITS_FILEPATH = "/unitsfile.txt"; /** The default place where dimensions are stored. */ private static final String DEFAULT_DIMENSIONS_FILEPATH = "/dimensionfile.txt"; /** The default place where exceptions are stored. */ private static final String DEFAULT_EXCEPTIONS_FILEPATH = "/metric_exceptions.txt"; - + private static final Path userConfigDir() { if (System.getProperty("os.name").startsWith("Windows")) { final String envFolder = System.getenv("LOCALAPPDATA"); @@ -116,14 +117,14 @@ public final class Presenter { // nonlinear units - must be loaded manually database.addUnit("tempCelsius", Metric.CELSIUS); database.addUnit("tempFahrenheit", BritishImperial.FAHRENHEIT); - + // load initial dimensions database.addDimension("Length", Metric.Dimensions.LENGTH); database.addDimension("Mass", Metric.Dimensions.MASS); database.addDimension("Time", Metric.Dimensions.TIME); database.addDimension("Temperature", Metric.Dimensions.TEMPERATURE); } - + /** * @return text in About file * @since 2022-02-19 @@ -133,7 +134,7 @@ public final class Presenter { .map(Presenter::withoutComments).collect(Collectors.joining("\n")) .replaceAll("\\[VERSION\\]", ProgramInfo.VERSION.toString()); } - + /** * Gets the text of a resource file as a set of strings (each one is one line * of the text). @@ -144,7 +145,7 @@ public final class Presenter { */ private static final List<String> getLinesFromResource(String filename) { final List<String> lines = new ArrayList<>(); - + try (InputStream stream = inputStream(filename); Scanner scanner = new Scanner(stream)) { while (scanner.hasNextLine()) { @@ -154,10 +155,10 @@ public final class Presenter { throw new AssertionError( "Error occurred while loading file " + filename, e); } - + return lines; } - + /** * Gets an input stream for a resource file. * @@ -168,7 +169,7 @@ public final class Presenter { private static final InputStream inputStream(String filepath) { return Presenter.class.getResourceAsStream(filepath); } - + /** * @return true iff a and b have any elements in common * @since 2022-04-19 @@ -180,7 +181,7 @@ public final class Presenter { } return false; } - + /** * @return {@code line} with any comments removed. * @since 2021-03-13 @@ -189,25 +190,25 @@ public final class Presenter { final int index = line.indexOf('#'); return index == -1 ? line : line.substring(0, index); } - + // ====== SETTINGS ====== - + /** * The view that this presenter communicates with */ private final View view; - + /** * The database that this presenter communicates with (effectively the model) */ final UnitDatabase database; - + /** * The rule used for parsing input numbers. Any number-string inputted into * this program will be parsed using this method. <b>Not implemented yet.</b> */ private Function<String, UncertainDouble> numberParsingRule; - + /** * The rule used for displaying the results of unit conversions. The result * of unit conversions will be put into this function, and the resulting @@ -215,41 +216,41 @@ public final class Presenter { */ private Function<UncertainDouble, String> numberDisplayRule = StandardDisplayRules .uncertaintyBased(); - + /** * A predicate that determines whether or not a certain combination of * prefixes is allowed. If it returns false, a combination of prefixes will * not be allowed. Prefixes are put in the list from right to left. */ private Predicate<List<UnitPrefix>> prefixRepetitionRule = DefaultPrefixRepetitionRule.NO_RESTRICTION; - + /** * A rule that accepts a prefixless name-unit pair and returns a map mapping * names to prefixed versions of that unit (including the unit itself) that * should be searchable. */ private Function<Map.Entry<String, LinearUnit>, Map<String, LinearUnit>> searchRule = PrefixSearchRule.NO_PREFIXES; - + /** * The set of units that is considered neither metric nor nonmetric for the * purposes of the metric-imperial one-way conversion. These units are * included in both From and To, even if One Way Conversion is enabled. */ private final Set<String> metricExceptions; - + /** * If this is true, 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. */ private boolean oneWayConversionEnabled = false; - + /** * If this is false, duplicate units and prefixes will be removed from the * unit view in views that show units as a list to choose from. */ private boolean showDuplicates = false; - + /** * Creates a Presenter * @@ -260,14 +261,14 @@ public final class Presenter { this.view = view; this.database = new UnitDatabase(); addDefaults(this.database); - + // load units and prefixes try (final InputStream units = inputStream(DEFAULT_UNITS_FILEPATH)) { this.database.loadUnitsFromStream(units); } catch (final IOException e) { throw new AssertionError("Loading of unitsfile.txt failed.", e); } - + // load dimensions try (final InputStream dimensions = inputStream( DEFAULT_DIMENSIONS_FILEPATH)) { @@ -275,7 +276,7 @@ public final class Presenter { } catch (final IOException e) { throw new AssertionError("Loading of dimensionfile.txt failed.", e); } - + // load metric exceptions try { this.metricExceptions = new HashSet<>(); @@ -293,16 +294,16 @@ public final class Presenter { throw new AssertionError("Loading of metric_exceptions.txt failed.", e); } - + // set default settings temporarily if (Files.exists(CONFIG_FILE)) { this.loadSettings(CONFIG_FILE); } - + // a Predicate that returns true iff the argument is a full base unit final Predicate<Unit> isFullBase = unit -> unit instanceof LinearUnit && ((LinearUnit) unit).isBase(); - + // print out unit counts System.out.printf( "Successfully loaded %d units with %d unit names (%d base units).%n", @@ -311,7 +312,7 @@ public final class Presenter { this.database.unitMapPrefixless(false).values().stream() .filter(isFullBase).count()); } - + /** * Applies a search rule to an entry in a name-unit map. * @@ -331,7 +332,7 @@ public final class Presenter { } else return Stream.of(e); } - + /** * Converts from the view's input expression to its output expression. * Displays an error message if any of the required fields are invalid. @@ -345,10 +346,10 @@ public final class Presenter { public void convertExpressions() { if (this.view instanceof ExpressionConversionView) { final ExpressionConversionView xcview = (ExpressionConversionView) this.view; - + final String fromExpression = xcview.getFromExpression(); final String toExpression = xcview.getToExpression(); - + // expressions must not be empty if (fromExpression.isEmpty()) { this.view.showErrorMessage("Parse Error", @@ -360,7 +361,7 @@ public final class Presenter { "Please enter a unit expression in the To: box."); return; } - + // evaluate expressions final LinearUnitValue from; final Unit to; @@ -378,11 +379,11 @@ public final class Presenter { "Could not recognize text in To entry: " + e.getMessage()); return; } - + // convert and show output if (from.getUnit().canConvertTo(to)) { final UncertainDouble uncertainValue; - + // uncertainty is meaningless for non-linear units, so we will have // to erase uncertainty information for them if (to instanceof LinearUnit) { @@ -392,7 +393,7 @@ public final class Presenter { final double value = from.asUnitValue().convertTo(to).getValue(); uncertainValue = UncertainDouble.of(value, 0); } - + final UnitConversionRecord uc = UnitConversionRecord.valueOf( fromExpression, toExpression, "", this.numberDisplayRule.apply(uncertainValue)); @@ -402,12 +403,12 @@ public final class Presenter { "Cannot convert between \"" + fromExpression + "\" and \"" + toExpression + "\"."); } - + } else throw new UnsupportedOperationException( "This function can only be called when the view is an ExpressionConversionView"); } - + /** * Converts from the view's input unit to its output unit. Displays an error * message if any of the required fields are invalid. @@ -421,11 +422,11 @@ public final class Presenter { public void convertUnits() { if (this.view instanceof UnitConversionView) { final UnitConversionView ucview = (UnitConversionView) this.view; - + final Optional<String> fromUnitOptional = ucview.getFromSelection(); final Optional<String> toUnitOptional = ucview.getToSelection(); final String inputValueString = ucview.getInputValue(); - + // extract values from optionals final String fromUnitString, toUnitString; if (fromUnitOptional.isPresent()) { @@ -442,11 +443,11 @@ public final class Presenter { "Please specify a To unit"); return; } - + // convert strings to data, checking if anything is invalid final Unit fromUnit, toUnit; final UncertainDouble uncertainValue; - + if (this.database.containsUnitName(fromUnitString)) { fromUnit = this.database.getUnit(fromUnitString); } else @@ -463,11 +464,11 @@ public final class Presenter { "Invalid value " + inputValueString); return; } - + if (!fromUnit.canConvertTo(toUnit)) throw this.viewError("Could not convert between %s and %s", fromUnit, toUnit); - + // convert - we will need to erase uncertainty for non-linear units, so // we need to treat linear and non-linear units differently final String outputValueString; @@ -477,18 +478,18 @@ public final class Presenter { final LinearUnitValue initialValue = LinearUnitValue.of(fromLinear, uncertainValue); final LinearUnitValue converted = initialValue.convertTo(toLinear); - + outputValueString = this.numberDisplayRule .apply(converted.getValue()); } else { final UnitValue initialValue = UnitValue.of(fromUnit, uncertainValue.value()); final UnitValue converted = initialValue.convertTo(toUnit); - + outputValueString = this.numberDisplayRule .apply(UncertainDouble.of(converted.getValue(), 0)); } - + ucview.showUnitConversionOutput( UnitConversionRecord.valueOf(fromUnitString, toUnitString, inputValueString, outputValueString)); @@ -496,7 +497,7 @@ public final class Presenter { throw new UnsupportedOperationException( "This function can only be called when the view is a UnitConversionView."); } - + /** * @return true iff duplicate units are shown in unit lists * @since 2022-03-30 @@ -504,7 +505,7 @@ public final class Presenter { public boolean duplicatesShown() { return this.showDuplicates; } - + /** * Gets a name for this dimension using the database * @@ -519,7 +520,7 @@ public final class Presenter { .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 @@ -528,7 +529,7 @@ public final class Presenter { public Function<UncertainDouble, String> getNumberDisplayRule() { return this.numberDisplayRule; } - + /** * @return the rule that is used by this presenter to convert strings into * numbers @@ -538,7 +539,7 @@ public final class Presenter { private Function<String, UncertainDouble> getNumberParsingRule() { return this.numberParsingRule; } - + /** * @return the rule that determines whether a set of prefixes is valid * @since 2022-04-19 @@ -546,7 +547,7 @@ public final class Presenter { public Predicate<List<UnitPrefix>> getPrefixRepetitionRule() { return this.prefixRepetitionRule; } - + /** * @return the rule that determines which units are prefixed * @since 2022-07-08 @@ -554,7 +555,7 @@ public final class Presenter { public Function<Map.Entry<String, LinearUnit>, Map<String, LinearUnit>> getSearchRule() { return this.searchRule; } - + /** * @return a search rule that shows all single prefixes * @since 2022-07-08 @@ -563,7 +564,7 @@ public final class Presenter { return PrefixSearchRule.getCoherentOnlyRule( new HashSet<>(this.database.prefixMap(true).values())); } - + /** * @return the view associated with this presenter * @since 2022-04-19 @@ -571,7 +572,7 @@ public final class Presenter { public View getView() { return this.view; } - + /** * @return whether or not the provided unit is semi-metric (i.e. an * exception) @@ -587,7 +588,7 @@ public final class Presenter { && this.metricExceptions.contains(symbol.orElseThrow()) || sharesAnyElements(this.metricExceptions, u.getOtherNames()); } - + /** * Loads settings from the user's settings file and applies them to the * presenter. @@ -616,7 +617,7 @@ public final class Presenter { break; case "prefix_rule": this.prefixRepetitionRule = DefaultPrefixRepetitionRule - .valueOf(value); + .valueOf(value); this.database.setPrefixRepetitionRule(this.prefixRepetitionRule); break; case "one_way": @@ -643,10 +644,11 @@ public final class Presenter { private List<Map.Entry<String, String>> settingsFromFile(Path settingsFile) { try (Stream<String> lines = Files.lines(settingsFile)) { return lines.map(Presenter::withoutComments) - .filter(line -> !line.isBlank()) - .map(Presenter::parseSettingLine).toList(); + .filter(line -> !line.isBlank()).map(Presenter::parseSettingLine) + .toList(); } catch (final IOException e) { - this.view.showErrorMessage("Settings Loading Error", "Error loading settings file. Using default settings."); + this.view.showErrorMessage("Settings Loading Error", + "Error loading settings file. Using default settings."); return null; } } @@ -662,7 +664,7 @@ public final class Presenter { return Map.entry(param, value); } - + private void setSearchRuleFromString(String ruleString) { switch (ruleString) { case "NO_PREFIXES": @@ -675,7 +677,9 @@ public final class Presenter { this.searchRule = PrefixSearchRule.ALL_METRIC_PREFIXES; break; default: - System.err.printf("Warning: unrecognized value for search_prefix_rule: %s\n", ruleString); + System.err.printf( + "Warning: unrecognized value for search_prefix_rule: %s\n", + ruleString); } } @@ -694,7 +698,8 @@ public final class Presenter { this.numberDisplayRule = StandardDisplayRules.uncertaintyBased(); break; default: - this.numberDisplayRule = StandardDisplayRules.getStandardRule(ruleString); + this.numberDisplayRule = StandardDisplayRules + .getStandardRule(ruleString); break; } } @@ -706,8 +711,7 @@ public final class Presenter { } catch (IOException e) { this.view.showErrorMessage("File Load Error", "Error loading configured metric exception file \"" - + exceptionFile + "\": " - + e.getLocalizedMessage()); + + exceptionFile + "\": " + e.getLocalizedMessage()); } } @@ -721,7 +725,7 @@ public final class Presenter { 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 @@ -735,10 +739,10 @@ public final class Presenter { final UnitConversionView ucview = (UnitConversionView) this.view; ucview.setDimensionNames(this.database.dimensionMap().keySet()); } - + this.updateView(); } - + void prefixSelected() { final Optional<String> selectedPrefixName = this.view .getViewedPrefixName(); @@ -750,10 +754,10 @@ public final class Presenter { .ifPresent(prefix -> this.view.showPrefix(prefix.getNameSymbol(), String.valueOf(prefix.getMultiplier()))); } - + /** - * Saves the presenter's current settings to the config file, - * creating it if it doesn't exist. + * Saves the presenter's current settings to the config file, creating it if + * it doesn't exist. * * @return false iff the presenter could not write to the file * @since 2022-04-19 @@ -770,7 +774,7 @@ public final class Presenter { return this.writeSettings(CONFIG_FILE); } - + /** * Saves the presenter's settings to the user settings file. * @@ -798,8 +802,9 @@ public final class Presenter { return false; } } - - private static String searchRuleToString(Function<Map.Entry<String, LinearUnit>, Map<String, LinearUnit>> searchRule) { + + private static String searchRuleToString( + Function<Map.Entry<String, LinearUnit>, Map<String, LinearUnit>> searchRule) { if (PrefixSearchRule.NO_PREFIXES.equals(searchRule)) { return "NO_PREFIXES"; } else if (PrefixSearchRule.COMMON_PREFIXES.equals(searchRule)) { @@ -810,10 +815,11 @@ public final class Presenter { return searchRule.toString(); } - private static String displayRuleToString(Function<UncertainDouble, String> numberDisplayRule) { + private static String displayRuleToString( + Function<UncertainDouble, String> numberDisplayRule) { if (numberDisplayRule instanceof FixedDecimals) { return String.format("FIXED_DECIMALS %d", - ((FixedDecimals) numberDisplayRule) .decimalPlaces()); + ((FixedDecimals) numberDisplayRule).decimalPlaces()); } else if (numberDisplayRule instanceof FixedPrecision) { return String.format("FIXED_PRECISION %d", ((FixedPrecision) numberDisplayRule).significantFigures()); @@ -832,7 +838,7 @@ public final class Presenter { Function<UncertainDouble, String> numberDisplayRule) { this.numberDisplayRule = numberDisplayRule; } - + /** * @param numberParsingRule the new rule that will be used by this presenter * to convert strings into numbers @@ -843,7 +849,7 @@ public final class Presenter { Function<String, UncertainDouble> numberParsingRule) { this.numberParsingRule = numberParsingRule; } - + /** * @param oneWayConversionEnabled whether not one-way conversion should be * enabled @@ -854,7 +860,7 @@ public final class Presenter { this.oneWayConversionEnabled = oneWayConversionEnabled; this.updateView(); } - + /** * @param prefixRepetitionRule the rule that determines whether a set of * prefixes is valid @@ -865,7 +871,7 @@ public final class Presenter { this.prefixRepetitionRule = prefixRepetitionRule; this.database.setPrefixRepetitionRule(prefixRepetitionRule); } - + /** * @param searchRule A rule that accepts a prefixless name-unit pair and * returns a map mapping names to prefixed versions of that @@ -877,7 +883,7 @@ public final class Presenter { Function<Map.Entry<String, LinearUnit>, Map<String, LinearUnit>> searchRule) { this.searchRule = searchRule; } - + /** * @param showDuplicateUnits whether or not duplicate units should be shown * @since 2022-03-30 @@ -886,7 +892,7 @@ public final class Presenter { this.showDuplicates = showDuplicateUnits; this.updateView(); } - + /** * Shows a unit in the unit viewer * @@ -902,7 +908,7 @@ public final class Presenter { final var unitType = UnitType.getType(u, this::isSemiMetric); 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. @@ -918,7 +924,7 @@ public final class Presenter { : null); selectedUnit.ifPresent(this::showUnit); } - + /** * Updates the view's From and To units, if it has some * @@ -928,19 +934,19 @@ public final class Presenter { if (this.view instanceof UnitConversionView) { final UnitConversionView ucview = (UnitConversionView) this.view; final var selectedDimensionName = ucview.getSelectedDimensionName(); - + // load units & prefixes into viewers this.view.setViewableUnitNames( this.database.unitMapPrefixless(this.showDuplicates).keySet()); this.view.setViewablePrefixNames( this.database.prefixMap(this.showDuplicates).keySet()); - + // get From and To units var fromUnits = this.database.unitMapPrefixless(this.showDuplicates) .entrySet().stream(); var toUnits = this.database.unitMapPrefixless(this.showDuplicates) .entrySet().stream(); - + // filter by dimension, if one is selected if (selectedDimensionName.isPresent()) { final var viewDimension = this.database @@ -950,7 +956,7 @@ public final class Presenter { toUnits = toUnits.filter( u -> viewDimension.equals(u.getValue().getDimension())); } - + // filter by unit type, if desired if (this.oneWayConversionEnabled) { fromUnits = fromUnits.filter(u -> UnitType.getType(u.getValue(), @@ -958,7 +964,7 @@ public final class Presenter { toUnits = toUnits.filter(u -> UnitType.getType(u.getValue(), this::isSemiMetric) != UnitType.NON_METRIC); } - + // set unit names ucview.setFromUnitNames(fromUnits.flatMap(this::applySearchRule) .map(Map.Entry::getKey).collect(Collectors.toSet())); @@ -966,7 +972,7 @@ public final class Presenter { .map(Map.Entry::getKey).collect(Collectors.toSet())); } } - + /** * @param message message to add * @param args string formatting arguments for message diff --git a/src/main/java/sevenUnitsGUI/SearchBoxList.java b/src/main/java/sevenUnitsGUI/SearchBoxList.java index 9b41601..8fba459 100644 --- a/src/main/java/sevenUnitsGUI/SearchBoxList.java +++ b/src/main/java/sevenUnitsGUI/SearchBoxList.java @@ -40,13 +40,13 @@ import javax.swing.JTextField; * @since v0.2.0 */ final class SearchBoxList<E> extends JPanel { - + /** * @since 2019-04-13 * @since v0.2.0 */ private static final long serialVersionUID = 6226930279415983433L; - + /** * The text to place in an empty search box. * @@ -54,7 +54,7 @@ final class SearchBoxList<E> extends JPanel { * @since v0.2.0 */ private static final String EMPTY_TEXT = "Search..."; - + /** * The color to use for an empty foreground. * @@ -62,24 +62,24 @@ final class SearchBoxList<E> extends JPanel { * @since v0.2.0 */ private static final Color EMPTY_FOREGROUND = new Color(192, 192, 192); - + // the components private final Collection<E> itemsToFilter; private final DelegateListModel<E> listModel; private final JTextField searchBox; private final JList<E> searchItems; - + private boolean searchBoxEmpty = true; - + // I need to do this because, for some reason, Swing is auto-focusing my // search box without triggering a focus // event. private boolean searchBoxFocused = false; - + private Predicate<E> customSearchFilter = o -> true; private final Comparator<E> defaultOrdering; private final boolean caseSensitive; - + /** * Creates an empty SearchBoxList * @@ -88,7 +88,7 @@ final class SearchBoxList<E> extends JPanel { public SearchBoxList() { this(List.of(), null, false); } - + /** * Creates the {@code SearchBoxList}. * @@ -98,7 +98,7 @@ final class SearchBoxList<E> extends JPanel { public SearchBoxList(final Collection<E> itemsToFilter) { this(itemsToFilter, null, false); } - + /** * Creates the {@code SearchBoxList}. * @@ -116,35 +116,35 @@ final class SearchBoxList<E> extends JPanel { this.itemsToFilter = new ArrayList<>(itemsToFilter); this.defaultOrdering = defaultOrdering; this.caseSensitive = caseSensitive; - + // create the components this.listModel = new DelegateListModel<>(new ArrayList<>(itemsToFilter)); this.searchItems = new JList<>(this.listModel); - + this.searchBox = new JTextField(EMPTY_TEXT); this.searchBox.setForeground(EMPTY_FOREGROUND); - + // add them to the panel this.add(this.searchBox, BorderLayout.PAGE_START); this.add(new JScrollPane(this.searchItems), BorderLayout.CENTER); - + // set up the search box this.searchBox.addFocusListener(new FocusListener() { @Override public void focusGained(final FocusEvent e) { SearchBoxList.this.searchBoxFocusGained(e); } - + @Override public void focusLost(final FocusEvent e) { SearchBoxList.this.searchBoxFocusLost(e); } }); - + this.searchBox.addCaretListener(e -> this.searchBoxTextChanged()); this.searchBoxEmpty = true; } - + /** * Adds an additional filter for searching. * @@ -155,7 +155,7 @@ final class SearchBoxList<E> extends JPanel { public void addSearchFilter(final Predicate<E> filter) { this.customSearchFilter = this.customSearchFilter.and(filter); } - + /** * Resets the search filter. * @@ -165,7 +165,7 @@ final class SearchBoxList<E> extends JPanel { public void clearSearchFilters() { this.customSearchFilter = o -> true; } - + /** * @return items available in search list, including items that are hidden by * the search filter @@ -174,7 +174,7 @@ final class SearchBoxList<E> extends JPanel { public Collection<E> getItems() { return Collections.unmodifiableCollection(this.itemsToFilter); } - + /** * @return this component's search box component * @since 2019-04-14 @@ -183,7 +183,7 @@ final class SearchBoxList<E> extends JPanel { public final JTextField getSearchBox() { return this.searchBox; } - + /** * @param searchText text to search for * @return a filter that filters out that text, based on this list's case @@ -198,7 +198,7 @@ final class SearchBoxList<E> extends JPanel { return item -> item.toString().toLowerCase() .contains(searchText.toLowerCase()); } - + /** * @return this component's list component * @since 2019-04-14 @@ -207,7 +207,7 @@ final class SearchBoxList<E> extends JPanel { public final JList<E> getSearchList() { return this.searchItems; } - + /** * @return index selected in item list, -1 if no selection * @since 2019-04-14 @@ -216,7 +216,7 @@ final class SearchBoxList<E> extends JPanel { public int getSelectedIndex() { return this.searchItems.getSelectedIndex(); } - + /** * @return value selected in item list * @since 2019-04-13 @@ -225,7 +225,7 @@ final class SearchBoxList<E> extends JPanel { public Optional<E> getSelectedValue() { return Optional.ofNullable(this.searchItems.getSelectedValue()); } - + /** * Re-applies the filters. * @@ -238,21 +238,21 @@ final class SearchBoxList<E> extends JPanel { final FilterComparator<E> comparator = new FilterComparator<>(searchText, this.defaultOrdering, this.caseSensitive); final Predicate<E> searchFilter = this.getSearchFilter(searchText); - + this.listModel.clear(); this.itemsToFilter.forEach(item -> { if (searchFilter.test(item)) { this.listModel.add(item); } }); - + // applies the custom filters this.listModel.removeIf(this.customSearchFilter.negate()); - + // sorts the remaining items this.listModel.sort(comparator); } - + /** * Runs whenever the search box gains focus. * @@ -267,7 +267,7 @@ final class SearchBoxList<E> extends JPanel { this.searchBox.setForeground(Color.BLACK); } } - + /** * Runs whenever the search box loses focus. * @@ -282,7 +282,7 @@ final class SearchBoxList<E> extends JPanel { this.searchBox.setForeground(EMPTY_FOREGROUND); } } - + /** * Runs whenever the text in the search box is changed. * <p> @@ -301,7 +301,7 @@ final class SearchBoxList<E> extends JPanel { final FilterComparator<E> comparator = new FilterComparator<>(searchText, this.defaultOrdering, this.caseSensitive); final Predicate<E> searchFilter = this.getSearchFilter(searchText); - + // initialize list with items that match the filter then sort this.listModel.clear(); this.itemsToFilter.forEach(string -> { @@ -309,14 +309,14 @@ final class SearchBoxList<E> extends JPanel { this.listModel.add(string); } }); - + // applies the custom filters this.listModel.removeIf(this.customSearchFilter.negate()); - + // sorts the remaining items this.listModel.sort(comparator); } - + /** * Resets the search box list's contents to the provided items, removing any * old items @@ -329,7 +329,7 @@ final class SearchBoxList<E> extends JPanel { this.itemsToFilter.addAll(newItems); this.reapplyFilter(); } - + /** * Manually updates the search box's item list. * diff --git a/src/main/java/sevenUnitsGUI/StandardDisplayRules.java b/src/main/java/sevenUnitsGUI/StandardDisplayRules.java index cc69d31..d00263b 100644 --- a/src/main/java/sevenUnitsGUI/StandardDisplayRules.java +++ b/src/main/java/sevenUnitsGUI/StandardDisplayRules.java @@ -46,7 +46,7 @@ public final class StandardDisplayRules { * The number of places to round to. */ private final int decimalPlaces; - + /** * @param decimalPlaces * @since 2022-04-18 @@ -54,14 +54,14 @@ public final class StandardDisplayRules { private FixedDecimals(int decimalPlaces) { this.decimalPlaces = decimalPlaces; } - + @Override public String apply(UncertainDouble t) { final var toRound = new BigDecimal(t.value()); return toRound.setScale(this.decimalPlaces, RoundingMode.HALF_EVEN) .toPlainString(); } - + /** * @return the number of decimal places this rule rounds to * @since 2022-04-18 @@ -69,7 +69,7 @@ public final class StandardDisplayRules { public int decimalPlaces() { return this.decimalPlaces; } - + @Override public boolean equals(Object obj) { if (this == obj) @@ -81,18 +81,18 @@ public final class StandardDisplayRules { return false; return true; } - + @Override public int hashCode() { return 31 + this.decimalPlaces; } - + @Override public String toString() { return "Round to " + this.decimalPlaces + " decimal places"; } } - + /** * A rule that rounds to a fixed number of significant digits. * @@ -103,12 +103,12 @@ public final class StandardDisplayRules { implements Function<UncertainDouble, String> { public static final Pattern TO_STRING_PATTERN = Pattern .compile("Round to (\\d+) significant figures"); - + /** * The number of significant figures to round to. */ private final MathContext mathContext; - + /** * @param significantFigures * @since 2022-04-18 @@ -117,13 +117,13 @@ public final class StandardDisplayRules { this.mathContext = new MathContext(significantFigures, RoundingMode.HALF_EVEN); } - + @Override public String apply(UncertainDouble t) { final var toRound = new BigDecimal(t.value()); return toRound.round(this.mathContext).toString(); } - + @Override public boolean equals(Object obj) { if (this == obj) @@ -138,13 +138,13 @@ public final class StandardDisplayRules { return false; return true; } - + @Override public int hashCode() { return 127 + (this.mathContext == null ? 0 : this.mathContext.hashCode()); } - + /** * @return the number of significant figures this rule rounds to * @since 2022-04-18 @@ -152,14 +152,14 @@ public final class StandardDisplayRules { public int significantFigures() { return this.mathContext.getPrecision(); } - + @Override public String toString() { return "Round to " + this.mathContext.getPrecision() + " significant figures"; } } - + /** * A rounding rule that rounds based on UncertainDouble's toString method. * This means the output will have around as many significant figures as the @@ -170,25 +170,26 @@ public final class StandardDisplayRules { */ public static final class UncertaintyBased implements Function<UncertainDouble, String> { - private UncertaintyBased() {} - + private UncertaintyBased() { + } + @Override public String apply(UncertainDouble t) { return t.toString(false, RoundingMode.HALF_EVEN); } - + @Override public String toString() { return "Uncertainty-Based Rounding"; } } - + /** * For now, I want this to be a singleton. I might want to add a parameter * later, so I won't make it an enum. */ private static final UncertaintyBased UNCERTAINTY_BASED_ROUNDING_RULE = new UncertaintyBased(); - + /** * @param decimalPlaces decimal places to round to * @return a rounding rule that rounds to fixed number of decimal places @@ -198,7 +199,7 @@ public final class StandardDisplayRules { public static final FixedDecimals fixedDecimals(int decimalPlaces) { return new FixedDecimals(decimalPlaces); } - + /** * @param significantFigures significant figures to round to * @return a rounding rule that rounds to a fixed number of significant @@ -209,7 +210,7 @@ public final class StandardDisplayRules { public static final FixedPrecision fixedPrecision(int significantFigures) { return new FixedPrecision(significantFigures); } - + /** * Gets one of the standard rules from its string representation. * @@ -224,23 +225,23 @@ public final class StandardDisplayRules { String ruleToString) { if (UNCERTAINTY_BASED_ROUNDING_RULE.toString().equals(ruleToString)) return UNCERTAINTY_BASED_ROUNDING_RULE; - + // test if it is a fixed-places rule final var placesMatch = FixedDecimals.TO_STRING_PATTERN .matcher(ruleToString); if (placesMatch.matches()) return new FixedDecimals(Integer.valueOf(placesMatch.group(1))); - + // test if it is a fixed-sig-fig rule final var sigFigMatch = FixedPrecision.TO_STRING_PATTERN .matcher(ruleToString); if (sigFigMatch.matches()) return new FixedPrecision(Integer.valueOf(sigFigMatch.group(1))); - + throw new IllegalArgumentException( "Provided string does not match any given rules."); } - + /** * @return an UncertainDouble-based rounding rule * @since v0.4.0 @@ -249,6 +250,7 @@ public final class StandardDisplayRules { public static final UncertaintyBased uncertaintyBased() { return UNCERTAINTY_BASED_ROUNDING_RULE; } - - private StandardDisplayRules() {} + + private StandardDisplayRules() { + } } diff --git a/src/main/java/sevenUnitsGUI/TabbedView.java b/src/main/java/sevenUnitsGUI/TabbedView.java index 6181eae..997acc3 100644 --- a/src/main/java/sevenUnitsGUI/TabbedView.java +++ b/src/main/java/sevenUnitsGUI/TabbedView.java @@ -78,7 +78,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { */ private static final class JComboBoxItemSet<E> extends AbstractSet<E> { private final JComboBox<E> comboBox; - + /** * @param comboBox combo box to get items from * @since 2022-02-19 @@ -86,17 +86,17 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { public JComboBoxItemSet(JComboBox<E> comboBox) { this.comboBox = comboBox; } - + @Override public Iterator<E> iterator() { return new Iterator<>() { private int index = 0; - + @Override public boolean hasNext() { return this.index < JComboBoxItemSet.this.size(); } - + @Override public E next() { if (this.hasNext()) @@ -107,14 +107,14 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { } }; } - + @Override public int size() { return this.comboBox.getItemCount(); } - + } - + /** * The standard types of rounding, corresponding to the options on the * TabbedView's settings panel. @@ -139,7 +139,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { */ UNCERTAINTY; } - + /** * Creates a TabbedView. * @@ -153,14 +153,14 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { @SuppressWarnings("unused") final View view = new TabbedView(); } - + /** The Presenter that handles this View */ final Presenter presenter; /** The frame that this view lives on */ final JFrame frame; /** The tabbed pane that contains all of the components */ final JTabbedPane masterPane; - + // DIMENSION-BASED CONVERTER /** The combo box that selects dimensions */ final JComboBox<String> dimensionSelector; @@ -174,7 +174,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { final JButton convertUnitButton; /** The output area in the dimension-based converter */ final JTextArea unitOutput; - + // EXPRESSION-BASED CONVERTER /** The "From" entry in the conversion panel */ final JTextField fromEntry; @@ -184,7 +184,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { final JButton convertExpressionButton; /** The output area in the conversion panel */ final JTextArea expressionOutput; - + // UNIT AND PREFIX VIEWERS /** The searchable list of unit names in the unit viewer */ private final SearchBoxList<String> unitNameList; @@ -194,11 +194,11 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { private final JTextArea unitTextBox; /** The text box for prefix data in the prefix viewer */ private final JTextArea prefixTextBox; - + // SETTINGS STUFF private StandardRoundingType roundingType; private int precision; - + /** * Creates the view and makes it visible to the user * @@ -215,161 +215,161 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { System.err.println("Failed to enable system look-and-feel."); e.printStackTrace(); } - + // initialize important components this.presenter = new Presenter(this); this.frame = new JFrame("7Units " + ProgramInfo.VERSION); this.frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - + // master components (those that contain everything else within them) this.masterPane = new JTabbedPane(); this.frame.add(this.masterPane); - + // ============ UNIT CONVERSION TAB ============ final JPanel convertUnitPanel = new JPanel(); this.masterPane.addTab("Convert Units", convertUnitPanel); this.masterPane.setMnemonicAt(0, KeyEvent.VK_U); convertUnitPanel.setLayout(new BorderLayout()); - + { // panel for input part final JPanel inputPanel = new JPanel(); convertUnitPanel.add(inputPanel, BorderLayout.CENTER); inputPanel.setLayout(new GridLayout(1, 3)); inputPanel.setBorder(new EmptyBorder(6, 6, 3, 6)); - + this.fromSearch = new SearchBoxList<>(); inputPanel.add(this.fromSearch); - + final JPanel inBetweenPanel = new JPanel(); inputPanel.add(inBetweenPanel); inBetweenPanel.setLayout(new BorderLayout()); - + this.dimensionSelector = new JComboBox<>(); inBetweenPanel.add(this.dimensionSelector, BorderLayout.PAGE_START); this.dimensionSelector .addItemListener(e -> this.presenter.updateView()); - + final JLabel arrowLabel = new JLabel("-->"); inBetweenPanel.add(arrowLabel, BorderLayout.CENTER); arrowLabel.setHorizontalAlignment(SwingConstants.CENTER); - + this.toSearch = new SearchBoxList<>(); inputPanel.add(this.toSearch); } - + { // panel for submit and output, and also value entry final JPanel outputPanel = new JPanel(); convertUnitPanel.add(outputPanel, BorderLayout.PAGE_END); outputPanel.setLayout(new BorderLayout()); outputPanel.setBorder(new EmptyBorder(3, 6, 6, 6)); - + final JLabel valuePrompt = new JLabel("Value to convert: "); outputPanel.add(valuePrompt, BorderLayout.LINE_START); - + this.valueInput = new JTextField(); outputPanel.add(this.valueInput, BorderLayout.CENTER); - + // conversion button this.convertUnitButton = new JButton("Convert"); outputPanel.add(this.convertUnitButton, BorderLayout.LINE_END); this.convertUnitButton .addActionListener(e -> this.presenter.convertUnits()); this.convertUnitButton.setMnemonic(KeyEvent.VK_ENTER); - + // conversion output this.unitOutput = new JTextArea(2, 32); outputPanel.add(this.unitOutput, BorderLayout.PAGE_END); this.unitOutput.setEditable(false); } - + // ============ EXPRESSION CONVERSION TAB ============ final JPanel convertExpressionPanel = new JPanel(); this.masterPane.addTab("Convert Unit Expressions", convertExpressionPanel); this.masterPane.setMnemonicAt(1, KeyEvent.VK_E); convertExpressionPanel.setLayout(new GridLayout(4, 1)); - + // from and to expressions this.fromEntry = new JTextField(); convertExpressionPanel.add(this.fromEntry); this.fromEntry.setBorder(BorderFactory.createTitledBorder("From")); - + this.toEntry = new JTextField(); convertExpressionPanel.add(this.toEntry); this.toEntry.setBorder(BorderFactory.createTitledBorder("To")); - + // button to convert this.convertExpressionButton = new JButton("Convert"); convertExpressionPanel.add(this.convertExpressionButton); - + this.convertExpressionButton .addActionListener(e -> this.presenter.convertExpressions()); this.convertExpressionButton.setMnemonic(KeyEvent.VK_ENTER); - + // output of conversion this.expressionOutput = new JTextArea(2, 32); convertExpressionPanel.add(this.expressionOutput); this.expressionOutput .setBorder(BorderFactory.createTitledBorder("Output")); this.expressionOutput.setEditable(false); - + // =========== UNIT VIEWER =========== final JPanel unitLookupPanel = new JPanel(); this.masterPane.addTab("Unit Viewer", unitLookupPanel); this.masterPane.setMnemonicAt(2, KeyEvent.VK_V); unitLookupPanel.setLayout(new GridLayout()); - + this.unitNameList = new SearchBoxList<>(); unitLookupPanel.add(this.unitNameList); this.unitNameList.getSearchList() .addListSelectionListener(e -> this.presenter.unitNameSelected()); - + // the text box for unit's toString this.unitTextBox = new JTextArea(); unitLookupPanel.add(this.unitTextBox); this.unitTextBox.setEditable(false); this.unitTextBox.setLineWrap(true); - + // ============ PREFIX VIEWER ============= final JPanel prefixLookupPanel = new JPanel(); this.masterPane.addTab("Prefix Viewer", prefixLookupPanel); this.masterPane.setMnemonicAt(3, KeyEvent.VK_P); prefixLookupPanel.setLayout(new GridLayout(1, 2)); - + this.prefixNameList = new SearchBoxList<>(); prefixLookupPanel.add(this.prefixNameList); this.prefixNameList.getSearchList() .addListSelectionListener(e -> this.presenter.prefixSelected()); - + // the text box for prefix's toString this.prefixTextBox = new JTextArea(); prefixLookupPanel.add(this.prefixTextBox); this.prefixTextBox.setEditable(false); this.prefixTextBox.setLineWrap(true); - + // ============ INFO PANEL ============ - + final JPanel infoPanel = new JPanel(); this.masterPane.addTab("\uD83D\uDEC8", // info (i) character new JScrollPane(infoPanel)); - + final JTextArea infoTextArea = new JTextArea(); infoTextArea.setEditable(false); infoTextArea.setOpaque(false); infoPanel.add(infoTextArea); infoTextArea.setText(Presenter.getAboutText()); - + // ============ SETTINGS PANEL ============ this.masterPane.addTab("\u2699", new JScrollPane(this.createSettingsPanel())); this.masterPane.setMnemonicAt(5, KeyEvent.VK_S); - + // ============ FINALIZE CREATION OF VIEW ============ this.presenter.postViewInitialize(); this.frame.pack(); this.frame.setVisible(true); } - + /** * Creates and returns the settings panel (in its own function to make this * code more organized, as this function is massive!) @@ -378,28 +378,28 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { */ private JPanel createSettingsPanel() { final JPanel settingsPanel = new JPanel(); - + settingsPanel .setLayout(new BoxLayout(settingsPanel, BoxLayout.PAGE_AXIS)); - + // ============ ROUNDING SETTINGS ============ { final JPanel roundingPanel = new JPanel(); settingsPanel.add(roundingPanel); roundingPanel.setBorder(new TitledBorder("Rounding Settings")); roundingPanel.setLayout(new GridBagLayout()); - + // rounding rule selection final ButtonGroup roundingRuleButtons = new ButtonGroup(); this.roundingType = this.getPresenterRoundingType() .orElseThrow(() -> new AssertionError( "Presenter loaded non-standard rounding rule")); this.precision = this.getPresenterPrecision().orElse(6); - + final JLabel roundingRuleLabel = new JLabel("Rounding Rule:"); roundingPanel.add(roundingRuleLabel, new GridBagBuilder(0, 0) .setAnchor(GridBagConstraints.LINE_START).build()); - + // sigDigSlider needs to be first so that the rounding-type buttons can // show and hide it final JLabel sliderLabel = new JLabel("Precision:"); @@ -407,26 +407,26 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { this.roundingType != StandardRoundingType.UNCERTAINTY); roundingPanel.add(sliderLabel, new GridBagBuilder(0, 4) .setAnchor(GridBagConstraints.LINE_START).build()); - + final JSlider sigDigSlider = new JSlider(0, 12); roundingPanel.add(sigDigSlider, new GridBagBuilder(0, 5) .setAnchor(GridBagConstraints.LINE_START).build()); - + sigDigSlider.setMajorTickSpacing(4); sigDigSlider.setMinorTickSpacing(1); sigDigSlider.setSnapToTicks(true); sigDigSlider.setPaintTicks(true); sigDigSlider.setPaintLabels(true); - + sigDigSlider.setVisible( this.roundingType != StandardRoundingType.UNCERTAINTY); sigDigSlider.setValue(this.precision); - + sigDigSlider.addChangeListener(e -> { this.precision = sigDigSlider.getValue(); this.updatePresenterRoundingRule(); }); - + // significant digit rounding final JRadioButton fixedPrecision = new JRadioButton( "Fixed Precision"); @@ -442,7 +442,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { roundingRuleButtons.add(fixedPrecision); roundingPanel.add(fixedPrecision, new GridBagBuilder(0, 1) .setAnchor(GridBagConstraints.LINE_START).build()); - + // decimal place rounding final JRadioButton fixedDecimals = new JRadioButton( "Fixed Decimal Places"); @@ -458,7 +458,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { roundingRuleButtons.add(fixedDecimals); roundingPanel.add(fixedDecimals, new GridBagBuilder(0, 2) .setAnchor(GridBagConstraints.LINE_START).build()); - + // scientific rounding final JRadioButton relativePrecision = new JRadioButton( "Uncertainty-Based Rounding"); @@ -475,7 +475,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { roundingPanel.add(relativePrecision, new GridBagBuilder(0, 3) .setAnchor(GridBagConstraints.LINE_START).build()); } - + // ============ PREFIX REPETITION SETTINGS ============ { final JPanel prefixRepetitionPanel = new JPanel(); @@ -483,14 +483,14 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { prefixRepetitionPanel .setBorder(new TitledBorder("Prefix Repetition Settings")); prefixRepetitionPanel.setLayout(new GridBagLayout()); - + final var prefixRule = this.getPresenterPrefixRule() .orElseThrow(() -> new AssertionError( "Presenter loaded non-standard prefix rule")); - + // prefix rules final ButtonGroup prefixRuleButtons = new ButtonGroup(); - + final JRadioButton noRepetition = new JRadioButton("No Repetition"); if (prefixRule == DefaultPrefixRepetitionRule.NO_REPETITION) { noRepetition.setSelected(true); @@ -503,7 +503,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { prefixRuleButtons.add(noRepetition); prefixRepetitionPanel.add(noRepetition, new GridBagBuilder(0, 0) .setAnchor(GridBagConstraints.LINE_START).build()); - + final JRadioButton noRestriction = new JRadioButton("No Restriction"); if (prefixRule == DefaultPrefixRepetitionRule.NO_RESTRICTION) { noRestriction.setSelected(true); @@ -516,7 +516,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { prefixRuleButtons.add(noRestriction); prefixRepetitionPanel.add(noRestriction, new GridBagBuilder(0, 1) .setAnchor(GridBagConstraints.LINE_START).build()); - + final JRadioButton customRepetition = new JRadioButton( "Complex Repetition"); if (prefixRule == DefaultPrefixRepetitionRule.COMPLEX_REPETITION) { @@ -531,19 +531,19 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { prefixRepetitionPanel.add(customRepetition, new GridBagBuilder(0, 2) .setAnchor(GridBagConstraints.LINE_START).build()); } - + // ============ SEARCH SETTINGS ============ { final JPanel searchingPanel = new JPanel(); settingsPanel.add(searchingPanel); searchingPanel.setBorder(new TitledBorder("Search Settings")); searchingPanel.setLayout(new GridBagLayout()); - + // searching rules final ButtonGroup searchRuleButtons = new ButtonGroup(); - + final var searchRule = this.presenter.getSearchRule(); - + final JRadioButton noPrefixes = new JRadioButton( "Never Include Prefixed Units"); noPrefixes.addActionListener(e -> { @@ -554,7 +554,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { searchRuleButtons.add(noPrefixes); searchingPanel.add(noPrefixes, new GridBagBuilder(0, 0) .setAnchor(GridBagConstraints.LINE_START).build()); - + final JRadioButton commonPrefixes = new JRadioButton( "Include Common Prefixes"); commonPrefixes.addActionListener(e -> { @@ -565,7 +565,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { searchRuleButtons.add(commonPrefixes); searchingPanel.add(commonPrefixes, new GridBagBuilder(0, 1) .setAnchor(GridBagConstraints.LINE_START).build()); - + final JRadioButton alwaysInclude = new JRadioButton( "Include All Single Prefixes"); alwaysInclude.addActionListener(e -> { @@ -577,7 +577,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { searchRuleButtons.add(alwaysInclude); searchingPanel.add(alwaysInclude, new GridBagBuilder(0, 3) .setAnchor(GridBagConstraints.LINE_START).build()); - + if (PrefixSearchRule.NO_PREFIXES.equals(searchRule)) { noPrefixes.setSelected(true); } else if (PrefixSearchRule.COMMON_PREFIXES.equals(searchRule)) { @@ -589,13 +589,13 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { this.presenter.saveSettings(); } } - + // ============ OTHER SETTINGS ============ { final JPanel miscPanel = new JPanel(); settingsPanel.add(miscPanel); miscPanel.setLayout(new GridBagLayout()); - + final JCheckBox oneWay = new JCheckBox("Convert One Way Only"); oneWay.setSelected(this.presenter.oneWayConversionEnabled()); oneWay.addItemListener(e -> { @@ -605,7 +605,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { }); miscPanel.add(oneWay, new GridBagBuilder(0, 0) .setAnchor(GridBagConstraints.LINE_START).build()); - + final JCheckBox showAllVariations = new JCheckBox( "Show Duplicate Units & Prefixes"); showAllVariations.setSelected(this.presenter.duplicatesShown()); @@ -616,49 +616,49 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { }); miscPanel.add(showAllVariations, new GridBagBuilder(0, 1) .setAnchor(GridBagConstraints.LINE_START).build()); - + final JButton unitFileButton = new JButton("Manage Unit Data Files"); unitFileButton.setEnabled(false); miscPanel.add(unitFileButton, new GridBagBuilder(0, 2) .setAnchor(GridBagConstraints.LINE_START).build()); } - + return settingsPanel; } - + @Override public Set<String> getDimensionNames() { return Collections .unmodifiableSet(new JComboBoxItemSet<>(this.dimensionSelector)); } - + @Override public String getFromExpression() { return this.fromEntry.getText(); } - + @Override public Optional<String> getFromSelection() { return this.fromSearch.getSelectedValue(); } - + @Override public Set<String> getFromUnitNames() { // this should work because the only way I can mutate the item list is // with setFromUnits which only accepts a Set return new HashSet<>(this.fromSearch.getItems()); } - + @Override public String getInputValue() { return this.valueInput.getText(); } - + @Override public Presenter getPresenter() { return this.presenter; } - + /** * @return the precision of the presenter's rounding rule, if that is * meaningful @@ -678,7 +678,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { else return OptionalInt.empty(); } - + /** * @return presenter's prefix repetition rule * @since v0.4.0 @@ -690,7 +690,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { ? Optional.of((DefaultPrefixRepetitionRule) prefixRule) : Optional.empty(); } - + /** * Determines which rounding type the presenter is currently using, if any. * @@ -709,41 +709,41 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { else return Optional.empty(); } - + @Override public Optional<String> getSelectedDimensionName() { final String selectedItem = (String) this.dimensionSelector .getSelectedItem(); return Optional.ofNullable(selectedItem); } - + @Override public String getToExpression() { return this.toEntry.getText(); } - + @Override public Optional<String> getToSelection() { return this.toSearch.getSelectedValue(); } - + @Override public Set<String> getToUnitNames() { // this should work because the only way I can mutate the item list is // with setToUnits which only accepts a Set return new HashSet<>(this.toSearch.getItems()); } - + @Override public Optional<String> getViewedPrefixName() { return this.prefixNameList.getSelectedValue(); } - + @Override public Optional<String> getViewedUnitName() { return this.unitNameList.getSelectedValue(); } - + @Override public void setDimensionNames(Set<String> dimensionNames) { this.dimensionSelector.removeAllItems(); @@ -751,45 +751,45 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { this.dimensionSelector.addItem(d); } } - + @Override public void setFromUnitNames(Set<String> units) { this.fromSearch.setItems(units); } - + @Override public void setToUnitNames(Set<String> units) { this.toSearch.setItems(units); } - + @Override public void setViewablePrefixNames(Set<String> prefixNames) { this.prefixNameList.setItems(prefixNames); } - + @Override public void setViewableUnitNames(Set<String> unitNames) { this.unitNameList.setItems(unitNames); } - + @Override public void showErrorMessage(String title, String message) { JOptionPane.showMessageDialog(this.frame, message, title, JOptionPane.ERROR_MESSAGE); } - + @Override public void showExpressionConversionOutput(UnitConversionRecord uc) { this.expressionOutput.setText(String.format("%s = %s %s", uc.fromName(), uc.outputValueString(), uc.toName())); } - + @Override public void showPrefix(NameSymbol name, String multiplierString) { this.prefixTextBox.setText( String.format("%s%nMultiplier: %s", name, multiplierString)); } - + @Override public void showUnit(NameSymbol name, String definition, String dimensionName, UnitType type) { @@ -797,12 +797,12 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { String.format("%s%nDefinition: %s%nDimension: %s%nType: %s", name, definition, dimensionName, type)); } - + @Override public void showUnitConversionOutput(UnitConversionRecord uc) { this.unitOutput.setText(uc.toString()); } - + /** * Sets the presenter's rounding rule to the one specified by the current * settings diff --git a/src/main/java/sevenUnitsGUI/UnitConversionRecord.java b/src/main/java/sevenUnitsGUI/UnitConversionRecord.java index fa64ee9..43a62e6 100644 --- a/src/main/java/sevenUnitsGUI/UnitConversionRecord.java +++ b/src/main/java/sevenUnitsGUI/UnitConversionRecord.java @@ -44,7 +44,7 @@ public final class UnitConversionRecord { input.getValue().toString(false, RoundingMode.HALF_EVEN), output.getValue().toString(false, RoundingMode.HALF_EVEN)); } - + /** * Gets a {@code UnitConversionRecord} from two unit values * @@ -60,7 +60,7 @@ public final class UnitConversionRecord { output.getUnit().getName(), String.valueOf(input.getValue()), String.valueOf(output.getValue())); } - + /** * Gets a {@code UnitConversionRecord} * @@ -78,7 +78,7 @@ public final class UnitConversionRecord { return new UnitConversionRecord(fromName, toName, inputValueString, outputValueString); } - + /** * The name of the unit or expression that was converted from */ @@ -87,7 +87,7 @@ public final class UnitConversionRecord { * The name of the unit or expression that was converted to */ private final String toName; - + /** * A string representing the input value. It doesn't need to be the same as * the input value's string representation; it could be rounded, for example. @@ -98,7 +98,7 @@ public final class UnitConversionRecord { * the input value's string representation; it could be rounded, for example. */ private final String outputValueString; - + /** * @param fromName name of unit or expression that was converted * from @@ -114,7 +114,7 @@ public final class UnitConversionRecord { this.inputValueString = inputValueString; this.outputValueString = outputValueString; } - + @Override public boolean equals(Object obj) { if (this == obj) @@ -144,7 +144,7 @@ public final class UnitConversionRecord { return false; return true; } - + /** * @return name of unit or expression that was converted from * @since v0.4.0 @@ -153,7 +153,7 @@ public final class UnitConversionRecord { public String fromName() { return this.fromName; } - + @Override public int hashCode() { final int prime = 31; @@ -168,7 +168,7 @@ public final class UnitConversionRecord { + (this.toName == null ? 0 : this.toName.hashCode()); return result; } - + /** * @return string representing input value * @since v0.4.0 @@ -177,7 +177,7 @@ public final class UnitConversionRecord { public String inputValueString() { return this.inputValueString; } - + /** * @return string representing output value * @since v0.4.0 @@ -186,7 +186,7 @@ public final class UnitConversionRecord { public String outputValueString() { return this.outputValueString; } - + /** * @return name of unit or expression that was converted to * @since v0.4.0 @@ -195,7 +195,7 @@ public final class UnitConversionRecord { public String toName() { return this.toName; } - + @Override public String toString() { final String inputString = this.inputValueString.isBlank() ? this.fromName diff --git a/src/main/java/sevenUnitsGUI/UnitConversionView.java b/src/main/java/sevenUnitsGUI/UnitConversionView.java index 0d07823..b9077f7 100644 --- a/src/main/java/sevenUnitsGUI/UnitConversionView.java +++ b/src/main/java/sevenUnitsGUI/UnitConversionView.java @@ -33,21 +33,21 @@ public interface UnitConversionView extends View { * @since 2022-01-29 */ Set<String> getDimensionNames(); - + /** * @return name of unit to convert <em>from</em> * @since v0.4.0 * @since 2021-12-15 */ Optional<String> getFromSelection(); - + /** * @return list of names of units available to convert from * @since v0.4.0 * @since 2022-03-30 */ Set<String> getFromUnitNames(); - + /** * @return value to convert between the units (specifically, the numeric * string provided by the user) @@ -55,28 +55,28 @@ public interface UnitConversionView extends View { * @since 2021-12-15 */ String getInputValue(); - + /** * @return selected dimension * @since v0.4.0 * @since 2021-12-15 */ Optional<String> getSelectedDimensionName(); - + /** * @return name of unit to convert <em>to</em> * @since v0.4.0 * @since 2021-12-15 */ Optional<String> getToSelection(); - + /** * @return list of names of units available to convert to * @since v0.4.0 * @since 2022-03-30 */ Set<String> getToUnitNames(); - + /** * Sets the available dimensions for filtering. * @@ -85,7 +85,7 @@ public interface UnitConversionView extends View { * @since 2021-12-15 */ void setDimensionNames(Set<String> dimensionNames); - + /** * Sets the available units to convert from. {@link #getFromSelection} is not * required to use one of these units; this method is to be used for views @@ -96,7 +96,7 @@ public interface UnitConversionView extends View { * @since 2021-12-15 */ void setFromUnitNames(Set<String> unitNames); - + /** * Sets the available units to convert to. {@link #getToSelection} is not * required to use one of these units; this method is to be used for views @@ -107,7 +107,7 @@ public interface UnitConversionView extends View { * @since 2021-12-15 */ void setToUnitNames(Set<String> unitNames); - + /** * Shows the output of a unit conversion. * diff --git a/src/main/java/sevenUnitsGUI/View.java b/src/main/java/sevenUnitsGUI/View.java index bb810ec..7dd0c44 100644 --- a/src/main/java/sevenUnitsGUI/View.java +++ b/src/main/java/sevenUnitsGUI/View.java @@ -38,28 +38,28 @@ public interface View { static View createTabbedView() { return new TabbedView(); } - + /** * @return the presenter associated with this view * @since v0.4.0 * @since 2022-04-19 */ Presenter getPresenter(); - + /** * @return name of prefix currently being viewed * @since v0.4.0 * @since 2022-04-10 */ Optional<String> getViewedPrefixName(); - + /** * @return name of unit currently being viewed * @since v0.4.0 * @since 2022-04-10 */ Optional<String> getViewedUnitName(); - + /** * Sets the list of prefixes that are available to be viewed in a prefix * viewer @@ -69,7 +69,7 @@ public interface View { * @since 2022-04-10 */ void setViewablePrefixNames(Set<String> prefixNames); - + /** * Sets the list of units that are available to be viewed in a unit viewer * @@ -78,7 +78,7 @@ public interface View { * @since 2022-04-10 */ void setViewableUnitNames(Set<String> unitNames); - + /** * Shows an error message. * @@ -89,7 +89,7 @@ public interface View { * @since 2021-12-15 */ void showErrorMessage(String title, String message); - + /** * Shows information about a prefix to the user. * @@ -99,7 +99,7 @@ public interface View { * @since 2022-04-10 */ void showPrefix(NameSymbol name, String multiplierString); - + /** * Shows information about a unit to the user. * diff --git a/src/main/java/sevenUnitsGUI/ViewBot.java b/src/main/java/sevenUnitsGUI/ViewBot.java index e7304c4..e6593fb 100644 --- a/src/main/java/sevenUnitsGUI/ViewBot.java +++ b/src/main/java/sevenUnitsGUI/ViewBot.java @@ -46,7 +46,7 @@ public final class ViewBot public static final class PrefixViewingRecord implements Nameable { private final NameSymbol nameSymbol; private final String multiplierString; - + /** * @param nameSymbol * @param multiplierString @@ -57,7 +57,7 @@ public final class ViewBot this.nameSymbol = nameSymbol; this.multiplierString = multiplierString; } - + @Override public boolean equals(Object obj) { if (this == obj) @@ -68,25 +68,25 @@ public final class ViewBot return Objects.equals(this.multiplierString, other.multiplierString) && Objects.equals(this.nameSymbol, other.nameSymbol); } - + @Override public NameSymbol getNameSymbol() { return this.nameSymbol; } - + @Override public int hashCode() { return Objects.hash(this.multiplierString, this.nameSymbol); } - + public String multiplierString() { return this.multiplierString; } - + public NameSymbol nameSymbol() { return this.nameSymbol; } - + @Override public String toString() { final StringBuilder builder = new StringBuilder(); @@ -98,7 +98,7 @@ public final class ViewBot return builder.toString(); } } - + /** * A record of the parameters given to * {@link View#showUnit(NameSymbol, String, String, UnitType)}, for testing. @@ -110,7 +110,7 @@ public final class ViewBot private final String definition; private final String dimensionName; private final UnitType unitType; - + /** * @since 2022-04-16 */ @@ -121,7 +121,7 @@ public final class ViewBot this.dimensionName = dimensionName; this.unitType = unitType; } - + /** * @return the definition * @since 2022-04-16 @@ -129,7 +129,7 @@ public final class ViewBot public String definition() { return this.definition; } - + /** * @return the dimensionName * @since 2022-04-16 @@ -137,7 +137,7 @@ public final class ViewBot public String dimensionName() { return this.dimensionName; } - + @Override public boolean equals(Object obj) { if (this == obj) @@ -150,7 +150,7 @@ public final class ViewBot && Objects.equals(this.nameSymbol, other.nameSymbol) && this.unitType == other.unitType; } - + /** * @return the nameSymbol * @since 2022-04-16 @@ -159,17 +159,17 @@ public final class ViewBot public NameSymbol getNameSymbol() { return this.nameSymbol; } - + @Override public int hashCode() { return Objects.hash(this.definition, this.dimensionName, this.nameSymbol, this.unitType); } - + public NameSymbol nameSymbol() { return this.nameSymbol; } - + @Override public String toString() { final StringBuilder builder = new StringBuilder(); @@ -184,7 +184,7 @@ public final class ViewBot builder.append("]"); return builder.toString(); } - + /** * @return the unitType * @since 2022-04-16 @@ -193,10 +193,10 @@ public final class ViewBot return this.unitType; } } - + /** The presenter that works with this ViewBot */ private final Presenter presenter; - + /** The dimensions available to select from */ private Set<String> dimensionNames = Set.of(); /** The expression in the From field */ @@ -217,12 +217,12 @@ public final class ViewBot private Set<String> fromUnits = Set.of(); /** The units available in the To selection */ private Set<String> toUnits = Set.of(); - + /** The selected unit in the unit viewer */ private Optional<String> unitViewerSelection = Optional.empty(); /** The selected unit in the prefix viewer */ private Optional<String> prefixViewerSelection = Optional.empty(); - + /** Saved outputs of all unit conversions */ private final List<UnitConversionRecord> unitConversions; /** Saved outputs of all unit expressions */ @@ -231,7 +231,7 @@ public final class ViewBot private final List<UnitViewingRecord> unitViewingRecords; /** Saved outputs of all prefix viewings */ private final List<PrefixViewingRecord> prefixViewingRecords; - + /** * Creates a new {@code ViewBot} with a new presenter. * @@ -239,13 +239,13 @@ public final class ViewBot */ public ViewBot() { this.presenter = new Presenter(this); - + this.unitConversions = new ArrayList<>(); this.expressionConversions = new ArrayList<>(); this.unitViewingRecords = new ArrayList<>(); this.prefixViewingRecords = new ArrayList<>(); } - + /** * @return list of records of expression conversions done by this bot * @since 2022-04-09 @@ -253,7 +253,7 @@ public final class ViewBot public List<UnitConversionRecord> expressionConversionList() { return Collections.unmodifiableList(this.expressionConversions); } - + /** * @return the available dimensions * @since 2022-01-29 @@ -262,17 +262,17 @@ public final class ViewBot public Set<String> getDimensionNames() { return this.dimensionNames; } - + @Override public String getFromExpression() { return this.fromExpression; } - + @Override public Optional<String> getFromSelection() { return this.fromSelection; } - + /** * @return the units available for selection in From * @since 2022-01-29 @@ -281,12 +281,12 @@ public final class ViewBot public Set<String> getFromUnitNames() { return Collections.unmodifiableSet(this.fromUnits); } - + @Override public String getInputValue() { return this.inputValue; } - + /** * @return the presenter associated with tihs view * @since 2022-01-29 @@ -295,22 +295,22 @@ public final class ViewBot public Presenter getPresenter() { return this.presenter; } - + @Override public Optional<String> getSelectedDimensionName() { return this.selectedDimensionName; } - + @Override public String getToExpression() { return this.toExpression; } - + @Override public Optional<String> getToSelection() { return this.toSelection; } - + /** * @return the units available for selection in To * @since 2022-01-29 @@ -319,17 +319,17 @@ public final class ViewBot public Set<String> getToUnitNames() { return Collections.unmodifiableSet(this.toUnits); } - + @Override public Optional<String> getViewedPrefixName() { return this.prefixViewerSelection; } - + @Override public Optional<String> getViewedUnitName() { return this.unitViewerSelection; } - + /** * @return list of records of this viewBot's prefix views * @since 2022-04-16 @@ -337,13 +337,13 @@ public final class ViewBot public List<PrefixViewingRecord> prefixViewList() { return Collections.unmodifiableList(this.prefixViewingRecords); } - + @Override public void setDimensionNames(Set<String> dimensionNames) { this.dimensionNames = Objects.requireNonNull(dimensionNames, "dimensions may not be null"); } - + /** * Sets the From expression (as in {@link #getFromExpression}). * @@ -355,7 +355,7 @@ public final class ViewBot this.fromExpression = Objects.requireNonNull(fromExpression, "fromExpression cannot be null."); } - + /** * @param fromSelection the fromSelection to set * @since 2022-01-29 @@ -364,7 +364,7 @@ public final class ViewBot this.fromSelection = Objects.requireNonNull(fromSelection, "fromSelection cannot be null"); } - + /** * @param fromSelection the fromSelection to set * @since 2022-02-10 @@ -372,12 +372,12 @@ public final class ViewBot public void setFromSelection(String fromSelection) { this.setFromSelection(Optional.of(fromSelection)); } - + @Override public void setFromUnitNames(Set<String> units) { this.fromUnits = Objects.requireNonNull(units, "units may not be null"); } - + /** * @param inputValue the inputValue to set * @since 2022-01-29 @@ -385,7 +385,7 @@ public final class ViewBot public void setInputValue(String inputValue) { this.inputValue = inputValue; } - + /** * @param selectedDimension the selectedDimension to set * @since 2022-01-29 @@ -394,11 +394,11 @@ public final class ViewBot Optional<String> selectedDimensionName) { this.selectedDimensionName = selectedDimensionName; } - + public void setSelectedDimensionName(String selectedDimensionName) { this.setSelectedDimensionName(Optional.of(selectedDimensionName)); } - + /** * Sets the To expression (as in {@link #getToExpression}). * @@ -410,7 +410,7 @@ public final class ViewBot this.toExpression = Objects.requireNonNull(toExpression, "toExpression cannot be null."); } - + /** * @param toSelection the toSelection to set * @since 2022-01-29 @@ -419,77 +419,77 @@ public final class ViewBot this.toSelection = Objects.requireNonNull(toSelection, "toSelection cannot be null."); } - + public void setToSelection(String toSelection) { this.setToSelection(Optional.of(toSelection)); } - + @Override public void setToUnitNames(Set<String> units) { this.toUnits = Objects.requireNonNull(units, "units may not be null"); } - + @Override public void setViewablePrefixNames(Set<String> prefixNames) { // do nothing, ViewBot supports selecting any prefix } - + @Override public void setViewableUnitNames(Set<String> unitNames) { // do nothing, ViewBot supports selecting any unit } - + public void setViewedPrefixName(Optional<String> viewedPrefixName) { this.prefixViewerSelection = viewedPrefixName; } - + public void setViewedPrefixName(String viewedPrefixName) { this.setViewedPrefixName(Optional.of(viewedPrefixName)); } - + public void setViewedUnitName(Optional<String> viewedUnitName) { this.unitViewerSelection = viewedUnitName; } - + public void setViewedUnitName(String viewedUnitName) { this.setViewedUnitName(Optional.of(viewedUnitName)); } - + @Override public void showErrorMessage(String title, String message) { System.err.printf("%s: %s%n", title, message); } - + @Override public void showExpressionConversionOutput(UnitConversionRecord uc) { this.expressionConversions.add(uc); System.out.println("Expression Conversion: " + uc); } - + @Override public void showPrefix(NameSymbol name, String multiplierString) { this.prefixViewingRecords .add(new PrefixViewingRecord(name, multiplierString)); } - + @Override public void showUnit(NameSymbol name, String definition, String dimensionName, UnitType type) { this.unitViewingRecords .add(new UnitViewingRecord(name, definition, dimensionName, type)); } - + @Override public void showUnitConversionOutput(UnitConversionRecord uc) { this.unitConversions.add(uc); System.out.println("Unit Conversion: " + uc); } - + @Override public String toString() { return super.toString() + String.format("[presenter=%s]", this.presenter); } - + /** * @return list of records of every unit conversion made by this bot * @since 2022-04-09 @@ -497,7 +497,7 @@ public final class ViewBot public List<UnitConversionRecord> unitConversionList() { return Collections.unmodifiableList(this.unitConversions); } - + /** * @return list of records of unit viewings made by this bot * @since 2022-04-16 |