Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab3840e4a4 | ||
|
|
e25d3a425d | ||
|
|
a628490fcb | ||
|
|
395363e4bd | ||
|
|
12497594e4 | ||
|
|
6a597092fe | ||
|
|
ffd474e7ff | ||
|
|
4d39648ee7 | ||
|
|
095af14463 | ||
|
|
d0083e8069 | ||
|
|
dda324228f | ||
|
|
840183ee9f | ||
|
|
eb3ce132cd | ||
|
|
d1dc427185 | ||
|
|
7c9e61ce0f | ||
|
|
6538dac8af | ||
|
|
67813e4881 | ||
|
|
4cc07a3754 | ||
|
|
fa696194aa | ||
|
|
9fb4952f32 | ||
|
|
96b8faca5b | ||
|
|
cac549f1ee | ||
|
|
a86f4dbf82 | ||
|
|
7168431bcd | ||
|
|
0b7c67fef6 | ||
|
|
15ea8ac207 |
No files matched your search
+3
-9
@@ -1,9 +1,3 @@
|
||||
/pitiupi/build/
|
||||
/pitiupi/dist/
|
||||
/pitiupi.chat/build/
|
||||
/pitiupi.chat/dist/
|
||||
/pitiupi.chat/nbproject/private/
|
||||
/pitiupi.screenCast/build/
|
||||
/pitiupi.screenCast/dist/
|
||||
|
||||
.idea/
|
||||
build/
|
||||
dist/
|
||||
*.class
|
||||
Generated
+10
@@ -0,0 +1,10 @@
|
||||
# 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
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
<component name="libraryTable">
|
||||
<library name="pitiupi">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/pitiupi.screenCast/dist/lib/pitiupi.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
<component name="libraryTable">
|
||||
<library name="pitiupi.chat">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/pitiupi.chat/dist/pitiupi.chat.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
<component name="libraryTable">
|
||||
<library name="pitiupi.screenCast">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/pitiupi.screenCast/dist/pitiupi.screenCast.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
Generated
+10
@@ -0,0 +1,10 @@
|
||||
<component name="libraryTable">
|
||||
<library name="plugins">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/pitiupi/plugins/pitiupi.screenCast.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/pitiupi/plugins/pitiupi.chat.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
Generated
+3
@@ -0,0 +1,3 @@
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="openjdk-27" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/pitiupi.iml" filepath="$PROJECT_DIR$/.idea/pitiupi.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/udpTest" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,10 +1,13 @@
|
||||
# pitiupi
|
||||
|
||||
Ferramenta p2p para práticas em rede
|
||||
Este repositório tem 4 projetos Java que são independentes:
|
||||
|
||||
Este repositório tem 3 projetos Java que são independentes:
|
||||
### Sistema:
|
||||
- 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.
|
||||
@@ -21,9 +24,26 @@ 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!
|
||||
|
||||
Para criar um novo plugin:
|
||||
## Como um plugin conversa com o pitiupi
|
||||
|
||||
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.
|
||||
@@ -1,6 +0,0 @@
|
||||
#Mon, 17 Aug 2026 14:26:26 -0300
|
||||
|
||||
|
||||
C\:\\Users\\extre\\OneDrive\\Documentos\\Faculdade\\2026_02\\Monitoria\\Pitiupi\\pitiupi.chat=
|
||||
|
||||
C\:\\Users\\extre\\OneDrive\\Documentos\\Faculdade\\2026_02\\Monitoria\\Pitiupi\\pitiupi=
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -47,8 +47,8 @@ javac.modulepath=
|
||||
javac.processormodulepath=
|
||||
javac.processorpath=\
|
||||
${javac.classpath}
|
||||
javac.source=25
|
||||
javac.target=25
|
||||
javac.source=17
|
||||
javac.target=17
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
|
||||
File renamed without changes.
@@ -1 +0,0 @@
|
||||
pitiupi.chat.plugin.ChatPlugin
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../../pitiupi/dist/pitiupi.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -4,28 +4,29 @@
|
||||
*/
|
||||
package pitiupi.chat.GUI;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.JMenu;
|
||||
import pitiupi.models.Menus.MulticastMenus.MulticastMenu;
|
||||
import pitiupi.models.Menus.MulticastMenus.MulticastSubMenu;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author flavio
|
||||
*/
|
||||
public class ChatMenu extends JMenu {
|
||||
|
||||
private final ChatWindow chatWindow;
|
||||
private javax.swing.JMenuItem menuItem;
|
||||
public class ChatMenu extends MulticastSubMenu {
|
||||
ChatMulticastMenu chatMulticastMenu;
|
||||
|
||||
public ChatMenu(ChatWindow chatWindow) {
|
||||
this.chatWindow = chatWindow;
|
||||
this.setText("Chat");
|
||||
menuItem = new javax.swing.JMenuItem();
|
||||
menuItem.setText("Show Chat Window");
|
||||
menuItem.addActionListener(this::chatMenuActionPerformed);
|
||||
this.add(menuItem);
|
||||
this.chatMulticastMenu = new ChatMulticastMenu(chatWindow);
|
||||
}
|
||||
|
||||
private void chatMenuActionPerformed(ActionEvent ae) {
|
||||
this.chatWindow.setVisible(true);
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Chat";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MulticastMenu> getMenus() {
|
||||
return List.of(chatMulticastMenu);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package pitiupi.chat.GUI;
|
||||
|
||||
import pitiupi.models.Menus.MulticastMenus.MulticastActionMenu;;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -5,37 +5,35 @@
|
||||
*/
|
||||
package pitiupi.chat.GUI;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import pitiupi.chat.net.ChatMessage;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import pitiupi.net.Message;
|
||||
import pitiupi.plugin.Pitiupi;
|
||||
import pitiupi.models.Messages.Message;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tony
|
||||
* @author flavio
|
||||
*/
|
||||
public class ChatWindow extends javax.swing.JDialog {
|
||||
public class ChatWindow extends JDialog {
|
||||
|
||||
private javax.swing.JButton jButton1;
|
||||
private javax.swing.JEditorPane jEditorPane1;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JPanel jPanel2;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JScrollPane jScrollPane2;
|
||||
private javax.swing.JSplitPane jSplitPane1;
|
||||
private javax.swing.JTextArea jTextArea1;
|
||||
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 MainWindow mainWindow;
|
||||
private final Pitiupi pitiupi;
|
||||
|
||||
public ChatWindow(MainWindow mainWindow) {
|
||||
this.mainWindow = mainWindow;
|
||||
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
|
||||
@@ -43,23 +41,23 @@ public class ChatWindow extends javax.swing.JDialog {
|
||||
*/
|
||||
private void initComponents() {
|
||||
|
||||
this.setDefaultCloseOperation(javax.swing.WindowConstants.HIDE_ON_CLOSE);
|
||||
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 javax.swing.JSplitPane();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
jEditorPane1 = new javax.swing.JEditorPane();
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
jScrollPane2 = new javax.swing.JScrollPane();
|
||||
jTextArea1 = new javax.swing.JTextArea();
|
||||
jPanel2 = new javax.swing.JPanel();
|
||||
jButton1 = new javax.swing.JButton();
|
||||
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(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
||||
jSplitPane1.setOrientation(JSplitPane.VERTICAL_SPLIT);
|
||||
jEditorPane1.setContentType("text/html");
|
||||
jPanel1.setLayout(new java.awt.BorderLayout());
|
||||
jTextArea1.setColumns(20);
|
||||
@@ -94,17 +92,13 @@ public class ChatWindow extends javax.swing.JDialog {
|
||||
if (jTextArea1.getText().trim().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ChatMessage message = new ChatMessage(mainWindow.getUserName(), jTextArea1.getText());
|
||||
ChatMessage message = new ChatMessage(pitiupi.getUserName(), jTextArea1.getText());
|
||||
this.sendChatMessage(message);
|
||||
jTextArea1.setText("");
|
||||
}
|
||||
|
||||
public void sendChatMessage(Message message) {
|
||||
try {
|
||||
mainWindow.getSocketUDP().sendMulticast(message.toByteArray());
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
pitiupi.sendUdpMulticast(message);
|
||||
}
|
||||
|
||||
public void receiveChatMessage(ChatMessage message) {
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
*/
|
||||
package pitiupi.chat.net;
|
||||
|
||||
import pitiupi.net.Message;
|
||||
import pitiupi.net.Message;
|
||||
|
||||
import pitiupi.models.Messages.Message;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author flavio
|
||||
*/
|
||||
public class ChatMessage extends Message{
|
||||
public class ChatMessage extends Message {
|
||||
|
||||
private String text;
|
||||
private String name;
|
||||
|
||||
@@ -4,49 +4,44 @@
|
||||
*/
|
||||
package pitiupi.chat.plugin;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
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.net.Message;
|
||||
import pitiupi.plugin.Plugin;
|
||||
import pitiupi.models.Menus.MenuCategory;
|
||||
import pitiupi.models.Messages.Message;
|
||||
import pitiupi.models.Plugin;
|
||||
|
||||
/**
|
||||
*
|
||||
*@author tony
|
||||
* @author flavio
|
||||
*/
|
||||
public class ChatPlugin implements Plugin {
|
||||
public class ChatPlugin extends Plugin {
|
||||
|
||||
private ChatWindow chatWindow;
|
||||
private MainWindow mainWindow;
|
||||
|
||||
public ChatPlugin() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createPlugin(MainWindow mainWindow) {
|
||||
this.mainWindow = mainWindow;
|
||||
this.chatWindow = new ChatWindow(mainWindow);
|
||||
this.mainWindow.addMenu(new ChatMenu(chatWindow));
|
||||
public void createPlugin(Pitiupi pitiupi) {
|
||||
this.chatWindow = new ChatWindow(pitiupi);
|
||||
pitiupi.createMenu(MenuCategory.Social, new ChatMenu(chatWindow));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receiveMessage(byte[] message) {
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(message);
|
||||
ObjectInputStream ois;
|
||||
try {
|
||||
ois = new ObjectInputStream(bis);
|
||||
if (ois.readObject() instanceof ChatMessage msg) {
|
||||
public List<Class<? extends Message>> getMessages() {
|
||||
return List.of(ChatMessage.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receiveMessage(Message message) {
|
||||
if (message instanceof ChatMessage msg) {
|
||||
this.chatWindow.receiveChatMessage(msg);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
System.out.println(ex.toString());
|
||||
} catch (ClassNotFoundException ex) {
|
||||
System.out.println(ex.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,7 +60,9 @@ public class ChatPlugin implements Plugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getMessage() {
|
||||
return new ChatMessage();
|
||||
public String getIdentifier() {
|
||||
return "Pitiupi.Chat.Example";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Generated
+85
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="e2cdacc6-69cd-4190-bef1-27719e32140a" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/../.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../.idea/misc.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../.idea/vcs.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../.idea/vcs.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/GUI/PrivateChatWindow.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/GUI/PrivateChatWindow.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/GUI/PublicChatWindow.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/GUI/PublicChatWindow.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/plugin/MultiProtocolChat.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/plugin/MultiProtocolChat.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/.idea/misc.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/build/built-jar.properties" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/build/built-jar.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastMenu.class" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastMenu.class" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastWindow.class" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastWindow.class" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/build/classes/pitiupi/screenCast/net/ScreenCastMessage.class" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/build/classes/pitiupi/screenCast/net/ScreenCastMessage.class" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/build/classes/pitiupi/screenCast/plugin/ScreenCastPlugin.class" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/build/classes/pitiupi/screenCast/plugin/ScreenCastPlugin.class" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/src/pitiupi.screenCast.iml" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/src/pitiupi.screenCast.iml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastMenu.java" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastMenu.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastWindow.java" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastWindow.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/src/pitiupi/screenCast/net/ScreenCastMessage.java" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/src/pitiupi/screenCast/net/ScreenCastMessage.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.screenCast/src/pitiupi/screenCast/plugin/ScreenCastPlugin.java" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.screenCast/src/pitiupi/screenCast/plugin/ScreenCastPlugin.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi/src/pitiupi/control/plugins/PluginManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi/src/pitiupi/control/plugins/PluginManager.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi/src/pitiupi/net/tcp/SocketTCP.java" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi/src/pitiupi/net/tcp/SocketTCP.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi/src/pitiupi/net/tcp/TcpConnection.java" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi/src/pitiupi/net/tcp/TcpConnection.java" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="Class" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
|
||||
</component>
|
||||
<component name="ProjectColorInfo">{
|
||||
"associatedIndex": 6
|
||||
}</component>
|
||||
<component name="ProjectId" id="3K7MYfvmfmI7sWODbOakShpPyuR" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">{
|
||||
"keyToString": {
|
||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"git-widget-placeholder": "update/mpChat",
|
||||
"ignore.virus.scanning.warn.message": "true",
|
||||
"kotlin-language-version-configured": "true",
|
||||
"last_opened_file_path": "C:/Users/extre/OneDrive/Documentos/Faculdade/2026_02/Monitoria/Pitiupi/pitiupi.mpChat",
|
||||
"project.structure.last.edited": "Modules",
|
||||
"project.structure.proportion": "0.15",
|
||||
"project.structure.side.proportion": "0.2",
|
||||
"settings.editor.selected.configurable": "preferences.keymap"
|
||||
}
|
||||
}</component>
|
||||
<component name="SharedIndexes">
|
||||
<attachedChunks>
|
||||
<set>
|
||||
<option value="bundled-jdk-9823dce3aa75-bf35d07a577b-intellij.indexing.shared.core-IU-252.28539.97" />
|
||||
</set>
|
||||
</attachedChunks>
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="e2cdacc6-69cd-4190-bef1-27719e32140a" name="Changes" comment="" />
|
||||
<created>1790904201925</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1790904201925</updated>
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,16 @@
|
||||
JAR = ../pitiupi/dist/pitiupi.jar
|
||||
OUT_DIR = out
|
||||
META-INF_DIR = src/META-INF
|
||||
DIST = dist/mpChat.jar
|
||||
|
||||
SOURCES = $(shell find -name "*.java")
|
||||
|
||||
all:
|
||||
mkdir -p "$(OUT_DIR)"
|
||||
mkdir -p "$(dir $(DIST))"
|
||||
javac -cp "$(JAR)" -d "$(OUT_DIR)" $(SOURCES)
|
||||
cp -r "$(META-INF_DIR)" "$(OUT_DIR)"
|
||||
jar cf "$(DIST)" -C "$(OUT_DIR)" .
|
||||
|
||||
clean:
|
||||
rm -rf "$(OUT_DIR)"/*
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
||||
plugin.MultiProtocolChat
|
||||
BIN
Binary file not shown.
Binary file not shown.
File renamed without changes.
File renamed without changes.
Binary file not shown.
File renamed without changes.
Binary file not shown.
File renamed without changes.
@@ -0,0 +1,40 @@
|
||||
package GUI;
|
||||
|
||||
import pitiupi.models.Menus.MenuCategory;
|
||||
import pitiupi.models.Menus.MulticastMenus.MulticastSubMenu;
|
||||
import plugin.MultiProtocolChat;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class ChatMenu extends MulticastSubMenu {
|
||||
private final MultiProtocolChat multiProtocolChat;
|
||||
|
||||
public ChatMenu(MultiProtocolChat multiProtocolChat) {
|
||||
this.multiProtocolChat = multiProtocolChat;
|
||||
this.setText("MP-Chat");
|
||||
|
||||
JMenuItem startPrivateChat = new JMenuItem("start Private Chat");
|
||||
startPrivateChat.addActionListener(e -> showPrivateChatDialog());
|
||||
this.add(startPrivateChat);
|
||||
}
|
||||
|
||||
public void newMenuItem(JMenuItem newMenuItem, ChatWindow chatWindow) {
|
||||
newMenuItem.addActionListener(e -> chatWindow.setVisible(true));
|
||||
|
||||
this.add(newMenuItem);
|
||||
}
|
||||
|
||||
public void removeMenuItem(JMenuItem removeMenuItem) {
|
||||
this.remove(removeMenuItem);
|
||||
}
|
||||
|
||||
private void showPrivateChatDialog() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "MP-Chat";
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package GUI;
|
||||
|
||||
import net.TestChatMessage;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import net.MpChatMessage;
|
||||
import pitiupi.control.ConnectionManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -10,13 +10,13 @@ import java.net.UnknownHostException;
|
||||
|
||||
public abstract class ChatWindow extends JFrame {
|
||||
|
||||
protected final MainWindow mainWindow;
|
||||
protected final ConnectionManager connectionManager;
|
||||
|
||||
private JTextArea receivedMessagesArea;
|
||||
protected JTextField messageField;
|
||||
|
||||
public ChatWindow(MainWindow mainWindow) {
|
||||
this.mainWindow = mainWindow;
|
||||
public ChatWindow(ConnectionManager connectionManager) {
|
||||
this.connectionManager = connectionManager;
|
||||
initComponents();
|
||||
}
|
||||
|
||||
@@ -63,20 +63,20 @@ public abstract class ChatWindow extends JFrame {
|
||||
|
||||
protected abstract void initButtons(JPanel bottomPanel);
|
||||
|
||||
protected TestChatMessage createMessage(String tipoMensagem) {
|
||||
protected MpChatMessage createMessage(String tipoMensagem) {
|
||||
try {
|
||||
String nome = mainWindow.getUserName();
|
||||
String nome = connectionManager.getUserName();
|
||||
String ip = InetAddress.getLocalHost().getHostAddress();
|
||||
String message = messageField.getText();
|
||||
|
||||
return new TestChatMessage(nome, ip, tipoMensagem, message);
|
||||
return new MpChatMessage(nome, ip, tipoMensagem, message);
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveMessage(TestChatMessage msg) {
|
||||
public void receiveMessage(MpChatMessage msg) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
String mensagem = String.format(
|
||||
"[%s] %s (%s): %s%n",
|
||||
@@ -0,0 +1,38 @@
|
||||
package GUI;
|
||||
|
||||
import control.ChatController;
|
||||
import pitiupi.models.Menus.UnicastMenus.UnicastActionMenu;
|
||||
import pitiupi.models.User;
|
||||
import plugin.MultiProtocolChat;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.net.InetAddress;
|
||||
|
||||
public class PrivateChatMenu extends UnicastActionMenu {
|
||||
PrivateChatWindow privateChatWindow;
|
||||
private final MultiProtocolChat multiProtocolChat;
|
||||
private final ChatController chatController;
|
||||
|
||||
public PrivateChatMenu(PrivateChatWindow PrivateChatWindow, MultiProtocolChat multiProtocolChat, ChatController chatController) {
|
||||
this.privateChatWindow = PrivateChatWindow;
|
||||
this.multiProtocolChat = multiProtocolChat;
|
||||
this.chatController = chatController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(User user) {
|
||||
if (multiProtocolChat.openConnection(user.getAddress())
|
||||
else errorLabel.setVisible(true);
|
||||
|
||||
dialog.setContentPane(contentPanel);
|
||||
dialog.pack();
|
||||
dialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(privateChatWindow));
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "start Private Chat";
|
||||
}
|
||||
}
|
||||
+6
-9
@@ -1,7 +1,7 @@
|
||||
package GUI;
|
||||
|
||||
import net.TestChatMessage;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import net.MpChatMessage;
|
||||
import pitiupi.control.ConnectionManager;
|
||||
import pitiupi.net.tcp.TcpConnection;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -13,10 +13,9 @@ public class PrivateChatWindow extends ChatWindow {
|
||||
|
||||
private final TcpConnection connection;
|
||||
|
||||
public PrivateChatWindow(MainWindow mainWindow, TcpConnection connection) {
|
||||
public PrivateChatWindow(ConnectionManager ConnectionManager, TcpConnection connection) {
|
||||
super(ConnectionManager);
|
||||
this.connection = connection;
|
||||
|
||||
super(mainWindow);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -34,13 +33,11 @@ public class PrivateChatWindow extends ChatWindow {
|
||||
|
||||
private void sendTCP() {
|
||||
try {
|
||||
TestChatMessage msg = createMessage("TCP Private");
|
||||
MpChatMessage msg = createMessage("TCP Private");
|
||||
connection.send(msg.toByteArray());
|
||||
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(
|
||||
PrivateChatWindow.class.getName()
|
||||
).log(Level.SEVERE, null, ex);
|
||||
Logger.getLogger(PrivateChatWindow.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package GUI;
|
||||
|
||||
import pitiupi.models.Menus.MulticastMenus.MulticastActionMenu;
|
||||
|
||||
public class PublicChatMenu extends MulticastActionMenu {
|
||||
PublicChatWindow publicChatWindow;
|
||||
|
||||
PublicChatMenu(PublicChatWindow publicChatWindow) {
|
||||
this.publicChatWindow = publicChatWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
publicChatWindow.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
+10
-10
@@ -1,7 +1,7 @@
|
||||
package GUI;
|
||||
|
||||
import net.TestChatMessage;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import net.MpChatMessage;
|
||||
import pitiupi.control.ConnectionManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -13,8 +13,8 @@ public class PublicChatWindow extends ChatWindow {
|
||||
|
||||
private JTextField ipField;
|
||||
|
||||
public PublicChatWindow(MainWindow mainWindow) {
|
||||
super(mainWindow);
|
||||
public PublicChatWindow(ConnectionManager connectionManager) {
|
||||
super(connectionManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,11 +56,11 @@ public class PublicChatWindow extends ChatWindow {
|
||||
|
||||
private void sendTCP() {
|
||||
try {
|
||||
TestChatMessage msg = createMessage("TCP Unicast");
|
||||
MpChatMessage msg = createMessage("TCP Unicast");
|
||||
|
||||
InetAddress ip = InetAddress.getByName(ipField.getText());
|
||||
|
||||
mainWindow.getSocketTCP().send(msg, ip);
|
||||
connectionManager.sendTcp(msg, ip);
|
||||
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(PublicChatWindow.class.getName()).log(Level.SEVERE, null, ex);
|
||||
@@ -69,11 +69,11 @@ public class PublicChatWindow extends ChatWindow {
|
||||
|
||||
private void sendUDP() {
|
||||
try {
|
||||
TestChatMessage msg = createMessage("UDP Unicast");
|
||||
MpChatMessage msg = createMessage("UDP Unicast");
|
||||
|
||||
InetAddress ip = InetAddress.getByName(ipField.getText());
|
||||
|
||||
mainWindow.getSocketUDP().sendUnicast(msg, ip);
|
||||
connectionManager.sendUdpUnicast(msg, ip);
|
||||
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(PublicChatWindow.class.getName()).log(Level.SEVERE, null, ex);
|
||||
@@ -82,9 +82,9 @@ public class PublicChatWindow extends ChatWindow {
|
||||
|
||||
private void sendMulticast() {
|
||||
try {
|
||||
TestChatMessage msg = createMessage("UDP Multicast");
|
||||
MpChatMessage msg = createMessage("UDP Multicast");
|
||||
|
||||
mainWindow.getSocketUDP().sendMulticast(msg);
|
||||
connectionManager.sendUdpMulticast(msg);
|
||||
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(PublicChatWindow.class.getName()).log(Level.SEVERE, null, ex);
|
||||
@@ -0,0 +1 @@
|
||||
plugin.MultiProtocolChat
|
||||
+4
-4
@@ -1,21 +1,21 @@
|
||||
package net;
|
||||
|
||||
import pitiupi.net.Message;
|
||||
import pitiupi.models.Messages.Message;
|
||||
|
||||
public class TestChatMessage extends Message {
|
||||
public class MpChatMessage extends Message {
|
||||
private String nome;
|
||||
private String ip;
|
||||
private String tipoMensagem;
|
||||
private String message;
|
||||
|
||||
public TestChatMessage(String nome, String ip, String tipoMensagem, String message) {
|
||||
public MpChatMessage(String nome, String ip, String tipoMensagem, String message) {
|
||||
this.nome = nome;
|
||||
this.ip = ip;
|
||||
this.tipoMensagem = tipoMensagem;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public TestChatMessage(){}
|
||||
public MpChatMessage(){}
|
||||
|
||||
public String getNome() {
|
||||
return nome;
|
||||
+29
-24
@@ -2,11 +2,12 @@ package plugin;
|
||||
|
||||
import GUI.ChatMenu;
|
||||
import control.ChatController;
|
||||
import net.TestChatMessage;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import pitiupi.net.Message;
|
||||
import net.MpChatMessage;
|
||||
import pitiupi.control.ConnectionManager;
|
||||
import pitiupi.control.GuiManager;
|
||||
import pitiupi.models.Messages.Message;
|
||||
import pitiupi.net.tcp.TcpConnection;
|
||||
import pitiupi.plugin.PrivateConnectionPlugin;
|
||||
import pitiupi.models.Plugin;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -14,9 +15,10 @@ import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.net.InetAddress;
|
||||
|
||||
public class TestChat implements PrivateConnectionPlugin{
|
||||
public class MultiProtocolChat extends Plugin {
|
||||
ChatController chatController;
|
||||
MainWindow mainWindow;
|
||||
ConnectionManager connectionManager;
|
||||
GuiManager guiManager;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -39,47 +41,50 @@ public class TestChat implements PrivateConnectionPlugin{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createPlugin(MainWindow mainWindow) {
|
||||
this.mainWindow = mainWindow;
|
||||
public void createPlugin(ConnectionManager connectionManager, GuiManager guiManager) {
|
||||
this.connectionManager = connectionManager;
|
||||
this.guiManager = guiManager;
|
||||
|
||||
ChatMenu chatMenu = new ChatMenu(this);
|
||||
chatController = new ChatController(mainWindow, chatMenu);
|
||||
mainWindow.addMenu(chatMenu);
|
||||
chatController = new ChatController(connectionManager, chatMenu);
|
||||
guiManager.addMulticastMenu(chatMenu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getMessage() {
|
||||
return new TestChatMessage();
|
||||
return new MpChatMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveMessage(byte[] message) {
|
||||
TestChatMessage testChatMessage = parseMessage(message);
|
||||
chatController.receivePublic(testChatMessage);
|
||||
MpChatMessage mpChatMessage = parseMessage(message);
|
||||
chatController.receivePublic(mpChatMessage);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receivePrivateConnection(TcpConnection tcpConnection) {
|
||||
public boolean receivePrivateConnection(TcpConnection connection) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
chatController.addChatWindow(tcpConnection);
|
||||
chatController.addChatWindow(connection);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveBytes(TcpConnection connection, byte[] bytes) {
|
||||
TestChatMessage testChatMessage = parseMessage(bytes);
|
||||
chatController.receivePrivate(connection, testChatMessage);
|
||||
public boolean receiveBytes(TcpConnection connection, byte[] bytes) {
|
||||
MpChatMessage mpChatMessage = parseMessage(bytes);
|
||||
chatController.receivePrivate(connection, mpChatMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSocketClosed(TcpConnection tcpConnection) {
|
||||
chatController.removeChatWindow(tcpConnection);
|
||||
public boolean onSocketClosed(TcpConnection connection) {
|
||||
chatController.removeChatWindow(connection);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean openConnection(String ip) {
|
||||
try {
|
||||
mainWindow.getSocketTCP().createPrivateConnection(InetAddress.getByName(ip), getIdentifier(), getIdentifier());
|
||||
connectionManager.connectPluginTcp(InetAddress.getByName(ip), getIdentifier(), getIdentifier());
|
||||
return true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -88,12 +93,12 @@ public class TestChat implements PrivateConnectionPlugin{
|
||||
return false;
|
||||
}
|
||||
|
||||
private TestChatMessage parseMessage(byte[] bytes) {
|
||||
private MpChatMessage parseMessage(byte[] bytes) {
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
|
||||
ObjectInputStream ois;
|
||||
try {
|
||||
ois = new ObjectInputStream(bis);
|
||||
if (ois.readObject() instanceof TestChatMessage msg) {
|
||||
if (ois.readObject() instanceof MpChatMessage msg) {
|
||||
return msg;
|
||||
}
|
||||
} catch (IOException | ClassNotFoundException ex) {
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/pitiupi.screenCast.iml" filepath="$PROJECT_DIR$/.idea/pitiupi.screenCast.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+10
-20
@@ -6,23 +6,8 @@
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="083e72ce-fa9b-4ddf-a0ef-24105aa3eabb" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/../.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../.idea/misc.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../.idea/vcs.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.chat/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.chat/.idea/misc.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.chat/build/built-jar.properties" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.chat/build/built-jar.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.chat/dist/pitiupi.chat.jar" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.chat/pitiupi.chat.iml" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.chat/pitiupi.chat.iml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi.chat/src/pitiupi/chat/GUI/ChatWindow.java" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi.chat/src/pitiupi/chat/GUI/ChatWindow.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/build/built-jar.properties" beforeDir="false" afterPath="$PROJECT_DIR$/build/built-jar.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/build/classes/pitiupi/screenCast/GUI/ScreenCastWindow.class" beforeDir="false" afterPath="$PROJECT_DIR$/build/classes/pitiupi/screenCast/GUI/ScreenCastWindow.class" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/dist/pitiupi.screenCast.jar" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pitiupi/screenCast/GUI/ScreenCastWindow.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/pitiupi/screenCast/GUI/ScreenCastWindow.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi/plugins/pitiupi.chat.jar" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi/plugins/pitiupi.chat.jar" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi/plugins/pitiupi.screenCast.jar" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi/plugins/pitiupi.screenCast.jar" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi/src/pitiupi/GUI/MainWindow.java" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi/src/pitiupi/GUI/MainWindow.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../pitiupi/src/pitiupi/control/HeartbeatManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/../pitiupi/src/pitiupi/control/HeartbeatManager.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../.idea/vcs.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../.idea/vcs.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -46,10 +31,12 @@
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"git-widget-placeholder": "feature/unicast",
|
||||
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
||||
"codeWithMe.voiceChat.enabledByDefault": "false",
|
||||
"git-widget-placeholder": "update/screenCast",
|
||||
"ignore.virus.scanning.warn.message": "true",
|
||||
"kotlin-language-version-configured": "true",
|
||||
"last_opened_file_path": "C:/Users/extre/OneDrive/Documentos/Faculdade/2026_02/Monitoria/Pitiupi/pitiupi.screenCast",
|
||||
"last_opened_file_path": "C:/Users/Gustavo/OneDrive/Documentos/Faculdade/2026_2/Monitoria/pitiupi/pitiupi.screenCast",
|
||||
"project.structure.last.edited": "Modules",
|
||||
"project.structure.proportion": "0.15",
|
||||
"project.structure.side.proportion": "0.2",
|
||||
@@ -106,7 +93,7 @@
|
||||
<component name="SharedIndexes">
|
||||
<attachedChunks>
|
||||
<set>
|
||||
<option value="bundled-jdk-9823dce3aa75-bf35d07a577b-intellij.indexing.shared.core-IU-252.28539.54" />
|
||||
<option value="bundled-jdk-9823dce3aa75-bf35d07a577b-intellij.indexing.shared.core-IU-252.28539.97" />
|
||||
</set>
|
||||
</attachedChunks>
|
||||
</component>
|
||||
@@ -120,4 +107,7 @@
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,4 +1,4 @@
|
||||
#Mon, 17 Aug 2026 14:35:40 -0300
|
||||
#Wed, 07 Oct 2026 15:36:37 -0300
|
||||
|
||||
|
||||
C\:\\Users\\extre\\OneDrive\\Documentos\\Faculdade\\2026_02\\Monitoria\\Pitiupi\\pitiupi.screenCast=
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Generated
+5
@@ -0,0 +1,5 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" default="true" project-jdk-name="openjdk-26" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/pitiupi.screenCast.iml" filepath="$PROJECT_DIR$/pitiupi.screenCast.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../../pitiupi/dist/pitiupi.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
@@ -4,28 +4,29 @@
|
||||
*/
|
||||
package pitiupi.screenCast.GUI;
|
||||
|
||||
import pitiupi.models.Menus.MulticastMenus.MulticastActionMenu;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.JMenu;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author flavio
|
||||
*/
|
||||
public class ScreenCastMenu extends JMenu {
|
||||
public class ScreenCastMenu extends MulticastActionMenu {
|
||||
|
||||
private final ScreenCastWindow screenCastWindow;
|
||||
private final javax.swing.JMenuItem menuItem;
|
||||
|
||||
public ScreenCastMenu(ScreenCastWindow screenCastWindow) {
|
||||
this.screenCastWindow = screenCastWindow;
|
||||
this.setText("Screen Cast");
|
||||
menuItem = new javax.swing.JMenuItem();
|
||||
menuItem.setText("ScreenCast Window");
|
||||
menuItem.addActionListener(this::chatMenuActionPerformed);
|
||||
this.add(menuItem);
|
||||
}
|
||||
|
||||
private void chatMenuActionPerformed(ActionEvent ae) {
|
||||
@Override
|
||||
public void onClick() {
|
||||
this.screenCastWindow.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Screen Cast";
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,9 @@
|
||||
*/
|
||||
package pitiupi.screenCast.GUI;
|
||||
|
||||
import pitiupi.control.ConnectionManager;
|
||||
import pitiupi.control.GuiManager;
|
||||
import pitiupi.plugin.Pitiupi;
|
||||
import pitiupi.screenCast.control.AlarmClock;
|
||||
import pitiupi.screenCast.control.ImageTransformation;
|
||||
import pitiupi.screenCast.control.ScreenShot;
|
||||
@@ -20,8 +23,6 @@ import java.util.logging.Logger;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import pitiupi.net.Message;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -38,10 +39,11 @@ public class ScreenCastWindow extends javax.swing.JFrame {
|
||||
public final static int TIME = 1000;
|
||||
|
||||
private float compressRatio;
|
||||
private final MainWindow mainWindow;
|
||||
|
||||
public ScreenCastWindow(MainWindow mainWindow) {
|
||||
this.mainWindow = mainWindow;
|
||||
private final Pitiupi pitiupi;
|
||||
|
||||
public ScreenCastWindow(Pitiupi pitiupi) {
|
||||
this.pitiupi = pitiupi;
|
||||
this.compressRatio = 0.5f;
|
||||
this.initComponents();
|
||||
}
|
||||
@@ -91,19 +93,12 @@ public class ScreenCastWindow extends javax.swing.JFrame {
|
||||
BufferedImage image = ScreenShot.takeAShot();
|
||||
BufferedImage rescaled = ImageTransformation.resize(image, 1024, 768);
|
||||
byte[] byteImage = ImageTransformation.compress(rescaled, compressRatio);
|
||||
ScreenCastMessage message = new ScreenCastMessage(this.mainWindow.getUserName(), byteImage);
|
||||
msg = message.toByteArray();
|
||||
ScreenCastMessage message = new ScreenCastMessage(pitiupi.getUserName(), byteImage);
|
||||
|
||||
if (!pitiupi.sendUdpMulticast(message)) this.compressRatio -= 0.1f;
|
||||
} catch (AWTException | IOException ex) {
|
||||
Logger.getLogger(AlarmClock.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
if (msg != null) {
|
||||
try {
|
||||
this.mainWindow.getSocketUDP().sendMulticast(msg);
|
||||
} catch (IOException ex) {
|
||||
System.out.println(ex.toString());
|
||||
this.compressRatio -= 0.1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveScreenCastMessage(ScreenCastMessage message) {
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
*/
|
||||
package pitiupi.screenCast.net;
|
||||
|
||||
import pitiupi.net.Message;
|
||||
|
||||
import pitiupi.models.Messages.Message;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
*/
|
||||
package pitiupi.screenCast.plugin;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import pitiupi.net.Message;
|
||||
import pitiupi.plugin.Plugin;
|
||||
import java.util.List;
|
||||
|
||||
import pitiupi.models.Menus.MenuCategory;
|
||||
import pitiupi.models.Messages.Message;
|
||||
import pitiupi.models.Plugin;
|
||||
import pitiupi.plugin.Pitiupi;
|
||||
import pitiupi.screenCast.GUI.ScreenCastMenu;
|
||||
import pitiupi.screenCast.GUI.ScreenCastWindow;
|
||||
import pitiupi.screenCast.net.ScreenCastMessage;
|
||||
@@ -18,10 +18,9 @@ import pitiupi.screenCast.net.ScreenCastMessage;
|
||||
*
|
||||
* @author flavio
|
||||
*/
|
||||
public class ScreenCastPlugin implements Plugin {
|
||||
public class ScreenCastPlugin extends Plugin {
|
||||
|
||||
private ScreenCastWindow screenCastWindow;
|
||||
private MainWindow mainWindow;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -39,31 +38,25 @@ public class ScreenCastPlugin implements Plugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createPlugin(MainWindow mainWindow) {
|
||||
this.mainWindow = mainWindow;
|
||||
this.screenCastWindow = new ScreenCastWindow(mainWindow);
|
||||
this.mainWindow.addMenu(new ScreenCastMenu(screenCastWindow));
|
||||
public String getIdentifier() {
|
||||
return "Pitiupi.ScreenCast.Example";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveMessage(byte[] message) {
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(message);
|
||||
ObjectInputStream ois;
|
||||
try {
|
||||
ois = new ObjectInputStream(bis);
|
||||
if (ois.readObject() instanceof ScreenCastMessage msg) {
|
||||
public void createPlugin(Pitiupi pitiupi) {
|
||||
this.screenCastWindow = new ScreenCastWindow(pitiupi);
|
||||
pitiupi.createMenu(MenuCategory.Streaming, new ScreenCastMenu(screenCastWindow));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends Message>> getMessages() {
|
||||
return List.of(ScreenCastMessage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveMessage(Message message) {
|
||||
if (message instanceof ScreenCastMessage msg) {
|
||||
this.screenCastWindow.receiveScreenCastMessage(msg);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
System.out.println(ex.toString());
|
||||
} catch (ClassNotFoundException ex) {
|
||||
System.out.println(ex.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getMessage() {
|
||||
return new ScreenCastMessage();
|
||||
}
|
||||
|
||||
}
|
||||
Generated
+10
@@ -0,0 +1,10 @@
|
||||
# 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
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/pitiupi.testSocket.iml" filepath="$PROJECT_DIR$/pitiupi.testSocket.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
plugin.TestChat
|
||||
Binary file not shown.
@@ -1,84 +0,0 @@
|
||||
package GUI;
|
||||
|
||||
import plugin.TestChat;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ChatMenu extends JMenu {
|
||||
private final TestChat testChat;
|
||||
|
||||
public ChatMenu(TestChat testChat) {
|
||||
this.testChat = testChat;
|
||||
this.setText("MP-Chat");
|
||||
|
||||
JMenuItem startPrivateChat = new JMenuItem("start Private Chat");
|
||||
startPrivateChat.addActionListener(_ -> showPrivateChatDialog());
|
||||
this.add(startPrivateChat);
|
||||
}
|
||||
|
||||
public void newMenuItem(JMenuItem newMenuItem, ChatWindow chatWindow) {
|
||||
newMenuItem.addActionListener(_ -> chatWindow.setVisible(true));
|
||||
|
||||
this.add(newMenuItem);
|
||||
}
|
||||
|
||||
public void removeMenuItem(JMenuItem removeMenuItem) {
|
||||
this.remove(removeMenuItem);
|
||||
}
|
||||
|
||||
private void showPrivateChatDialog() {
|
||||
JDialog dialog = new JDialog(
|
||||
SwingUtilities.getWindowAncestor(this),
|
||||
"Novo chat privado",
|
||||
Dialog.ModalityType.APPLICATION_MODAL
|
||||
);
|
||||
|
||||
JTextField ipField = new JTextField();
|
||||
|
||||
JButton startButton = new JButton("Iniciar");
|
||||
JButton cancelButton = new JButton("Cancelar");
|
||||
|
||||
JPanel contentPanel = new JPanel(new BorderLayout(10, 10));
|
||||
contentPanel.setBorder(
|
||||
BorderFactory.createEmptyBorder(10, 10, 10, 10)
|
||||
);
|
||||
|
||||
JPanel ipPanel = new JPanel(new BorderLayout(5, 5));
|
||||
ipPanel.add(new JLabel("IP:"), BorderLayout.WEST);
|
||||
ipPanel.add(ipField, BorderLayout.CENTER);
|
||||
|
||||
JPanel buttonsPanel = new JPanel(
|
||||
new FlowLayout(FlowLayout.RIGHT)
|
||||
);
|
||||
|
||||
buttonsPanel.add(cancelButton);
|
||||
buttonsPanel.add(startButton);
|
||||
|
||||
JLabel errorLabel = new JLabel("Não foi possível estabelecer a conexão.");
|
||||
errorLabel.setForeground(Color.RED);
|
||||
errorLabel.setVisible(false);
|
||||
|
||||
contentPanel.add(errorLabel, BorderLayout.NORTH);
|
||||
contentPanel.add(ipPanel, BorderLayout.CENTER);
|
||||
contentPanel.add(buttonsPanel, BorderLayout.SOUTH);
|
||||
|
||||
cancelButton.addActionListener(e -> dialog.dispose());
|
||||
|
||||
startButton.addActionListener(e -> {
|
||||
String ip = ipField.getText();
|
||||
|
||||
if (testChat.openConnection(ip)) dialog.dispose();
|
||||
else errorLabel.setVisible(true);
|
||||
|
||||
});
|
||||
|
||||
dialog.setContentPane(contentPanel);
|
||||
dialog.pack();
|
||||
dialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(this));
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
plugin.TestChat
|
||||
@@ -1,61 +0,0 @@
|
||||
package control;
|
||||
|
||||
import GUI.ChatMenu;
|
||||
import GUI.ChatWindow;
|
||||
import GUI.PrivateChatWindow;
|
||||
import GUI.PublicChatWindow;
|
||||
import net.TestChatMessage;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import pitiupi.net.tcp.TcpConnection;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ChatController {
|
||||
MainWindow mainWindow;
|
||||
ChatMenu chatMenu;
|
||||
|
||||
PublicChatWindow publicChatWindow;
|
||||
|
||||
private final HashMap<TcpConnection, JMenuItem> chatMenus;
|
||||
private final HashMap<TcpConnection, ChatWindow> chatWindows;
|
||||
|
||||
public ChatController(MainWindow mainWindow, ChatMenu chatMenu) {
|
||||
this.mainWindow = mainWindow;
|
||||
publicChatWindow = new PublicChatWindow(mainWindow);
|
||||
|
||||
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(mainWindow, 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(TestChatMessage message) {
|
||||
publicChatWindow.receiveMessage(message);
|
||||
}
|
||||
public void receivePrivate(TcpConnection tcpConnection, TestChatMessage message) {
|
||||
chatWindows.get(tcpConnection).receiveMessage(message);
|
||||
}
|
||||
}
|
||||
Generated
+1
-1
@@ -1,5 +1,5 @@
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" default="true" project-jdk-name="openjdk-26" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_26_PREVIEW" project-jdk-name="openjdk-26" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -468,10 +468,10 @@ MeusPlugins
|
||||
|
|
||||
+---services
|
||||
|
|
||||
+---pitiupi.plugin.Plugin
|
||||
+---pitiupi.models.Plugin
|
||||
```
|
||||
|
||||
O arquivo `pitiupi.plugin.Plugin` deve conter o nome completo das classes que
|
||||
O arquivo `pitiupi.models.Plugin` deve conter o nome completo das classes que
|
||||
implementam a interface Plugin:
|
||||
|
||||
```
|
||||
|
||||
@@ -1,2 +1,512 @@
|
||||
# Como criar plugins para o Share my Sheet
|
||||
# Como criar plugins para o Pitiupi
|
||||
|
||||
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 <span style="color: red;">[REF]</span>, 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 receiverAddress)
|
||||
|
||||
Envia uma mensagem unicast via udp para o endereço fornecido, retorna `boolean` indicando se teve sucesso.
|
||||
|
||||
### boolean sendTcp(Message message, InetAddress receiverAddress)
|
||||
|
||||
Envia uma mensagem unicast via tcp para o endereço fornecido, retorna `boolean` indicando se teve sucesso.
|
||||
|
||||
### <span style="color: red;">[REF]</span> TcpConnection connectTcp(InetAddress receiverAddress, 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.
|
||||
|
||||
### <span style="color: red;">[REF]</span> 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.
|
||||
|
||||
### <span style="color: red;">[REF]</span> receiveAllTypes()
|
||||
|
||||
Indica ao Pitiupi que seu plugin deseja receber todas as mensagens publicas da plataforma, independente do tipo.
|
||||
|
||||
### <span style="color: red;">[REF]</span> 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.
|
||||
|
||||
### <span style="color: red;">[REF]</span> receiveBytes(TcpConnection connection, byte[] bytes)
|
||||
|
||||
Esse método é chamado para entregar as mensagens recebidas por um `TcpConnection`, o tcpPitiupi no parametro indica qual a fonte da mensagem.
|
||||
|
||||
### <span style="color: red;">[REF]</span> 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.
|
||||
|
||||
<span style="color: red;">[REF]</span> 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`.
|
||||
|
||||
## <span style="color: red;">[REF]</span> 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.
|
||||
|
||||
### <span style="color: red;">[REF]</span> 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.
|
||||
|
||||
### <span style="color: red;">[REF]</span> boolean isClosed()
|
||||
|
||||
Indica se a conexão esta fechada
|
||||
|
||||
### <span style="color: red;">[REF]</span> InetAddress getAddress()
|
||||
|
||||
Retorna o endereço do peer que ela esta conectada.
|
||||
|
||||
### <span style="color: red;">[REF]</span> String getReceiver()
|
||||
|
||||
Retorna o identificador do plugin que ela esta conectada.
|
||||
|
||||
### <span style="color: red;">[REF]</span> 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<UnicastMenu>`
|
||||
|
||||
`MulticastSubMenu` o método `getMenu()` retorna `List<MulticastMenu>`
|
||||
|
||||
Exemplo:
|
||||
|
||||
```
|
||||
|
||||
ChatCasualMulticastMenu chatCasualMulticastMenu;
|
||||
ChatEstudoMutlticastMenu chatEstudoMutlticastMenu;
|
||||
|
||||
...
|
||||
|
||||
@Override
|
||||
public List<MulticastMenu> 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<Class<? extends Message>> 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<MulticastMenu> 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) + " "
|
||||
+ "<b>" + message.getName() + "</b>: "
|
||||
+ message.getText() + "<br>");
|
||||
}
|
||||
|
||||
public void receiveChatMessage(String message) {
|
||||
jEditorPane1.setText(message + jEditorPane1.getText());
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -700,7 +700,7 @@ is divided into following sections:
|
||||
<sequential>
|
||||
<j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
|
||||
<customize>
|
||||
<jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/>
|
||||
<jvmarg value="-agentlib:jdwp=transport=${debug-transport},receiverAddress=${jpda.receiverAddress}"/>
|
||||
<customizeDebuggee/>
|
||||
</customize>
|
||||
</j2seproject3:junit>
|
||||
@@ -843,7 +843,7 @@ is divided into following sections:
|
||||
<attribute default="${debug.classpath}" name="classpath"/>
|
||||
<attribute default="" name="stopclassname"/>
|
||||
<sequential>
|
||||
<nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
|
||||
<nbjpdastart addressproperty="jpda.receiverAddress" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
|
||||
<modulepath>
|
||||
<path path="@{modulepath}"/>
|
||||
</modulepath>
|
||||
@@ -882,7 +882,7 @@ is divided into following sections:
|
||||
<sequential>
|
||||
<j2seproject1:java classname="@{classname}" classpath="@{classpath}" modulename="@{modulename}" modulepath="@{modulepath}">
|
||||
<customize>
|
||||
<jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/>
|
||||
<jvmarg value="-agentlib:jdwp=transport=${debug-transport},receiverAddress=${jpda.receiverAddress}"/>
|
||||
<customizeDebuggee/>
|
||||
</customize>
|
||||
</j2seproject1:java>
|
||||
@@ -1434,7 +1434,7 @@ is divided into following sections:
|
||||
</nbprofiledirect>
|
||||
<j2seproject3:junit excludes="${excludes}" includes="${includes}" testincludes="${profile.class}" testmethods="">
|
||||
<customize>
|
||||
<jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/>
|
||||
<jvmarg value="-agentlib:jdwp=transport=${debug-transport},receiverAddress=${jpda.receiverAddress}"/>
|
||||
<env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
|
||||
<jvmarg value="${profiler.info.jvmargs.agent}"/>
|
||||
<jvmarg line="${profiler.info.jvmargs}"/>
|
||||
|
||||
@@ -46,8 +46,8 @@ javac.modulepath=
|
||||
javac.processormodulepath=
|
||||
javac.processorpath=\
|
||||
${javac.classpath}
|
||||
javac.source=25
|
||||
javac.target=25
|
||||
javac.source=17
|
||||
javac.target=17
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
*/
|
||||
package pitiupi.GUI;
|
||||
|
||||
import pitiupi.net.tcp.SocketTCP;
|
||||
import pitiupi.net.udp.SocketUDP;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.JMenu;
|
||||
import pitiupi.control.PluginLoader;
|
||||
import pitiupi.plugin.Plugin;
|
||||
import pitiupi.control.HeartbeatManager;
|
||||
import pitiupi.control.ConnectionManager;
|
||||
import pitiupi.control.GuiManager;
|
||||
import pitiupi.control.plugins.PluginManager;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* Janela principal da aplicação.
|
||||
@@ -28,28 +28,15 @@ import pitiupi.control.HeartbeatManager;
|
||||
* @author tony
|
||||
* @author Gustavo
|
||||
*/
|
||||
public class MainWindow extends javax.swing.JFrame {
|
||||
public class MainWindow extends JFrame {
|
||||
|
||||
private final MenuBar menuBar;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JLabel status;
|
||||
private javax.swing.JPanel statusPanel;
|
||||
private javax.swing.JTabbedPane tabbedPane;
|
||||
private MenuBar menuBar;
|
||||
private JLabel status;
|
||||
OnlineUsersPanel onlineUsersPanel;
|
||||
|
||||
private HeartbeatManager heartbeatManager;
|
||||
private OnlineUsersPanel onlineUsersPanel;
|
||||
|
||||
|
||||
private SocketUDP socketUDP;
|
||||
private SocketTCP socketTCP;
|
||||
|
||||
private String userName;
|
||||
private int port;
|
||||
|
||||
private String pitiupiIdentifier;
|
||||
|
||||
private PluginLoader pluginManager;
|
||||
private final List<Plugin> plugins;
|
||||
private ConnectionManager connectionManager;
|
||||
private PluginManager pluginManager;
|
||||
private GuiManager guiManager;
|
||||
|
||||
/**
|
||||
* Cria a janela principal da aplicação.
|
||||
@@ -58,62 +45,66 @@ public class MainWindow extends javax.swing.JFrame {
|
||||
* @param port porta utilizada na comunicação multicast.
|
||||
*/
|
||||
public MainWindow(String userName, int port) {
|
||||
this.userName = userName;
|
||||
this.port = port;
|
||||
this.pitiupiIdentifier = "Pitiupi.Alice.2026";
|
||||
this.menuBar = new MenuBar(this);
|
||||
this.plugins = new ArrayList<>();
|
||||
this.initComponents();
|
||||
}
|
||||
try {
|
||||
initMenu();
|
||||
|
||||
private void initComponents() {
|
||||
initGUI();
|
||||
initSocket();
|
||||
initHeartbeat();
|
||||
initPlugins();
|
||||
this.setSize(new java.awt.Dimension(1024, 768));
|
||||
}
|
||||
pluginManager = new PluginManager();
|
||||
connectionManager = new ConnectionManager(userName, pluginManager, port);
|
||||
|
||||
private void initGUI() {
|
||||
this.setJMenuBar(menuBar);
|
||||
this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
|
||||
this.setTitle("Share My Sheet");
|
||||
initUserPanel();
|
||||
initStatusPanel();
|
||||
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
tabbedPane = new javax.swing.JTabbedPane();
|
||||
statusPanel = new javax.swing.JPanel();
|
||||
status = new javax.swing.JLabel();
|
||||
guiManager = new GuiManager(this, menuBar, onlineUsersPanel);
|
||||
|
||||
jScrollPane1.setViewportView(tabbedPane);
|
||||
statusPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));
|
||||
status.setText("Connected on port " + this.port + " name " + this.userName);
|
||||
statusPanel.add(status);
|
||||
|
||||
this.getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
|
||||
this.getContentPane().add(statusPanel, java.awt.BorderLayout.PAGE_END);
|
||||
loadPlugins();
|
||||
|
||||
this.pack();
|
||||
|
||||
this.setSize(new java.awt.Dimension(1024, 768));
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
JOptionPane.showMessageDialog(
|
||||
null,
|
||||
"Ocorreu um erro abrindo a conexão TCP, verifique sua rede. \n" +
|
||||
"Se o problema persistir entre em contato com a equipe do Pitiupi.",
|
||||
"Erro na conexão TCP",
|
||||
JOptionPane.ERROR_MESSAGE
|
||||
);
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void initSocket() {
|
||||
this.socketUDP = new SocketUDP(this);
|
||||
this.socketTCP = new SocketTCP(this);
|
||||
private void initMenu() {
|
||||
menuBar = new MenuBar(this);
|
||||
|
||||
this.socketUDP.start();
|
||||
this.socketTCP.start();
|
||||
this.setJMenuBar(menuBar);
|
||||
this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
|
||||
this.setTitle("Pitiupi");
|
||||
|
||||
javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
|
||||
javax.swing.JTabbedPane tabbedPane = new javax.swing.JTabbedPane();
|
||||
|
||||
jScrollPane1.setViewportView(tabbedPane);
|
||||
|
||||
this.getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
private void initHeartbeat() {
|
||||
this.heartbeatManager = new HeartbeatManager(this);
|
||||
this.onlineUsersPanel = new OnlineUsersPanel();
|
||||
this.heartbeatManager.addPeerListener(this.onlineUsersPanel);
|
||||
this.getContentPane().add(this.onlineUsersPanel, java.awt.BorderLayout.LINE_END);
|
||||
this.heartbeatManager.start();
|
||||
private void initUserPanel() {
|
||||
onlineUsersPanel = new OnlineUsersPanel();
|
||||
this.connectionManager.addPeerListener(onlineUsersPanel);
|
||||
this.getContentPane().add(onlineUsersPanel, java.awt.BorderLayout.LINE_END);
|
||||
}
|
||||
|
||||
private void initPlugins() {
|
||||
this.pluginManager = new PluginLoader(this);
|
||||
this.pluginManager.loadPlugins();
|
||||
private void initStatusPanel() {
|
||||
JPanel statusPanel = new JPanel();
|
||||
status = new JLabel();
|
||||
|
||||
statusPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
||||
updateStatus();
|
||||
statusPanel.add(status);
|
||||
|
||||
this.getContentPane().add(statusPanel, BorderLayout.PAGE_END);
|
||||
}
|
||||
|
||||
public void exit() {
|
||||
@@ -122,65 +113,21 @@ public class MainWindow extends javax.swing.JFrame {
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
public HeartbeatManager getHeartbeatManager() {
|
||||
return heartbeatManager;
|
||||
public ConnectionManager getConnectionManager() {
|
||||
return connectionManager;
|
||||
}
|
||||
|
||||
public String getUserName(){
|
||||
return this.userName;
|
||||
}
|
||||
|
||||
public String getIdentifier(){
|
||||
return this.pitiupiIdentifier;
|
||||
}
|
||||
|
||||
public void addMenu(JMenu menu) {
|
||||
this.menuBar.addPlugin(menu);
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
public SocketUDP getSocketUDP() {
|
||||
return this.socketUDP;
|
||||
}
|
||||
|
||||
public SocketTCP getSocketTCP() {
|
||||
return this.socketTCP;
|
||||
}
|
||||
|
||||
public List<Plugin> getPlugins() {
|
||||
return plugins;
|
||||
public void loadPlugins() {
|
||||
pluginManager.loadPlugins(connectionManager, guiManager);
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
reconnect();
|
||||
connectionManager.setUserName(userName);
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
private void updateStatus() {
|
||||
this.status.setText("Connected on port " + this.port + " name " + this.userName);
|
||||
this.status.setText("Connected on port " + connectionManager.getPort() + " name " + connectionManager.getUserName());
|
||||
}
|
||||
|
||||
private void reconnect() {
|
||||
if (this.socketUDP != null) {
|
||||
this.socketUDP.close();
|
||||
}
|
||||
if (this.socketTCP != null) {
|
||||
this.socketTCP.close();
|
||||
}
|
||||
|
||||
this.socketUDP = new SocketUDP(this);
|
||||
this.socketTCP = new SocketTCP(this);
|
||||
|
||||
this.socketUDP.start();
|
||||
this.socketTCP.start();
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,14 @@
|
||||
*/
|
||||
package pitiupi.GUI;
|
||||
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import pitiupi.models.Menus.MenuCategory;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Barra de menus principal da aplicação.
|
||||
@@ -21,12 +27,14 @@ import javax.swing.JMenuBar;
|
||||
*/
|
||||
public class MenuBar extends JMenuBar {
|
||||
|
||||
private javax.swing.JMenuItem setupMenu;
|
||||
private javax.swing.JMenuItem aboutMenu;
|
||||
private javax.swing.JMenu fileMenu;
|
||||
private javax.swing.JMenu helpMenu;
|
||||
private javax.swing.JMenu pluginMenu;
|
||||
private javax.swing.JMenuItem exitMenu;
|
||||
private JMenuItem preferencesMenu;
|
||||
private JMenuItem aboutMenu;
|
||||
private JMenu fileMenu;
|
||||
private JMenu helpMenu;
|
||||
private JMenu pluginMenu;
|
||||
private Map<MenuCategory, JMenu> categories;
|
||||
|
||||
private JMenuItem exitMenu;
|
||||
private final MainWindow mainWindow;
|
||||
|
||||
/**
|
||||
@@ -40,63 +48,70 @@ public class MenuBar extends JMenuBar {
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
fileMenu = new javax.swing.JMenu();
|
||||
exitMenu = new javax.swing.JMenuItem();
|
||||
helpMenu = new javax.swing.JMenu();
|
||||
pluginMenu = new javax.swing.JMenu();
|
||||
setupMenu = new javax.swing.JMenuItem();
|
||||
aboutMenu = new javax.swing.JMenuItem();
|
||||
initFileMenu();
|
||||
initPluginMenu();
|
||||
initHelpMenu();
|
||||
}
|
||||
|
||||
fileMenu.setText("File");
|
||||
exitMenu.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F4, java.awt.event.InputEvent.ALT_MASK));
|
||||
exitMenu.setText("Exit");
|
||||
private void initFileMenu() {
|
||||
fileMenu = new JMenu("File");
|
||||
exitMenu = new JMenuItem("Exit");
|
||||
|
||||
exitMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.ALT_DOWN_MASK));
|
||||
exitMenu.addActionListener(this::exitMenuActionPerformed);
|
||||
fileMenu.add(exitMenu);
|
||||
this.add(fileMenu);
|
||||
}
|
||||
|
||||
private void initPluginMenu() {
|
||||
pluginMenu = new JMenu("Plugin");
|
||||
categories = new HashMap<>();
|
||||
|
||||
for (MenuCategory category : MenuCategory.values()) {
|
||||
JMenu newCategoryMenu = new JMenu(category.toString());
|
||||
|
||||
pluginMenu.add(newCategoryMenu);
|
||||
categories.put(category, newCategoryMenu);
|
||||
}
|
||||
|
||||
pluginMenu.setText("Plugin");
|
||||
this.add(pluginMenu);
|
||||
}
|
||||
|
||||
helpMenu.setText("Help");
|
||||
private void initHelpMenu() {
|
||||
helpMenu = new JMenu("Help");
|
||||
preferencesMenu = new JMenuItem("Preferences");
|
||||
aboutMenu = new JMenuItem("About");
|
||||
|
||||
setupMenu.setText("Preferences");
|
||||
setupMenu.addActionListener(this::setupMenuActionPerformed);
|
||||
helpMenu.add(setupMenu);
|
||||
preferencesMenu.addActionListener(this::setupMenuActionPerformed);
|
||||
helpMenu.add(preferencesMenu);
|
||||
|
||||
aboutMenu.setText("About");
|
||||
aboutMenu.addActionListener(this::aboutMenuActionPerformed);
|
||||
helpMenu.add(aboutMenu);
|
||||
|
||||
this.add(helpMenu);
|
||||
}
|
||||
|
||||
private void exitMenuActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
private void exitMenuActionPerformed(ActionEvent evt) {
|
||||
mainWindow.exit();
|
||||
}
|
||||
|
||||
|
||||
private void setupMenuActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
private void setupMenuActionPerformed(ActionEvent evt) {
|
||||
Login login = new Login();
|
||||
login.setVisible(true);
|
||||
|
||||
mainWindow.setUserName(login.getName());
|
||||
mainWindow.setPort(login.getPort());
|
||||
mainWindow.getConnectionManager().setPort(login.getPort());
|
||||
|
||||
login.dispose();
|
||||
}
|
||||
|
||||
private void aboutMenuActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
private void aboutMenuActionPerformed(ActionEvent evt) {
|
||||
About about = new About();
|
||||
about.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adiciona um menu fornecido por um plugin à seção de plugins da barra
|
||||
* de menus.
|
||||
*
|
||||
* @param menu menu criado pelo plugin.
|
||||
*/
|
||||
public void addPlugin(JMenu menu){
|
||||
this.pluginMenu.add(menu);
|
||||
public void addPluginMenu(MenuCategory category, JMenuItem menu){
|
||||
System.out.println("addPluginMenu");
|
||||
categories.get(category).add(menu);
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,16 @@ package pitiupi.GUI;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import pitiupi.control.PeerInfo;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import javax.swing.*;
|
||||
|
||||
import pitiupi.models.Menus.MenuCategory;
|
||||
import pitiupi.models.User;
|
||||
import pitiupi.control.PeerListener;
|
||||
|
||||
/**
|
||||
@@ -20,10 +22,16 @@ import pitiupi.control.PeerListener;
|
||||
*/
|
||||
public class OnlineUsersPanel extends JPanel implements PeerListener {
|
||||
|
||||
private final DefaultListModel<String> listModel;
|
||||
private final JList<String> userList;
|
||||
private final DefaultListModel<User> listModel;
|
||||
private final JList<User> userList;
|
||||
JPopupMenu menu;
|
||||
private Map<MenuCategory, JMenu> categories;
|
||||
|
||||
public OnlineUsersPanel() {
|
||||
menu = new JPopupMenu();
|
||||
categories = new HashMap<>();
|
||||
initMenu();
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
setBorder(BorderFactory.createTitledBorder("Online"));
|
||||
setPreferredSize(new Dimension(160, 0));
|
||||
@@ -31,6 +39,48 @@ public class OnlineUsersPanel extends JPanel implements PeerListener {
|
||||
listModel = new DefaultListModel<>();
|
||||
userList = new JList<>(listModel);
|
||||
add(new JScrollPane(userList), BorderLayout.CENTER);
|
||||
|
||||
setupUserListActions();
|
||||
}
|
||||
|
||||
private void initMenu() {
|
||||
for (MenuCategory category : MenuCategory.values()) {
|
||||
JMenu newCategory = new JMenu(category.toString());
|
||||
|
||||
menu.add(newCategory);
|
||||
categories.put(category, newCategory);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupUserListActions() {
|
||||
userList.addMouseListener(new MouseAdapter() {
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
int index = userList.locationToIndex(e.getPoint());
|
||||
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
userList.setSelectedIndex(index);
|
||||
menu.show(userList, e.getX(), e.getY());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void initUnicastMenu(JMenuItem menuItem, Consumer<User> action) {
|
||||
menuItem.addActionListener(e -> {
|
||||
User user = userList.getSelectedValue();
|
||||
|
||||
if (user != null) {
|
||||
action.accept(user);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addUnicastMenu(MenuCategory category, JMenuItem menuItem) {
|
||||
categories.get(category).add(menuItem);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,11 +89,11 @@ public class OnlineUsersPanel extends JPanel implements PeerListener {
|
||||
* @param peers lista atualizada de usuários ativos na rede.
|
||||
*/
|
||||
@Override
|
||||
public void onPeersChanged(List<PeerInfo> peers) {
|
||||
public void onPeersChanged(List<User> peers) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
listModel.clear();
|
||||
for (PeerInfo peer : peers) {
|
||||
listModel.addElement(peer.toString());
|
||||
for (User peer : peers) {
|
||||
listModel.addElement(peer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
package pitiupi.control;
|
||||
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import pitiupi.control.plugins.PluginManager;
|
||||
import pitiupi.models.ConnectionData;
|
||||
import pitiupi.models.Messages.HeartbeatMessage;
|
||||
import pitiupi.models.Messages.Message;
|
||||
import pitiupi.net.tcp.TcpClient;
|
||||
import pitiupi.net.tcp.TcpManager;
|
||||
import pitiupi.net.tcp.TcpServer;
|
||||
import pitiupi.net.udp.SocketUDP;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class ConnectionManager {
|
||||
private final PluginManager pluginManager;
|
||||
|
||||
private final HeartbeatManager heartbeatManager;
|
||||
|
||||
private TcpManager tcpManager;
|
||||
private SocketUDP socketUDP;
|
||||
private String username;
|
||||
private final InetAddress address;
|
||||
private int port;
|
||||
|
||||
public ConnectionManager(String username, PluginManager pluginManager, int port) throws UnknownHostException {
|
||||
this.pluginManager = pluginManager;
|
||||
|
||||
this.username = username;
|
||||
this.address = InetAddress.getLocalHost();
|
||||
this.port = port;
|
||||
|
||||
reconnect();
|
||||
|
||||
heartbeatManager = new HeartbeatManager(this);
|
||||
heartbeatManager.start();
|
||||
}
|
||||
|
||||
public TcpClient connectToTcpServer(ConnectionData serverData, String pluginId) {
|
||||
return tcpManager.getClient(serverData, pluginId, username);
|
||||
}
|
||||
|
||||
public TcpServer getTcpServer(String serverName, String pluginId) {
|
||||
return tcpManager.getServer(serverName, pluginId, username, address, port);
|
||||
}
|
||||
|
||||
public void closeTcpServer(TcpServer tcpServer) {
|
||||
tcpManager.closeServer(tcpServer);
|
||||
}
|
||||
|
||||
public boolean sendTcp(Message message, InetAddress destinationAddress) {
|
||||
return tcpManager.send(message, destinationAddress, port);
|
||||
}
|
||||
|
||||
public boolean sendUdpUnicast(Message message, InetAddress destinationAddress) {
|
||||
try {
|
||||
socketUDP.sendUnicast(message, destinationAddress);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean sendUdpMulticast(Message message) {
|
||||
try {
|
||||
socketUDP.sendMulticast(message);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error sending UDP Multicast");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void receiveMessage(byte[] message) {
|
||||
pluginManager.handleMessage(message);
|
||||
}
|
||||
|
||||
public void addPeerListener(PeerListener peerListener) {
|
||||
heartbeatManager.addPeerListener(peerListener);
|
||||
}
|
||||
|
||||
public void receiveHeartbeat(HeartbeatMessage message, InetAddress destinationAddress) {
|
||||
heartbeatManager.receiveHeartbeat(message, destinationAddress);
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
reconnect();
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
private void reconnect() {
|
||||
try {
|
||||
if (this.socketUDP != null) {
|
||||
this.socketUDP.close();
|
||||
}
|
||||
if (this.tcpManager != null) {
|
||||
this.tcpManager.closeManager();
|
||||
}
|
||||
|
||||
this.socketUDP = new SocketUDP(this, pluginManager);
|
||||
this.tcpManager = new TcpManager(port, this::receiveMessage);
|
||||
|
||||
this.socketUDP.start();
|
||||
this.tcpManager.start();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.getLogger(ConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public InetAddress getAddress() {
|
||||
return this.address;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.username = userName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package pitiupi.control;
|
||||
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import pitiupi.GUI.MenuBar;
|
||||
import pitiupi.GUI.OnlineUsersPanel;
|
||||
import pitiupi.models.Menus.*;
|
||||
import pitiupi.models.Menus.MulticastMenus.MulticastActionMenu;
|
||||
import pitiupi.models.Menus.MulticastMenus.MulticastMenu;
|
||||
import pitiupi.models.Menus.MulticastMenus.MulticastSubMenu;
|
||||
import pitiupi.models.Menus.UnicastMenus.UnicastActionMenu;
|
||||
import pitiupi.models.Menus.UnicastMenus.UnicastMenu;
|
||||
import pitiupi.models.Menus.UnicastMenus.UnicastSubMenu;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class GuiManager {
|
||||
private MainWindow mainWindow;
|
||||
private MenuBar menuBar;
|
||||
private OnlineUsersPanel onlineUsersPanel;
|
||||
|
||||
private Logger logger;
|
||||
|
||||
public GuiManager(MainWindow mainWindow, MenuBar menuBar, OnlineUsersPanel onlineUsersPanel) {
|
||||
this.mainWindow = mainWindow;
|
||||
this.menuBar = menuBar;
|
||||
this.onlineUsersPanel = onlineUsersPanel;
|
||||
this.logger = Logger.getLogger(GuiManager.class.getName());
|
||||
}
|
||||
|
||||
public void createMenu(MenuCategory category, Menu menu) {
|
||||
try {
|
||||
JMenuItem newMenu = buildMenu(menu);
|
||||
if (menu instanceof MulticastMenu) {
|
||||
menuBar.addPluginMenu(category, newMenu);
|
||||
}
|
||||
if (menu instanceof UnicastMenu) {
|
||||
onlineUsersPanel.addUnicastMenu(category, newMenu);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
logger.log(Level.WARNING, e.getMessage());
|
||||
}
|
||||
}
|
||||
private JMenuItem buildMenu(Menu menu) {
|
||||
if (menu instanceof MulticastSubMenu multicastSubMenu) {
|
||||
JMenu newMenu = new JMenu(menu.getText());
|
||||
|
||||
for (Menu child : multicastSubMenu.getMenus()) {
|
||||
newMenu.add(buildMenu(child));
|
||||
}
|
||||
|
||||
return newMenu;
|
||||
}
|
||||
|
||||
if (menu instanceof UnicastSubMenu unicastSubMenu) {
|
||||
JMenu newMenu = new JMenu(menu.getText());
|
||||
|
||||
for (Menu child : unicastSubMenu.getMenus()) {
|
||||
newMenu.add(buildMenu(child));
|
||||
}
|
||||
|
||||
return newMenu;
|
||||
}
|
||||
|
||||
if (menu instanceof MulticastActionMenu multicastActionMenu) {
|
||||
JMenuItem newMenu = new JMenuItem(menu.getText());
|
||||
newMenu.addActionListener(e -> multicastActionMenu.onClick());
|
||||
return newMenu;
|
||||
}
|
||||
|
||||
if (menu instanceof UnicastActionMenu unicastActionMenu) {
|
||||
JMenuItem newMenu = new JMenuItem(menu.getText());
|
||||
|
||||
onlineUsersPanel.initUnicastMenu(newMenu, unicastActionMenu::onClick);
|
||||
return newMenu;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid menu type");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package pitiupi.control;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -10,10 +9,9 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import pitiupi.net.HeartbeatMessage;
|
||||
|
||||
import pitiupi.models.User;
|
||||
import pitiupi.models.Messages.HeartbeatMessage;
|
||||
import java.util.UUID;
|
||||
/**
|
||||
* Gerencia o mecanismo de heartbeat da aplicação.
|
||||
@@ -28,9 +26,8 @@ public class HeartbeatManager {
|
||||
|
||||
private static final long HEARTBEAT_INTERVAL_MS = 5000;
|
||||
private static final long PEER_TIMEOUT_MS = 15000; // ~3 batimentos perdidos
|
||||
|
||||
private final MainWindow mainWindow;
|
||||
private final Map<String, PeerInfo> peers = new ConcurrentHashMap<>();
|
||||
private final ConnectionManager connectionManager;
|
||||
private final Map<String, User> peers = new ConcurrentHashMap<>();
|
||||
private final List<PeerListener> listeners = new CopyOnWriteArrayList<>();
|
||||
private ScheduledExecutorService scheduler;
|
||||
private final String instanceId = UUID.randomUUID().toString();
|
||||
@@ -38,11 +35,9 @@ public class HeartbeatManager {
|
||||
/**
|
||||
* Cria um gerenciador de heartbeat associado à janela principal da aplicação.
|
||||
*
|
||||
* @param mainWindow janela principal utilizada para obter o nome do usuário
|
||||
* e o socket de comunicação.
|
||||
*/
|
||||
public HeartbeatManager(MainWindow mainWindow) {
|
||||
this.mainWindow = mainWindow;
|
||||
public HeartbeatManager(ConnectionManager connectionManager) {
|
||||
this.connectionManager = connectionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,12 +59,8 @@ public class HeartbeatManager {
|
||||
}
|
||||
|
||||
private void announce() {
|
||||
try {
|
||||
HeartbeatMessage msg = new HeartbeatMessage(mainWindow.getUserName(), instanceId);
|
||||
mainWindow.getSocketUDP().sendMulticast(msg);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(HeartbeatManager.class.getName()).log(Level.WARNING, "Falha ao enviar heartbeat", ex);
|
||||
}
|
||||
HeartbeatMessage msg = new HeartbeatMessage(connectionManager.getUserName(), instanceId);
|
||||
connectionManager.sendUdpMulticast(msg);
|
||||
}
|
||||
|
||||
// Chamado pelo Socket quando um pacote é identificado como heartbeat
|
||||
@@ -94,7 +85,7 @@ public class HeartbeatManager {
|
||||
String key = msg.getInstanceId();
|
||||
boolean isNew = !peers.containsKey(key);
|
||||
|
||||
PeerInfo peer = peers.computeIfAbsent(key, k -> new PeerInfo(msg.getUserName(), from, msg.getTimestamp()));
|
||||
User peer = peers.computeIfAbsent(key, k -> new User(msg.getUserName(), from, msg.getTimestamp()));
|
||||
peer.touch(System.currentTimeMillis());
|
||||
|
||||
if (isNew) {
|
||||
@@ -111,7 +102,7 @@ public class HeartbeatManager {
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
List<PeerInfo> snapshot = new ArrayList<>(peers.values());
|
||||
List<User> snapshot = new ArrayList<>(peers.values());
|
||||
for (PeerListener l : listeners) {
|
||||
l.onPeersChanged(snapshot);
|
||||
}
|
||||
@@ -144,7 +135,7 @@ public class HeartbeatManager {
|
||||
*
|
||||
* @return lista contendo os peers atualmente conhecidos.
|
||||
*/
|
||||
public List<PeerInfo> getPeers() {
|
||||
public List<User> getPeers() {
|
||||
return new ArrayList<>(peers.values());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package pitiupi.control;
|
||||
|
||||
import pitiupi.models.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -17,5 +19,5 @@ public interface PeerListener {
|
||||
*
|
||||
* @param peers lista atualizada de usuários ativos.
|
||||
*/
|
||||
void onPeersChanged(List<PeerInfo> peers);
|
||||
void onPeersChanged(List<User> peers);
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
||||
*/
|
||||
package pitiupi.control;
|
||||
|
||||
import java.awt.List;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Vector;
|
||||
import pitiupi.GUI.MainWindow;
|
||||
import pitiupi.Main;
|
||||
import pitiupi.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Responsável por localizar, carregar e registrar os plugins
|
||||
* presentes no diretório {@code plugins}.
|
||||
*
|
||||
* <p>Os plugins são descobertos utilizando {@link java.util.ServiceLoader}
|
||||
* e devem estar empacotados como arquivos JAR contendo a configuração
|
||||
* {@code META-INF/services} correspondente.</p>
|
||||
* @author flavio
|
||||
*/
|
||||
public class PluginLoader {
|
||||
|
||||
private final pitiupi.GUI.MainWindow mainWindow;
|
||||
|
||||
public PluginLoader(MainWindow main) {
|
||||
this.mainWindow = main;
|
||||
}
|
||||
|
||||
public void loadPlugins() {
|
||||
File pluginDir = new File("plugins");
|
||||
File[] jarFiles = pluginDir.listFiles((dir, name) -> name.endsWith(".jar"));
|
||||
|
||||
if (jarFiles == null || jarFiles.length == 0) {
|
||||
System.out.println("No plugins found in the " + pluginDir.getAbsolutePath() + " directory.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 2. Convert jar file paths into URLs
|
||||
ArrayList urls = new ArrayList();
|
||||
for (File file : jarFiles) {
|
||||
urls.add(file.toURI().toURL());
|
||||
System.out.println("Discovered plugin package: " + file.getName());
|
||||
}
|
||||
|
||||
// 3. Create a class loader isolated from the application's default loader
|
||||
URLClassLoader pluginClassLoader = new URLClassLoader(
|
||||
(URL[])urls.toArray(new URL[0]),
|
||||
Main.class.getClassLoader()
|
||||
);
|
||||
System.out.println(pluginClassLoader);
|
||||
|
||||
// 4. Locate and instantiate all classes implementing the Plugin interface
|
||||
ServiceLoader<Plugin> serviceLoader = ServiceLoader.load(Plugin.class, pluginClassLoader);
|
||||
|
||||
System.out.println("\n--- Executing Discovered Plugins ---" + serviceLoader.findFirst());
|
||||
for (Plugin plugin : serviceLoader) {
|
||||
System.out.println("Loading: " + plugin.getName());
|
||||
plugin.createPlugin(this.mainWindow);
|
||||
this.mainWindow.getPlugins().add(plugin);
|
||||
}
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package pitiupi.control.plugins;
|
||||
|
||||
import pitiupi.models.Plugin;
|
||||
|
||||
class LoadedPlugin {
|
||||
|
||||
private final Plugin plugin;
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public LoadedPlugin(Plugin plugin, ClassLoader classLoader) {
|
||||
this.plugin = plugin;
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package pitiupi.control.plugins;
|
||||
|
||||
import pitiupi.plugin.Pitiupi;
|
||||
import pitiupi.Main;
|
||||
import pitiupi.control.ConnectionManager;
|
||||
import pitiupi.control.GuiManager;
|
||||
import pitiupi.models.Messages.Message;
|
||||
import pitiupi.models.Plugin;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class PluginManager {
|
||||
private final List<LoadedPlugin> loadedPlugins;
|
||||
private final HashSet<String> loadedJars;
|
||||
|
||||
private final Logger logger;
|
||||
|
||||
public PluginManager() {
|
||||
this.loadedPlugins = new ArrayList<>();
|
||||
this.loadedJars = new HashSet<>();
|
||||
|
||||
logger = Logger.getLogger(getClass().getName());
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] msg) {
|
||||
Message message = null;
|
||||
|
||||
for (LoadedPlugin loadedPlugin : loadedPlugins) {
|
||||
message = deserialize(msg, loadedPlugin.getClassLoader());
|
||||
if (message != null) break;
|
||||
}
|
||||
if (message == null) return;
|
||||
|
||||
for (LoadedPlugin loadedPlugin : loadedPlugins) {
|
||||
Plugin plugin = loadedPlugin.getPlugin();
|
||||
|
||||
if (plugin.receiveAllTypes() && message.isPublic()) {
|
||||
plugin.receiveMessage(message);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Class<? extends Message> messageType : plugin.getMessages()) {
|
||||
if (messageType.isInstance(message)) {
|
||||
plugin.receiveMessage(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Plugin getPlugin(String pluginId) {
|
||||
for (LoadedPlugin loadedPlugin : loadedPlugins) {
|
||||
if (loadedPlugin.getPlugin().getIdentifier().equals(pluginId))
|
||||
return loadedPlugin.getPlugin();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (File file : jarFiles) {
|
||||
|
||||
if (loadedJars.contains(file.getName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
System.out.println("Discovered plugin package: " + file.getName());
|
||||
|
||||
try {
|
||||
URLClassLoader classLoader = new URLClassLoader(
|
||||
new URL[]{file.toURI().toURL()},
|
||||
Main.class.getClassLoader()
|
||||
);
|
||||
|
||||
ServiceLoader<Plugin> serviceLoader = ServiceLoader.load(Plugin.class, classLoader);
|
||||
|
||||
for (Plugin plugin : serviceLoader) {
|
||||
System.out.println("Loading: " + plugin.getName());
|
||||
LoadedPlugin loadedPlugin = new LoadedPlugin(plugin, classLoader);
|
||||
|
||||
plugin.createPlugin(pitiupi);
|
||||
loadedPlugins.add(loadedPlugin);
|
||||
loadedJars.add(file.getName());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Failed to load plugin " + file.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Message deserialize(byte[] data, ClassLoader classLoader) {
|
||||
try {
|
||||
ByteArrayInputStream input = new ByteArrayInputStream(data);
|
||||
|
||||
PluginObjectInputStream objectInput = new PluginObjectInputStream(input, classLoader);
|
||||
|
||||
Object object = objectInput.readObject();
|
||||
|
||||
if (!(object instanceof Message)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (Message) object;
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.log(Level.SEVERE, "Failed to load plugin package", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package pitiupi.control.plugins;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
|
||||
public class PluginObjectInputStream extends ObjectInputStream {
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public PluginObjectInputStream(InputStream input, ClassLoader classLoader) throws IOException {
|
||||
super(input);
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> resolveClass(ObjectStreamClass description) throws ClassNotFoundException {
|
||||
return Class.forName(description.getName(), false, classLoader);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package pitiupi.models;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class ConnectionData implements Serializable {
|
||||
private final UUID uuid;
|
||||
private final int port;
|
||||
|
||||
private final String connectionName;
|
||||
|
||||
private final String ownerName;
|
||||
private final InetAddress ownerAddress;
|
||||
private final String pluginId;
|
||||
private final boolean isServer;
|
||||
|
||||
public ConnectionData(String connectionName, String ownerName, InetAddress ownerAddress, String pluginId, int port, boolean isServer) {
|
||||
uuid = UUID.randomUUID();
|
||||
|
||||
this.port = port;
|
||||
this.connectionName = connectionName;
|
||||
this.ownerName = ownerName;
|
||||
this.ownerAddress = ownerAddress;
|
||||
this.pluginId = pluginId;
|
||||
this.isServer = isServer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public String getConnectionName() {
|
||||
return connectionName;
|
||||
}
|
||||
|
||||
public String getOwnerName() {
|
||||
return ownerName;
|
||||
}
|
||||
public InetAddress getOwnerAddress() {
|
||||
return ownerAddress;
|
||||
}
|
||||
public String getPluginId() {
|
||||
return pluginId;
|
||||
}
|
||||
public boolean isServer() {
|
||||
return isServer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ConnectionData that = (ConnectionData) o;
|
||||
|
||||
if (port != that.port) return false;
|
||||
if (!uuid.equals(that.uuid)) return false;
|
||||
if (!connectionName.equals(that.connectionName)) return false;
|
||||
if (!Objects.equals(ownerName, that.ownerName)) return false;
|
||||
if (!Objects.equals(ownerAddress, that.ownerAddress)) return false;
|
||||
if (!Objects.equals(pluginId, that.pluginId)) return false;
|
||||
return isServer == that.isServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(
|
||||
uuid,
|
||||
port,
|
||||
connectionName,
|
||||
ownerName,
|
||||
ownerAddress,
|
||||
pluginId,
|
||||
isServer
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return connectionName + ": " + pluginId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package pitiupi.models.Menus;
|
||||
|
||||
public abstract class Menu {
|
||||
public abstract String getText();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package pitiupi.models.Menus;
|
||||
|
||||
public enum MenuCategory {
|
||||
Jogos,
|
||||
Social,
|
||||
Streaming
|
||||
}
|
||||
Loaded 100 of 127 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user