diff --git a/.gitignore b/.gitignore index 79f7dce..237cb8c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ -build/ -dist/ -*.class +/pitiupi/build/ +/pitiupi/dist/ +/pitiupi.chat/build/ +/pitiupi.chat/dist/ +/pitiupi.chat/nbproject/private/ +/pitiupi.screenCast/build/ +/pitiupi.screenCast/dist/ + +.idea/ diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 30cf57e..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Ignored default folder with query files -/queries/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/libraries/pitiupi.xml b/.idea/libraries/pitiupi.xml deleted file mode 100644 index 4207ae9..0000000 --- a/.idea/libraries/pitiupi.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/pitiupi_chat.xml b/.idea/libraries/pitiupi_chat.xml deleted file mode 100644 index a84f0a3..0000000 --- a/.idea/libraries/pitiupi_chat.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/pitiupi_screenCast.xml b/.idea/libraries/pitiupi_screenCast.xml deleted file mode 100644 index 410fe64..0000000 --- a/.idea/libraries/pitiupi_screenCast.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/plugins.xml b/.idea/libraries/plugins.xml deleted file mode 100644 index 5d318c9..0000000 --- a/.idea/libraries/plugins.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index b1566b1..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index b6bf55e..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/pitiupi.iml b/.idea/pitiupi.iml deleted file mode 100644 index d6ebd48..0000000 --- a/.idea/pitiupi.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index 1f92201..e2b66f8 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,10 @@ # pitiupi -Este repositório tem 4 projetos Java que são independentes: +Ferramenta p2p para práticas em rede -### Sistema: +Este repositório tem 3 projetos Java que são independentes: - A ferramenta pitiupi (P2P) - -### Plugins: - Um plugin de Chat -- Um plugin de Chat multiprotocolo (TCP/UDP) - Um plugin de ScreenCast Cada um destes projetos deve ser compilado individualmente. Para isso, use a ferramenta ant no diretório do projeto. @@ -24,26 +21,9 @@ Para criar links simbólicos no Linux, use o comando: ``` cd pitiupi/plugins ln -s ../../pitiupi.chat/dist/*.jar . -ln -s ../../pitiupi.mpChat/dist/*.jar . ln -s ../../pitiupi.screenCast/dist/*.jar . ``` Isso deve resolver! -## Como um plugin conversa com o pitiupi +Para criar um novo plugin: -Um plugin nunca recebe acesso direto às classes internas do núcleo (ConnectionManager, GuiManager). Em vez disso, recebe uma facade, a classe Pitiupi, que expõe só o que um plugin precisa: enviar mensagem (multicast, unicast ou tcp), abrir conexão tcp privada, ler nome de usuário e porta, criar menu. - -```java -public abstract void createPlugin(Pitiupi pitiupi); -``` - -## Para criar um novo plugin - -1. Implemente `pitiupi.models.Plugin`, incluindo `createPlugin(Pitiupi pitiupi)` -2. Registre a classe em `src/META-INF/services/pitiupi.models.Plugin`, com o nome completo da classe numa linha -3. Compile com `ant jar` -4. Linke o `.jar` em `pitiupi/plugins` - -Use `pitiupi.chat` como referência — é o exemplo mais simples e completo. - -Plugins que ainda não foram atualizados para a Pitiupi (como uma versão mais antiga do screenCast) não compilam contra o núcleo atual e precisam de migração antes de serem usados. diff --git a/pitiupi.chat/build/built-jar.properties b/pitiupi.chat/build/built-jar.properties new file mode 100644 index 0000000..54fc683 --- /dev/null +++ b/pitiupi.chat/build/built-jar.properties @@ -0,0 +1,6 @@ +#Fri, 02 Oct 2026 20:11:21 -0300 + + +C\:\\Users\\extre\\OneDrive\\Documentos\\Faculdade\\2026_02\\Monitoria\\Pitiupi\\pitiupi.chat= + +C\:\\Users\\extre\\OneDrive\\Documentos\\Faculdade\\2026_02\\Monitoria\\Pitiupi\\pitiupi= diff --git a/pitiupi.chat/build/classes/META-INF/services/pitiupi.plugin.Plugin b/pitiupi.chat/build/classes/META-INF/services/pitiupi.plugin.Plugin new file mode 100644 index 0000000..eea07c1 --- /dev/null +++ b/pitiupi.chat/build/classes/META-INF/services/pitiupi.plugin.Plugin @@ -0,0 +1 @@ +pitiupi.chat.plugin.ChatPlugin diff --git a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatMenu.class b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatMenu.class new file mode 100644 index 0000000..af3942e Binary files /dev/null and b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatMenu.class differ diff --git a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow$1.class b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow$1.class new file mode 100644 index 0000000..3d3023d Binary files /dev/null and b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow$1.class differ diff --git a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class new file mode 100644 index 0000000..34763e9 Binary files /dev/null and b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class differ diff --git a/pitiupi.chat/build/classes/pitiupi/chat/net/ChatMessage.class b/pitiupi.chat/build/classes/pitiupi/chat/net/ChatMessage.class new file mode 100644 index 0000000..661793b Binary files /dev/null and b/pitiupi.chat/build/classes/pitiupi/chat/net/ChatMessage.class differ diff --git a/pitiupi.chat/build/classes/pitiupi/chat/plugin/ChatPlugin.class b/pitiupi.chat/build/classes/pitiupi/chat/plugin/ChatPlugin.class new file mode 100644 index 0000000..dca047b Binary files /dev/null and b/pitiupi.chat/build/classes/pitiupi/chat/plugin/ChatPlugin.class differ diff --git a/pitiupi.chat/nbproject/project.properties b/pitiupi.chat/nbproject/project.properties index 6f8cc9a..b87aa66 100644 --- a/pitiupi.chat/nbproject/project.properties +++ b/pitiupi.chat/nbproject/project.properties @@ -47,8 +47,8 @@ javac.modulepath= javac.processormodulepath= javac.processorpath=\ ${javac.classpath} -javac.source=17 -javac.target=17 +javac.source=25 +javac.target=25 javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir} diff --git a/pitiupi.chat/src/pitiupi/chat/GUI/ChatWindow.java b/pitiupi.chat/src/pitiupi/chat/GUI/ChatWindow.java index 708ddb9..7aeed97 100644 --- a/pitiupi.chat/src/pitiupi/chat/GUI/ChatWindow.java +++ b/pitiupi.chat/src/pitiupi/chat/GUI/ChatWindow.java @@ -8,13 +8,13 @@ package pitiupi.chat.GUI; import java.text.SimpleDateFormat; import java.util.Date; import pitiupi.chat.net.ChatMessage; -import pitiupi.plugin.Pitiupi; +import pitiupi.control.ConnectionManager; import pitiupi.models.Messages.Message; import javax.swing.*; /** - * @author tony + * * @author flavio */ public class ChatWindow extends JDialog { @@ -28,12 +28,13 @@ public class ChatWindow extends JDialog { private JSplitPane jSplitPane1; private JTextArea jTextArea1; - private final Pitiupi pitiupi; + private final ConnectionManager connectionManager; + + public ChatWindow(ConnectionManager connectionManager) { + this.connectionManager = connectionManager; + initComponents(); + } - public ChatWindow(Pitiupi pitiupi) { - this.pitiupi = pitiupi; - initComponents(); - } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -92,13 +93,13 @@ public class ChatWindow extends JDialog { if (jTextArea1.getText().trim().isEmpty()) { return; } - ChatMessage message = new ChatMessage(pitiupi.getUserName(), jTextArea1.getText()); + ChatMessage message = new ChatMessage(connectionManager.getUserName(), jTextArea1.getText()); this.sendChatMessage(message); jTextArea1.setText(""); } public void sendChatMessage(Message message) { - pitiupi.sendUdpMulticast(message); + connectionManager.sendUdpMulticast(message); } public void receiveChatMessage(ChatMessage message) { diff --git a/pitiupi.chat/src/pitiupi/chat/plugin/ChatPlugin.java b/pitiupi.chat/src/pitiupi/chat/plugin/ChatPlugin.java index e33709c..cb9b16f 100644 --- a/pitiupi.chat/src/pitiupi/chat/plugin/ChatPlugin.java +++ b/pitiupi.chat/src/pitiupi/chat/plugin/ChatPlugin.java @@ -8,29 +8,29 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import pitiupi.plugin.Pitiupi; import pitiupi.chat.GUI.ChatMenu; import pitiupi.chat.GUI.ChatWindow; import pitiupi.chat.net.ChatMessage; +import pitiupi.control.ConnectionManager; +import pitiupi.control.GuiManager; import pitiupi.models.Menus.MenuCategory; import pitiupi.models.Messages.Message; import pitiupi.models.Plugin; /** - *@author tony + * * @author flavio */ public class ChatPlugin extends Plugin { private ChatWindow chatWindow; - @Override - public void createPlugin(Pitiupi pitiupi) { - this.chatWindow = new ChatWindow(pitiupi); - pitiupi.createMenu(MenuCategory.Social, new ChatMenu(chatWindow)); + @Override + public void createPlugin(ConnectionManager connectionManager, GuiManager guiManager) { + this.chatWindow = new ChatWindow(connectionManager); + guiManager.createMenu(MenuCategory.Social, new ChatMenu(chatWindow)); } - @Override public List> getMessages() { return List.of(ChatMessage.class); diff --git a/pitiupi.mpChat/src/control/ChatController.java b/pitiupi.mpChat/src/control/ChatController.java new file mode 100644 index 0000000..07f7bb7 --- /dev/null +++ b/pitiupi.mpChat/src/control/ChatController.java @@ -0,0 +1,73 @@ +package control; + +import GUI.ChatMenu; +import GUI.ChatWindow; +import GUI.PrivateChatWindow; +import GUI.PublicChatWindow; +import net.MpChatMessage; +import pitiupi.control.ConnectionManager; +import pitiupi.control.PeerListener; +import pitiupi.models.User; +import pitiupi.net.tcp.TcpConnection; + +import javax.swing.*; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.List; + +public class ChatController implements PeerListener { + ConnectionManager connectionManager; + ChatMenu chatMenu; + + PublicChatWindow publicChatWindow; + + private final HashMap chatWindows; + + public ChatController(ConnectionManager connectionManager, ChatMenu chatMenu) { + this.connectionManager = connectionManager; + publicChatWindow = new PublicChatWindow(connectionManager); + + chatMenus = new HashMap<>(); + chatWindows = new HashMap<>(); + + this.chatMenu = chatMenu; + + this.chatMenu.newMenuItem(new JMenuItem("Show global chat"), publicChatWindow); + } + + public void addChatWindow(TcpConnection tcpConnection) { + if (chatWindows.containsKey(tcpConnection)) return; + + PrivateChatWindow newChat = new PrivateChatWindow(connectionManager, tcpConnection); + chatWindows.put(tcpConnection, newChat); + JMenuItem newMenuItem = new JMenuItem(); + chatMenus.put(tcpConnection, newMenuItem); + newMenuItem.setText(tcpConnection.getAddress().toString()); + chatMenu.newMenuItem(newMenuItem, newChat); + } + + public void removeChatWindow(TcpConnection tcpConnection) { + ChatWindow removedWindow = chatWindows.remove(tcpConnection); + JMenuItem removedMenu = chatMenus.remove(tcpConnection); + + chatMenu.removeMenuItem(removedMenu); + removedWindow.setVisible(false); + removedWindow.dispose(); + } + + public void receivePublic(MpChatMessage message) { + publicChatWindow.receiveMessage(message); + } + public void receivePrivate(TcpConnection tcpConnection, MpChatMessage message) { + chatWindows.get(tcpConnection).receiveMessage(message); + } + + public void openChatWindow(InetAddress address) { + + } + + @Override + public void onPeersChanged(List list) { + + } +} diff --git a/pitiupi.testSocket/.idea/.gitignore b/pitiupi.testSocket/.idea/.gitignore deleted file mode 100644 index 30cf57e..0000000 --- a/pitiupi.testSocket/.idea/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Ignored default folder with query files -/queries/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/pitiupi.testSocket/.idea/misc.xml b/pitiupi.testSocket/.idea/misc.xml deleted file mode 100644 index 07115cd..0000000 --- a/pitiupi.testSocket/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/pitiupi.testSocket/.idea/modules.xml b/pitiupi.testSocket/.idea/modules.xml deleted file mode 100644 index 83d481a..0000000 --- a/pitiupi.testSocket/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/pitiupi.testSocket/.idea/vcs.xml b/pitiupi.testSocket/.idea/vcs.xml deleted file mode 100644 index 6c0b863..0000000 --- a/pitiupi.testSocket/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/pitiupi/docs/PluginTutorial.md b/pitiupi/docs/PluginTutorial.md index 9734902..120dcfd 100644 --- a/pitiupi/docs/PluginTutorial.md +++ b/pitiupi/docs/PluginTutorial.md @@ -1,512 +1,2 @@ -# Como criar plugins para o Pitiupi +# Como criar plugins para o Share my Sheet -Aqui serão discutidos os métodos e classes que um desenvolvedor pode ou deve usar para criar um plugin para a plataforma Pitiupi. - -Alguns deles estarão marcados com um [REF], isso indica que eles estão sendo alterados para a versão 3.0 e deixarão de existir ou vão mudar consideravelmente. - -## GUI - -O Pitiupi é feito usando a biblioteca Swing do Java, por isso é altamente recomendado que os plugins também a utilizem na hora de criar sua interface gráfica, porém não é obrigatório. - -## Como tornar o seu plugin visível para o Pitiupi - -A busca por plugins é realizada em três etapas pelo pitiupi: - -1. Encontra todos os jars em `plugins`. -2. Verifica o `META-INF` dos jars para saber onde estão as implementações da classe `Plugin`. -3. Carrega o plugin no sistema. - -Em relação ao `META-INF`, ele deve conter um diretório `resources` e dentro dele um arquivo contendo o nome completamente qualificado da classe `Plugin` do pitiupi: `pitiupi.models.Plugin`, por fim dentro desse arquivo você deve colocar o nome completamente qualificado de todas as classes que implementam `Plugin` do seu projeto, um em cada linha. - -``` -build/ - |---->META-INF/resources/pitiupi.models.Plugin - |---->MeusPlugins/... - |---->MinhasMensagens/... - |---->Restante dos .class -``` - - -``` -src/MeusPlugins/MeuPrimeiroPlugin -src/MeusPlugins/MeuSegundoPlugin -... -``` - -### Dicas - -- Faça um makefile que automaticamente mova o META-INF para o build/ quando você compilar uma nova versão caso ele esteja sendo alterado com frequência. -Ex: -``` -JAR = ../pitiupi/dist/pitiupi.jar -BUILD_DIR = build -META-INF_DIR = src/META-INF -DIST = dist/mpChat.jar - -SOURCES = $(shell find -name "*.java") - -all: - mkdir -p "$(BUILD_DIR)" - mkdir -p "$(dir $(DIST))" - javac -cp "$(JAR)" -d "$(BUILD_DIR)" $(SOURCES) - cp -r "$(META-INF_DIR)" "$(BUILD_DIR)" - jar cf "$(DIST)" -C "$(BUILD_DIR)" . - -clean: - rm -rf "$(BUILD_DIR)"/* -``` - -- Para a versão 3.0 será necessário fazer o mesmo processo para as implementações da classe `Message`, então se quiser deixar preparado para a nova versão adicione `pitiupi.models.Messages.Message` em `resources` e coloque nele todas suas implementações de `Message`, assim como você fez para os de `Plugin`. - -## Pitiupi - -A classe `Pitiupi` é a interface que o seu plugin vai receber quando for criado, ela fornece os métodos necessários para interagir com a interface gráfica e comunicação para outros peers. - -### boolean sendUdpMulticast(Message message) - -Envia uma mensagem multicast, retorna `boolean` indicando se teve sucesso. - -### boolean sendUdpUnicast(Message message, InetAddress address) - -Envia uma mensagem unicast via udp para o endereço fornecido, retorna `boolean` indicando se teve sucesso. - -### boolean sendTcp(Message message, InetAddress address) - -Envia uma mensagem unicast via tcp para o endereço fornecido, retorna `boolean` indicando se teve sucesso. - -### [REF] TcpConnection connectTcp(InetAddress address, String senderId, String receiverId) - -Pede uma conexão tcp privada para o seu plugin com outro usuário, para utilizar essa funcionalidade é necessário implementar alguns métodos opcionais em Plugin. Maisinformações serão discutidas na seção TcpConnection. - -### String getUserName() - -Retorna o nome do usuário conectado - -### int getPort() - -Retorna a porta que o usuário está usando o Pitiupi - -### void createMenu(MenuCategory category, Menu menu) - -Adiciona um menu ao pitiupi, category define em qual das categoria de Menus ele será adicionado: Jogos, Social, Streaming. - -Os `Menus` serão discutidos em uma seção posterior. - -## Classe Plugin - -Essa é a classe que o pitiupi vai procurar ao carregar o seu plugin, ela define um contrato de métodos que todo plugin deve possuir. - -### getName() - -Indica o nome público do plugin. - -### getAuthor() - -Indica o nome dos desenvolvedores do plugin. - -### getVersion() - -Indica a versão atual do plugin. - -### getIdentifier() - -Indica um id que o pitiupi vai utilizar para enontrar seu plugin, por isso é importante que ele seja bem especifico para evitar que dois plugins sejam confundidos durante a comunicação. Procure usar algo como: MeuPlugin.Autor.Números - -### createPlugin(Pitiupi pitiupi) - -Após o pitiupi identificar e carregar o seu plugin, ele vai chamar esse método para inicializá-lo, por isso pense nele como o construtor do seu plugin, é aqui que você inicializa atributos, adiciona os menus inciais, etc. - -### getMessages() - -Esse método indica ao pitiupi quais tipos de mensagem seu plugin quer receber, normalmente as que ele mesmo implementar. -Nesse caso, é normal que ele faça: - -``` -return List.of( - SuaMensagem1.class, - SuaMensagem2.class, - ... - ); -``` - -Caso você queira que seu plugin receba todo tipo de mensagem, existe um método `receiveAllTypes()` que ele pode sobreescrever para receber todas mensagens -que não sejam consideradas privadas. - -### receiveMessage(Message message) - -Esse é o método que o pitiupi vai chamar quando quiser te entregar uma mensagem pelo canal publico de mensagens. Note que ele entrega uma `Message`, então é necessário que -seu plugin confira o tipo real ele mesmo. Como em: - -``` -if (message instanceOf MinhaMensagem minhaMensagem) {...} -``` - -O pitiupi garante que é uma mensagem de um tipo que o seu plugin diz aceitar. - -### [REF] métodos opcionais - -Os métodos a seguir possuem uma implementação padrão da própria classe que retornam false. Os três ultimos são necessários caso seu plugin deseje criar e receber conexões privadas. - -### [REF] receiveAllTypes() - -Indica ao Pitiupi que seu plugin deseja receber todas as mensagens publicas da plataforma, independente do tipo. - -### [REF] receivePrivateConnection(TcpConnection connection) - -Esse método é chamado quando o Pitiupi precisa entregar uma `TcpConnection` ao seu plugin, seja um que você pediu ou recebeu de um peer. - -### [REF] receiveBytes(TcpConnection connection, byte[] bytes) - -Esse método é chamado para entregar as mensagens recebidas por um `TcpConnection`, o tcpConnection no parametro indica qual a fonte da mensagem. - -### [REF] onSocketClosed(TcpConnection connection) - -Esse é método é chamado quando o socket de um `TcpConnection` pertencente ao plugin é fechado. - -## Message - -Essa é a classe abstrata que o pitiupi usa para comunicação nos canais publicos. - -[REF] Ela possui um atributo isPublic que por padrão é true, mas é possível defini-lo no construtor como false caso a mensagem deva ser privada. - -Essa classe implementa `Serializable` e possui um método `toByteArray` que transforma a mensagem em `byte[]`. Porém é importante notar que caso ela possua um objeto de outra classe como atributo aquela classe também deve implementar `Serializable`. - -## [REF] TcpConnection - -Representa uma conexão Tcp ativa para algum outro peer, mensagens enviadas por essa conexão não chegam ao canal publico e em vez disso vão direto para destinatário. - -Caso fique inativa (Sem enviar ou receber mensagens) por 5 minutos a conexão é fechada automaticamente e o dono é notificado. - -### [REF] void send(byte[] message) - -Envia um conjunto de bytes[] para o destinatario. - -Caso queira enviar uma `Message` chame o método toByteArray para transforma-la em bytes primeiro. - -### [REF] boolean isClosed() - -Indica se a conexão esta fechada - -### [REF] InetAddress getAddress() - -Retorna o endereço do peer que ela esta conectada. - -### [REF] String getReceiver() - -Retorna o identificador do plugin que ela esta conectada. - -### [REF] getReceiver() - -Retorna o identifador do plugin que pediu pela conexão. - -## Menu - -Essa é a classe que indica ao pitiupi que um menu deve ser adicionado a janela principal da aplicação. - -Menus podem ser de dois tipos `UnicastMenu` e `MulticastMenu` com a principal diferença entre eles sendo onde eles são adicionados na janela principal. Outras mudanças serão discutidas quando for relevante nas classes a seguir. - -Atualmente Menus não podem ser alterados uma vez que são adicionados, então é importante que eles sejam feitos com isso em mente. - -Tem um método `String getText()` que retorna o que deve ser escrito no Menu`. - -### SubMenu - -Permite que o `Menu` expanda em uma nova seção de menus. - -`UnicastSubMenu` o método `getMenu()` retorna `List` - -`MulticastSubMenu` o método `getMenu()` retorna `List` - -Exemplo: - -``` - -ChatCasualMulticastMenu chatCasualMulticastMenu; -ChatEstudoMutlticastMenu chatEstudoMutlticastMenu; - -... - -@Override - public List getMenus() { - return List.of(chatCasualMulticastMenu, chatEstudoMutlticastMenu); - } -``` - -### ActionMenu - -É um `Menu` que que realiza alguma ação quando selecionado pelo usuário. - -`UnicastActionMenu` o método `onClick(User user)` é chamado quando selecionado pelo usuário, recebendo como parametro o peer escolhido pelo usuário. - -`MulticastActionMenu` o método `onClick()` é chamado quando selecionado pelo usuário. - -Exemplo: - -``` - -@Override - public void onClick(User user) { - callManager.openCallWindow(user); - } -``` - -## Exemplo de plugin no pitiupi: - -### Plugin - -Implementa o contrato de plugin. - -Inicializa a janela principal e cria os menus. - -Também define quais tipos de mensagem ele quer receber. - -``` -public class ChatPlugin extends Plugin { - - private ChatWindow chatWindow; - - @Override - public void createPlugin(Pitiupi pitiupi) { - this.chatWindow = new ChatWindow(pitiupi); - pitiupi.createMenu(MenuCategory.Social, new ChatMenu(chatWindow)); - } - - - @Override - public List> getMessages() { - return List.of(ChatMessage.class); - } - - - @Override - public void receiveMessage(Message message) { - if (message instanceof ChatMessage msg) { - this.chatWindow.receiveChatMessage(msg); - } - } - - @Override - public String getName() { - return "Chat"; - } - - @Override - public String getAuthor() { - return "Flávio Schiavoni"; - } - - @Override - public String getVersion() { - return "0"; - } - - @Override - public String getIdentifier() { - return "Pitiupi.Chat.Example.123456"; - } -} -``` - -### Message - -Implementa uma mensagem customizada que o plugin vai utilizar para comunicação. - -``` -public class ChatMessage extends Message { - - private String text; - private String name; - - - public ChatMessage(){ - - } - - public ChatMessage(String name, String text){ - this.name = name; - this.text = text; - } - /** - * @return the name - */ - public String getName() { - return name; - } - - /** - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } - - /** - * @return the text - */ - public String getText() { - return text; - } - - /** - * @param text the text to set - */ - public void setText(String text) { - this.text = text; - } -} -``` - -### Menus - -Implementa os dois menus de Multicast utilizados pela aplicação. - -#### ActionMenu - -Esse menu apenas abre a janela principal do plugin. - -``` -public class ChatMulticastMenu extends MulticastActionMenu { - ChatWindow chatWindow; - - public ChatMulticastMenu(ChatWindow chatWindow) { - this.chatWindow = chatWindow; - } - - @Override - public String getText() { - return "Show Chat Window"; - } - - @Override - public void onClick() { - chatWindow.setVisible(true); - } -} -``` - -Esse menu abre a seção de menus do plugin Chat. - -#### SubMenu - -``` -public class ChatMenu extends MulticastSubMenu { - ChatMulticastMenu chatMulticastMenu; - - public ChatMenu(ChatWindow chatWindow) { - this.chatMulticastMenu = new ChatMulticastMenu(chatWindow); - } - - @Override - public String getText() { - return "Chat"; - } - - @Override - public List getMenus() { - return List.of(chatMulticastMenu); - } -} -``` - -### GUI - -Essa é a janela principal do plugin de chat. - -``` -public class ChatWindow extends JDialog { - - private JButton jButton1; - private JEditorPane jEditorPane1; - private JPanel jPanel1; - private JPanel jPanel2; - private JScrollPane jScrollPane1; - private JScrollPane jScrollPane2; - private JSplitPane jSplitPane1; - private JTextArea jTextArea1; - - private final Pitiupi pitiupi; - - public ChatWindow(Pitiupi pitiupi) { - this.pitiupi = pitiupi; - initComponents(); - } - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - private void initComponents() { - - this.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); - this.setTitle("Chat Window"); - this.setBounds(new java.awt.Rectangle(0, 0, 800, 600)); - this.getContentPane().setLayout(new java.awt.BorderLayout(5, 5)); - this.setPreferredSize(new java.awt.Dimension(800, 600)); - - jSplitPane1 = new JSplitPane(); - jScrollPane1 = new JScrollPane(); - jEditorPane1 = new JEditorPane(); - jPanel1 = new JPanel(); - jScrollPane2 = new JScrollPane(); - jTextArea1 = new JTextArea(); - jPanel2 = new JPanel(); - jButton1 = new JButton(); - - jSplitPane1.setDividerLocation(500); - jSplitPane1.setOrientation(JSplitPane.VERTICAL_SPLIT); - jEditorPane1.setContentType("text/html"); - jPanel1.setLayout(new java.awt.BorderLayout()); - jTextArea1.setColumns(20); - jTextArea1.setRows(5); - jTextArea1.addKeyListener(new java.awt.event.KeyAdapter() { - @Override - public void keyTyped(java.awt.event.KeyEvent evt) { - if (evt.getKeyChar() == '\n') { - sendMessage(); - } - } - }); - jButton1.setText("Send"); - - jScrollPane1.setViewportView(jEditorPane1); - jScrollPane2.setViewportView(jTextArea1); - jSplitPane1.setTopComponent(jScrollPane1); - - jPanel1.add(jScrollPane2, java.awt.BorderLayout.CENTER); - jPanel2.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT)); - jButton1.addActionListener((java.awt.event.ActionEvent evt) -> { - sendMessage(); - }); - jPanel2.add(jButton1); - jPanel1.add(jPanel2, java.awt.BorderLayout.PAGE_END); - jSplitPane1.setRightComponent(jPanel1); - getContentPane().add(jSplitPane1, java.awt.BorderLayout.CENTER); - pack(); - } - - private void sendMessage() { - if (jTextArea1.getText().trim().isEmpty()) { - return; - } - ChatMessage message = new ChatMessage(pitiupi.getUserName(), jTextArea1.getText()); - this.sendChatMessage(message); - jTextArea1.setText(""); - } - - public void sendChatMessage(Message message) { - pitiupi.sendUdpMulticast(message); - } - - public void receiveChatMessage(ChatMessage message) { - SimpleDateFormat dt = new SimpleDateFormat("dd/MM/yyyyy hh:mm:ss"); - Date date = new Date(); - this.receiveChatMessage(dt.format(date) + " " - + "" + message.getName() + ": " - + message.getText() + "
"); - } - - public void receiveChatMessage(String message) { - jEditorPane1.setText(message + jEditorPane1.getText()); - } -} -``` \ No newline at end of file diff --git a/pitiupi/src/pitiupi/control/GuiManager.java b/pitiupi/src/pitiupi/control/GuiManager.java index 02c3c29..b2a6f63 100644 --- a/pitiupi/src/pitiupi/control/GuiManager.java +++ b/pitiupi/src/pitiupi/control/GuiManager.java @@ -30,6 +30,18 @@ public class GuiManager { } public void createMenu(MenuCategory category, Menu menu) { + System.out.println( + menu.getClass().getSuperclass().getSuperclass() + ); + + System.out.println( + MulticastMenu.class + ); + + System.out.println( + menu.getClass().getSuperclass().getSuperclass() + == MulticastMenu.class + ); try { JMenuItem newMenu = buildMenu(menu); if (menu instanceof MulticastMenu) { @@ -43,6 +55,7 @@ public class GuiManager { logger.log(Level.WARNING, e.getMessage()); } } + private JMenuItem buildMenu(Menu menu) { if (menu instanceof MulticastSubMenu multicastSubMenu) { JMenu newMenu = new JMenu(menu.getText()); diff --git a/pitiupi/src/pitiupi/control/plugins/PluginManager.java b/pitiupi/src/pitiupi/control/plugins/PluginManager.java index 60f29f4..ada270d 100644 --- a/pitiupi/src/pitiupi/control/plugins/PluginManager.java +++ b/pitiupi/src/pitiupi/control/plugins/PluginManager.java @@ -1,6 +1,5 @@ package pitiupi.control.plugins; -import pitiupi.plugin.Pitiupi; import pitiupi.Main; import pitiupi.control.ConnectionManager; import pitiupi.control.GuiManager; @@ -93,7 +92,6 @@ public class PluginManager { public void loadPlugins(ConnectionManager connectionManager, GuiManager guiManager) { File pluginDir = new File("plugins"); File[] jarFiles = pluginDir.listFiles((dir, name) -> name.endsWith(".jar")); - Pitiupi pitiupi = new Pitiupi(connectionManager, guiManager); if (jarFiles == null || jarFiles.length == 0) { System.out.println("No plugins found in the " + pluginDir.getAbsolutePath() + " directory."); @@ -120,7 +118,7 @@ public class PluginManager { System.out.println("Loading: " + plugin.getName()); LoadedPlugin loadedPlugin = new LoadedPlugin(plugin, classLoader); - plugin.createPlugin(pitiupi); + plugin.createPlugin(connectionManager, guiManager); loadedPlugins.add(loadedPlugin); loadedJars.add(file.getName()); } diff --git a/pitiupi/src/pitiupi/models/Plugin.java b/pitiupi/src/pitiupi/models/Plugin.java index f28e62b..ffd898c 100644 --- a/pitiupi/src/pitiupi/models/Plugin.java +++ b/pitiupi/src/pitiupi/models/Plugin.java @@ -3,7 +3,9 @@ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Interface.java to edit this template */ package pitiupi.models; -import pitiupi.plugin.Pitiupi; + +import pitiupi.control.ConnectionManager; +import pitiupi.control.GuiManager; import pitiupi.models.Messages.Message; import pitiupi.net.tcp.TcpConnection; @@ -28,9 +30,10 @@ public abstract class Plugin { * *

Este método é chamado pela aplicação após o carregamento do plugin.

* - * @param pitiupi interface com o sistema de conexões da aplicação. + * @param connectionManager interface com o sistema de conexões da aplicação. + * @param guiManager interface com a janela principal da aplicação */ - public abstract void createPlugin(Pitiupi pitiupi); + public abstract void createPlugin(ConnectionManager connectionManager, GuiManager guiManager); /** * Retorna uma mensagem utilizada pelo plugin. @@ -59,4 +62,4 @@ public abstract class Plugin { public boolean onSocketClosed(TcpConnection connection) { return false; } -} +} \ No newline at end of file diff --git a/pitiupi/src/pitiupi/plugin/Pitiupi.java b/pitiupi/src/pitiupi/plugin/Pitiupi.java deleted file mode 100644 index 071de18..0000000 --- a/pitiupi/src/pitiupi/plugin/Pitiupi.java +++ /dev/null @@ -1,49 +0,0 @@ -package pitiupi.plugin; - -import pitiupi.control.ConnectionManager; -import pitiupi.control.GuiManager; -import pitiupi.models.Menus.Menu; -import pitiupi.models.Menus.MenuCategory; -import pitiupi.models.Messages.Message; -import pitiupi.net.tcp.TcpConnection; - -import java.net.InetAddress; - -public class Pitiupi { - - private final ConnectionManager connectionManager; - private final GuiManager guiManager; - - public Pitiupi(ConnectionManager connectionManager, GuiManager guiManager) { - this.connectionManager = connectionManager; - this.guiManager = guiManager; - } - - public boolean sendUdpMulticast(Message message) { - return connectionManager.sendUdpMulticast(message); - } - - public boolean sendUdpUnicast(Message message, InetAddress address) { - return connectionManager.sendUdpUnicast(message, address); - } - - public boolean sendTcp(Message message, InetAddress address) { - return connectionManager.sendTcp(message, address); - } - - public TcpConnection connectTcp(InetAddress address, String senderId, String receiverId) { - return connectionManager.connectPluginTcp(address, senderId, receiverId); - } - - public String getUserName() { - return connectionManager.getUserName(); - } - - public int getPort() { - return connectionManager.getPort(); - } - - public void createMenu(MenuCategory category, Menu menu) { - guiManager.createMenu(category, menu); - } -}