diff --git a/Application/Clavardage/src/controller/Controller.java b/Application/Clavardage/src/controller/Controller.java index e70b9e0..1998196 100644 --- a/Application/Clavardage/src/controller/Controller.java +++ b/Application/Clavardage/src/controller/Controller.java @@ -28,17 +28,22 @@ import view.Interface; public class Controller { /*** CONSTANTES ***/ - final static int portUDPlistening_remoteUsr2 = 31002; // TO REMOVE when we use broadcast - final static int portUDPlistening_remoteUsr3 = 31003; // TO REMOVE when we use broadcast - - public Boolean interfaceRunning; + int NB_SECOND_WAITING_RESPONSE_BROADCAST = 2; + + // TO REMOVE when we use broadcast + final static int portUDPlistening_usr1 = 31001; + final static int portUDPlistening_remoteUsr2 = 31002; + final static int portUDPlistening_remoteUsr3 = 31003; + final static int [] tabBroadcast = {portUDPlistening_usr1,portUDPlistening_remoteUsr2,portUDPlistening_remoteUsr3}; + + public Boolean interfaceRunning = false; /*** ATTRIBUTS ***/ protected LocalUser myUser; protected Interface view; private ListeningThreadUDP udp_connect_thread; private ListeningThreadTCPConnection tcp_connect_thread; private Historique histoire; - private Chat activeChat; + protected Chat activeChat; /** * Constructor of Controller @@ -82,7 +87,8 @@ public class Controller { notify_remote_users(); - + interfaceRunning =true; + view=Interface.createAndShowGUI(this); } /** @@ -110,13 +116,32 @@ public class Controller { catch(UnknownHostException e) { JOptionPane.showMessageDialog(null ,"Could not find local address!"); } + this.myUser = new LocalUser(pseudo,addIP,portUDPsend,portUDPlistening,portTCP); + try { + if(this.validatePseudo(pseudo)) { + + + this.udp_connect_thread = new ListeningThreadUDP("UDP Listening thread",this); + this.udp_connect_thread.start(); + + this.tcp_connect_thread = new ListeningThreadTCPConnection("TCP main Listening thread",this); + this.tcp_connect_thread.start(); + + interfaceRunning =true; + view=Interface.createAndShowGUI(this); + } + else { + System.out.println("Unavailable "+pseudo); + } + } catch (IOException e) { + e.printStackTrace(); + } + + + - this.udp_connect_thread = new ListeningThreadUDP("UDP Listening thread",this); - this.udp_connect_thread.start(); - this.tcp_connect_thread = new ListeningThreadTCPConnection("TCP main Listening thread",this); - this.tcp_connect_thread.start(); notify_remote_users(); } @@ -188,11 +213,11 @@ public class Controller { public void changePseudo() throws IOException { String oldPseudo = this.myUser.getPseudo(); //Saves the old one for comparison - String tmpPseudo = view.PseudotextField.getText(); // Read user input + String tmpPseudo = view.ChangePseudotextField.getText(); // Read user input if(!(this.validatePseudo(tmpPseudo)) || tmpPseudo.equals(oldPseudo)) { view.Pseudolabel.setText("Already exists, enter another nickname. Your current username is: " + oldPseudo); // Read user input - tmpPseudo = view.PseudotextField.getText(); // Read user input + tmpPseudo = view.ChangePseudotextField.getText(); // Read user input } else { this.myUser.setPseudo(tmpPseudo); @@ -221,46 +246,45 @@ public class Controller { // Call broadcast InetAddress broadcastIP = InetAddress.getLocalHost(); // change to broadcast - //System.out.println(broadcastIP); + //System.out.println(this.myUser.getPortUDPsend()); DatagramSocket dgramSocket = new DatagramSocket(this.myUser.getPortUDPsend(),this.myUser.getAddIP()); byte[] buffer = new byte[256]; // Création du message à envoyer - String toSend = this.myUser.getAddIP()+":"+this.myUser.getPortUDPsend()+":test"; + String toSend = this.myUser.getAddIP()+":"+this.myUser.getPortUDPsend()+":info"; - // Send to remote user 1 - DatagramPacket outPacket= new DatagramPacket(toSend.getBytes(), toSend.length(),broadcastIP, portUDPlistening_remoteUsr2); - dgramSocket.send(outPacket); - - // Send to remote user 2 - outPacket= new DatagramPacket(toSend.getBytes(), toSend.length(),broadcastIP, portUDPlistening_remoteUsr3); - dgramSocket.send(outPacket); - - // Initialisation des variables de la boucle - Boolean valid = true; + // Send to other active user (simulation of broadcast) + DatagramPacket outPacket = null; + int tabBroadcastSize = tabBroadcast.length; + for(int i=0;i * En utilisant le port UDP d'envoi, on envoie en broadcast les informations nous concernant *

*/ public void notify_remote_users() { - // Création du socket d'envoi d'information DatagramSocket dgramSocket= null; try { dgramSocket= new DatagramSocket(this.myUser.getPortUDPsend(),this.myUser.getAddIP()); } catch (IOException e) { e.printStackTrace(); } - - // Construction du message à envoyer - String toSend = this.myUser.getAddIP().toString()+":"+this.myUser.getPortTCP()+":"+this.myUser.getPseudo()+":test"; + // Send to other active user (simulation of broadcast) + String toSend = this.myUser.getAddIP().toString()+":"+this.myUser.getPortTCP()+":"+this.myUser.getPseudo()+":notify"; DatagramPacket outPacket =null; - - // Send information to usr2 - if(this.myUser.getPortUDPlistening()!=portUDPlistening_remoteUsr2) { - outPacket = new DatagramPacket(toSend.getBytes(), toSend.length(),this.myUser.getAddIP(), portUDPlistening_remoteUsr2); - try { - dgramSocket.send(outPacket); - } catch (IOException e) { - e.printStackTrace(); - } - } - - - // Send information to usr3 - if(this.myUser.getPortUDPlistening()!=portUDPlistening_remoteUsr3) { - - outPacket= new DatagramPacket(toSend.getBytes(), toSend.length(),this.myUser.getAddIP(), portUDPlistening_remoteUsr3); - try { - dgramSocket.send(outPacket); - } catch (IOException e) { - e.printStackTrace(); - } - } + int tabBroadcastSize = tabBroadcast.length; + for(int i=0;i "+rm.getPseudo()+" : "+input); + Msg_Text message = new Msg_Text(rm,input); + c.addMessage(message); + if(controller.activeChat==c) { + controller.view.notifyNewMessage("("+message.getDate()+")\n"+c.getRemoteUser().getPseudo()+" : "+input); + } + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } else { System.out.println("("+this.controller.myUser.getPseudo()+") Remote User unidentifiable => CLOSING CONNECTION"); } - /*** listening tcp message from rm until session is close ***/ - - try { - System.out.println("("+this.controller.myUser.getPseudo()+") WAIT FOR NEW MESSAGE FROM "+rm.getPseudo()); - - while (!(input=in.readLine()).equals("end")/* && c.getActive()*/) { - System.out.println("("+this.controller.myUser.getPseudo()+") recoit => "+rm.getPseudo()+" : "+input); - c.addMessage(new Msg_Text(rm.getAddIP(),input)); - // TODO Prévenir l'interface de la réception d'un nouveau message - controller.view.notifyNewMessage(); - - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + diff --git a/Application/Clavardage/src/controller/ListeningThreadTCPConnection.java b/Application/Clavardage/src/controller/ListeningThreadTCPConnection.java index 614b3c4..31833a4 100644 --- a/Application/Clavardage/src/controller/ListeningThreadTCPConnection.java +++ b/Application/Clavardage/src/controller/ListeningThreadTCPConnection.java @@ -1,7 +1,5 @@ package controller; -import model.LocalUser; - import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; @@ -51,9 +49,8 @@ public class ListeningThreadTCPConnection extends ListeningThread{ System.out.println("("+this.controller.myUser.getPseudo()+") Server is not listening on port "+this.controller.myUser.getPortTCP()); e.printStackTrace(); } - // TODO changer le true while(true) { - System.out.println("("+this.controller.myUser.getPseudo()+") WAITING FOR NEW CONNECTION"); + System.out.println("("+this.controller.myUser.getPseudo()+") TCP Server waiting for new connection ..."); try { this.accept(servSocket); diff --git a/Application/Clavardage/src/controller/ListeningThreadUDP.java b/Application/Clavardage/src/controller/ListeningThreadUDP.java index 808103e..12d51c3 100644 --- a/Application/Clavardage/src/controller/ListeningThreadUDP.java +++ b/Application/Clavardage/src/controller/ListeningThreadUDP.java @@ -86,7 +86,7 @@ public class ListeningThreadUDP extends ListeningThread{ else { try { // On récupère l'adresse IP et le port TCP de l'utilisateur distant et ajout à la liste de l'utilisateur utilisant ce thread - this.controller.myUser.addRemoteUser(InetAddress.getByName(tabMsg[0].split("/")[1]),Integer.parseInt(tabMsg[1]),tabMsg[2]); + controller.myUser.addRemoteUser(InetAddress.getByName(tabMsg[0].split("/")[1]),Integer.parseInt(tabMsg[1]),tabMsg[2]); } catch (NumberFormatException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -94,6 +94,9 @@ public class ListeningThreadUDP extends ListeningThread{ // TODO Auto-generated catch block e.printStackTrace(); } + if(controller.interfaceRunning) { + controller.view.updateActiveUsers(); + } } diff --git a/Application/Clavardage/src/model/LocalUser.java b/Application/Clavardage/src/model/LocalUser.java index e22672b..9230f63 100644 --- a/Application/Clavardage/src/model/LocalUser.java +++ b/Application/Clavardage/src/model/LocalUser.java @@ -69,11 +69,11 @@ public class LocalUser extends User{ RemoteUser tmpRemoteUser = new RemoteUser(remoteUserPseudo,remoteUserIP,remoteUserPortTCP); int index = this.remoteUsersList.indexOf(tmpRemoteUser); if(index!=-1) { - System.out.println("("+this.pseudo+") - "+"MAJ, IP(port) of user : "+remoteUserPseudo+" => "+remoteUserIP+"("+remoteUserPortTCP+")"); + System.out.println("("+this.pseudo+") "+"MAJ, IP(port) : "+remoteUserPseudo+" => "+remoteUserIP+"("+remoteUserPortTCP+")"); this.remoteUsersList.set(index,tmpRemoteUser); } else { - System.out.println("("+this.pseudo+") - "+"Add new user IP(port) of user : "+remoteUserPseudo+" => "+remoteUserIP+"("+remoteUserPortTCP+")"); + System.out.println("("+this.pseudo+") "+"Add new user IP(port) : "+remoteUserPseudo+" => "+remoteUserIP+"("+remoteUserPortTCP+")"); this.remoteUsersList.add(tmpRemoteUser); } } diff --git a/Application/Clavardage/src/model/Message.java b/Application/Clavardage/src/model/Message.java index c07ad47..7bf5a1a 100644 --- a/Application/Clavardage/src/model/Message.java +++ b/Application/Clavardage/src/model/Message.java @@ -8,9 +8,8 @@ import java.text.SimpleDateFormat; public abstract class Message { /*** ATTRIBUTS ***/ - private Date date; - private InetAddress autorIP; - + private String date; + private User autor; /** * Constructor of Message * @parametres @@ -20,25 +19,22 @@ public abstract class Message { * *

*/ - public Message(InetAddress autorIP) { - this.autorIP = autorIP; + public Message(User autor) { + this.autor = autor; DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); - this.date = new Date(); + this.date = dateFormat.format(new Date()); } /*** GETTERS ***/ - public Date getDate() { + public String getDate() { return date; } - public InetAddress getAutorIP() { - return autorIP; + public User getAutor() { + return autor; } /*** SETTERS ***/ - public void setDate(Date date) { - this.date = date; - } - public void setAutorIP(InetAddress autorIP) { - this.autorIP = autorIP; + public void setAutorIP(User autor) { + this.autor = autor; } diff --git a/Application/Clavardage/src/model/Msg_Text.java b/Application/Clavardage/src/model/Msg_Text.java index 954f400..7ec3750 100644 --- a/Application/Clavardage/src/model/Msg_Text.java +++ b/Application/Clavardage/src/model/Msg_Text.java @@ -7,8 +7,8 @@ public class Msg_Text extends Message{ /*** ATTRIBUT ***/ private String text; - public Msg_Text(InetAddress autorIP,String text) { - super(autorIP); + public Msg_Text(User autor,String text) { + super(autor); this.text = text; } diff --git a/Application/Clavardage/src/view/Interface.java b/Application/Clavardage/src/view/Interface.java index f439471..6ab128d 100644 --- a/Application/Clavardage/src/view/Interface.java +++ b/Application/Clavardage/src/view/Interface.java @@ -6,7 +6,6 @@ import java.awt.event.*; import java.io.IOException; import controller.Controller; -import model.RemoteUser; public class Interface extends JFrame implements ActionListener, WindowListener { @@ -18,14 +17,15 @@ public class Interface extends JFrame implements ActionListener, WindowListener public Controller controller; public JLabel Pseudolabel; - public JTextField PseudotextField; + public JLabel ChangePseudolabel; + public JTextField ChangePseudotextField; public JTextArea MessagetextArea; public JTextField MessagetextField; public JScrollPane scrollpane; public JButton RemoteUserButton; - public JComboBox RemoteUserbox; + public JComboBox RemoteUserbox; public JButton CloseConversationButton; //Specifies the look and feel to use. Valid values: @@ -47,53 +47,89 @@ public class Interface extends JFrame implements ActionListener, WindowListener public Component createComponents() { //Pseudo setup - PseudotextField = new JTextField(); - PseudotextField.setColumns(10); - PseudotextField.addActionListener(this); - Pseudolabel = new JLabel("Your current username is: " + controller.getMyUser().getPseudo()); - Pseudolabel.setLabelFor(PseudotextField); + JPanel changePseudoPanel = new JPanel(new GridLayout(1, 0)); + ChangePseudolabel = new JLabel("Change nickname : "); + changePseudoPanel.add(ChangePseudolabel); + ChangePseudotextField = new JTextField(); + ChangePseudotextField.setColumns(10); + ChangePseudotextField.addActionListener(this); + changePseudoPanel.add(ChangePseudotextField); + + Pseudolabel = new JLabel("Nickname : "+controller.getMyUser().getPseudo()); + Pseudolabel.setLabelFor(ChangePseudotextField); + + //Remote user list setup - RemoteUserButton = new JButton("Click to get Remote User list"); + RemoteUserButton = new JButton("Start session"); RemoteUserButton.addActionListener(this); + + + // Remote user list //Converts the Userlist to a Pseudotab for treatment in actionPerformed - String[] pseudotab = new String[controller.getMyUser().getRemoteUsersList().size()]; - for(int i=0; i < controller.getMyUser().getRemoteUsersList().size(); i++) { - pseudotab[i] = "(" + Integer.toString(i) + "): " + controller.getMyUser().getRemoteUsersList().get(i).getPseudo(); - } - RemoteUserbox = new JComboBox(pseudotab); + String[] pseudotab = controller.askUpdateActiveUsers(); + RemoteUserbox = new JComboBox(pseudotab); RemoteUserbox.setEditable(true); RemoteUserbox.addActionListener(this); RemoteUserbox.setVisible(false); - CloseConversationButton = new JButton("Click to close active chat"); + + // Close session + CloseConversationButton = new JButton("Close session"); CloseConversationButton.addActionListener(this); CloseConversationButton.setVisible(false); + JPanel userListsPanel = new JPanel(new GridLayout(1, 0)); + + userListsPanel.add(RemoteUserButton); + userListsPanel.add(RemoteUserbox); + userListsPanel.add(CloseConversationButton); + + //Messages setup MessagetextField = new JTextField(); MessagetextField.setColumns(10); MessagetextField.addActionListener(this); - MessagetextArea = new JTextArea("Message field: "); + MessagetextArea = new JTextArea("Chat"); scrollpane = new JScrollPane(); scrollpane.getViewport().add(MessagetextArea); scrollpane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + scrollpane.setPreferredSize(new Dimension(600,60)); MessagetextField.setVisible(false); MessagetextArea.setVisible(false); scrollpane.setVisible(false); + // Create a placeholder on JTextField + MessagetextField.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + if (MessagetextField.getText().equals("Your message")) { + MessagetextField.setText(""); + MessagetextField.setForeground(Color.BLACK); + } + } + @Override + public void focusLost(FocusEvent e) { + if (MessagetextField.getText().isEmpty()) { + MessagetextField.setForeground(Color.GRAY); + MessagetextField.setText("Your message"); + } + } + }); + /* * An easy way to put space between a top-level container * and its contents is to put the contents in a JPanel * that has an "empty" border. */ - JPanel pane = new JPanel(new GridLayout(0, 2)); - pane.add(Pseudolabel); - pane.add(PseudotextField); - pane.add(RemoteUserButton); - pane.add(RemoteUserbox); - pane.add(scrollpane); - pane.add(MessagetextField); - pane.add(CloseConversationButton); + JPanel header = new JPanel(new GridLayout(0, 1)); + header.add(Pseudolabel); + header.add(changePseudoPanel); + header.add(userListsPanel); + + JPanel pane = new JPanel(new BorderLayout()); + pane.add(header,BorderLayout.NORTH); + pane.add(scrollpane,BorderLayout.CENTER); + pane.add(MessagetextField,BorderLayout.SOUTH); pane.setBorder(BorderFactory.createEmptyBorder( 30, //top 30, //left @@ -105,8 +141,8 @@ public class Interface extends JFrame implements ActionListener, WindowListener } public void actionPerformed(ActionEvent e) { - if(e.getSource() == PseudotextField) { //Changing pseudo - String Textinput = PseudotextField.getText(); + if(e.getSource() == ChangePseudotextField) { //Changing pseudo + String Textinput = ChangePseudotextField.getText(); Pseudolabel.setText("Your current username is: " + Textinput); try { @@ -117,7 +153,7 @@ public class Interface extends JFrame implements ActionListener, WindowListener } }else if(e.getSource() == MessagetextField){ //Messages String Textinput = MessagetextField.getText(); - MessagetextArea.setText(MessagetextArea.getText() + controller.getMyUser().getPseudo() + ": " + Textinput + "\n"); + MessagetextArea.setText(MessagetextArea.getText() + "\n" + controller.getMyUser().getPseudo() + " : " + Textinput ); MessagetextField.setText(""); controller.askToSend(Textinput); // ask to send to controller @@ -129,15 +165,16 @@ public class Interface extends JFrame implements ActionListener, WindowListener scrollpane.setVisible(false); MessagetextField.setVisible(false); CloseConversationButton.setVisible(false); - }else { // Choice in remote user list + }else if(e.getSource() == RemoteUserbox){ // Choice in remote user list - JComboBox cb = (JComboBox)e.getSource(); //Casts obscurs pour récupérer le numéro du user dans la liste - int selectedUsernb = Integer.parseInt(String.valueOf(((String) cb.getSelectedItem()).charAt(1))); + //JComboBox cb = (JComboBox)e.getSource(); //Casts obscurs pour récupérer le numéro du user dans la liste + int selectedUsernb = RemoteUserbox.getSelectedIndex(); + //String.valueOf(((String) cb.getSelectedItem()).charAt(1))); // start or switch chat => get history String history = controller.askOpenSession(selectedUsernb); // display it - MessagetextArea.setText("Message:"+history); + MessagetextArea.setText(history); MessagetextField.setVisible(true); scrollpane.setVisible(true); MessagetextArea.setVisible(true); @@ -198,14 +235,15 @@ public class Interface extends JFrame implements ActionListener, WindowListener Interface app = new Interface(controller); Component contents = app.createComponents(); frame.getContentPane().add(contents, BorderLayout.CENTER); + frame.setPreferredSize(new Dimension(400,300)); //Ends all running background tasks upon closing the window frame.addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(java.awt.event.WindowEvent windowEvent) { - System.out.println("Window has been closed"); - app.controller.interfaceRunning = false; - System.exit(0); + System.out.println("("+controller.getMyUser().getPseudo()+") Window has been closed"); + controller.askForClose(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }); @@ -225,14 +263,14 @@ public class Interface extends JFrame implements ActionListener, WindowListener public void windowClosing(WindowEvent e) {} - public void notifyNewMessage() { - String newMessage = controller.askNewMessage(); - //TOCHECK maybe better way to do it - if(newMessage!="") { - //TODO afficher le message - - } + public void notifyNewMessage(String msg) { + MessagetextArea.setText(MessagetextArea.getText() + "\n" + msg); + } + + public void updateActiveUsers() { + DefaultComboBoxModel model = new DefaultComboBoxModel<>( controller.askUpdateActiveUsers() ); + RemoteUserbox.setModel( model ); } /* public static void main(String[] args) throws IOException {