/* Author: Josh Holtrop * GVSU, CS654, Project 1 * Date: 2008-03-11 */ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; /* KaZaGUI provides a tabbed interface for launching a server, * connecting to a server, and search for files on a server */ public class KaZaGUI extends JFrame { private ActionEventHandler m_handler; private KaZaClient m_client; private KaZaServer m_server; private Thread m_serverThread; private javax.swing.Timer m_timer; private HashMap m_activeDownloads; /* client tab components */ private JButton m_browseButton; private JButton m_connectButton; private JButton m_closeButton; private JButton m_searchButton; private JTextField m_userNameField; private JTextField m_shareFolderField; private JLabel m_statusLabel; private JTextField m_serverNameField; private JTextField m_queryField; private JComboBox m_speedCombo; private JPanel m_searchResultsPanel; private JScrollPane m_searchResultsScrollPane; private JList m_searchResultsList; private JPanel m_transfersPanel; private JTextArea m_transfersTextArea; /* server tab components */ private JLabel m_serverClientsLabel; private JLabel m_serverStatusLabel; private JButton m_serverStartButton; private JTextField m_serverPeerAddressField; private JButton m_serverPeerConnectButton; private JLabel m_serverPeerGroupLeadersLabel; /* construct the GUI and initialize parameters */ public KaZaGUI() { super("Josh's KaZa application for CS654!"); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(700, 600); setVisible(true); m_handler = new ActionEventHandler(this); Container c = getContentPane(); JTabbedPane pane = new JTabbedPane(); c.add(pane); JPanel clientPanel = getClientPanel(); pane.add("Client", clientPanel); JPanel serverPanel = getServerPanel(); pane.add("Server", serverPanel); m_activeDownloads = new HashMap(); m_timer = new javax.swing.Timer(1000, m_handler); m_timer.start(); } /* a class that receives messages when GUI events such as buttons * being pressed occur */ private class ActionEventHandler implements ActionListener { private KaZaGUI m_kg; public ActionEventHandler(KaZaGUI kg) { m_kg = kg; } public void actionPerformed(ActionEvent e) { if (e.getSource() == m_browseButton) { /* show a directory selection dialog box */ JFileChooser fc = new JFileChooser(); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); fc.showOpenDialog(m_kg); m_shareFolderField.setText(fc.getSelectedFile().getAbsolutePath()); } else if (e.getSource() == m_closeButton) { /* exit the application */ if (m_client != null) m_client.close(); System.exit(0); } else if (e.getSource() == m_connectButton) { /* client wants to connect to a MNH server */ ConnectionSpeed cs = (ConnectionSpeed) m_speedCombo.getSelectedItem(); m_client = new KaZaClient(m_userNameField.getText(), cs.getKbps(), m_shareFolderField.getText(), m_serverNameField.getText()); if (m_client.connected()) { m_statusLabel.setText("Connected to " + m_serverNameField.getText()); m_connectButton.setEnabled(false); } else { m_statusLabel.setText("Could not connect to " + m_serverNameField.getText() + "!"); m_client = null; } } else if (e.getSource() == m_serverStartButton) { /* start MNH server */ if (m_server == null) { m_server = new KaZaServer(); m_serverThread = new Thread(m_server); m_serverThread.start(); m_serverStatusLabel.setText("MNH Server Running"); m_serverStartButton.setEnabled(false); } } else if (e.getSource() == m_searchButton) { if ( m_client != null && m_client.connected() && (!m_queryField.getText().trim().equals("")) ) { performSearch(m_queryField.getText()); } } else if (e.getSource() == m_timer) { if (m_server != null) { /* update server status messages */ Object[] clients = m_server.getClientList(); String caption = "Clients (" + clients.length + "): "; boolean first = true; for (Object o : clients) { String s = (String) o; if (!first) caption += ", "; caption += s; first = false; } m_serverClientsLabel.setText(caption); Object[] peers = m_server.getPeerGroupLeaderList(); caption = "Peer Group Leaders (" + peers.length + "): "; first = true; for (Object o : peers) { String s = (String) o; if (!first) caption += ", "; caption += s; first = false; } m_serverPeerGroupLeadersLabel.setText(caption); } /* print transfer status messages to the Transfers panel */ synchronized (m_activeDownloads) { Set indices = m_activeDownloads.keySet(); Object[] arr = indices.toArray(); for (Object o : arr) { Integer i = (Integer) o; if (!m_client.isDownloadActive(i)) { KaZaClient.SearchResult sr = m_activeDownloads.get(i); m_transfersTextArea.setText(m_transfersTextArea.getText() + "\n" + "Completed downloading \"" + sr.fileName + "\""); m_activeDownloads.remove(i); } } } } else if (e.getSource() == m_serverPeerConnectButton) { /* instruct the MNH server (group leader) to connect to * a peer group leader */ if (m_server != null) { m_server.connectToPeerGroupLeader( m_serverPeerAddressField.getText(), true); m_serverPeerAddressField.setText(""); } } } } /* client has initiated a keyword search */ private void performSearch(String query) { Vector results = m_client.performSearch(query); if (m_searchResultsList != null) { m_searchResultsPanel.remove(m_searchResultsScrollPane); m_searchResultsScrollPane = null; m_searchResultsList = null; m_searchResultsPanel.validate(); } m_searchResultsList = new JList(results.toArray()); m_searchResultsList.setVisibleRowCount(-1); m_searchResultsScrollPane = new JScrollPane(m_searchResultsList); m_searchResultsScrollPane.setPreferredSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE)); m_searchResultsPanel.add(m_searchResultsScrollPane); MouseListener mouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { KaZaClient.SearchResult sr = (KaZaClient.SearchResult) m_searchResultsList.getSelectedValue(); m_activeDownloads.put(m_client.downloadFile(sr.peerAddress, sr.fileName), sr); String curText = m_transfersTextArea.getText(); m_transfersTextArea.setText(curText + (curText.equals("") ? "" : "\n") + "Started download of \"" + sr.fileName + "\" from " + sr.userName + " [" + sr.peerAddress + "]"); } } }; m_searchResultsList.addMouseListener(mouseListener); m_searchResultsPanel.validate(); m_searchResultsPanel.repaint(); repaint(); } /* simple class to store a connection speed * in kbps with a string caption */ private class ConnectionSpeed { private String m_caption; private int m_kbps; public ConnectionSpeed(String caption, int kbps) { m_caption = caption; m_kbps = kbps; } public String toString() { return m_caption; } public int getKbps() { return m_kbps; } } /* construct the panel for the client tab of the GUI */ private JPanel getClientPanel() { m_shareFolderField = new JTextField(); m_browseButton = new JButton("..."); m_browseButton.addActionListener(m_handler); m_serverNameField = new JTextField(); m_statusLabel = new JLabel(); m_connectButton = new JButton("Connect"); m_connectButton.addActionListener(m_handler); m_closeButton = new JButton("Exit"); m_closeButton.addActionListener(m_handler); m_searchButton = new JButton("Search"); m_searchButton.addActionListener(m_handler); Vector speeds = new Vector(); speeds.add(new ConnectionSpeed("Modem", 50)); speeds.add(new ConnectionSpeed("768 Kbps", 768)); speeds.add(new ConnectionSpeed("1.5 Mbps", 1500)); speeds.add(new ConnectionSpeed("3 Mbps", 3000)); speeds.add(new ConnectionSpeed("6 Mbps", 6000)); speeds.add(new ConnectionSpeed("10 Mbps", 10000)); speeds.add(new ConnectionSpeed("45 Mbps", 45000)); speeds.add(new ConnectionSpeed("100 Mbps", 100000)); speeds.add(new ConnectionSpeed("1 Gbps", 1000000)); speeds.add(new ConnectionSpeed("10 Gbps", 10000000)); m_speedCombo = new JComboBox(speeds); m_speedCombo.setSelectedIndex(3); m_userNameField = new JTextField(); m_queryField = new JTextField(); m_searchResultsPanel = new JPanel(); m_searchResultsPanel.setLayout(new BoxLayout(m_searchResultsPanel, BoxLayout.X_AXIS)); m_searchResultsPanel.setBorder( BorderFactory.createTitledBorder("Search Results")); m_searchResultsList = new JList(); m_searchResultsList.setVisibleRowCount(-1); m_searchResultsScrollPane = new JScrollPane(m_searchResultsList); m_searchResultsScrollPane.setPreferredSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE)); m_searchResultsPanel.add(m_searchResultsScrollPane); m_transfersPanel = new JPanel(); m_transfersPanel.setLayout(new BoxLayout(m_transfersPanel, BoxLayout.X_AXIS)); m_transfersPanel.setBorder( BorderFactory.createTitledBorder("Transfers")); m_transfersTextArea = new JTextArea(); m_transfersTextArea.setEditable(false); JScrollPane jsp = new JScrollPane(m_transfersTextArea); jsp.setPreferredSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE)); m_transfersPanel.add(jsp); JPanel clientPanel = new JPanel(); clientPanel.setLayout(new BoxLayout(clientPanel, BoxLayout.Y_AXIS)); JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(new JLabel("User name: ")); p.add(m_userNameField); clientPanel.add(p); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(new JLabel("Connection speed: ")); p.add(m_speedCombo); clientPanel.add(p); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(new JLabel("Shared folder: ")); p.add(m_shareFolderField); p.add(m_browseButton); clientPanel.add(p); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(new JLabel("Server: ")); p.add(m_serverNameField); clientPanel.add(p); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(new JLabel("Search query: ")); p.add(m_queryField); p.add(m_searchButton); clientPanel.add(p); clientPanel.add(m_searchResultsPanel); clientPanel.add(m_transfersPanel); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(m_statusLabel); p.add(new Box.Filler(new Dimension(0, 0), new Dimension(Short.MAX_VALUE, 0), new Dimension(Short.MAX_VALUE, Short.MAX_VALUE))); p.add(m_connectButton); p.add(new Box.Filler(new Dimension(8, 0), new Dimension(8, 0), new Dimension(8, Short.MAX_VALUE))); p.add(m_closeButton); clientPanel.add(p); return clientPanel; } /* construct the GUI elements for the server tab of the GUI */ private JPanel getServerPanel() { m_serverStatusLabel = new JLabel(); m_serverStartButton = new JButton("Start MNH Server"); m_serverStartButton.addActionListener(m_handler); m_serverClientsLabel = new JLabel("Server Not Running"); m_serverPeerAddressField = new JTextField(); m_serverPeerConnectButton = new JButton("Connect"); m_serverPeerConnectButton.addActionListener(m_handler); m_serverPeerGroupLeadersLabel = new JLabel(); JPanel serverPanel = new JPanel(); serverPanel.setLayout(new BoxLayout(serverPanel, BoxLayout.Y_AXIS)); JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(m_serverClientsLabel); p.add(new Box.Filler(new Dimension(0, 0), new Dimension(Short.MAX_VALUE, 0), new Dimension(Short.MAX_VALUE, Short.MAX_VALUE))); serverPanel.add(p); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(m_serverPeerGroupLeadersLabel); p.add(new Box.Filler(new Dimension(0, 0), new Dimension(Short.MAX_VALUE, 0), new Dimension(Short.MAX_VALUE, Short.MAX_VALUE))); serverPanel.add(p); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(new JLabel("Peer Group Leader to link to: ")); p.add(m_serverPeerAddressField); p.add(m_serverPeerConnectButton); serverPanel.add(p); serverPanel.add(new Box.Filler(new Dimension(0, 0), new Dimension(0, Short.MAX_VALUE), new Dimension(Short.MAX_VALUE, Short.MAX_VALUE))); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(m_serverStatusLabel); p.add(new Box.Filler(new Dimension(0, 0), new Dimension(Short.MAX_VALUE, 0), new Dimension(Short.MAX_VALUE, Short.MAX_VALUE))); p.add(m_serverStartButton); serverPanel.add(p); return serverPanel; } }