package org.opentrafficsim.imb.demo; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Calendar; import java.util.Date; import javax.swing.JButton; import javax.swing.JFormattedTextField; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; import nl.tno.imb.TByteBuffer; import nl.tno.imb.TConnection; import nl.tno.imb.TEventEntry; /** *

* Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License. *

* @version $Revision$, $LastChangedDate$, by $Author$, initial version Aug 19, 2016
* @author TNO * @author Peter Knoppers * @author Walter Lohman */ public class IMBChat extends JFrame { /** */ private static final long serialVersionUID = 1L; /** Name of this chat user. */ private JTextField editName; /** IMB Federation. */ private JTextField editFederation; /** Message the the user is typing. */ private JTextField editMessage; /** Messages that have been exchanged. */ private JTextArea messages; /** Initiate connection to the IMB hub. */ JButton btnConnect; /** Connection to the IMB hub. */ private static TConnection connection = null; /** Message channel. */ private static TEventEntry chatMessageEvent = null; /** * Convert a time. * @param comTime double; the time in days since windows epoch * @return Date */ static public Date convertWindowsTimeToDate(double comTime) { return new Date(convertWindowsTimeToMilliseconds(comTime)); } /** * Convert a time. * @param comTime double; the time in days since windows epoch * @return double; java time in milliseconds */ static public long convertWindowsTimeToMilliseconds(double comTime) { long result = 0; comTime = comTime - 25569D; Calendar cal = Calendar.getInstance(); result = Math.round(86400000L * comTime) - cal.get(Calendar.ZONE_OFFSET); cal.setTime(new Date(result)); result -= cal.get(Calendar.DST_OFFSET); return result; } /** * Convert a Date to windows time. * @param javaDate Date; the date to convert * @return double; time in milliseconds */ static public double convertDateToWindowsTime(Date javaDate) { if (javaDate == null) { throw new IllegalArgumentException("cannot convert null to windows time"); } return convertMillisecondsToWindowsTime(javaDate.getTime()); } /** * Convert a java time in milliseconds to windows time * @param milliseconds long; the java time in milliseconds * @return double; time in days since windows epoch */ static public double convertMillisecondsToWindowsTime(long milliseconds) { double result = 0.0; Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(milliseconds); milliseconds += (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)); // add GMT offset result = (milliseconds / 86400000D) + 25569D; return result; } /** * Add received message to the message received box * @param aDateTime Date; when was the message sent * @param aName String; name of sender * @param aMessage String; the message that was sent */ void AddMessage(final Date aDateTime, final String aName, final String aMessage) { final JTextArea ta = this.messages; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { ta.setText(aDateTime.toString() + " " + aName + ": " + aMessage); } }); } /** * Are we currently connected to an IMB server? * @return boolean */ private boolean getConnected() { if (connection != null) return connection.isConnected(); else return false; } /** * Connect to the hub. */ void Connect() { String server = "localhost"; int port = 4000; connection = new TConnection(server, port, this.editName.getText(), 1, this.editFederation.getText()); // TODO: connection.onDisconnect // connection.onDisconnect = new TConnection.TOnDisconnect() // { // @Override // public void dispatch(TConnection aConnection) // { // // dispatch on display thread // Display.getDefault().syncExec(new Runnable() // { // public void run() // { // chatMainForm.this.btnConnect.setText("Connect"); // } // }); // } // }; chatMessageEvent = connection.subscribe("Chat.Message"); chatMessageEvent.onNormalEvent = new TEventEntry.TOnNormalEvent() { @Override public void dispatch(TEventEntry aEvent, TByteBuffer aPayload) { // decode message double datetime = aPayload.readDouble(); final String name = aPayload.readString(); final String message = aPayload.readString(); final Date javaDateTime = convertWindowsTimeToDate(datetime); // dispatch on display thread // show received message AddMessage(javaDateTime, name, message); } }; // TODO: chatMessageEvent.OnNormalEvent if (getConnected()) this.btnConnect.setText("Disconnect"); else // ShowMessage("## Could not connect to hub " + aServerURI); // java.awt.Dialog. JOptionPane.showMessageDialog(null, "## Could not connect to hub "); } /** * Close the connection to the IMB hub. */ void Disconnect() { if (getConnected()) { connection.close(); this.btnConnect.setText("Connect"); } } /** * Send the message in the editMessage buffer to the IMB hub and clear the editMessage buffer. */ void Send() { Date javaDateTime; double datetime; String name; String message; TByteBuffer payload; // send message javaDateTime = new Date(); datetime = convertDateToWindowsTime(javaDateTime); name = this.editName.getText(); message = this.editMessage.getText(); // encode message payload = new TByteBuffer(); payload.prepare(datetime); payload.prepare(name); payload.prepare(message); payload.prepareApply(); payload.qWrite(datetime); payload.qWrite(name); payload.qWrite(message); chatMessageEvent.signalEvent(TEventEntry.EK_NORMAL_EVENT, payload.getBuffer()); // show our own message AddMessage(javaDateTime, "me", message); // clear previous message text this.editMessage.setText(""); } /** * Start up the application. * @param args String[] args for main - should be empty */ public static void main(String[] args) { try { EventQueue.invokeAndWait(new Runnable() { public void run() { try { new IMBChat(); } catch (Exception e) { e.printStackTrace(); } } }); } catch (Exception e) { e.printStackTrace(); } } /** * Create the window. */ public IMBChat() { this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(java.awt.event.WindowEvent windowEvent) { Disconnect(); } }); setPreferredSize(new Dimension(693, 443)); setTitle("Chat - Java"); JPanel mainPanel = new JPanel(new BorderLayout()); getContentPane().add(mainPanel); JPanel topPanel = new JPanel(new BorderLayout()); mainPanel.add(topPanel, BorderLayout.NORTH); JPanel namePanel = new JPanel(new BorderLayout()); topPanel.add(namePanel, BorderLayout.LINE_START); JLabel lblName = new JLabel("Name"); namePanel.add(lblName, BorderLayout.LINE_START); this.editName = new JFormattedTextField(System.getProperty("user.name")); this.editName.setPreferredSize(new Dimension(100, 20)); namePanel.add(this.editName, BorderLayout.LINE_END); JPanel federationPanel = new JPanel(new BorderLayout()); topPanel.add(federationPanel, BorderLayout.CENTER); JLabel lblFederation = new JLabel("Federation"); federationPanel.add(lblFederation, BorderLayout.LINE_START); this.editFederation = new JFormattedTextField(TConnection.DEFAULT_FEDERATION); federationPanel.add(this.editFederation, BorderLayout.LINE_END); this.btnConnect = new JButton("Connect"); this.btnConnect.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (IMBChat.this.btnConnect.getText().compareTo("Connect") == 0) Connect(); else Disconnect(); } }); topPanel.add(this.btnConnect, BorderLayout.LINE_END); this.messages = new JTextArea("hier komen de messages"); mainPanel.add(this.messages, BorderLayout.CENTER); JPanel bottomPanel = new JPanel(new BorderLayout()); mainPanel.add(bottomPanel, BorderLayout.SOUTH); this.editMessage = new JTextField(""); this.editMessage.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { if (e.getKeyChar() == 13) { Send(); } } @Override public void keyPressed(KeyEvent e) { // ignore } @Override public void keyReleased(KeyEvent e) { // ignore } }); bottomPanel.add(this.editMessage, BorderLayout.CENTER); JButton btnSend = new JButton("Send"); btnSend.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Send(); } }); bottomPanel.add(btnSend, BorderLayout.LINE_END); this.pack(); this.setVisible(true); } }