ChatWindow.java 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. package eu.tankernn.chat.client;
  2. import java.awt.BorderLayout;
  3. import java.awt.Dimension;
  4. import java.awt.GridBagConstraints;
  5. import java.awt.GridBagLayout;
  6. import java.awt.Point;
  7. import java.awt.event.ActionEvent;
  8. import java.awt.event.ActionListener;
  9. import java.awt.event.KeyEvent;
  10. import java.awt.event.KeyListener;
  11. import java.awt.event.WindowEvent;
  12. import java.awt.event.WindowListener;
  13. import java.io.File;
  14. import java.util.ArrayList;
  15. import javax.swing.DefaultListModel;
  16. import javax.swing.JButton;
  17. import javax.swing.JFrame;
  18. import javax.swing.JLabel;
  19. import javax.swing.JList;
  20. import javax.swing.JPanel;
  21. import javax.swing.JScrollPane;
  22. import javax.swing.JTextField;
  23. import javax.swing.ListSelectionModel;
  24. import javax.swing.WindowConstants;
  25. import javax.swing.border.EmptyBorder;
  26. import eu.tankernn.chat.common.MessagePacket;
  27. import eu.tankernn.chat.common.MessagePacket.MessageType;
  28. import eu.tankernn.chat.common.Packet;
  29. import io.netty.bootstrap.Bootstrap;
  30. import io.netty.channel.Channel;
  31. import io.netty.channel.ChannelFuture;
  32. import io.netty.channel.ChannelInitializer;
  33. import io.netty.channel.ChannelOption;
  34. import io.netty.channel.EventLoopGroup;
  35. import io.netty.channel.nio.NioEventLoopGroup;
  36. import io.netty.channel.socket.SocketChannel;
  37. import io.netty.channel.socket.nio.NioSocketChannel;
  38. import io.netty.handler.codec.serialization.ClassResolvers;
  39. import io.netty.handler.codec.serialization.ObjectDecoder;
  40. import io.netty.handler.codec.string.StringEncoder;
  41. import io.netty.handler.timeout.IdleStateHandler;
  42. @SuppressWarnings("serial")
  43. public class ChatWindow extends JFrame implements ActionListener, KeyListener, WindowListener {
  44. Thread getMessages;
  45. static File confFile = new File("client.properties");
  46. EventLoopGroup workerGroup = new NioEventLoopGroup();
  47. Channel c;
  48. String adress, username;
  49. ArrayList<String> lastMess = new ArrayList<String>();
  50. int port, messIndex = 0;
  51. GridBagLayout g = new GridBagLayout();
  52. GridBagConstraints con = new GridBagConstraints();
  53. JPanel right = new JPanel();
  54. JLabel infoLabel = new JLabel("Users online:");
  55. DefaultListModel<String> model = new DefaultListModel<String>();
  56. JList<String> userList = new JList<String>(model);
  57. JButton reconnect = new JButton("Reconnect");
  58. Console chat = new Console();
  59. JScrollPane scroll = new JScrollPane(chat);
  60. JTextField write = new JTextField();
  61. public ChatWindow(String adress, int port, String username) {
  62. this.adress = adress;
  63. this.port = port;
  64. this.username = username;
  65. // List config
  66. userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  67. userList.setLayoutOrientation(JList.VERTICAL);
  68. // Label config
  69. infoLabel.setHorizontalAlignment(JLabel.CENTER);
  70. infoLabel.setBorder(new EmptyBorder(5, 5, 5, 5));
  71. // Layout config
  72. right.setLayout(g);
  73. con.fill = GridBagConstraints.HORIZONTAL;
  74. con.weightx = 1;
  75. con.gridx = 0;
  76. right.add(infoLabel, con);
  77. con.weighty = 1;
  78. con.fill = GridBagConstraints.BOTH;
  79. right.add(userList, con);
  80. con.weighty = 0;
  81. con.fill = GridBagConstraints.HORIZONTAL;
  82. right.add(reconnect, con);
  83. setLayout(new BorderLayout());
  84. add(chat, BorderLayout.NORTH);
  85. add(write, BorderLayout.SOUTH);
  86. add(right, BorderLayout.EAST);
  87. // Scrollbar config
  88. add(scroll);
  89. scroll.setMinimumSize(new Dimension(100, 100));
  90. scroll.setViewportView(chat);
  91. scroll.setSize(500, 130);
  92. // Listener config
  93. reconnect.addActionListener(this);
  94. write.addKeyListener(this);
  95. // Window config
  96. this.setLocation(new Point(100, 100));
  97. setSize(600, 600);
  98. setVisible(true);
  99. setTitle("Chat on " + adress + " | Username: " + username);
  100. setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
  101. addWindowListener(this);
  102. connect(adress, port, username);
  103. }
  104. public void send(String text) {
  105. ChannelFuture cf = null;
  106. try {
  107. cf = c.writeAndFlush(text).sync();
  108. } catch (InterruptedException e) {
  109. e.printStackTrace();
  110. }
  111. if (!cf.isSuccess()) {
  112. chat.log(new MessagePacket(
  113. "Error sending message.",
  114. MessageType.WARNING));
  115. cf.cause().printStackTrace();
  116. write.setEnabled(false);
  117. }
  118. }
  119. protected void connect(String address, int port, String username) {
  120. if (!workerGroup.isShutdown())
  121. workerGroup.shutdownGracefully();
  122. workerGroup = new NioEventLoopGroup();
  123. Bootstrap b = new Bootstrap();
  124. b.group(workerGroup);
  125. b.channel(NioSocketChannel.class);
  126. b.option(ChannelOption.SO_KEEPALIVE, true);
  127. b.handler(new ChannelInitializer<SocketChannel>() {
  128. @Override
  129. public void initChannel(SocketChannel ch) throws Exception {
  130. ch.pipeline().addLast("decoder",
  131. new ObjectDecoder(ClassResolvers.weakCachingResolver(
  132. Packet.class.getClassLoader())));
  133. ch.pipeline().addLast("encoder", new StringEncoder());
  134. ch.pipeline().addLast(new IdleStateHandler(0, 4, 0));
  135. ch.pipeline().addLast("handler",
  136. new ChatClientHandler(ChatWindow.this));
  137. }
  138. });
  139. // Start the client.
  140. try {
  141. c = b.connect(address, port).sync().channel();
  142. // Set username
  143. send(username);
  144. } catch (InterruptedException e) {
  145. e.printStackTrace();
  146. }
  147. }
  148. @Override
  149. public void actionPerformed(ActionEvent e) {
  150. if (e.getSource().equals(reconnect))
  151. connect(adress, port, username);
  152. }
  153. @Override
  154. public void keyPressed(KeyEvent eKey) {
  155. int keyCode = eKey.getKeyCode();
  156. switch (keyCode) {
  157. case KeyEvent.VK_UP:
  158. if (messIndex > 0)
  159. messIndex--;
  160. if (!lastMess.isEmpty())
  161. write.setText(lastMess.get(messIndex));
  162. break;
  163. case KeyEvent.VK_DOWN:
  164. if (messIndex <= lastMess.size())
  165. messIndex++;
  166. if (messIndex >= lastMess.size()) {
  167. messIndex = lastMess.size();
  168. write.setText("");
  169. } else
  170. write.setText(lastMess.get(messIndex));
  171. break;
  172. case KeyEvent.VK_ENTER:
  173. String text = write.getText().trim();
  174. if (!text.equals("")) {
  175. send(text);
  176. lastMess.add(text);
  177. messIndex = lastMess.size();
  178. write.setText("");
  179. }
  180. break;
  181. }
  182. }
  183. @Override
  184. public void keyReleased(KeyEvent arg0) {}
  185. @Override
  186. public void keyTyped(KeyEvent arg0) {}
  187. public boolean isConnected() {
  188. return c.isActive();
  189. }
  190. @Override
  191. public void windowOpened(WindowEvent e) {
  192. // TODO Auto-generated method stub
  193. }
  194. @Override
  195. public void windowClosing(WindowEvent e) {
  196. workerGroup.shutdownGracefully();
  197. System.exit(0);
  198. }
  199. @Override
  200. public void windowClosed(WindowEvent e) {
  201. // TODO Auto-generated method stub
  202. }
  203. @Override
  204. public void windowIconified(WindowEvent e) {
  205. // TODO Auto-generated method stub
  206. }
  207. @Override
  208. public void windowDeiconified(WindowEvent e) {
  209. // TODO Auto-generated method stub
  210. }
  211. @Override
  212. public void windowActivated(WindowEvent e) {
  213. // TODO Auto-generated method stub
  214. }
  215. @Override
  216. public void windowDeactivated(WindowEvent e) {
  217. // TODO Auto-generated method stub
  218. }
  219. }