diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/CSVReader.java | 2 | ||||
| -rw-r--r-- | src/ComparisonView.java | 42 | ||||
| -rw-r--r-- | src/FamilyButton.java | 31 | ||||
| -rw-r--r-- | src/FamilyButtonListener.java | 61 | ||||
| -rw-r--r-- | src/FontFamily.java | 62 | ||||
| -rw-r--r-- | src/JSONReader.java | 15 | ||||
| -rw-r--r-- | src/LineGraph.java | 46 | ||||
| -rw-r--r-- | src/MetadataView.java | 35 | ||||
| -rw-r--r-- | src/Reader.java | 2 | 
9 files changed, 248 insertions, 48 deletions
diff --git a/src/CSVReader.java b/src/CSVReader.java index da11f36..62e7845 100644 --- a/src/CSVReader.java +++ b/src/CSVReader.java @@ -10,7 +10,7 @@ import java.util.Arrays;   * References:   *    * Date: - * 2024-05-20 + * 2024-05-25   *    * Purpose of class:   * Read from and interpret CSV files. diff --git a/src/ComparisonView.java b/src/ComparisonView.java index e1104ef..636cd18 100644 --- a/src/ComparisonView.java +++ b/src/ComparisonView.java @@ -16,7 +16,7 @@ import java.awt.*;   *    *    * Date: - * 2024-05-20 + * 2024-05-25   *    * Purpose of class:   * Provide a view for comparing font families. @@ -28,7 +28,10 @@ public class ComparisonView extends JFrame {  	private final int WINDOW_MIN_HEIGHT = 540; // A ComparisonView has a minimum width  	private ArrayList<FontFamily> fonts; // A ComparisonView has a list of fonts  	private Font textFont; // A ComparisonView has a preferred text font +	private Font buttonFont; // A ComparisonView has a preferred button font  	private final int TEXT_SIZE = 20; // A ComparisonView has a constant text size. +	private FamilyButton buttons[]; // A ComparisonView has an array of buttons. +	private final int BUTTON_MAX = 10; // A ComparisonView has a set maximum number of buttons.  	/**  	 * Walk the file tree. @@ -70,6 +73,10 @@ public class ComparisonView extends JFrame {  		getContentPane().setFont(textFont);  		UIManager.put("Label.font", textFont);  		UIManager.put("Panel.font", textFont); +		UIManager.put("TextArea.font", textFont); +		/* Set button font to a DejaVu Sans Condensed at a smaller point size. */ +		buttonFont = new Font("DejaVu Sans Condensed", Font.PLAIN, TEXT_SIZE * 3 / 4); +		UIManager.put("ToggleButton.font", buttonFont);  		setTitle("Google Fonts Style vs. Popularity"); // Window title @@ -121,14 +128,37 @@ public class ComparisonView extends JFrame {  			fonts.add(new FontFamily(metadata, popularity, style));  		} +		/* Sort fonts by their views over the past 30 days. */ +		fonts = FontFamily.sort(fonts, "30day"); +  		waiting.remove(waitingLabel); // Remove waiting message. -		JPanel author = new JPanel(); -		JLabel authorLabel = new JLabel("Written by Kian Agheli"); -		author.add(authorLabel); -		add(author, BorderLayout.SOUTH); // Add author panel. + +		/* Add panel for font family metadata. */ +		JPanel metadataPanel = new JPanel(); +		MetadataView metadataView = new MetadataView(); +		metadataPanel.add(metadataView); +		this.add(metadataPanel, BorderLayout.WEST);  		LineGraph graph = new LineGraph(fonts); // Draw a line graph of the font views metadata. -		add(graph, BorderLayout.NORTH); // Add the line graph. +		add(graph, BorderLayout.EAST); // Add the line graph. + +		/* Add panel for font family metadata activation buttons. BUTTON_MAX buttons +		in horizontal orientation. */ +		JPanel buttonPanel = new JPanel(); +		buttonPanel.setLayout(new GridLayout(1, BUTTON_MAX)); +		buttons = new FamilyButton[BUTTON_MAX]; +		/* Display buttons for the top families. */ +		for (int i = 0; i < BUTTON_MAX; i++) { +			/* Get the family associated with the given iteration's sort order. */ +			FamilyButton button = new FamilyButton(fonts.get(i)); +			/* Set the text of the button to the name of the font family. */ +			button.setText(button.getFamily().getFamilyName()); +			button.setBackground(new Color(LineGraph.getColors()[i])); +			button.addItemListener(new FamilyButtonListener(buttons, i, metadataView)); +			buttons[i] = button; +			buttonPanel.add(button); +		} +		this.add(buttonPanel, BorderLayout.SOUTH);  		pack(); // Pack the window.  		setVisible(true); // Re-draw the window. diff --git a/src/FamilyButton.java b/src/FamilyButton.java new file mode 100644 index 0000000..994e848 --- /dev/null +++ b/src/FamilyButton.java @@ -0,0 +1,31 @@ +import javax.swing.JToggleButton; + +/* + * @author + * Kian Agheli + * + * References: + * https://www.geeksforgeeks.org/java-swing-jtogglebutton-class/ + * + * Date: + * 2024-05-25 + * + * Purpose of class: + * Provide an interative button to toggle FontFamily metadata. + */ + +public class FamilyButton extends JToggleButton { +	private FontFamily family; // A FamilyButton has-a font family + +	public FamilyButton(FontFamily family) +	{ +		this.family = family; // Set family to provided +	} + +	/** +	 * Return the FontFamily associated with the instantiated button. +	 */ +	public FontFamily getFamily() { +		return family; +	} +} diff --git a/src/FamilyButtonListener.java b/src/FamilyButtonListener.java new file mode 100644 index 0000000..95a4bc4 --- /dev/null +++ b/src/FamilyButtonListener.java @@ -0,0 +1,61 @@ +import java.awt.event.*; + +/* + * @author + * Kian Agheli + * + * References: + * + * Date: + * 2024-05-25 + * + * Purpose of class: + * Listen for state changes in an instantiation of FamilyButton. + */ +public class FamilyButtonListener implements ItemListener +{ +	private MetadataView metadataView; // A FamilyButtonListener has a metadataView +	private FamilyButton[] buttons; // A FamilyButtonListener has an array of buttons +	private int buttonIndex; // A FamilyButtonListener has a button at a specified index in the array + +	public FamilyButtonListener(FamilyButton[] buttons, int buttonIndex, MetadataView metadataView) { +		/* Set each of the instance's fields to the given objects. */ +		this.buttons = buttons; +		this.buttonIndex = buttonIndex; +		this.metadataView = metadataView; +	} + +	@Override +	public void itemStateChanged(ItemEvent e) { +		/* Get the state of the button. */ +		int state = e.getStateChange(); +		/* If the button is selected: */ +		if (state == ItemEvent.SELECTED) { +			/* Deselect all other buttons. */ +			for (int i = 0; i < buttons.length; i++) { +				if (i != buttonIndex) { +					buttons[i].setSelected(false); +				} +			} + +			/* Set the metadata on display to the metadata of the FontFamily +			associated with the selected button. */ +			metadataView.setText(buttons[buttonIndex].getFamily().toString()); +		/* If the button is deselected: */ +		} else { +			/* Check if every button is deselected. */ +			boolean selected = true; +			for (int i = 0; i < buttons.length; i++) { +				if (!buttons[i].isSelected()) { +					selected = false; +				} +			} + +			/* If every button is deselected, reset the metadata to display +			the default text. */ +			if (!selected) { +				metadataView.reset(); +			} +		} +	} +} diff --git a/src/FontFamily.java b/src/FontFamily.java index 97328d8..0b7c458 100644 --- a/src/FontFamily.java +++ b/src/FontFamily.java @@ -1,4 +1,7 @@  import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator;  import java.util.HashMap;  /* @@ -8,7 +11,7 @@ import java.util.HashMap;   * References:   *    * Date: - * 2024-05-20 + * 2024-05-25   *    * Purpose of class:   * Store and operate on font family metadata. @@ -153,4 +156,61 @@ public class FontFamily {  	public HashMap<String,Long> getViews() {  		return views;  	} + +	/* Sort an ArrayList by a given metric of views, in descending order. */ +	public static ArrayList<FontFamily> sort(ArrayList<FontFamily> fonts, String metric) { +		Collections.sort(fonts, new Comparator<FontFamily>() { +			/* If a is lesser, return 1. If b is lesser, return -1. +			Otherwise, they are equal, return 0. */ +			public int compare (FontFamily a, FontFamily b) { +				/* If equal, return 0. */ +				if (a.getViews().get(metric) == b.getViews().get(metric)) { +					return 0; +				} + +				/* If either is null, it is lesser. */ +				if (a.getViews().get(metric) == null) { +					return 1; +				} +				if (b.getViews().get(metric) == null) { +					return -1; +				} + +				/* Neither are null, compare. */ +				if (a.getViews().get(metric) > b.getViews().get(metric)) { +					return -1; +				} + +				/* aViews must be lesser. */ +				return 1; +			} +		}); + +		return fonts; // Return sorted ArrayList. +	} + +	public String toString() { +		String string = String.format("%s\nPublished %s\n", familyName, dateAdded); +		string += "Styles:\n"; +		for (String style : styles.keySet()) { +			string += String.format("    %s: %d%%\n", style, styles.get(style)); +		} +		string += String.format("Designed by %s\n", designer); +		string += String.format("Distributed under the terms of the %s\n", license); +		string += String.format("Vaguely categorized as %s\n", category); +		string += "Unicode subsets:\n"; +		/* Print two subsets on each line. */ +		for (int i = 0; i < subsets.length - 1; i++) { +			if (i % 2 == 0) { +				string += String.format("    %s", subsets[i]); +			} else { +				string += String.format("; %s\n", subsets[i]); +			} +		} +		if (subsets.length % 2 == 0) { +			string += '\n'; +		} + +		return string; +	}  } diff --git a/src/JSONReader.java b/src/JSONReader.java index a4af8c9..4cc72ad 100644 --- a/src/JSONReader.java +++ b/src/JSONReader.java @@ -12,9 +12,10 @@ import java.io.*;   * https://stackoverflow.com/questions/3880274/how-to-convert-the-object-to-string-in-java   * https://stackoverflow.com/questions/8938498/get-the-index-of-a-pattern-in-a-string-using-regex   * https://howtodoinjava.com/java/regex/start-end-of-string/ + * https://www.baeldung.com/java-remove-last-character-of-string   *    * Date: - * 2024-05-20 + * 2024-05-25   *    * Purpose of class:   * Read from and interpret JSON files. @@ -77,9 +78,15 @@ public class JSONReader extends Reader {  		/* This JSON is pretty-printed. */  		int nl = json.indexOf("\n", start); -		/* Extract substring. Remove any quotation marks and commas. */ -		String substring = json.substring(start, nl); -		return substring.replaceAll("[\",]", ""); +		/* Extract substring. Remove any quotation marks. */ +		String extract = json.substring(start, nl); +		extract = extract.replaceAll("\"", ""); + +		/* If the string ends with a comma, remove it. */ +		if (extract.endsWith(",")) { +			extract = extract.substring(0, extract.length() - 1); +		} +		return extract;  	}  	/** diff --git a/src/LineGraph.java b/src/LineGraph.java index 7c4b8ac..7ef9a94 100644 --- a/src/LineGraph.java +++ b/src/LineGraph.java @@ -21,7 +21,7 @@ import java.util.Date;   * https://stackoverflow.com/questions/5799140/java-get-month-string-from-integer   *   * Date: - * 2024-05-20 + * 2024-05-25   *   * Purpose of class:   * Draw a line graph. @@ -32,15 +32,17 @@ public class LineGraph extends JPanel {  	private ArrayList<FontFamily> fonts; // A line graph has-a set of fonts  	private final int WIDTH = 640; // A line graph has a preferred width  	private final int HEIGHT = 480; // A line graph has a preferred height -	private final int LINES = 0x10; // A line graph has a maximum lines graphed at a time +	private final int LINES = 10; // A line graph has a maximum lines graphed at a time  	private final int LINE_WIDTH = 3; // A line graph has lines with a given pixel width  	private final int TICK_HEIGHT = 10; // A line graph has ticks with a given pixel height  	/* A line graph has an array of abbreviated month names. */  	private final String[] ABBREVIATED_MONTH = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",  		"Aug", "Sep", "Oct", "Nov", "Dec"}; -	/* A line graph has an array of unique color values to use for each of the lines. */ -	private final int[] COLORS = {0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff, -		0xff8040, 0xff4080, 0x80ff40, 0x40ff80, 0x4080ff, 0x8040ff, 0xff8080, 0x80ff80, 0x8080ff, +	/* A line graph has an array of unique color values to use for each of the lines. +	Made static so that it may be referenced from ComparisonView, so that the colors used for line +	drawings and their associated buttons may match. */ +	private static final int[] COLORS = {0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff, +		0xff8040, 0xff4080, 0x4080ff, 0xff8080, 0x80ff80, 0x8080ff,  		0xff4040, 0x40ff40, 0x4040ff};  	/** @@ -111,8 +113,6 @@ public class LineGraph extends JPanel {  		graphics.drawLine(TICK_HEIGHT + xOffset - LINE_WIDTH / 3, 0, TICK_HEIGHT + xOffset -  			LINE_WIDTH / 3, yMax); -		sortFonts("30day"); // Sort the list of fonts by their 30day metrics. -  		int y = 0 + metrics.getHeight();  		/* Cast to double within parentheses for floating-point  		division, cast back to int to remove fractional part. @@ -187,33 +187,9 @@ public class LineGraph extends JPanel {  		}  	} -	/* Sort by views, in descending order. */ -	private void sortFonts(String metric) { -		Collections.sort(fonts, new Comparator<FontFamily>() { -			/* If a is lesser, return 1. If b is lesser, return -1. -			Otherwise, they are equal, return 0. */ -			public int compare (FontFamily a, FontFamily b) { -				/* If equal, return 0. */ -				if (a.getViews().get(metric) == b.getViews().get(metric)) { -					return 0; -				} - -				/* If either is null, it is lesser. */ -				if (a.getViews().get(metric) == null) { -					return 1; -				} -				if (b.getViews().get(metric) == null) { -					return -1; -				} - -				/* Neither are null, compare. */ -				if (a.getViews().get(metric) > b.getViews().get(metric)) { -					return -1; -				} - -				/* aViews must be lesser. */ -				return 1; -			} -		}); +	/* Return the array of hex values used to color the lines on the graph. +	The background color of each FamilyButton match the associated line on the graph. */ +	public static int[] getColors() { +		return COLORS;  	}  } diff --git a/src/MetadataView.java b/src/MetadataView.java new file mode 100644 index 0000000..5837aca --- /dev/null +++ b/src/MetadataView.java @@ -0,0 +1,35 @@ +import javax.swing.JTextArea; +import java.awt.*; + +/* + * @author + * Kian Agheli + * + * References: + * https://docs.oracle.com/javase/tutorial/uiswing/components/textarea.html + * + * Date: + * 2024-05-25 + * + * Purpose of class: + * Provide an area to show metadata. + */ + +public class MetadataView extends JTextArea { +	// A MetadataView has-a default text. +	private final String defaultText = "Toggle a font family using a colorful button below.\n" +  +		"Each color corresponds with a line on the graph to the right.\n" +  +		"The graph tracks monthly views."; + +	public MetadataView() { +		super(); // Call parent constructor +		setEditable(false); // Disable editing of the widget. +		setFocusable(false); // Disable focusing of the widget. +		setText(defaultText); // Set to the default text. +	} + +	/* Reset the MetadataView. Set the text to the default. */ +	public void reset() { +		setText(defaultText); +	} +} diff --git a/src/Reader.java b/src/Reader.java index d4a46fa..d066d6d 100644 --- a/src/Reader.java +++ b/src/Reader.java @@ -11,7 +11,7 @@ import java.util.List;   * https://www.baeldung.com/java-scanner   *    * Date: - * 2024-05-20 + * 2024-05-25   *    * Purpose of class:   * Read from a file.  | 
