diff --git a/pitiupi.mpChat/.idea/.gitignore b/pitiupi.mpChat/.idea/.gitignore
new file mode 100644
index 0000000..b58b603
--- /dev/null
+++ b/pitiupi.mpChat/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/pitiupi.mpChat/.idea/misc.xml b/pitiupi.mpChat/.idea/misc.xml
new file mode 100644
index 0000000..8547fc5
--- /dev/null
+++ b/pitiupi.mpChat/.idea/misc.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/pitiupi.mpChat/.idea/modules.xml b/pitiupi.mpChat/.idea/modules.xml
new file mode 100644
index 0000000..93aa0d1
--- /dev/null
+++ b/pitiupi.mpChat/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pitiupi.mpChat/.idea/vcs.xml b/pitiupi.mpChat/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/pitiupi.mpChat/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pitiupi.mpChat/out/META-INF/services/pitiupi.models.Plugin b/pitiupi.mpChat/out/META-INF/services/pitiupi.models.Plugin
new file mode 100644
index 0000000..3240a6f
--- /dev/null
+++ b/pitiupi.mpChat/out/META-INF/services/pitiupi.models.Plugin
@@ -0,0 +1 @@
+plugin.MultiProtocolChat
diff --git a/pitiupi.mpChat/src/GUI/PrivateChatWindow.java b/pitiupi.mpChat/src/GUI/PrivateChatWindow.java
index ad60dc4..d811a9b 100644
--- a/pitiupi.mpChat/src/GUI/PrivateChatWindow.java
+++ b/pitiupi.mpChat/src/GUI/PrivateChatWindow.java
@@ -3,41 +3,199 @@ package GUI;
import net.MpChatMessage;
import pitiupi.control.ConnectionManager;
import pitiupi.net.tcp.TcpConnection;
+import pitiupi.plugin.Pitiupi;
import javax.swing.*;
import java.awt.*;
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
-public class PrivateChatWindow extends ChatWindow {
+public class PrivateChatWindow extends JFrame {
- private final TcpConnection connection;
+ private final Pitiupi pitiupi;
- public PrivateChatWindow(ConnectionManager ConnectionManager, TcpConnection connection) {
- super(ConnectionManager);
- this.connection = connection;
+ private final Map chats;
+
+ private final JPanel chatPanel;
+ private final CardLayout cardLayout;
+
+ private final DefaultListModel connectionListModel;
+ private final JList connectionList;
+
+ public PrivateChatWindow(Pitiupi pitiupi) {
+ this.pitiupi = pitiupi;
+ this.chats = new HashMap<>();
+
+ setTitle("Chats privados");
+ setSize(700, 500);
+ setLocationRelativeTo(null);
+ setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
+
+ JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+ connectionListModel = new DefaultListModel<>();
+ connectionList = new JList<>(connectionListModel);
+
+ connectionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ connectionList.setPreferredSize(new Dimension(180, 0));
+
+ connectionList.addListSelectionListener(e -> {
+ if (!e.getValueIsAdjusting()) {
+ TcpConnection connection = connectionList.getSelectedValue();
+
+ if (connection != null) {
+ showChat(connection);
+ }
+ }
+ });
+
+ JScrollPane connectionScrollPane = new JScrollPane(connectionList);
+ connectionScrollPane.setBorder(
+ BorderFactory.createTitledBorder("Usuários")
+ );
+
+ mainPanel.add(connectionScrollPane, BorderLayout.WEST);
+
+ cardLayout = new CardLayout();
+ chatPanel = new JPanel(cardLayout);
+
+ mainPanel.add(chatPanel, BorderLayout.CENTER);
+
+ setContentPane(mainPanel);
}
- @Override
- protected void initButtons(JPanel bottomPanel) {
- JButton tcpButton = new JButton("TCP");
+ public void addConnection(TcpConnection connection) {
+ if (chats.containsKey(connection)) {
+ return;
+ }
- tcpButton.addActionListener(e -> sendTCP());
+ PrivateChatPanel panel = new PrivateChatPanel(connection);
- JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
+ chats.put(connection, panel);
+ connectionListModel.addElement(connection);
- buttonsPanel.add(tcpButton);
+ String cardName = getCardName(connection);
+ chatPanel.add(panel, cardName);
- bottomPanel.add(buttonsPanel, BorderLayout.EAST);
+ if (connectionList.getSelectedValue() == null) {
+ connectionList.setSelectedValue(connection, true);
+ }
}
- private void sendTCP() {
- try {
- MpChatMessage msg = createMessage("TCP Private");
- connection.send(msg.toByteArray());
+ public void removeConnection(TcpConnection connection) {
+ PrivateChatPanel panel = chats.remove(connection);
- } catch (Exception ex) {
- Logger.getLogger(PrivateChatWindow.class.getName()).log(Level.SEVERE, null, ex);
+ if (panel == null) {
+ return;
+ }
+
+ chatPanel.remove(panel);
+ connectionListModel.removeElement(connection);
+
+ if (!connectionListModel.isEmpty()) {
+ connectionList.setSelectedIndex(0);
+ }
+ }
+
+ public void receiveMessage(TcpConnection connection, MpChatMessage message) {
+ PrivateChatPanel panel = chats.get(connection);
+
+ if (panel == null) {
+ return;
+ }
+
+ panel.receiveMessage(message);
+ }
+
+ private void showChat(TcpConnection connection) {
+ cardLayout.show(chatPanel, getCardName(connection));
+ }
+
+ private String getCardName(TcpConnection connection) {
+ return Integer.toHexString(System.identityHashCode(connection));
+ }
+
+ private class PrivateChatPanel extends JPanel {
+
+ private final TcpConnection connection;
+
+ private final JTextArea receivedMessagesArea;
+ private final JTextField messageField;
+
+ public PrivateChatPanel(TcpConnection connection) {
+ this.connection = connection;
+
+ setLayout(new BorderLayout(10, 10));
+
+ receivedMessagesArea = new JTextArea();
+ receivedMessagesArea.setEditable(false);
+ receivedMessagesArea.setLineWrap(true);
+ receivedMessagesArea.setWrapStyleWord(true);
+
+ JScrollPane messagesScrollPane =
+ new JScrollPane(receivedMessagesArea);
+
+ messagesScrollPane.setBorder(
+ BorderFactory.createTitledBorder("Mensagens")
+ );
+
+ add(messagesScrollPane, BorderLayout.CENTER);
+
+ JPanel bottomPanel = new JPanel(new BorderLayout(10, 10));
+
+ messageField = new JTextField();
+
+ JButton tcpButton = new JButton("TCP");
+ tcpButton.addActionListener(e -> sendTCP());
+
+ bottomPanel.add(messageField, BorderLayout.CENTER);
+ bottomPanel.add(tcpButton, BorderLayout.EAST);
+
+ add(bottomPanel, BorderLayout.SOUTH);
+ }
+
+ private void sendTCP() {
+ try {
+ String nome = pitiupi.getUserName();
+
+ MpChatMessage message = new MpChatMessage(
+ nome,
+ InetAddress.getLocalHost().toString(),
+ "TCP Private",
+ messageField.getText()
+ );
+
+ connection.send(message.toByteArray());
+
+ messageField.setText("");
+
+ } catch (Exception ex) {
+ Logger.getLogger(
+ PrivateChatWindow.class.getName()
+ ).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ public void receiveMessage(MpChatMessage message) {
+ SwingUtilities.invokeLater(() -> {
+ String texto = String.format(
+ "[%s] %s (%s): %s%n",
+ message.getTipoMensagem(),
+ message.getNome(),
+ message.getIp(),
+ message.getMessage()
+ );
+
+ receivedMessagesArea.append(texto);
+
+ receivedMessagesArea.setCaretPosition(
+ receivedMessagesArea.getDocument().getLength()
+ );
+ });
}
}
}
diff --git a/pitiupi.mpChat/src/GUI/PublicChatWindow.java b/pitiupi.mpChat/src/GUI/PublicChatWindow.java
index ff6967e..3599eb8 100644
--- a/pitiupi.mpChat/src/GUI/PublicChatWindow.java
+++ b/pitiupi.mpChat/src/GUI/PublicChatWindow.java
@@ -2,36 +2,95 @@ package GUI;
import net.MpChatMessage;
import pitiupi.control.ConnectionManager;
+import pitiupi.plugin.Pitiupi;
import javax.swing.*;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyledDocument;
import java.awt.*;
import java.net.InetAddress;
import java.util.logging.Level;
import java.util.logging.Logger;
-public class PublicChatWindow extends ChatWindow {
+public class PublicChatWindow extends JFrame {
+ private final Pitiupi pitiupi;
+ private JTextPane receivedMessagesArea;
+ private JTextField messageField;
private JTextField ipField;
- public PublicChatWindow(ConnectionManager connectionManager) {
- super(connectionManager);
+ public PublicChatWindow(Pitiupi pitiupi) {
+ this.pitiupi = pitiupi;
+
+ initComponents();
}
- @Override
- protected void initButtons(JPanel bottomPanel) {
+ private void initComponents() {
+ setTitle("Public Chat");
+ setSize(700, 500);
+ setLocationRelativeTo(null);
+ setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
+
+ JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
+
+ mainPanel.setBorder(
+ BorderFactory.createEmptyBorder(10, 10, 10, 10)
+ );
+
+ initReceivedMessagesPanel(mainPanel);
+ initBottomPanel(mainPanel);
+
+ setContentPane(mainPanel);
+ }
+
+ private void initReceivedMessagesPanel(JPanel mainPanel) {
+ receivedMessagesArea = new JTextPane();
+
+ receivedMessagesArea.setEditable(false);
+
+ JScrollPane messagesScrollPane = new JScrollPane(receivedMessagesArea);
+
+ messagesScrollPane.setBorder(
+ BorderFactory.createTitledBorder("Mensagens recebidas")
+ );
+
+ mainPanel.add(messagesScrollPane, BorderLayout.CENTER);
+ }
+
+ private void initBottomPanel(JPanel mainPanel) {
+ messageField = new JTextField();
+
+ JPanel bottomPanel = new JPanel(
+ new BorderLayout(10, 10)
+ );
+
+ bottomPanel.add(messageField, BorderLayout.CENTER);
+
initIpField(bottomPanel);
initCommunicationButtons(bottomPanel);
+
+ mainPanel.add(bottomPanel, BorderLayout.SOUTH);
}
private void initIpField(JPanel bottomPanel) {
ipField = new JTextField();
ipField.setPreferredSize(new Dimension(130, 30));
- JPanel ipPanel = new JPanel(new BorderLayout(5, 5));
+ JPanel ipPanel = new JPanel(
+ new BorderLayout(5, 5)
+ );
- ipPanel.add(new JLabel("IP destino:"), BorderLayout.WEST);
+ ipPanel.add(
+ new JLabel("IP destino:"),
+ BorderLayout.WEST
+ );
- ipPanel.add(ipField, BorderLayout.CENTER);
+ ipPanel.add(
+ ipField,
+ BorderLayout.CENTER
+ );
bottomPanel.add(ipPanel, BorderLayout.WEST);
}
@@ -45,13 +104,71 @@ public class PublicChatWindow extends ChatWindow {
udpButton.addActionListener(e -> sendUDP());
multicastButton.addActionListener(e -> sendMulticast());
- JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
+ JPanel buttonsPanel = new JPanel(
+ new FlowLayout(FlowLayout.RIGHT, 5, 0)
+ );
buttonsPanel.add(tcpButton);
buttonsPanel.add(udpButton);
buttonsPanel.add(multicastButton);
- bottomPanel.add(buttonsPanel, BorderLayout.EAST);
+ bottomPanel.add(
+ buttonsPanel,
+ BorderLayout.EAST
+ );
+ }
+
+ private MpChatMessage createMessage(String tipoMensagem) {
+ try {
+ String nome = pitiupi.getUserName();
+ String ip = InetAddress.getLocalHost().getHostAddress();
+ String message = messageField.getText();
+
+ return new MpChatMessage(
+ nome,
+ ip,
+ tipoMensagem,
+ message
+ );
+
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public void receiveMessage(MpChatMessage msg) {
+ SwingUtilities.invokeLater(() -> {
+ String mensagem = String.format(
+ "[%s] %s (%s): %s%n",
+ msg.getTipoMensagem(),
+ msg.getNome(),
+ msg.getIp(),
+ msg.getMessage()
+ );
+
+ StyledDocument document = receivedMessagesArea.getStyledDocument();
+
+ SimpleAttributeSet attributes = new SimpleAttributeSet();
+
+ if (msg.getTipoMensagem().equals("TCP Unicast") || msg.getTipoMensagem().equals("UDP Unicast")) {
+ StyleConstants.setForeground(attributes, new Color(128, 0, 128));
+ }
+
+ try {
+ document.insertString(
+ document.getLength(),
+ mensagem,
+ attributes
+ );
+
+ receivedMessagesArea.setCaretPosition(
+ document.getLength()
+ );
+
+ } catch (BadLocationException ex) {
+ Logger.getLogger(PublicChatWindow.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ });
}
private void sendTCP() {
@@ -60,10 +177,12 @@ public class PublicChatWindow extends ChatWindow {
InetAddress ip = InetAddress.getByName(ipField.getText());
- connectionManager.sendTcp(msg, ip);
+ pitiupi.sendTcp(msg, ip);
} catch (Exception ex) {
- Logger.getLogger(PublicChatWindow.class.getName()).log(Level.SEVERE, null, ex);
+ Logger.getLogger(
+ PublicChatWindow.class.getName()
+ ).log(Level.SEVERE, null, ex);
}
}
@@ -73,10 +192,12 @@ public class PublicChatWindow extends ChatWindow {
InetAddress ip = InetAddress.getByName(ipField.getText());
- connectionManager.sendUdpUnicast(msg, ip);
+ pitiupi.sendUdpUnicast(msg, ip);
} catch (Exception ex) {
- Logger.getLogger(PublicChatWindow.class.getName()).log(Level.SEVERE, null, ex);
+ Logger.getLogger(
+ PublicChatWindow.class.getName()
+ ).log(Level.SEVERE, null, ex);
}
}
@@ -84,10 +205,12 @@ public class PublicChatWindow extends ChatWindow {
try {
MpChatMessage msg = createMessage("UDP Multicast");
- connectionManager.sendUdpMulticast(msg);
+ pitiupi.sendUdpMulticast(msg);
} catch (Exception ex) {
- Logger.getLogger(PublicChatWindow.class.getName()).log(Level.SEVERE, null, ex);
+ Logger.getLogger(
+ PublicChatWindow.class.getName()
+ ).log(Level.SEVERE, null, ex);
}
}
}
\ No newline at end of file
diff --git a/pitiupi.mpChat/src/GUI/UnicastMpChatMenu.java b/pitiupi.mpChat/src/GUI/UnicastMpChatMenu.java
index 52cc699..a1816f9 100644
--- a/pitiupi.mpChat/src/GUI/UnicastMpChatMenu.java
+++ b/pitiupi.mpChat/src/GUI/UnicastMpChatMenu.java
@@ -1,4 +1,25 @@
package GUI;
-public class UnicastMpChatMenu {
+import pitiupi.models.Menus.UnicastMenus.UnicastActionMenu;
+import pitiupi.models.User;
+import plugin.MultiProtocolChat;
+
+import javax.swing.*;
+
+public class UnicastMpChatMenu extends UnicastActionMenu {
+ private final MultiProtocolChat multiProtocolChat;
+
+ public UnicastMpChatMenu(MultiProtocolChat multiProtocolChat) {
+ this.multiProtocolChat = multiProtocolChat;
+ }
+
+ @Override
+ public void onClick(User user) {
+ multiProtocolChat.openConnection(user.getAddress().toString());
+ }
+
+ @Override
+ public String getText() {
+ return "start Private Chat";
+ }
}
diff --git a/pitiupi.mpChat/src/plugin/MultiProtocolChat.java b/pitiupi.mpChat/src/plugin/MultiProtocolChat.java
index a9999bd..766f973 100644
--- a/pitiupi.mpChat/src/plugin/MultiProtocolChat.java
+++ b/pitiupi.mpChat/src/plugin/MultiProtocolChat.java
@@ -1,24 +1,28 @@
package plugin;
-import GUI.ChatMenu;
-import control.ChatController;
+import GUI.MulticastMpChatMenu;
+import GUI.PrivateChatWindow;
+import GUI.PublicChatWindow;
+import GUI.UnicastMpChatMenu;
import net.MpChatMessage;
-import pitiupi.control.ConnectionManager;
-import pitiupi.control.GuiManager;
+import pitiupi.models.Menus.MenuCategory;
import pitiupi.models.Messages.Message;
import pitiupi.net.tcp.TcpConnection;
import pitiupi.models.Plugin;
+import pitiupi.plugin.Pitiupi;
import javax.swing.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.InetAddress;
+import java.util.List;
public class MultiProtocolChat extends Plugin {
- ChatController chatController;
- ConnectionManager connectionManager;
- GuiManager guiManager;
+ Pitiupi pitiupi;
+
+ PublicChatWindow publicChatWindow;
+ PrivateChatWindow privateChatWindow;
@Override
public String getName() {
@@ -41,30 +45,36 @@ public class MultiProtocolChat extends Plugin {
}
@Override
- public void createPlugin(ConnectionManager connectionManager, GuiManager guiManager) {
- this.connectionManager = connectionManager;
- this.guiManager = guiManager;
+ public void createPlugin(Pitiupi pitiupi) {
+ this.pitiupi = pitiupi;
- ChatMenu chatMenu = new ChatMenu(this);
- chatController = new ChatController(connectionManager, chatMenu);
- guiManager.addMulticastMenu(chatMenu);
+ publicChatWindow = new PublicChatWindow(pitiupi);
+ privateChatWindow = new PrivateChatWindow(pitiupi);
+
+ MulticastMpChatMenu multicastMpChatMenu = new MulticastMpChatMenu(publicChatWindow);
+ UnicastMpChatMenu unicastMpChatMenu = new UnicastMpChatMenu(this);
+
+ pitiupi.createMenu(MenuCategory.Social, multicastMpChatMenu);
+ pitiupi.createMenu(MenuCategory.Social, unicastMpChatMenu);
}
@Override
- public Message getMessage() {
- return new MpChatMessage();
+ public List> getMessages() {
+ return List.of(MpChatMessage.class);
}
@Override
- public void receiveMessage(byte[] message) {
- MpChatMessage mpChatMessage = parseMessage(message);
- chatController.receivePublic(mpChatMessage);
+ public void receiveMessage(Message message) {
+ if (message instanceof MpChatMessage mpChatMessage) {
+ publicChatWindow.receiveMessage(mpChatMessage);
+ }
}
+
@Override
public boolean receivePrivateConnection(TcpConnection connection) {
SwingUtilities.invokeLater(() -> {
- chatController.addChatWindow(connection);
+ privateChatWindow.addConnection(connection);
});
return true;
}
@@ -72,25 +82,23 @@ public class MultiProtocolChat extends Plugin {
@Override
public boolean receiveBytes(TcpConnection connection, byte[] bytes) {
MpChatMessage mpChatMessage = parseMessage(bytes);
- chatController.receivePrivate(connection, mpChatMessage);
+ privateChatWindow.receiveMessage(connection, mpChatMessage);
return true;
}
@Override
public boolean onSocketClosed(TcpConnection connection) {
- chatController.removeChatWindow(connection);
+ privateChatWindow.removeConnection(connection);
return true;
}
- public boolean openConnection(String ip) {
+ public void openConnection(String ip) {
try {
- connectionManager.connectPluginTcp(InetAddress.getByName(ip), getIdentifier(), getIdentifier());
- return true;
+ pitiupi.connectTcp(InetAddress.getByName(ip), getIdentifier(), getIdentifier());
}
catch (Exception e) {
System.out.println("Error opening connection: " + e.getMessage());
}
- return false;
}
private MpChatMessage parseMessage(byte[] bytes) {