package context.apps.demos.imautostatus; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextPane; import weka.core.Instance; import context.arch.enactor.Generator; import context.arch.storage.Attributes; import context.arch.widget.ClassifierWidget; /** * Window to display GUI for the instant messaging chat simulation. * It has a combo box on top to choose a scenario to load, a chat history in the middle, * and an input field at the bottom to type messages. * @author Brian Y. Lim * */ public class ChatWindow extends JFrame implements KeyListener { private static final long serialVersionUID = 7559239744697886505L; public static final Icon alicePic = new ImageIcon("demos/imautostatus-dtree/img/alice.png"); public static final Icon bobPic = new ImageIcon("demos/imautostatus-dtree/img/bob.png"); private JComboBox scenarioComboBox; private JPanel instanceChoicePanel; private JTextPane outputPane; private JTextPane inputField; private JButton inputButton; /** * * @param userId * @param sendListener to listen to when a new message is sent by the user in the inputField * @param scenarioListener to listen to when the user selects a scenario from a combo box */ public ChatWindow(String userId, ActionListener sendListener, Generator generator) { super("IM Autostatus - " + userId); setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); /* * Scenario chooser */ instanceChoicePanel = initInstanceChoicePanel(generator); add(instanceChoicePanel); /* * Outcome Pane */ JPanel outputPanel = new JPanel(); outputPanel.setBorder(BorderFactory.createLineBorder(Color.gray)); // outputPanel.setMinimumSize(new Dimension(20,0)); outputPanel.setLayout(new BoxLayout(outputPanel, BoxLayout.X_AXIS)); outputPane = new JTextPane(); outputPane.setEditable(false); JScrollPane scrollpane = new JScrollPane(outputPane); scrollpane.setPreferredSize(new Dimension(480, 300)); outputPanel.add(scrollpane); JPanel sidePanel = new JPanel(); sidePanel.setLayout(new BorderLayout()); JLabel avatar = new JLabel(bobPic); avatar.setBorder(BorderFactory.createLineBorder(Color.darkGray)); sidePanel.add(avatar, BorderLayout.NORTH); sidePanel.add(new JLabel(), BorderLayout.CENTER); outputPanel.add(sidePanel); add(outputPanel); /* * Input field */ JPanel inputPanel = new JPanel(); inputPanel.setBorder(BorderFactory.createLineBorder(Color.gray)); inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.X_AXIS)); inputField = new JTextPane(); inputField.addKeyListener(this); scrollpane = new JScrollPane(inputField); scrollpane.setPreferredSize(new Dimension(480, 100)); inputPanel.add(scrollpane); sidePanel = new JPanel(); sidePanel.setLayout(new BorderLayout()); avatar = new JLabel(alicePic); avatar.setBorder(BorderFactory.createLineBorder(Color.darkGray)); sidePanel.add(avatar, BorderLayout.NORTH); inputButton = new JButton("Send"); inputButton.setEnabled(false); inputButton.addActionListener(sendListener); sidePanel.add(inputButton, BorderLayout.SOUTH); inputPanel.add(sidePanel); add(inputPanel); /* ------------------------------------------------ * Window properties */ pack(); setLocationRelativeTo(null); // positions frame in center of screen setDefaultCloseOperation(EXIT_ON_CLOSE); setVisible(true); scenarioComboBox.setSelectedIndex(0); } private JPanel initInstanceChoicePanel(final Generator generator) { JPanel panel = new JPanel(); JLabel label = new JLabel("Choose scenario:"); panel.add(label); // combo box of six choices for choosing instance scenarios scenarioComboBox = new JComboBox(new Object[] {1, 2, 3, 4, 5, 6}); panel.add(scenarioComboBox); scenarioComboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { Instance instance = AutostatusApplication.scenarios.get(scenarioComboBox.getSelectedIndex()); Attributes atts = ClassifierWidget.instanceToAttributes(instance); generator.updateOutWidget(atts); } }); /* * Instructions button and dialog */ JButton instructionsButton = new JButton("Instructions"); instructionsButton.addActionListener(new ActionListener() { private JDialog dialog = new JDialog(ChatWindow.this, "Instructions") { private static final long serialVersionUID = 1L; { // constructor JEditorPane instructionsLabel = new JEditorPane("text/html", "<p style=\"font-family:sans-serif\">" + // instructions on how to use the UI "Type one of the following commands to ask for explanations:<br/><table border=1 cellspacing=0>" + "<tr valign=top><td><b>Command</b></td><td><b>Description</b></td><td><b>Example</b></td></tr>" + "<tr valign=top><td><b>im-why</b></td><td>Why the responsiveness was predicted as such</td><td></td></tr>" + "<tr valign=top><td><b>im-certainty</b></td><td>How certain the IM Autostatus plugin is of the responsiveness prediction</td><td></td></tr>" + "<tr valign=top><td><b>im-whynot x</b></td><td>Why the responsiveness was predicted as x, where x may be 'within' or 'after'</td><td>im-whynot within</td></tr>" + "<tr valign=top><td><b>im-howto</b></td><td>Under what circumstances (when would) the responsiveness be predicted as x, where x may be 'within' or 'after'</td><td>im-howto after</td></tr>" + "<tr valign=top><td><b>im-whatif a=#[,a2=#]</b></td><td>What if the inputs are different, what would the predicted responsiveness be? Choices for inputs: " + ConsoleStringPresenter.inputsDesc.toString().substring(1, ConsoleStringPresenter.inputsDesc.toString().length()-1) + "</td><td>im-whatif Focus=in focus</td></tr>" + "<tr valign=top><td><b>im-inputs</b></td><td>What the inputs to predict responsiveness are</td><td></td></tr>" + "<tr valign=top><td><b>im-outputs</b></td><td>What output values the predicted responsiveness can take</td><td></td></tr>" + "</table></p>"); instructionsLabel.setEditable(false); JScrollPane scrollpane = new JScrollPane(instructionsLabel); setSize(new Dimension(500, 320)); setLocationRelativeTo(null); add(scrollpane); } }; @Override public void actionPerformed(ActionEvent arg0) { dialog.setVisible(true); } }); panel.add(instructionsButton); return panel; } /** * Date formatter for printing a timestamp to the IM chat window. */ private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a"); /** * Encapsulated method to print a message from a sender to the history text box (outputPane). * @param sender * @param msg */ public void writeMessage(String sender, String msg) { String prevText = outputPane.getText(); if (prevText.trim().length() > 0) { prevText += "\n"; } String text = sender + " [" + df.format(new Date()) + "]> " + msg; outputPane.setText(prevText + text); } @Override public void keyReleased(KeyEvent evt) { // enable or disable Send button depending on whether there is text in the input box if (inputField.getText().length() > 0) { inputButton.setEnabled(true); } else { inputButton.setEnabled(false); } } @Override public void keyTyped(KeyEvent evt) {} @Override public void keyPressed(KeyEvent evt) { // parse when enter key is pressed if (evt.getKeyCode() == KeyEvent.VK_ENTER) { if (evt.isAltDown()) { // Alt+Enter gives new line inputField.setText(inputField.getText() + "\n"); } else { // Enter sends message evt.consume(); inputButton.doClick(); } } } public String getMessage() { return inputField.getText(); } public void clearInput() { inputField.setText(""); inputButton.setEnabled(false); } }