diff options
Diffstat (limited to 'src/org/unitConverter/converterGUI')
8 files changed, 0 insertions, 2770 deletions
| diff --git a/src/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java b/src/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java deleted file mode 100644 index bdc3a2e..0000000 --- a/src/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @since 2020-08-26 - */ -package org.unitConverter.converterGUI; - -import java.util.List; -import java.util.function.Predicate; - -import org.unitConverter.unit.SI; -import org.unitConverter.unit.UnitPrefix; - -/** - * A rule that specifies whether prefix repetition is allowed - * - * @since 2020-08-26 - */ -enum DefaultPrefixRepetitionRule implements Predicate<List<UnitPrefix>> { -	NO_REPETITION { -		@Override -		public boolean test(List<UnitPrefix> prefixes) { -			return prefixes.size() <= 1; -		} -	}, -	NO_RESTRICTION { -		@Override -		public boolean test(List<UnitPrefix> prefixes) { -			return true; -		} -	}, -	/** -	 * You are allowed to have any number of Yotta/Yocto followed by possibly one -	 * Kilo-Zetta/Milli-Zepto followed by possibly one Deca/Hecto. Same for -	 * reducing prefixes, don't mix magnifying and reducing. Non-metric -	 * (including binary) prefixes can't be repeated. -	 */ -	COMPLEX_REPETITION { -		@Override -		public boolean test(List<UnitPrefix> prefixes) { -			// determine whether we are magnifying or reducing -			final boolean magnifying; -			if (prefixes.isEmpty()) -				return true; -			else if (prefixes.get(0).getMultiplier() > 1) { -				magnifying = true; -			} 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 (!SI.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 -				if (!SI.DECIMAL_PREFIXES.contains(prefix)) -					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 -				switch (part) { -				case 0: -					// do nothing, any prefix is valid after a yotta -					break; -				case 1: -					// after a kilo-zetta, only deka/hecto are valid -					if (SI.THOUSAND_PREFIXES.contains(prefix)) -						return false; -					break; -				case 2: -					// deka/hecto must be the last prefix, so this is always invalid -					return false; -				} -				 -				// set part -				if (SI.YOTTA.equals(prefix) || SI.YOCTO.equals(prefix)) { -					part = 0; -				} else if (SI.THOUSAND_PREFIXES.contains(prefix)) { -					part = 1; -				} else { -					part = 2; -				} -			} -			return true; -		} -	}; -} diff --git a/src/org/unitConverter/converterGUI/DelegateListModel.java b/src/org/unitConverter/converterGUI/DelegateListModel.java deleted file mode 100644 index b80f63d..0000000 --- a/src/org/unitConverter/converterGUI/DelegateListModel.java +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Copyright (C) 2018 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ -package org.unitConverter.converterGUI; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -import javax.swing.AbstractListModel; - -/** - * A list model that delegates to a list. - * <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. - * </p> - *  - * @author Adrien Hopkins - * @since 2019-01-14 - * @since v0.1.0 - */ -final class DelegateListModel<E> extends AbstractListModel<E> implements List<E> { -	/** -	 * @since 2019-01-14 -	 * @since v0.1.0 -	 */ -	private static final long serialVersionUID = 8985494428224810045L; - -	/** -	 * The list that this model is a delegate to. -	 *  -	 * @since 2019-01-14 -	 * @since v0.1.0 -	 */ -	private final List<E> delegate; - -	/** -	 * Creates an empty {@code DelegateListModel}. -	 *  -	 * @since 2019-04-13 -	 */ -	public DelegateListModel() { -		this(new ArrayList<>()); -	} - -	/** -	 * Creates the {@code DelegateListModel}. -	 *  -	 * @param delegate -	 *            list to delegate -	 * @since 2019-01-14 -	 * @since v0.1.0 -	 */ -	public DelegateListModel(final List<E> delegate) { -		this.delegate = delegate; -	} - -	@Override -	public boolean add(final E element) { -		final int index = this.delegate.size(); -		final boolean success = this.delegate.add(element); -		this.fireIntervalAdded(this, index, index); -		return success; -	} - -	@Override -	public void add(final int index, final E element) { -		this.delegate.add(index, element); -		this.fireIntervalAdded(this, index, index); -	} - -	@Override -	public boolean addAll(final Collection<? extends E> c) { -		boolean changed = false; -		for (final E e : c) { -			if (this.add(e)) { -				changed = true; -			} -		} -		return changed; -	} - -	@Override -	public boolean addAll(final int index, final Collection<? extends E> c) { -		for (final E e : c) { -			this.add(index, e); -		} -		return !c.isEmpty(); // Since this is a list, it will always change if c has elements. -	} - -	@Override -	public void clear() { -		final int oldSize = this.delegate.size(); -		this.delegate.clear(); -		if (oldSize >= 1) { -			this.fireIntervalRemoved(this, 0, oldSize - 1); -		} -	} - -	@Override -	public boolean contains(final Object elem) { -		return this.delegate.contains(elem); -	} - -	@Override -	public boolean containsAll(final Collection<?> c) { -		for (final Object e : c) { -			if (!c.contains(e)) -				return false; -		} -		return true; -	} - -	@Override -	public E get(final int index) { -		return this.delegate.get(index); -	} - -	@Override -	public E getElementAt(final int index) { -		return this.delegate.get(index); -	} - -	@Override -	public int getSize() { -		return this.delegate.size(); -	} - -	@Override -	public int indexOf(final Object elem) { -		return this.delegate.indexOf(elem); -	} - -	@Override -	public boolean isEmpty() { -		return this.delegate.isEmpty(); -	} - -	@Override -	public Iterator<E> iterator() { -		return this.delegate.iterator(); -	} - -	@Override -	public int lastIndexOf(final Object elem) { -		return this.delegate.lastIndexOf(elem); -	} - -	@Override -	public ListIterator<E> listIterator() { -		return this.delegate.listIterator(); -	} - -	@Override -	public ListIterator<E> listIterator(final int index) { -		return this.delegate.listIterator(index); -	} - -	@Override -	public E remove(final int index) { -		final E returnValue = this.delegate.get(index); -		this.delegate.remove(index); -		this.fireIntervalRemoved(this, index, index); -		return returnValue; -	} - -	@Override -	public boolean remove(final Object o) { -		final int index = this.delegate.indexOf(o); -		final boolean returnValue = this.delegate.remove(o); -		this.fireIntervalRemoved(this, index, index); -		return returnValue; -	} - -	@Override -	public boolean removeAll(final Collection<?> c) { -		boolean changed = false; -		for (final Object e : c) { -			if (this.remove(e)) { -				changed = true; -			} -		} -		return changed; -	} - -	@Override -	public boolean retainAll(final Collection<?> c) { -		final int oldSize = this.size(); -		final boolean returnValue = this.delegate.retainAll(c); -		this.fireIntervalRemoved(this, this.size(), oldSize - 1); -		return returnValue; -	} - -	@Override -	public E set(final int index, final E element) { -		final E returnValue = this.delegate.get(index); -		this.delegate.set(index, element); -		this.fireContentsChanged(this, index, index); -		return returnValue; -	} - -	@Override -	public int size() { -		return this.delegate.size(); -	} - -	@Override -	public List<E> subList(final int fromIndex, final int toIndex) { -		return this.delegate.subList(fromIndex, toIndex); -	} - -	@Override -	public Object[] toArray() { -		return this.delegate.toArray(); -	} - -	@Override -	public <T> T[] toArray(final T[] a) { -		return this.delegate.toArray(a); -	} - -	@Override -	public String toString() { -		return this.delegate.toString(); -	} -} diff --git a/src/org/unitConverter/converterGUI/FilterComparator.java b/src/org/unitConverter/converterGUI/FilterComparator.java deleted file mode 100644 index 7b17bfc..0000000 --- a/src/org/unitConverter/converterGUI/FilterComparator.java +++ /dev/null @@ -1,129 +0,0 @@ -/**
 - * Copyright (C) 2018 Adrien Hopkins
 - *
 - * This program is free software: you can redistribute it and/or modify
 - * it under the terms of the GNU Affero General Public License as published by
 - * the Free Software Foundation, either version 3 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU Affero General Public License for more details.
 - *
 - * You should have received a copy of the GNU Affero General Public License
 - * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 - */
 -package org.unitConverter.converterGUI;
 -
 -import java.util.Comparator;
 -import java.util.Objects;
 -
 -/**
 - * A comparator that compares strings using a filter.
 - * 
 - * @author Adrien Hopkins
 - * @since 2019-01-15
 - * @since v0.1.0
 - */
 -final class FilterComparator implements Comparator<String> {
 -	/**
 -	 * The filter that the comparator is filtered by.
 -	 * 
 -	 * @since 2019-01-15
 -	 * @since v0.1.0
 -	 */
 -	private final String filter;
 -	/**
 -	 * The comparator to use if the arguments are otherwise equal.
 -	 * 
 -	 * @since 2019-01-15
 -	 * @since v0.1.0
 -	 */
 -	private final Comparator<String> comparator;
 -	/**
 -	 * Whether or not the comparison is case-sensitive.
 -	 * 
 -	 * @since 2019-04-14
 -	 * @since v0.2.0
 -	 */
 -	private final boolean caseSensitive;
 -
 -	/**
 -	 * Creates the {@code FilterComparator}.
 -	 * 
 -	 * @param filter
 -	 * @since 2019-01-15
 -	 * @since v0.1.0
 -	 */
 -	public FilterComparator(final String filter) {
 -		this(filter, null);
 -	}
 -
 -	/**
 -	 * Creates the {@code FilterComparator}.
 -	 * 
 -	 * @param filter
 -	 *            string to filter by
 -	 * @param comparator
 -	 *            comparator to fall back to if all else fails, null is compareTo.
 -	 * @throws NullPointerException
 -	 *             if filter is null
 -	 * @since 2019-01-15
 -	 * @since v0.1.0
 -	 */
 -	public FilterComparator(final String filter, final Comparator<String> comparator) {
 -		this(filter, comparator, false);
 -	}
 -
 -	/**
 -	 * Creates the {@code FilterComparator}.
 -	 * 
 -	 * @param filter
 -	 *            string to filter by
 -	 * @param comparator
 -	 *            comparator to fall back to if all else fails, null is compareTo.
 -	 * @param caseSensitive
 -	 *            whether or not the comparator is case-sensitive
 -	 * @throws NullPointerException
 -	 *             if filter is null
 -	 * @since 2019-04-14
 -	 * @since v0.2.0
 -	 */
 -	public FilterComparator(final String filter, final Comparator<String> comparator, final boolean caseSensitive) {
 -		this.filter = Objects.requireNonNull(filter, "filter must not be null.");
 -		this.comparator = comparator;
 -		this.caseSensitive = caseSensitive;
 -	}
 -
 -	@Override
 -	public int compare(final String arg0, final String arg1) {
 -		// if this is case insensitive, make them lowercase
 -		final String str0, str1;
 -		if (this.caseSensitive) {
 -			str0 = arg0;
 -			str1 = arg1;
 -		} else {
 -			str0 = arg0.toLowerCase();
 -			str1 = arg1.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);
 -		else
 -			return this.comparator.compare(str0, str1);
 -	}
 -}
 diff --git a/src/org/unitConverter/converterGUI/GridBagBuilder.java b/src/org/unitConverter/converterGUI/GridBagBuilder.java deleted file mode 100644 index f1229b2..0000000 --- a/src/org/unitConverter/converterGUI/GridBagBuilder.java +++ /dev/null @@ -1,479 +0,0 @@ -/** - * Copyright (C) 2018 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ -package org.unitConverter.converterGUI; - -import java.awt.GridBagConstraints; -import java.awt.Insets; - -/** - * A builder for Java's {@link java.awt.GridBagConstraints} class. - *  - * @author Adrien Hopkins - * @since 2018-11-30 - * @since v0.1.0 - */ -final class GridBagBuilder { -	/** -	 * The built {@code GridBagConstraints}'s {@code gridx} property. -	 * <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. -	 * <p> -	 * The default value is <code>RELATIVE</code>. <code>gridx</code> should be a non-negative value. -	 *  -	 * @serial -	 * @see #clone() -	 * @see java.awt.GridBagConstraints#gridy -	 * @see java.awt.ComponentOrientation -	 */ -	private final int gridx; - -	/** -	 * 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. -	 * <p> -	 * The default value is <code>RELATIVE</code>. <code>gridy</code> should be a non-negative value. -	 *  -	 * @serial -	 * @see #clone() -	 * @see java.awt.GridBagConstraints#gridx -	 */ -	private final int gridy; - -	/** -	 * The built {@code GridBagConstraints}'s {@code gridwidth} property. -	 * <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. -	 * <p> -	 * <code>gridwidth</code> should be non-negative and the default value is 1. -	 *  -	 * @serial -	 * @see #clone() -	 * @see java.awt.GridBagConstraints#gridheight -	 */ -	private final int gridwidth; - -	/** -	 * The built {@code GridBagConstraints}'s {@code gridheight} property. -	 * <p> -	 * 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. -	 * <p> -	 * <code>gridheight</code> should be a non-negative value and the default value is 1. -	 *  -	 * @serial -	 * @see #clone() -	 * @see java.awt.GridBagConstraints#gridwidth -	 */ -	private final int gridheight; - -	/** -	 * The built {@code GridBagConstraints}'s {@code weightx} property. -	 * <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. -	 * <p> -	 * 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. -	 *  -	 * @serial -	 * @see #clone() -	 * @see java.awt.GridBagConstraints#weighty -	 */ -	private double weightx; - -	/** -	 * The built {@code GridBagConstraints}'s {@code weighty} property. -	 * <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. -	 * <p> -	 * 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. -	 *  -	 * @serial -	 * @see #clone() -	 * @see java.awt.GridBagConstraints#weightx -	 */ -	private double weighty; - -	/** -	 * 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. -	 * <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 -	 * <code>CENTER</code>. -	 *  -	 * @serial -	 * @see #clone() -	 * @see java.awt.ComponentOrientation -	 */ -	private int anchor; - -	/** -	 * 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. -	 * <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>BOTH</code>: Make the component fill its display area entirely. -	 * </ul> -	 * <p> -	 * The default value is <code>NONE</code>. -	 *  -	 * @serial -	 * @see #clone() -	 */ -	private int fill; - -	/** -	 * 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. -	 * <p> -	 * The default value is <code>new Insets(0, 0, 0, 0)</code>. -	 *  -	 * @serial -	 * @see #clone() -	 */ -	private Insets insets; - -	/** -	 * 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. -	 * <p> -	 * The default value is <code>0</code>. -	 *  -	 * @serial -	 * @see #clone() -	 * @see java.awt.GridBagConstraints#ipady -	 */ -	private int ipadx; - -	/** -	 * 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. -	 * <p> -	 * The default value is 0. -	 *  -	 * @serial -	 * @see #clone() -	 * @see java.awt.GridBagConstraints#ipadx -	 */ -	private int ipady; - -	/** -	 * @param gridx -	 *            x position -	 * @param gridy -	 *            y position -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public GridBagBuilder(final int gridx, final int gridy) { -		this(gridx, gridy, 1, 1); -	} - -	/** -	 * @param gridx -	 *            x position -	 * @param gridy -	 *            y position -	 * @param gridwidth -	 *            number of cells occupied horizontally -	 * @param gridheight -	 *            number of cells occupied vertically -	 * @since 2018-11-30 -	 * @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, -				new Insets(0, 0, 0, 0), 0, 0); -	} - -	/** -	 * @param gridx -	 *            x position -	 * @param gridy -	 *            y position -	 * @param gridwidth -	 *            number of cells occupied horizontally -	 * @param gridheight -	 *            number of cells occupied vertically -	 * @param weightx -	 * @param weighty -	 * @param anchor -	 * @param fill -	 * @param insets -	 * @param ipadx -	 * @param ipady -	 * @since 2018-11-30 -	 * @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) { -		super(); -		this.gridx = gridx; -		this.gridy = gridy; -		this.gridwidth = gridwidth; -		this.gridheight = gridheight; -		this.weightx = weightx; -		this.weighty = weighty; -		this.anchor = anchor; -		this.fill = fill; -		this.insets = (Insets) insets.clone(); -		this.ipadx = ipadx; -		this.ipady = ipady; -	} - -	/** -	 * @return {@code GridBagConstraints} created by this builder -	 * @since 2018-11-30 -	 * @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 anchor -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public int getAnchor() { -		return this.anchor; -	} - -	/** -	 * @return fill -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public int getFill() { -		return this.fill; -	} - -	/** -	 * @return gridheight -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public int getGridheight() { -		return this.gridheight; -	} - -	/** -	 * @return gridwidth -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public int getGridwidth() { -		return this.gridwidth; -	} - -	/** -	 * @return gridx -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public int getGridx() { -		return this.gridx; -	} - -	/** -	 * @return gridy -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public int getGridy() { -		return this.gridy; -	} - -	/** -	 * @return insets -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public Insets getInsets() { -		return this.insets; -	} - -	/** -	 * @return ipadx -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public int getIpadx() { -		return this.ipadx; -	} - -	/** -	 * @return ipady -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public int getIpady() { -		return this.ipady; -	} - -	/** -	 * @return weightx -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public double getWeightx() { -		return this.weightx; -	} - -	/** -	 * @return weighty -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public double getWeighty() { -		return this.weighty; -	} - -	/** -	 * @param anchor -	 *            anchor to set -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public GridBagBuilder setAnchor(final int anchor) { -		this.anchor = anchor; -		return this; -	} - -	/** -	 * @param fill -	 *            fill to set -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public GridBagBuilder setFill(final int fill) { -		this.fill = fill; -		return this; -	} - -	/** -	 * @param insets -	 *            insets to set -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public GridBagBuilder setInsets(final Insets insets) { -		this.insets = insets; -		return this; -	} - -	/** -	 * @param ipadx -	 *            ipadx to set -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public GridBagBuilder setIpadx(final int ipadx) { -		this.ipadx = ipadx; -		return this; -	} - -	/** -	 * @param ipady -	 *            ipady to set -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public GridBagBuilder setIpady(final int ipady) { -		this.ipady = ipady; -		return this; -	} - -	/** -	 * @param weightx -	 *            weightx to set -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public GridBagBuilder setWeightx(final double weightx) { -		this.weightx = weightx; -		return this; -	} - -	/** -	 * @param weighty -	 *            weighty to set -	 * @since 2018-11-30 -	 * @since v0.1.0 -	 */ -	public GridBagBuilder setWeighty(final double weighty) { -		this.weighty = weighty; -		return this; -	} -} diff --git a/src/org/unitConverter/converterGUI/MutablePredicate.java b/src/org/unitConverter/converterGUI/MutablePredicate.java deleted file mode 100644 index e15b3cd..0000000 --- a/src/org/unitConverter/converterGUI/MutablePredicate.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ -package org.unitConverter.converterGUI; - -import java.util.function.Predicate; - -/** - * A container for a predicate, which can be changed later. - *  - * @author Adrien Hopkins - * @since 2019-04-13 - * @since v0.2.0 - */ -final class MutablePredicate<T> implements Predicate<T> { -	/** -	 * The predicate stored in this {@code MutablePredicate} -	 *  -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	private Predicate<T> predicate; - -	/** -	 * Creates the {@code MutablePredicate}. -	 *  -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	public MutablePredicate(final Predicate<T> predicate) { -		this.predicate = predicate; -	} - -	/** -	 * @return predicate -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	public final Predicate<T> getPredicate() { -		return this.predicate; -	} - -	/** -	 * @param predicate -	 *            new value of predicate -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	public final void setPredicate(final Predicate<T> predicate) { -		this.predicate = predicate; -	} - -	@Override -	public boolean test(final T t) { -		return this.predicate.test(t); -	} -} diff --git a/src/org/unitConverter/converterGUI/SearchBoxList.java b/src/org/unitConverter/converterGUI/SearchBoxList.java deleted file mode 100644 index 10ef589..0000000 --- a/src/org/unitConverter/converterGUI/SearchBoxList.java +++ /dev/null @@ -1,307 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ -package org.unitConverter.converterGUI; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.function.Predicate; - -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; - -/** - * @author Adrien Hopkins - * @since 2019-04-13 - * @since v0.2.0 - */ -final class SearchBoxList 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. -	 *  -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	private static final String EMPTY_TEXT = "Search..."; -	 -	/** -	 * The color to use for an empty foreground. -	 *  -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	private static final Color EMPTY_FOREGROUND = new Color(192, 192, 192); -	 -	// the components -	private final Collection<String> itemsToFilter; -	private final DelegateListModel<String> listModel; -	private final JTextField searchBox; -	private final JList<String> 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<String> customSearchFilter = o -> true; -	private final Comparator<String> defaultOrdering; -	private final boolean caseSensitive; -	 -	/** -	 * Creates the {@code SearchBoxList}. -	 *  -	 * @param itemsToFilter items to put in the list -	 * @since 2019-04-14 -	 */ -	public SearchBoxList(final Collection<String> itemsToFilter) { -		this(itemsToFilter, null, false); -	} -	 -	/** -	 * Creates the {@code SearchBoxList}. -	 *  -	 * @param itemsToFilter   items to put in the list -	 * @param defaultOrdering default ordering of items after filtration -	 *                        (null=Comparable) -	 * @param caseSensitive   whether or not the filtration is case-sensitive -	 *  -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	public SearchBoxList(final Collection<String> itemsToFilter, -			final Comparator<String> defaultOrdering, -			final boolean caseSensitive) { -		super(new BorderLayout(), true); -		this.itemsToFilter = 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. -	 *  -	 * @param filter filter to add. -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	public void addSearchFilter(final Predicate<String> filter) { -		this.customSearchFilter = this.customSearchFilter.and(filter); -	} -	 -	/** -	 * Resets the search filter. -	 *  -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	public void clearSearchFilters() { -		this.customSearchFilter = o -> true; -	} -	 -	/** -	 * @return this component's search box component -	 * @since 2019-04-14 -	 * @since v0.2.0 -	 */ -	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 -	 *         sensitive setting -	 * @since 2019-04-14 -	 * @since v0.2.0 -	 */ -	private Predicate<String> getSearchFilter(final String searchText) { -		if (this.caseSensitive) -			return string -> string.contains(searchText); -		else -			return string -> string.toLowerCase() -					.contains(searchText.toLowerCase()); -	} -	 -	/** -	 * @return this component's list component -	 * @since 2019-04-14 -	 * @since v0.2.0 -	 */ -	public final JList<String> getSearchList() { -		return this.searchItems; -	} -	 -	/** -	 * @return index selected in item list -	 * @since 2019-04-14 -	 * @since v0.2.0 -	 */ -	public int getSelectedIndex() { -		return this.searchItems.getSelectedIndex(); -	} -	 -	/** -	 * @return value selected in item list -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	public String getSelectedValue() { -		return this.searchItems.getSelectedValue(); -	} -	 -	/** -	 * Re-applies the filters. -	 *  -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	public void reapplyFilter() { -		final String searchText = this.searchBoxEmpty ? "" -				: this.searchBox.getText(); -		final FilterComparator comparator = new FilterComparator(searchText, -				this.defaultOrdering, this.caseSensitive); -		final Predicate<String> searchFilter = this.getSearchFilter(searchText); -		 -		this.listModel.clear(); -		this.itemsToFilter.forEach(string -> { -			if (searchFilter.test(string)) { -				this.listModel.add(string); -			} -		}); -		 -		// 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. -	 *  -	 * @param e focus event -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	private void searchBoxFocusGained(final FocusEvent e) { -		this.searchBoxFocused = true; -		if (this.searchBoxEmpty) { -			this.searchBox.setText(""); -			this.searchBox.setForeground(Color.BLACK); -		} -	} -	 -	/** -	 * Runs whenever the search box loses focus. -	 *  -	 * @param e focus event -	 * @since 2019-04-13 -	 * @since v0.2.0 -	 */ -	private void searchBoxFocusLost(final FocusEvent e) { -		this.searchBoxFocused = false; -		if (this.searchBoxEmpty) { -			this.searchBox.setText(EMPTY_TEXT); -			this.searchBox.setForeground(EMPTY_FOREGROUND); -		} -	} -	 -	/** -	 * Runs whenever the text in the search box is changed. -	 * <p> -	 * Reapplies the search filter, and custom filters. -	 * </p> -	 *  -	 * @since 2019-04-14 -	 * @since v0.2.0 -	 */ -	private void searchBoxTextChanged() { -		if (this.searchBoxFocused) { -			this.searchBoxEmpty = this.searchBox.getText().equals(""); -		} -		final String searchText = this.searchBoxEmpty ? "" -				: this.searchBox.getText(); -		final FilterComparator comparator = new FilterComparator(searchText, -				this.defaultOrdering, this.caseSensitive); -		final Predicate<String> searchFilter = this.getSearchFilter(searchText); -		 -		// initialize list with items that match the filter then sort -		this.listModel.clear(); -		this.itemsToFilter.forEach(string -> { -			if (searchFilter.test(string)) { -				this.listModel.add(string); -			} -		}); -		 -		// applies the custom filters -		this.listModel.removeIf(this.customSearchFilter.negate()); -		 -		// sorts the remaining items -		this.listModel.sort(comparator); -	} -	 -	/** -	 * Manually updates the search box's item list. -	 *  -	 * @since 2020-08-27 -	 */ -	public void updateList() { -		this.searchBoxTextChanged(); -	} -} diff --git a/src/org/unitConverter/converterGUI/UnitConverterGUI.java b/src/org/unitConverter/converterGUI/UnitConverterGUI.java deleted file mode 100644 index 6ddc4a0..0000000 --- a/src/org/unitConverter/converterGUI/UnitConverterGUI.java +++ /dev/null @@ -1,1424 +0,0 @@ -/** - * Copyright (C) 2018-2021 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ -package org.unitConverter.converterGUI; - -import java.awt.BorderLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.event.KeyEvent; -import java.io.BufferedWriter; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; -import java.nio.file.Files; -import java.nio.file.Path; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JFormattedTextField; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JScrollPane; -import javax.swing.JSlider; -import javax.swing.JTabbedPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import javax.swing.WindowConstants; -import javax.swing.border.TitledBorder; - -import org.unitConverter.math.ConditionalExistenceCollections; -import org.unitConverter.math.ObjectProduct; -import org.unitConverter.unit.BaseDimension; -import org.unitConverter.unit.BritishImperial; -import org.unitConverter.unit.LinearUnit; -import org.unitConverter.unit.LinearUnitValue; -import org.unitConverter.unit.NameSymbol; -import org.unitConverter.unit.SI; -import org.unitConverter.unit.Unit; -import org.unitConverter.unit.UnitDatabase; -import org.unitConverter.unit.UnitPrefix; -import org.unitConverter.unit.UnitValue; - -/** - * @author Adrien Hopkins - * @since 2018-12-27 - * @since v0.1.0 - */ -final class UnitConverterGUI { -	/** -	 * A tab in the View. -	 */ -	private enum Pane { -		UNIT_CONVERTER, EXPRESSION_CONVERTER, UNIT_VIEWER, PREFIX_VIEWER, ABOUT, -		SETTINGS; -	} -	 -	private static class Presenter { -		/** The default place where settings are stored. */ -		private static final String DEFAULT_SETTINGS_FILEPATH = "settings.txt"; -		/** The default place where units are stored. */ -		private static final Path DEFAULT_UNITS_FILE = Path.of("unitsfile.txt"); -		/** The default place where dimensions are stored. */ -		private static final Path DEFAULT_DIMENSION_FILE = Path -				.of("dimensionfile.txt"); -		/** The default place where exceptions are stored. */ -		private static final Path DEFAULT_EXCEPTIONS_FILE = Path -				.of("metric_exceptions.txt"); -		 -		/** -		 * Adds default units and dimensions to a database. -		 *  -		 * @param database database to add to -		 * @since 2019-04-14 -		 * @since v0.2.0 -		 */ -		private static void addDefaults(final UnitDatabase database) { -			database.addUnit("metre", SI.METRE); -			database.addUnit("kilogram", SI.KILOGRAM); -			database.addUnit("gram", SI.KILOGRAM.dividedBy(1000)); -			database.addUnit("second", SI.SECOND); -			database.addUnit("ampere", SI.AMPERE); -			database.addUnit("kelvin", SI.KELVIN); -			database.addUnit("mole", SI.MOLE); -			database.addUnit("candela", SI.CANDELA); -			database.addUnit("bit", SI.BIT); -			database.addUnit("unit", SI.ONE); -			// nonlinear units - must be loaded manually -			database.addUnit("tempCelsius", SI.CELSIUS); -			database.addUnit("tempFahrenheit", BritishImperial.FAHRENHEIT); -			 -			// load initial dimensions -			database.addDimension("LENGTH", SI.Dimensions.LENGTH); -			database.addDimension("MASS", SI.Dimensions.MASS); -			database.addDimension("TIME", SI.Dimensions.TIME); -			database.addDimension("TEMPERATURE", SI.Dimensions.TEMPERATURE); -		} -		 -		/** -		 * @return {@code line} with any comments removed. -		 * @since 2021-03-13 -		 */ -		private static final String withoutComments(String line) { -			final int index = line.indexOf('#'); -			return index == -1 ? line : line.substring(index); -		} -		 -		/** The presenter's associated view. */ -		private final View view; -		 -		/** The units known by the program. */ -		private final UnitDatabase database; -		 -		/** The names of all of the units */ -		private final List<String> unitNames; -		 -		/** The names of all of the prefixes */ -		private final List<String> prefixNames; -		 -		/** The names of all of the dimensions */ -		private final List<String> dimensionNames; -		 -		/** Unit names that are ignored by the metric-only/imperial-only filter */ -		private final Set<String> metricExceptions; -		 -		private final Comparator<String> prefixNameComparator; -		 -		/** A boolean remembering whether or not one-way conversion is on */ -		private boolean oneWay = true; -		 -		/** The prefix rule */ -		private DefaultPrefixRepetitionRule prefixRule = null; -		// conditions for existence of From and To entries -		// used for one-way conversion -		private final MutablePredicate<String> fromExistenceCondition = new MutablePredicate<>( -				s -> true); -		 -		private final MutablePredicate<String> toExistenceCondition = new MutablePredicate<>( -				s -> true); -		 -		/* -		 * Rounding-related settings. I am using my own system, and not -		 * MathContext, because MathContext does not support decimal place based -		 * or scientific rounding, only significant digit based rounding. -		 */ -		private int precision = 6; -		 -		private RoundingType roundingType = RoundingType.SIGNIFICANT_DIGITS; -		 -		/** -		 * Creates the presenter. -		 *  -		 * @param view presenter's associated view -		 * @since 2018-12-27 -		 * @since v0.1.0 -		 */ -		Presenter(final View view) { -			this.view = view; -			 -			// load initial units -			this.database = new UnitDatabase( -					DefaultPrefixRepetitionRule.NO_RESTRICTION); -			Presenter.addDefaults(this.database); -			 -			this.database.loadUnitsFile(DEFAULT_UNITS_FILE); -			this.database.loadDimensionFile(DEFAULT_DIMENSION_FILE); -			 -			// load metric exceptions -			try { -				this.metricExceptions = Files.readAllLines(DEFAULT_EXCEPTIONS_FILE) -						.stream().map(Presenter::withoutComments) -						.filter(s -> !s.isBlank()).collect(Collectors.toSet()); -			} catch (final IOException e) { -				throw new AssertionError("Loading of metric_exceptions.txt failed.", -						e); -			} -			 -			// load settings - requires database to exist -			this.loadSettings(); -			 -			// a comparator that can be used to compare prefix names -			// any name that does not exist is less than a name that does. -			// otherwise, they are compared by value -			this.prefixNameComparator = (o1, o2) -> { -				if (!Presenter.this.database.containsPrefixName(o1)) -					return -1; -				else if (!Presenter.this.database.containsPrefixName(o2)) -					return 1; -				 -				final UnitPrefix p1 = Presenter.this.database.getPrefix(o1); -				final UnitPrefix p2 = Presenter.this.database.getPrefix(o2); -				 -				if (p1.getMultiplier() < p2.getMultiplier()) -					return -1; -				else if (p1.getMultiplier() > p2.getMultiplier()) -					return 1; -				 -				return o1.compareTo(o2); -			}; -			 -			this.unitNames = new ArrayList<>( -					this.database.unitMapPrefixless().keySet()); -			this.unitNames.sort(null); // sorts it using Comparable -			 -			this.prefixNames = new ArrayList<>(this.database.prefixMap().keySet()); -			this.prefixNames.sort(this.prefixNameComparator); // sorts it using my -																				// comparator -			 -			this.dimensionNames = new DelegateListModel<>( -					new ArrayList<>(this.database.dimensionMap().keySet())); -			this.dimensionNames.sort(null); // sorts it using Comparable -			 -			// a Predicate that returns true iff the argument is a full base unit -			final Predicate<Unit> isFullBase = unit -> unit instanceof LinearUnit -					&& ((LinearUnit) unit).isBase(); -			 -			// print out unit counts -			System.out.printf( -					"Successfully loaded %d units with %d unit names (%d base units).%n", -					new HashSet<>(this.database.unitMapPrefixless().values()).size(), -					this.database.unitMapPrefixless().size(), -					new HashSet<>(this.database.unitMapPrefixless().values()) -							.stream().filter(isFullBase).count()); -		} -		 -		/** -		 * Converts in the dimension-based converter -		 *  -		 * @since 2019-04-13 -		 * @since v0.2.0 -		 */ -		public final void convertDimensionBased() { -			final String fromSelection = this.view.getFromSelection(); -			if (fromSelection == null) { -				this.view.showErrorDialog("Error", -						"No unit selected in From field"); -				return; -			} -			final String toSelection = this.view.getToSelection(); -			if (toSelection == null) { -				this.view.showErrorDialog("Error", "No unit selected in To field"); -				return; -			} -			 -			final Unit from = this.database.getUnit(fromSelection); -			final Unit to = this.database.getUnit(toSelection) -					.withName(NameSymbol.ofName(toSelection)); -			 -			final UnitValue beforeValue; -			try { -				beforeValue = UnitValue.of(from, -						this.view.getDimensionConverterInput()); -			} catch (final ParseException e) { -				this.view.showErrorDialog("Error", -						"Error in parsing: " + e.getMessage()); -				return; -			} -			final UnitValue value = beforeValue.convertTo(to); -			 -			final String output = this.getRoundedString(value); -			 -			this.view.setDimensionConverterOutputText( -					String.format("%s = %s", beforeValue, output)); -		} -		 -		/** -		 * Runs whenever the convert button is pressed. -		 *  -		 * <p> -		 * Reads and parses a unit expression from the from and to boxes, then -		 * converts {@code from} to {@code to}. Any errors are shown in -		 * JOptionPanes. -		 * </p> -		 *  -		 * @since 2019-01-26 -		 * @since v0.1.0 -		 */ -		public final void convertExpressions() { -			final String fromUnitString = this.view.getFromText(); -			final String toUnitString = this.view.getToText(); -			 -			if (fromUnitString.isEmpty()) { -				this.view.showErrorDialog("Parse Error", -						"Please enter a unit expression in the From: box."); -				return; -			} -			if (toUnitString.isEmpty()) { -				this.view.showErrorDialog("Parse Error", -						"Please enter a unit expression in the To: box."); -				return; -			} -			 -			final LinearUnitValue from; -			final Unit to; -			try { -				from = this.database.evaluateUnitExpression(fromUnitString); -			} catch (final IllegalArgumentException | NoSuchElementException e) { -				this.view.showErrorDialog("Parse Error", -						"Could not recognize text in From entry: " + e.getMessage()); -				return; -			} -			try { -				to = this.database.getUnitFromExpression(toUnitString); -			} catch (final IllegalArgumentException | NoSuchElementException e) { -				this.view.showErrorDialog("Parse Error", -						"Could not recognize text in To entry: " + e.getMessage()); -				return; -			} -			 -			if (to instanceof LinearUnit) { -				// convert to LinearUnitValue -				final LinearUnitValue from2; -				final LinearUnit to2 = ((LinearUnit) to) -						.withName(NameSymbol.ofName(toUnitString)); -				final boolean useSlash; -				 -				if (from.canConvertTo(to2)) { -					from2 = from; -					useSlash = false; -				} else if (LinearUnitValue.ONE.dividedBy(from).canConvertTo(to2)) { -					from2 = LinearUnitValue.ONE.dividedBy(from); -					useSlash = true; -				} else { -					// if I can't convert, leave -					this.view.showErrorDialog("Conversion Error", -							String.format("Cannot convert between %s and %s", -									fromUnitString, toUnitString)); -					return; -				} -				 -				final LinearUnitValue converted = from2.convertTo(to2); -				this.view.setExpressionConverterOutputText((useSlash ? "1 / " : "") -						+ String.format("%s = %s", fromUnitString, -								this.getRoundedString(converted, false))); -				return; -			} else { -				// convert to UnitValue -				final UnitValue from2 = from.asUnitValue(); -				if (from2.canConvertTo(to)) { -					final UnitValue converted = from2.convertTo(to); -					 -					this.view -							.setExpressionConverterOutputText(String.format("%s = %s", -									fromUnitString, this.getRoundedString(converted))); -				} else { -					// if I can't convert, leave -					this.view.showErrorDialog("Conversion Error", -							String.format("Cannot convert between %s and %s", -									fromUnitString, toUnitString)); -				} -			} -		} -		 -		/** -		 * @return a list of all of the unit dimensions -		 * @since 2019-04-13 -		 * @since v0.2.0 -		 */ -		public final List<String> dimensionNameList() { -			return this.dimensionNames; -		} -		 -		/** -		 * @return a list of all the entries in the dimension-based converter's -		 *         From box -		 * @since 2020-08-27 -		 */ -		public final Set<String> fromEntries() { -			return ConditionalExistenceCollections.conditionalExistenceSet( -					this.unitNameSet(), this.fromExistenceCondition); -		} -		 -		/** -		 * @return a comparator to compare prefix names -		 * @since 2019-04-14 -		 * @since v0.2.0 -		 */ -		public final Comparator<String> getPrefixNameComparator() { -			return this.prefixNameComparator; -		} -		 -		/** -		 * Like {@link LinearUnitValue#toString(boolean)}, but obeys this unit -		 * converter's rounding settings. -		 *  -		 * @since 2020-08-04 -		 */ -		private final String getRoundedString(final LinearUnitValue value, -				boolean showUncertainty) { -			switch (this.roundingType) { -			case DECIMAL_PLACES: -			case SIGNIFICANT_DIGITS: -				return this.getRoundedString(value.asUnitValue()); -			case SCIENTIFIC: -				return value.toString(showUncertainty); -			default: -				throw new AssertionError("Invalid switch condition."); -			} -		} -		 -		/** -		 * Like {@link UnitValue#toString()}, but obeys this unit converter's -		 * rounding settings. -		 *  -		 * @since 2020-08-04 -		 */ -		private final String getRoundedString(final UnitValue value) { -			final BigDecimal unrounded = new BigDecimal(value.getValue()); -			final BigDecimal rounded; -			int precision = this.precision; -			 -			switch (this.roundingType) { -			case DECIMAL_PLACES: -				rounded = unrounded.setScale(precision, RoundingMode.HALF_EVEN); -				break; -			case SCIENTIFIC: -				precision = 12; -				//$FALL-THROUGH$ -			case SIGNIFICANT_DIGITS: -				rounded = unrounded -						.round(new MathContext(precision, RoundingMode.HALF_EVEN)); -				break; -			default: -				throw new AssertionError("Invalid switch condition."); -			} -			 -			String output = rounded.toString(); -			 -			// remove trailing zeroes -			if (output.contains(".")) { -				while (output.endsWith("0")) { -					output = output.substring(0, output.length() - 1); -				} -				if (output.endsWith(".")) { -					output = output.substring(0, output.length() - 1); -				} -			} -			 -			return output + " " + value.getUnit().getPrimaryName().get(); -		} -		 -		/** -		 * @return The file where settings are stored; -		 * @since 2020-12-11 -		 */ -		private final Path getSettingsFile() { -			return Path.of(DEFAULT_SETTINGS_FILEPATH); -		} -		 -		/** -		 * Loads settings from the settings file. -		 *  -		 * @since 2021-02-17 -		 */ -		public final void loadSettings() { -			try { -				// read file line by line -				final int lineNum = 0; -				for (final String line : Files -						.readAllLines(this.getSettingsFile())) { -					final int equalsIndex = line.indexOf('='); -					if (equalsIndex == -1) -						throw new IllegalStateException( -								"Settings file is malformed at line " + lineNum); -					 -					final String param = line.substring(0, equalsIndex); -					final String value = line.substring(equalsIndex + 1); -					 -					switch (param) { -					// set manually to avoid the unnecessary saving of the non-manual -					// methods -					case "precision": -						this.precision = Integer.valueOf(value); -						break; -					case "rounding_type": -						this.roundingType = RoundingType.valueOf(value); -						break; -					case "prefix_rule": -						this.prefixRule = DefaultPrefixRepetitionRule.valueOf(value); -						this.database.setPrefixRepetitionRule(this.prefixRule); -						break; -					case "one_way": -						this.oneWay = Boolean.valueOf(value); -						if (this.oneWay) { -							this.fromExistenceCondition.setPredicate( -									unitName -> this.metricExceptions.contains(unitName) -											|| !this.database.getUnit(unitName) -													.isMetric()); -							this.toExistenceCondition.setPredicate( -									unitName -> this.metricExceptions.contains(unitName) -											|| this.database.getUnit(unitName).isMetric()); -						} else { -							this.fromExistenceCondition.setPredicate(unitName -> true); -							this.toExistenceCondition.setPredicate(unitName -> true); -						} -						break; -					default: -						System.err.printf("Warning: unrecognized setting \"%s\".", -								param); -						break; -					} -				} -			} catch (final IOException e) {} -		} -		 -		/** -		 * @return a set of all prefix names in the database -		 * @since 2019-04-14 -		 * @since v0.2.0 -		 */ -		public final Set<String> prefixNameSet() { -			return this.database.prefixMap().keySet(); -		} -		 -		/** -		 * Runs whenever a prefix is selected in the viewer. -		 * <p> -		 * Shows its information in the text box to the right. -		 * </p> -		 *  -		 * @since 2019-01-15 -		 * @since v0.1.0 -		 */ -		public final void prefixSelected() { -			final String prefixName = this.view.getPrefixViewerSelection(); -			if (prefixName == null) -				return; -			else { -				final UnitPrefix prefix = this.database.getPrefix(prefixName); -				 -				this.view.setPrefixTextBoxText(String.format("%s%nMultiplier: %s", -						prefixName, prefix.getMultiplier())); -			} -		} -		 -		/** -		 * Saves the settings to the settings file. -		 * -		 * @since 2021-02-17 -		 */ -		public final void saveSettings() { -			try (BufferedWriter writer = Files -					.newBufferedWriter(this.getSettingsFile())) { -				writer.write(String.format("precision=%d\n", this.precision)); -				writer.write( -						String.format("rounding_type=%s\n", this.roundingType)); -				writer.write(String.format("prefix_rule=%s\n", this.prefixRule)); -				writer.write(String.format("one_way=%s\n", this.oneWay)); -			} catch (final IOException e) { -				e.printStackTrace(); -				this.view.showErrorDialog("I/O Error", -						"Error occurred while saving settings: " -								+ e.getLocalizedMessage()); -			} -		} -		 -		/** -		 * Enables or disables one-way conversion. -		 *  -		 * @param oneWay whether one-way conversion should be on (true) or off -		 *               (false) -		 * @since 2020-08-27 -		 */ -		public final void setOneWay(boolean oneWay) { -			this.oneWay = oneWay; -			if (oneWay) { -				this.fromExistenceCondition.setPredicate( -						unitName -> this.metricExceptions.contains(unitName) -								|| !this.database.getUnit(unitName).isMetric()); -				this.toExistenceCondition.setPredicate( -						unitName -> this.metricExceptions.contains(unitName) -								|| this.database.getUnit(unitName).isMetric()); -			} else { -				this.fromExistenceCondition.setPredicate(unitName -> true); -				this.toExistenceCondition.setPredicate(unitName -> true); -			} -			 -			this.saveSettings(); -		} -		 -		/** -		 * @param precision new value of precision -		 * @since 2019-01-15 -		 * @since v0.1.0 -		 */ -		public final void setPrecision(final int precision) { -			this.precision = precision; -			 -			this.saveSettings(); -		} -		 -		/** -		 * @param prefixRepetitionRule the prefixRepetitionRule to set -		 * @since 2020-08-26 -		 */ -		public void setPrefixRepetitionRule( -				Predicate<List<UnitPrefix>> prefixRepetitionRule) { -			if (prefixRepetitionRule instanceof DefaultPrefixRepetitionRule) { -				this.prefixRule = (DefaultPrefixRepetitionRule) prefixRepetitionRule; -			} else { -				this.prefixRule = null; -			} -			this.database.setPrefixRepetitionRule(prefixRepetitionRule); -			 -			this.saveSettings(); -		} -		 -		/** -		 * @param roundingType the roundingType to set -		 * @since 2020-07-16 -		 */ -		public final void setRoundingType(RoundingType roundingType) { -			this.roundingType = roundingType; -			 -			this.saveSettings(); -		} -		 -		/** -		 * @return a list of all the entries in the dimension-based converter's To -		 *         box -		 * @since 2020-08-27 -		 */ -		public final Set<String> toEntries() { -			return ConditionalExistenceCollections.conditionalExistenceSet( -					this.unitNameSet(), this.toExistenceCondition); -		} -		 -		/** -		 * Returns true if and only if the unit represented by {@code unitName} -		 * has the dimension represented by {@code dimensionName}. -		 *  -		 * @param unitName      name of unit to test -		 * @param dimensionName name of dimension to test -		 * @return whether unit has dimenision -		 * @since 2019-04-13 -		 * @since v0.2.0 -		 */ -		public final boolean unitMatchesDimension(final String unitName, -				final String dimensionName) { -			final Unit unit = this.database.getUnit(unitName); -			final ObjectProduct<BaseDimension> dimension = this.database -					.getDimension(dimensionName); -			return unit.getDimension().equals(dimension); -		} -		 -		/** -		 * Runs whenever a unit is selected in the viewer. -		 * <p> -		 * Shows its information in the text box to the right. -		 * </p> -		 *  -		 * @since 2019-01-15 -		 * @since v0.1.0 -		 */ -		public final void unitNameSelected() { -			final String unitName = this.view.getUnitViewerSelection(); -			if (unitName == null) -				return; -			else { -				final Unit unit = this.database.getUnit(unitName); -				 -				this.view.setUnitTextBoxText(unit.toString()); -			} -		} -		 -		/** -		 * @return a set of all of the unit names -		 * @since 2019-04-14 -		 * @since v0.2.0 -		 */ -		private final Set<String> unitNameSet() { -			return this.database.unitMapPrefixless().keySet(); -		} -	} -	 -	/** -	 * Different types of rounding. -	 *  -	 * Significant digits: Rounds to a number of digits. i.e. with precision 5, -	 * 12345.6789 rounds to 12346. Decimal places: Rounds to a number of digits -	 * after the decimal point, i.e. with precision 5, 12345.6789 rounds to -	 * 12345.67890. Scientific: Rounds based on the number of digits and -	 * operations, following standard scientific rounding. -	 */ -	private static enum RoundingType { -		SIGNIFICANT_DIGITS, DECIMAL_PLACES, SCIENTIFIC; -	} -	 -	private static class View { -		private static final NumberFormat NUMBER_FORMATTER = new DecimalFormat(); -		 -		/** The view's frame. */ -		private final JFrame frame; -		/** The view's associated presenter. */ -		private final Presenter presenter; -		/** The master pane containing all of the tabs. */ -		private final JTabbedPane masterPane; -		 -		// DIMENSION-BASED CONVERTER -		/** The panel for inputting values in the dimension-based converter */ -		private final JTextField valueInput; -		/** The panel for "From" in the dimension-based converter */ -		private final SearchBoxList fromSearch; -		/** The panel for "To" in the dimension-based converter */ -		private final SearchBoxList toSearch; -		/** The output area in the dimension-based converter */ -		private final JTextArea dimensionBasedOutput; -		 -		// EXPRESSION-BASED CONVERTER -		/** The "From" entry in the conversion panel */ -		private final JTextField fromEntry; -		/** The "To" entry in the conversion panel */ -		private final JTextField toEntry; -		/** The output area in the conversion panel */ -		private final JTextArea output; -		 -		// UNIT AND PREFIX VIEWERS -		/** The searchable list of unit names in the unit viewer */ -		private final SearchBoxList unitNameList; -		/** The searchable list of prefix names in the prefix viewer */ -		private final SearchBoxList prefixNameList; -		/** The text box for unit data in the unit viewer */ -		private final JTextArea unitTextBox; -		/** The text box for prefix data in the prefix viewer */ -		private final JTextArea prefixTextBox; -		 -		/** -		 * Creates the {@code View}. -		 *  -		 * @since 2019-01-14 -		 * @since v0.1.0 -		 */ -		public View() { -			this.presenter = new Presenter(this); -			this.frame = new JFrame("Unit Converter"); -			this.frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); -			 -			// enable system look and feel -			try { -				UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); -			} catch (ClassNotFoundException | InstantiationException -					| IllegalAccessException | UnsupportedLookAndFeelException e) { -				// oh well, just use default theme -				System.err.println("Failed to enable system look-and-feel."); -				e.printStackTrace(); -			} -			 -			// create the components -			this.masterPane = new JTabbedPane(); -			this.unitNameList = new SearchBoxList(this.presenter.unitNameSet()); -			this.prefixNameList = new SearchBoxList(this.presenter.prefixNameSet(), -					this.presenter.getPrefixNameComparator(), true); -			this.unitTextBox = new JTextArea(); -			this.prefixTextBox = new JTextArea(); -			this.fromSearch = new SearchBoxList(this.presenter.fromEntries()); -			this.toSearch = new SearchBoxList(this.presenter.toEntries()); -			this.valueInput = new JFormattedTextField(NUMBER_FORMATTER); -			this.dimensionBasedOutput = new JTextArea(2, 32); -			this.fromEntry = new JTextField(); -			this.toEntry = new JTextField(); -			this.output = new JTextArea(2, 32); -			 -			// create more components -			this.initComponents(); -			 -			this.frame.pack(); -		} -		 -		/** -		 * @return the currently selected pane. -		 * @throws AssertionError if no pane (or an invalid pane) is selected -		 */ -		public Pane getActivePane() { -			switch (this.masterPane.getSelectedIndex()) { -			case 0: -				return Pane.UNIT_CONVERTER; -			case 1: -				return Pane.EXPRESSION_CONVERTER; -			case 2: -				return Pane.UNIT_VIEWER; -			case 3: -				return Pane.PREFIX_VIEWER; -			case 4: -				return Pane.ABOUT; -			case 5: -				return Pane.SETTINGS; -			default: -				throw new AssertionError("No selected pane, or invalid pane."); -			} -		} -		 -		/** -		 * @return value in dimension-based converter -		 * @throws ParseException -		 * @since 2020-07-07 -		 */ -		public double getDimensionConverterInput() throws ParseException { -			final Number value = NUMBER_FORMATTER.parse(this.valueInput.getText()); -			if (value instanceof Double) -				return (double) value; -			else if (value instanceof Long) -				return ((Long) value).longValue(); -			else -				throw new AssertionError(); -		} -		 -		/** -		 * @return selection in "From" selector in dimension-based converter -		 * @since 2019-04-13 -		 * @since v0.2.0 -		 */ -		public String getFromSelection() { -			return this.fromSearch.getSelectedValue(); -		} -		 -		/** -		 * @return text in "From" box in converter panel -		 * @since 2019-01-15 -		 * @since v0.1.0 -		 */ -		public String getFromText() { -			return this.fromEntry.getText(); -		} -		 -		/** -		 * @return index of selected prefix in prefix viewer -		 * @since 2019-01-15 -		 * @since v0.1.0 -		 */ -		public String getPrefixViewerSelection() { -			return this.prefixNameList.getSelectedValue(); -		} -		 -		/** -		 * @return selection in "To" selector in dimension-based converter -		 * @since 2019-04-13 -		 * @since v0.2.0 -		 */ -		public String getToSelection() { -			return this.toSearch.getSelectedValue(); -		} -		 -		/** -		 * @return text in "To" box in converter panel -		 * @since 2019-01-26 -		 * @since v0.1.0 -		 */ -		public String getToText() { -			return this.toEntry.getText(); -		} -		 -		/** -		 * @return index of selected unit in unit viewer -		 * @since 2019-01-15 -		 * @since v0.1.0 -		 */ -		public String getUnitViewerSelection() { -			return this.unitNameList.getSelectedValue(); -		} -		 -		/** -		 * Starts up the application. -		 *  -		 * @since 2018-12-27 -		 * @since v0.1.0 -		 */ -		public final void init() { -			this.frame.setVisible(true); -		} -		 -		/** -		 * Initializes the view's components. -		 *  -		 * @since 2018-12-27 -		 * @since v0.1.0 -		 */ -		private final void initComponents() { -			final JPanel masterPanel = new JPanel(); -			this.frame.add(masterPanel); -			 -			masterPanel.setLayout(new BorderLayout()); -			 -			{ // pane with all of the tabs -				masterPanel.add(this.masterPane, BorderLayout.CENTER); -				 -				// update stuff -				this.masterPane.addChangeListener(e -> this.update()); -				 -				{ // a panel for unit conversion using a selector -					final JPanel convertUnitPanel = new JPanel(); -					this.masterPane.addTab("Convert Units", convertUnitPanel); -					this.masterPane.setMnemonicAt(0, KeyEvent.VK_U); -					 -					convertUnitPanel.setLayout(new BorderLayout()); -					 -					{ // panel for input part -						final JPanel inputPanel = new JPanel(); -						convertUnitPanel.add(inputPanel, BorderLayout.CENTER); -						 -						inputPanel.setLayout(new GridLayout(1, 3)); -						 -						final JComboBox<String> dimensionSelector = new JComboBox<>( -								this.presenter.dimensionNameList() -										.toArray(new String[0])); -						dimensionSelector.setSelectedItem("LENGTH"); -						 -						// handle dimension filter -						final MutablePredicate<String> dimensionFilter = new MutablePredicate<>( -								s -> true); -						 -						// panel for From things -						inputPanel.add(this.fromSearch); -						 -						this.fromSearch.addSearchFilter(dimensionFilter); -						 -						{ // for dimension selector and arrow that represents -							// conversion -							final JPanel inBetweenPanel = new JPanel(); -							inputPanel.add(inBetweenPanel); -							 -							inBetweenPanel.setLayout(new BorderLayout()); -							 -							{ // dimension selector -								inBetweenPanel.add(dimensionSelector, -										BorderLayout.PAGE_START); -							} -							 -							{ // the arrow in the middle -								final JLabel arrowLabel = new JLabel("->"); -								inBetweenPanel.add(arrowLabel, BorderLayout.CENTER); -							} -						} -						 -						// panel for To things -						 -						inputPanel.add(this.toSearch); -						 -						this.toSearch.addSearchFilter(dimensionFilter); -						 -						// code for dimension filter -						dimensionSelector.addItemListener(e -> { -							dimensionFilter.setPredicate(string -> View.this.presenter -									.unitMatchesDimension(string, -											(String) dimensionSelector.getSelectedItem())); -							this.fromSearch.reapplyFilter(); -							this.toSearch.reapplyFilter(); -						}); -						 -						// apply the item listener once because I have a default -						// selection -						dimensionFilter.setPredicate(string -> View.this.presenter -								.unitMatchesDimension(string, -										(String) dimensionSelector.getSelectedItem())); -						this.fromSearch.reapplyFilter(); -						this.toSearch.reapplyFilter(); -					} -					 -					{ // panel for submit and output, and also value entry -						final JPanel outputPanel = new JPanel(); -						convertUnitPanel.add(outputPanel, BorderLayout.PAGE_END); -						 -						outputPanel.setLayout(new GridLayout(3, 1)); -						 -						{ // unit input -							final JPanel valueInputPanel = new JPanel(); -							outputPanel.add(valueInputPanel); -							 -							valueInputPanel.setLayout(new BorderLayout()); -							 -							{ // prompt -								final JLabel valuePrompt = new JLabel( -										"Value to convert: "); -								valueInputPanel.add(valuePrompt, -										BorderLayout.LINE_START); -							} -							 -							{ // value to convert -								valueInputPanel.add(this.valueInput, -										BorderLayout.CENTER); -							} -						} -						 -						{ // button to convert -							final JButton convertButton = new JButton("Convert"); -							outputPanel.add(convertButton); -							 -							convertButton.addActionListener( -									e -> this.presenter.convertDimensionBased()); -							convertButton.setMnemonic(KeyEvent.VK_ENTER); -						} -						 -						{ // output of conversion -							outputPanel.add(this.dimensionBasedOutput); -							this.dimensionBasedOutput.setEditable(false); -						} -					} -				} -				 -				{ // panel for unit conversion using expressions -					final JPanel convertExpressionPanel = new JPanel(); -					this.masterPane.addTab("Convert Unit Expressions", -							convertExpressionPanel); -					this.masterPane.setMnemonicAt(1, KeyEvent.VK_E); -					 -					convertExpressionPanel.setLayout(new GridLayout(4, 1)); -					 -					{ // panel for units to convert from -						final JPanel fromPanel = new JPanel(); -						convertExpressionPanel.add(fromPanel); -						 -						fromPanel.setBorder(BorderFactory.createTitledBorder("From")); -						fromPanel.setLayout(new GridLayout(1, 1)); -						 -						{ // entry for units -							fromPanel.add(this.fromEntry); -						} -					} -					 -					{ // panel for units to convert to -						final JPanel toPanel = new JPanel(); -						convertExpressionPanel.add(toPanel); -						 -						toPanel.setBorder(BorderFactory.createTitledBorder("To")); -						toPanel.setLayout(new GridLayout(1, 1)); -						 -						{ // entry for units -							toPanel.add(this.toEntry); -						} -					} -					 -					{ // button to convert -						final JButton convertButton = new JButton("Convert"); -						convertExpressionPanel.add(convertButton); -						 -						convertButton.addActionListener( -								e -> this.presenter.convertExpressions()); -						convertButton.setMnemonic(KeyEvent.VK_ENTER); -					} -					 -					{ // output of conversion -						final JPanel outputPanel = new JPanel(); -						convertExpressionPanel.add(outputPanel); -						 -						outputPanel -								.setBorder(BorderFactory.createTitledBorder("Output")); -						outputPanel.setLayout(new GridLayout(1, 1)); -						 -						{ // output -							outputPanel.add(this.output); -							this.output.setEditable(false); -						} -					} -				} -				 -				{ // panel to look up units -					final JPanel unitLookupPanel = new JPanel(); -					this.masterPane.addTab("Unit Viewer", unitLookupPanel); -					this.masterPane.setMnemonicAt(2, KeyEvent.VK_V); -					 -					unitLookupPanel.setLayout(new GridLayout()); -					 -					{ // search panel -						unitLookupPanel.add(this.unitNameList); -						 -						this.unitNameList.getSearchList().addListSelectionListener( -								e -> this.presenter.unitNameSelected()); -					} -					 -					{ // the text box for unit's toString -						unitLookupPanel.add(this.unitTextBox); -						this.unitTextBox.setEditable(false); -						this.unitTextBox.setLineWrap(true); -					} -				} -				 -				{ // panel to look up prefixes -					final JPanel prefixLookupPanel = new JPanel(); -					this.masterPane.addTab("Prefix Viewer", prefixLookupPanel); -					this.masterPane.setMnemonicAt(3, KeyEvent.VK_P); -					 -					prefixLookupPanel.setLayout(new GridLayout(1, 2)); -					 -					{ // panel for listing and seaching -						prefixLookupPanel.add(this.prefixNameList); -						 -						this.prefixNameList.getSearchList().addListSelectionListener( -								e -> this.presenter.prefixSelected()); -					} -					 -					{ // the text box for prefix's toString -						prefixLookupPanel.add(this.prefixTextBox); -						this.prefixTextBox.setEditable(false); -						this.prefixTextBox.setLineWrap(true); -					} -				} -				 -				{ // Info panel -					final JPanel infoPanel = new JPanel(); -					this.masterPane.addTab("\uD83D\uDEC8", // info (i) character -							new JScrollPane(infoPanel)); -					 -					final JTextArea infoTextArea = new JTextArea(); -					infoTextArea.setEditable(false); -					infoTextArea.setOpaque(false); -					infoPanel.add(infoTextArea); -					 -					// get info text -					final String infoText; -					try { -						final Path aboutFile = Path.of("src", "about.txt"); -						infoText = Files.readAllLines(aboutFile).stream() -								.map(Presenter::withoutComments) -								.collect(Collectors.joining("\n")); -					} catch (final IOException e) { -						throw new AssertionError("I/O exception loading about.txt"); -					} -					infoTextArea.setText(infoText); -				} -				 -				{ // Settings panel -					final JPanel settingsPanel = new JPanel(); -					this.masterPane.addTab("\u2699", new JScrollPane(settingsPanel)); -					this.masterPane.setMnemonicAt(5, KeyEvent.VK_S); -					 -					settingsPanel.setLayout( -							new BoxLayout(settingsPanel, BoxLayout.PAGE_AXIS)); -					 -					{ // rounding settings -						final JPanel roundingPanel = new JPanel(); -						settingsPanel.add(roundingPanel); -						roundingPanel -								.setBorder(new TitledBorder("Rounding Settings")); -						roundingPanel.setLayout(new GridBagLayout()); -						 -						// rounding rule selection -						final ButtonGroup roundingRuleButtons = new ButtonGroup(); -						 -						final JLabel roundingRuleLabel = new JLabel("Rounding Rule:"); -						roundingPanel.add(roundingRuleLabel, new GridBagBuilder(0, 0) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						final JRadioButton fixedPrecision = new JRadioButton( -								"Fixed Precision"); -						if (this.presenter.roundingType == RoundingType.SIGNIFICANT_DIGITS) { -							fixedPrecision.setSelected(true); -						} -						fixedPrecision.addActionListener(e -> this.presenter -								.setRoundingType(RoundingType.SIGNIFICANT_DIGITS)); -						roundingRuleButtons.add(fixedPrecision); -						roundingPanel.add(fixedPrecision, new GridBagBuilder(0, 1) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						final JRadioButton fixedDecimals = new JRadioButton( -								"Fixed Decimal Places"); -						if (this.presenter.roundingType == RoundingType.DECIMAL_PLACES) { -							fixedDecimals.setSelected(true); -						} -						fixedDecimals.addActionListener(e -> this.presenter -								.setRoundingType(RoundingType.DECIMAL_PLACES)); -						roundingRuleButtons.add(fixedDecimals); -						roundingPanel.add(fixedDecimals, new GridBagBuilder(0, 2) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						final JRadioButton relativePrecision = new JRadioButton( -								"Scientific Precision"); -						if (this.presenter.roundingType == RoundingType.SCIENTIFIC) { -							relativePrecision.setSelected(true); -						} -						relativePrecision.addActionListener(e -> this.presenter -								.setRoundingType(RoundingType.SCIENTIFIC)); -						roundingRuleButtons.add(relativePrecision); -						roundingPanel.add(relativePrecision, new GridBagBuilder(0, 3) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						final JLabel sliderLabel = new JLabel("Precision:"); -						roundingPanel.add(sliderLabel, new GridBagBuilder(0, 4) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						final JSlider sigDigSlider = new JSlider(0, 12); -						roundingPanel.add(sigDigSlider, new GridBagBuilder(0, 5) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						sigDigSlider.setMajorTickSpacing(4); -						sigDigSlider.setMinorTickSpacing(1); -						sigDigSlider.setSnapToTicks(true); -						sigDigSlider.setPaintTicks(true); -						sigDigSlider.setPaintLabels(true); -						sigDigSlider.setValue(this.presenter.precision); -						 -						sigDigSlider.addChangeListener(e -> this.presenter -								.setPrecision(sigDigSlider.getValue())); -					} -					 -					{ // prefix repetition settings -						final JPanel prefixRepetitionPanel = new JPanel(); -						settingsPanel.add(prefixRepetitionPanel); -						prefixRepetitionPanel.setBorder( -								new TitledBorder("Prefix Repetition Settings")); -						prefixRepetitionPanel.setLayout(new GridBagLayout()); -						 -						// prefix rules -						final ButtonGroup prefixRuleButtons = new ButtonGroup(); -						 -						final JRadioButton noRepetition = new JRadioButton( -								"No Repetition"); -						if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.NO_REPETITION) { -							noRepetition.setSelected(true); -						} -						noRepetition.addActionListener( -								e -> this.presenter.setPrefixRepetitionRule( -										DefaultPrefixRepetitionRule.NO_REPETITION)); -						prefixRuleButtons.add(noRepetition); -						prefixRepetitionPanel.add(noRepetition, -								new GridBagBuilder(0, 0) -										.setAnchor(GridBagConstraints.LINE_START) -										.build()); -						 -						final JRadioButton noRestriction = new JRadioButton( -								"No Restriction"); -						if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.NO_RESTRICTION) { -							noRestriction.setSelected(true); -						} -						noRestriction.addActionListener( -								e -> this.presenter.setPrefixRepetitionRule( -										DefaultPrefixRepetitionRule.NO_RESTRICTION)); -						prefixRuleButtons.add(noRestriction); -						prefixRepetitionPanel.add(noRestriction, -								new GridBagBuilder(0, 1) -										.setAnchor(GridBagConstraints.LINE_START) -										.build()); -						 -						final JRadioButton customRepetition = new JRadioButton( -								"Complex Repetition"); -						if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.COMPLEX_REPETITION) { -							customRepetition.setSelected(true); -						} -						customRepetition.addActionListener( -								e -> this.presenter.setPrefixRepetitionRule( -										DefaultPrefixRepetitionRule.COMPLEX_REPETITION)); -						prefixRuleButtons.add(customRepetition); -						prefixRepetitionPanel.add(customRepetition, -								new GridBagBuilder(0, 2) -										.setAnchor(GridBagConstraints.LINE_START) -										.build()); -					} -					 -					{ // search settings -						final JPanel searchingPanel = new JPanel(); -						settingsPanel.add(searchingPanel); -						searchingPanel.setBorder(new TitledBorder("Search Settings")); -						searchingPanel.setLayout(new GridBagLayout()); -						 -						// searching rules -						final ButtonGroup searchRuleButtons = new ButtonGroup(); -						 -						final JRadioButton noPrefixes = new JRadioButton( -								"Never Include Prefixed Units"); -						noPrefixes.setEnabled(false); -						searchRuleButtons.add(noPrefixes); -						searchingPanel.add(noPrefixes, new GridBagBuilder(0, 0) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						final JRadioButton fixedPrefixes = new JRadioButton( -								"Include Some Prefixes"); -						fixedPrefixes.setEnabled(false); -						searchRuleButtons.add(fixedPrefixes); -						searchingPanel.add(fixedPrefixes, new GridBagBuilder(0, 1) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						final JRadioButton explicitPrefixes = new JRadioButton( -								"Include Explicit Prefixes"); -						explicitPrefixes.setEnabled(false); -						searchRuleButtons.add(explicitPrefixes); -						searchingPanel.add(explicitPrefixes, new GridBagBuilder(0, 2) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						final JRadioButton alwaysInclude = new JRadioButton( -								"Include All Single Prefixes"); -						alwaysInclude.setEnabled(false); -						searchRuleButtons.add(alwaysInclude); -						searchingPanel.add(alwaysInclude, new GridBagBuilder(0, 3) -								.setAnchor(GridBagConstraints.LINE_START).build()); -					} -					 -					{ // miscellaneous settings -						final JPanel miscPanel = new JPanel(); -						settingsPanel.add(miscPanel); -						miscPanel -								.setBorder(new TitledBorder("Miscellaneous Settings")); -						miscPanel.setLayout(new GridBagLayout()); -						 -						final JCheckBox oneWay = new JCheckBox( -								"Convert One Way Only"); -						oneWay.setSelected(this.presenter.oneWay); -						oneWay.addItemListener( -								e -> this.presenter.setOneWay(e.getStateChange() == 1)); -						miscPanel.add(oneWay, new GridBagBuilder(0, 0) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						final JCheckBox showAllVariations = new JCheckBox( -								"Show Symbols in \"Convert Units\""); -						showAllVariations.setSelected(true); -						showAllVariations.setEnabled(false); -						miscPanel.add(showAllVariations, new GridBagBuilder(0, 1) -								.setAnchor(GridBagConstraints.LINE_START).build()); -						 -						final JButton unitFileButton = new JButton( -								"Manage Unit Data Files"); -						unitFileButton.setEnabled(false); -						miscPanel.add(unitFileButton, new GridBagBuilder(0, 2) -								.setAnchor(GridBagConstraints.LINE_START).build()); -					} -				} -			} -		} -		 -		/** -		 * Sets the text in the output of the dimension-based converter. -		 *  -		 * @param text text to set -		 * @since 2019-04-13 -		 * @since v0.2.0 -		 */ -		public void setDimensionConverterOutputText(final String text) { -			this.dimensionBasedOutput.setText(text); -		} -		 -		/** -		 * Sets the text in the output of the conversion panel. -		 *  -		 * @param text text to set -		 * @since 2019-01-15 -		 * @since v0.1.0 -		 */ -		public void setExpressionConverterOutputText(final String text) { -			this.output.setText(text); -		} -		 -		/** -		 * Sets the text of the prefix text box in the prefix viewer. -		 *  -		 * @param text text to set -		 * @since 2019-01-15 -		 * @since v0.1.0 -		 */ -		public void setPrefixTextBoxText(final String text) { -			this.prefixTextBox.setText(text); -		} -		 -		/** -		 * Sets the text of the unit text box in the unit viewer. -		 *  -		 * @param text text to set -		 * @since 2019-01-15 -		 * @since v0.1.0 -		 */ -		public void setUnitTextBoxText(final String text) { -			this.unitTextBox.setText(text); -		} -		 -		/** -		 * Shows an error dialog. -		 *  -		 * @param title   title of dialog -		 * @param message message in dialog -		 * @since 2019-01-14 -		 * @since v0.1.0 -		 */ -		public void showErrorDialog(final String title, final String message) { -			JOptionPane.showMessageDialog(this.frame, message, title, -					JOptionPane.ERROR_MESSAGE); -		} -		 -		public void update() { -			switch (this.getActivePane()) { -			case UNIT_CONVERTER: -				this.fromSearch.updateList(); -				this.toSearch.updateList(); -				break; -			default: -				// do nothing, for now -				break; -			} -		} -	} -	 -	public static void main(final String[] args) { -		new View().init(); -	} -} diff --git a/src/org/unitConverter/converterGUI/package-info.java b/src/org/unitConverter/converterGUI/package-info.java deleted file mode 100644 index d85ecab..0000000 --- a/src/org/unitConverter/converterGUI/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ -/** - * The GUI interface of the Unit Converter. - *  - * @author Adrien Hopkins - * @since 2019-01-25 - * @since v0.2.0 - */ -package org.unitConverter.converterGUI;
\ No newline at end of file | 
