From 581a924afc5bb1ffca099de35b8c218a916144a4 Mon Sep 17 00:00:00 2001 From: GustavoHMDS Date: Wed, 7 Oct 2026 19:31:37 -0300 Subject: [PATCH] =?UTF-8?q?BugFix=20e=20atualiza=C3=A7=C3=A3o=20da=20inter?= =?UTF-8?q?face=20no=20mpChat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../META-INF/services/pitiupi.models.Plugin | 1 + pitiupi.mpChat/src/GUI/PrivateChatWindow.java | 244 ++++++------------ pitiupi.mpChat/src/GUI/UnicastMpChatMenu.java | 19 +- .../src/control/PrivateChatController.java | 116 +++++++++ .../src/plugin/MultiProtocolChat.java | 14 +- pitiupi/src/pitiupi/GUI/MenuBar.java | 1 - pitiupi/src/pitiupi/net/tcp/SocketTCP.java | 4 +- .../src/pitiupi/net/tcp/TcpConnection.java | 2 + 8 files changed, 222 insertions(+), 179 deletions(-) create mode 100644 pitiupi.mpChat/out/META-INF/META-INF/services/pitiupi.models.Plugin create mode 100644 pitiupi.mpChat/src/control/PrivateChatController.java diff --git a/pitiupi.mpChat/out/META-INF/META-INF/services/pitiupi.models.Plugin b/pitiupi.mpChat/out/META-INF/META-INF/services/pitiupi.models.Plugin new file mode 100644 index 0000000..3240a6f --- /dev/null +++ b/pitiupi.mpChat/out/META-INF/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 d811a9b..c07f342 100644 --- a/pitiupi.mpChat/src/GUI/PrivateChatWindow.java +++ b/pitiupi.mpChat/src/GUI/PrivateChatWindow.java @@ -1,201 +1,121 @@ 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 JFrame { private final Pitiupi pitiupi; + private final TcpConnection connection; - private final Map chats; + private final JTextArea receivedMessagesArea; + private final JTextField messageField; - private final JPanel chatPanel; - private final CardLayout cardLayout; - - private final DefaultListModel connectionListModel; - private final JList connectionList; - - public PrivateChatWindow(Pitiupi pitiupi) { + public PrivateChatWindow( + Pitiupi pitiupi, + TcpConnection connection + ) { this.pitiupi = pitiupi; - this.chats = new HashMap<>(); + this.connection = connection; - setTitle("Chats privados"); + setTitle("Chat privado"); 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.setBorder( + BorderFactory.createEmptyBorder(10, 10, 10, 10) ); - mainPanel.add(connectionScrollPane, BorderLayout.WEST); + receivedMessagesArea = new JTextArea(); + receivedMessagesArea.setEditable(false); + receivedMessagesArea.setLineWrap(true); + receivedMessagesArea.setWrapStyleWord(true); - cardLayout = new CardLayout(); - chatPanel = new JPanel(cardLayout); + JScrollPane messagesScrollPane = + new JScrollPane(receivedMessagesArea); - mainPanel.add(chatPanel, BorderLayout.CENTER); + messagesScrollPane.setBorder( + BorderFactory.createTitledBorder("Mensagens") + ); + + mainPanel.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 + ); + + mainPanel.add( + bottomPanel, + BorderLayout.SOUTH + ); setContentPane(mainPanel); } - public void addConnection(TcpConnection connection) { - if (chats.containsKey(connection)) { - return; - } + private void sendTCP() { + try { + String nome = pitiupi.getUserName(); - PrivateChatPanel panel = new PrivateChatPanel(connection); - - chats.put(connection, panel); - connectionListModel.addElement(connection); - - String cardName = getCardName(connection); - chatPanel.add(panel, cardName); - - if (connectionList.getSelectedValue() == null) { - connectionList.setSelectedValue(connection, true); - } - } - - public void removeConnection(TcpConnection connection) { - PrivateChatPanel panel = chats.remove(connection); - - 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") + MpChatMessage message = new MpChatMessage( + nome, + InetAddress.getLocalHost().getHostAddress(), + "TCP Private", + messageField.getText() ); - add(messagesScrollPane, BorderLayout.CENTER); + connection.send(message.toByteArray()); - JPanel bottomPanel = new JPanel(new BorderLayout(10, 10)); + messageField.setText(""); - 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() - ); - }); + } 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() + ); + }); + } +} \ No newline at end of file diff --git a/pitiupi.mpChat/src/GUI/UnicastMpChatMenu.java b/pitiupi.mpChat/src/GUI/UnicastMpChatMenu.java index a1816f9..e848440 100644 --- a/pitiupi.mpChat/src/GUI/UnicastMpChatMenu.java +++ b/pitiupi.mpChat/src/GUI/UnicastMpChatMenu.java @@ -1,25 +1,26 @@ package GUI; +import control.PrivateChatController; 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; + private final PrivateChatController controller; + + public UnicastMpChatMenu( + PrivateChatController controller + ) { + this.controller = controller; } @Override public void onClick(User user) { - multiProtocolChat.openConnection(user.getAddress().toString()); + controller.openChat(user); } @Override public String getText() { - return "start Private Chat"; + return "Start Private Chat"; } -} +} \ No newline at end of file diff --git a/pitiupi.mpChat/src/control/PrivateChatController.java b/pitiupi.mpChat/src/control/PrivateChatController.java new file mode 100644 index 0000000..aad138a --- /dev/null +++ b/pitiupi.mpChat/src/control/PrivateChatController.java @@ -0,0 +1,116 @@ +package control; + +import GUI.PrivateChatWindow; +import net.MpChatMessage; +import pitiupi.models.User; +import pitiupi.net.tcp.TcpConnection; +import pitiupi.plugin.Pitiupi; +import plugin.MultiProtocolChat; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class PrivateChatController { + + private final Pitiupi pitiupi; + private final MultiProtocolChat multiProtocolChat; + + /* + * Relaciona o endereço do usuário à janela de chat. + */ + private final Map windows; + + /* + * Endereços para os quais uma conexão já foi solicitada, + * mas ainda não chegou. + */ + private final Set pendingConnections; + + public PrivateChatController( + Pitiupi pitiupi, + MultiProtocolChat multiProtocolChat + ) { + this.pitiupi = pitiupi; + this.multiProtocolChat = multiProtocolChat; + + this.windows = new HashMap<>(); + this.pendingConnections = new HashSet<>(); + } + + public void openChat(User user) { + String address = user.getAddress().getHostAddress(); + + PrivateChatWindow window = windows.get(address); + + /* + * Já existe uma janela para esse usuário. + */ + if (window != null) { + window.setVisible(true); + window.toFront(); + window.requestFocus(); + return; + } + + /* + * Já estamos esperando uma conexão para esse usuário. + */ + if (pendingConnections.contains(address)) { + return; + } + + /* + * Ainda não existe conexão. + */ + pendingConnections.add(address); + + multiProtocolChat.openConnection(address); + } + + public void receiveMessage(TcpConnection connection, MpChatMessage message) { + String address = connection.getAddress().toString(); + + PrivateChatWindow window = windows.get(address); + + if (window == null) { + return; + } + + window.receiveMessage(message); + } + + /** + * Deve ser chamado quando uma nova conexão privada chegar. + */ + public void connectionReceived(TcpConnection connection) { + String address = connection.getAddress().toString(); + + pendingConnections.remove(address); + + PrivateChatWindow window = new PrivateChatWindow( + pitiupi, + connection + ); + + windows.put(address, window); + + window.setVisible(true); + window.toFront(); + window.requestFocus(); + } + + /** + * Fecha a janela e remove o relacionamento. + */ + public void closeChat(TcpConnection connection) { + String address = connection.getAddress().toString(); + + PrivateChatWindow window = windows.remove(address); + + if (window != null) { + window.dispose(); + } + } +} \ No newline at end of file diff --git a/pitiupi.mpChat/src/plugin/MultiProtocolChat.java b/pitiupi.mpChat/src/plugin/MultiProtocolChat.java index 766f973..8d58155 100644 --- a/pitiupi.mpChat/src/plugin/MultiProtocolChat.java +++ b/pitiupi.mpChat/src/plugin/MultiProtocolChat.java @@ -4,6 +4,7 @@ import GUI.MulticastMpChatMenu; import GUI.PrivateChatWindow; import GUI.PublicChatWindow; import GUI.UnicastMpChatMenu; +import control.PrivateChatController; import net.MpChatMessage; import pitiupi.models.Menus.MenuCategory; import pitiupi.models.Messages.Message; @@ -21,8 +22,8 @@ import java.util.List; public class MultiProtocolChat extends Plugin { Pitiupi pitiupi; + PrivateChatController privateChatController; PublicChatWindow publicChatWindow; - PrivateChatWindow privateChatWindow; @Override public String getName() { @@ -48,11 +49,12 @@ public class MultiProtocolChat extends Plugin { public void createPlugin(Pitiupi pitiupi) { this.pitiupi = pitiupi; + privateChatController = new PrivateChatController(pitiupi, this); + publicChatWindow = new PublicChatWindow(pitiupi); - privateChatWindow = new PrivateChatWindow(pitiupi); MulticastMpChatMenu multicastMpChatMenu = new MulticastMpChatMenu(publicChatWindow); - UnicastMpChatMenu unicastMpChatMenu = new UnicastMpChatMenu(this); + UnicastMpChatMenu unicastMpChatMenu = new UnicastMpChatMenu(privateChatController); pitiupi.createMenu(MenuCategory.Social, multicastMpChatMenu); pitiupi.createMenu(MenuCategory.Social, unicastMpChatMenu); @@ -74,7 +76,7 @@ public class MultiProtocolChat extends Plugin { @Override public boolean receivePrivateConnection(TcpConnection connection) { SwingUtilities.invokeLater(() -> { - privateChatWindow.addConnection(connection); + privateChatController.connectionReceived(connection); }); return true; } @@ -82,13 +84,13 @@ public class MultiProtocolChat extends Plugin { @Override public boolean receiveBytes(TcpConnection connection, byte[] bytes) { MpChatMessage mpChatMessage = parseMessage(bytes); - privateChatWindow.receiveMessage(connection, mpChatMessage); + privateChatController.receiveMessage(connection, mpChatMessage); return true; } @Override public boolean onSocketClosed(TcpConnection connection) { - privateChatWindow.removeConnection(connection); + privateChatController.closeChat(connection); return true; } diff --git a/pitiupi/src/pitiupi/GUI/MenuBar.java b/pitiupi/src/pitiupi/GUI/MenuBar.java index c6c67c8..846dd10 100644 --- a/pitiupi/src/pitiupi/GUI/MenuBar.java +++ b/pitiupi/src/pitiupi/GUI/MenuBar.java @@ -111,7 +111,6 @@ public class MenuBar extends JMenuBar { } public void addPluginMenu(MenuCategory category, JMenuItem menu){ - System.out.println("addPluginMenu"); categories.get(category).add(menu); } } diff --git a/pitiupi/src/pitiupi/net/tcp/SocketTCP.java b/pitiupi/src/pitiupi/net/tcp/SocketTCP.java index 688f638..8f994c1 100644 --- a/pitiupi/src/pitiupi/net/tcp/SocketTCP.java +++ b/pitiupi/src/pitiupi/net/tcp/SocketTCP.java @@ -66,6 +66,8 @@ public class SocketTCP extends Thread { try { serverSocket = new ServerSocket(connectionManager.getPort()); address = InetAddress.getByName(InetAddress.getLocalHost().getHostAddress()); + if (address != null) System.out.println("SocketTCP: "+ address); + else System.out.println("Adress: Null"); } catch (IOException ex) { System.out.println("There is no socket connection. Sorry."); System.out.println(ex.toString()); @@ -336,7 +338,7 @@ public class SocketTCP extends Thread { * ao plugin destinatário. * *

Dados que não representam mensagens de controle são entregues - * diretamente ao {@link PrivateConnectionPlugin}. Mensagens de controle + * diretamente ao {@link pitiupi.models.Plugin}. Mensagens de controle * relacionadas ao encerramento ou a erros internos provocam a notificação * do plugin e o fechamento da conexão.

* diff --git a/pitiupi/src/pitiupi/net/tcp/TcpConnection.java b/pitiupi/src/pitiupi/net/tcp/TcpConnection.java index be7c0e4..2194b9d 100644 --- a/pitiupi/src/pitiupi/net/tcp/TcpConnection.java +++ b/pitiupi/src/pitiupi/net/tcp/TcpConnection.java @@ -40,6 +40,8 @@ public class TcpConnection { this.input = new DataInputStream(socket.getInputStream()); this.output = new DataOutputStream(socket.getOutputStream()); this.address = socket.getInetAddress(); + if (address != null) System.out.println("TcpConnection: " + address); + else System.out.println("Adress: Null"); this.lastActivity = System.currentTimeMillis(); this.timeout = 300_000; // 5 minutos }