/** * DoubletsGUI.java * Boston University CAS CS 112 HW7 * By Ian Denhardt and Leo Reyzin */ import java.awt.*; import java.awt.event.*; import java.io.IOException; import java.util.*; import javax.swing.*; public class DoubletsGUI extends JFrame{ WordGraph g; int numWords; int maxLength; public DoubletsGUI() { Container contentPane = getContentPane(); contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS)); // Create a text area for error messages & info JTextArea errorAndProgressMessage = new JTextArea(); errorAndProgressMessage.setEditable(false); // add scroll bar to the error window JScrollPane scroll1 = new JScrollPane(errorAndProgressMessage); scroll1.setPreferredSize(new Dimension(400, 700)); // create the button to open the file JButton openButton = new JButton("Click to select a dictionary file"); openButton.addActionListener(new OpenListener(errorAndProgressMessage)); // Add the two to a panel JPanel openFilePanel = new JPanel(); openFilePanel.setLayout(new BoxLayout(openFilePanel, BoxLayout.Y_AXIS)); openFilePanel.add(scroll1); openFilePanel.add(openButton); contentPane.add(openFilePanel); // add some gray space contentPane.add(new JLabel(" ")); // Create a text area for output JTextArea output = new JTextArea(); output.setEditable(false); // add scroll a bar to the output window JScrollPane scroll2 = new JScrollPane(output); scroll2.setPreferredSize(new Dimension(400, 700)); // create a first word panel, with input area and button JPanel firstWordPanel = new JPanel(); firstWordPanel.setLayout(new BoxLayout(firstWordPanel, BoxLayout.X_AXIS)); JLabel beforeFirstWordText = new JLabel("Word1: "); firstWordPanel.add(beforeFirstWordText); JTextField firstWordInput = new JTextField(); firstWordPanel.add(firstWordInput); JButton listNeighborsButton = new JButton("List Neighbors"); listNeighborsButton.addActionListener(new ListNeighborsListener(firstWordInput, output)); firstWordPanel.add(listNeighborsButton); // create a second word panel, with input area and button JPanel secondWordPanel = new JPanel(); secondWordPanel.setLayout(new BoxLayout(secondWordPanel, BoxLayout.X_AXIS)); JLabel beforeSecondWordText = new JLabel("Word2: "); secondWordPanel.add(beforeSecondWordText); JTextField secondWordInput = new JTextField(); secondWordPanel.add(secondWordInput); JButton ConnectButton = new JButton("Find a chain"); ConnectButton.addActionListener(new ConnectListener(firstWordInput, secondWordInput, output)); secondWordPanel.add(ConnectButton); // add the two panels and the output window to a new panel JPanel workPanel = new JPanel(); workPanel.setLayout(new BoxLayout(workPanel, BoxLayout.Y_AXIS)); workPanel.add(scroll2); workPanel.add(firstWordPanel); workPanel.add(secondWordPanel); contentPane.add(workPanel); } public static void main(String[] args) { DoubletsGUI frame = new DoubletsGUI(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(900,800); frame.setVisible(true); } // This class is in charge of opening the file private class OpenListener implements ActionListener { private JTextArea out; // constructor: keeps track of where the information message (opened/failed) is to be displayed public OpenListener(JTextArea out) { this.out = out; } private boolean firstPass(Scanner fileScanner) { if (!fileScanner.hasNext()) { out.append("File is empty.\n"); return false; } numWords=1; String prev = fileScanner.next(); maxLength = prev.length(); String cur; while (fileScanner.hasNext()) { cur = fileScanner.next(); numWords++; if (cur.length()>maxLength) maxLength = cur.length(); if (cur.toLowerCase().compareTo(prev.toLowerCase())<=0) { out.append("Not in alphabetical order: " + cur.toLowerCase() + " preceeds " + prev.toLowerCase()+"!\n"); return false; } } return true; } private void buildGraph (Scanner fileScanner) { final int HOW_OFTEN_TO_PRINT = 10000, HOW_OFTEN_NEW_LINE = 50000; // read the file into the graph g = new WordGraph (numWords); int wordsRead = 0; out.append("Words read so far: "); while (fileScanner.hasNext()) { g.addVertex(fileScanner.next().toLowerCase()); // print the number of words processed every once in a while, to show progress if (++wordsRead % HOW_OFTEN_TO_PRINT == 0) { out.append(wordsRead+" "); if (wordsRead % HOW_OFTEN_NEW_LINE == 0) out.append("\n"); out.paintImmediately(out.getVisibleRect()); } } if (wordsRead % HOW_OFTEN_NEW_LINE !=0) out.append("\n"); } private void printStats() { int [] maxDegree = new int [maxLength+1]; WordGraph.Vertex[] highestDegreeVertex = new WordGraph.Vertex [maxLength+1]; for (WordGraph.Vertex v : g) { int len = v.toString().length(); int degree = v.getDegree(); if (degree > maxDegree[len]) { maxDegree[len] = degree; highestDegreeVertex[len] = v; } } for (int i = 1; i<=maxLength; i++) if (maxDegree[i]>0) out.append("Highest-degree word of length " + i + ": " + highestDegreeVertex[i] + " (degree " + maxDegree[i]+ ").\n" ); } // is invoked when file is chosen; processes the file or displays a failure message public void actionPerformed(ActionEvent e) { JFileChooser chooser = new JFileChooser(); int option = chooser.showOpenDialog(null); Scanner fileScanner; if(option == JFileChooser.APPROVE_OPTION) { try { fileScanner = new Scanner(chooser.getSelectedFile()); } catch (IOException exc) { out.append("Unable to open file because of the following error: \""+exc.getMessage()+"\""); return; } // Do the first pass through the file to get the number of words, check alphabetical order, get max length out.append("Opened file: " + chooser.getSelectedFile().getName()+"\n"); if (firstPass(fileScanner) == false) return; out.append("Words in the file: "+numWords+". Maximum length of a word: " + maxLength + ".\nProcessing file...\n"); // Do the second pass through the file to build the graph try { fileScanner = new Scanner(chooser.getSelectedFile()); } catch (IOException exc) { out.append("Unable to open file because of the following error: \""+exc.getMessage()+"\""); return; } buildGraph(fileScanner); printStats(); } } } // This class is in charge of processing requests to list neighbors of a word private class ListNeighborsListener implements ActionListener { private JTextField word; private JTextArea out; public ListNeighborsListener(JTextField word, JTextArea out) { this.word = word; this.out = out; } public void actionPerformed(ActionEvent e) { if (g == null) { out.append("Please select a file first!\n"); return; } WordGraph.Vertex v = g.find(word.getText()); if (v == null) { out.append(word.getText()+ ": word not in the dictionary.\n"); return; } LinkedList neighbors = v.getNeighbors(); out.append(word.getText()+" has " + neighbors.size() + " neighbors:\n" ); for (WordGraph.Vertex u : neighbors) out.append(u+"\n"); out.paintImmediately(out.getVisibleRect()); // out.append(Double.toString(g.Centrality(v))); } } // This class is in charge of processing requests to find a chain private class ConnectListener implements ActionListener { private JTextField beginWord, endWord; private JTextArea out; public ConnectListener(JTextField beginWord, JTextField endWord, JTextArea out) { this.beginWord = beginWord; this.endWord = endWord; this.out = out; } public void actionPerformed(ActionEvent e) { if (g == null) { out.append("Please select a file first!\n"); return; } String beginText = beginWord.getText(); WordGraph.Vertex begin = g.find(beginText); if (begin == null) { out.append(beginText+ ": word not in the dictionary.\n"); return; } String endText = endWord.getText(); WordGraph.Vertex end = g.find(endText); if (end == null) { out.append(endText + ": word not in the dictionary.\n"); return; } Stack path = g.bfs(begin, end); if (path == null) { out.append("There is no chain between " + beginText + " and " + endText + ".\n"); } else { out.append("The chain from " + beginText + " to " + endText + " is of length " + (path.size()-1) + ":\n"); while (!path.isEmpty()) out.append(path.pop()+"\n"); } } } }