Subtrees hinzugefügt
This commit is contained in:
parent
8ea74df22b
commit
a6a8c6d8c1
28 changed files with 2731 additions and 0 deletions
5
Software/run_n_imp8_kommunikationsprotokoll/.gitignore
vendored
Normal file
5
Software/run_n_imp8_kommunikationsprotokoll/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
*.class
|
||||
*.ctxt
|
||||
*.sh
|
||||
repo.adoc
|
||||
*.~lock
|
||||
117
Software/run_n_imp8_kommunikationsprotokoll/Base64.java
Normal file
117
Software/run_n_imp8_kommunikationsprotokoll/Base64.java
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Random;
|
||||
import java.util.Arrays;
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
/**
|
||||
*
|
||||
* Hilfsklasse zur Konvertierung in Base64 von Strings
|
||||
* @author Emil Hernvall (https://gist.github.com/emilhernvall/953733)
|
||||
*/
|
||||
|
||||
public class Base64
|
||||
{
|
||||
public static String encode(String text)
|
||||
{
|
||||
byte[] data = text.getBytes();
|
||||
return encode(data);
|
||||
}
|
||||
|
||||
public static String encode(byte[] data) {
|
||||
char[] tbl = {
|
||||
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
|
||||
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
|
||||
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
|
||||
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' };
|
||||
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
int pad = 0;
|
||||
for (int i = 0; i < data.length; i += 3) {
|
||||
|
||||
int b = ((data[i] & 0xFF) << 16) & 0xFFFFFF;
|
||||
if (i + 1 < data.length) {
|
||||
b |= (data[i+1] & 0xFF) << 8;
|
||||
} else {
|
||||
pad++;
|
||||
}
|
||||
if (i + 2 < data.length) {
|
||||
b |= (data[i+2] & 0xFF);
|
||||
} else {
|
||||
pad++;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 4 - pad; j++) {
|
||||
int c = (b & 0xFC0000) >> 18;
|
||||
buffer.append(tbl[c]);
|
||||
b <<= 6;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < pad; j++) {
|
||||
buffer.append("=");
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
public static String decodeStr(String data)
|
||||
{
|
||||
return new String(decode(data));
|
||||
}
|
||||
|
||||
public static byte[] decode(String data)
|
||||
{
|
||||
int[] tbl = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
|
||||
55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2,
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30,
|
||||
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
|
||||
byte[] bytes = data.getBytes();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
for (int i = 0; i < bytes.length; ) {
|
||||
int b = 0;
|
||||
if (tbl[bytes[i]] != -1) {
|
||||
b = (tbl[bytes[i]] & 0xFF) << 18;
|
||||
}
|
||||
// skip unknown characters
|
||||
else {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int num = 0;
|
||||
if (i + 1 < bytes.length && tbl[bytes[i+1]] != -1) {
|
||||
b = b | ((tbl[bytes[i+1]] & 0xFF) << 12);
|
||||
num++;
|
||||
}
|
||||
if (i + 2 < bytes.length && tbl[bytes[i+2]] != -1) {
|
||||
b = b | ((tbl[bytes[i+2]] & 0xFF) << 6);
|
||||
num++;
|
||||
}
|
||||
if (i + 3 < bytes.length && tbl[bytes[i+3]] != -1) {
|
||||
b = b | (tbl[bytes[i+3]] & 0xFF);
|
||||
num++;
|
||||
}
|
||||
|
||||
while (num > 0) {
|
||||
int c = (b & 0xFF0000) >> 16;
|
||||
buffer.write((char)c);
|
||||
b <<= 8;
|
||||
num--;
|
||||
}
|
||||
i += 4;
|
||||
}
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import java.awt.Color;
|
||||
|
||||
/**
|
||||
*
|
||||
* Hilfsklasse für ein Buchstaben-Element (varibaler Buchstabe)
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class BuchstabeElement extends Element {
|
||||
public BuchstabeElement() {
|
||||
super();
|
||||
super.setText("A");
|
||||
}
|
||||
|
||||
|
||||
public void setText(String t) {
|
||||
super.setText("A"); // kann man nicht ändern
|
||||
}
|
||||
|
||||
|
||||
public Color getColor() {
|
||||
return Color.blue;
|
||||
}
|
||||
|
||||
public Element getCopy() {
|
||||
BuchstabeElement e = new BuchstabeElement();
|
||||
return e;
|
||||
}
|
||||
|
||||
public String getXMLIdentifier() {
|
||||
return "buchstabe";
|
||||
}
|
||||
}
|
||||
BIN
Software/run_n_imp8_kommunikationsprotokoll/ChatClient.jar
Normal file
BIN
Software/run_n_imp8_kommunikationsprotokoll/ChatClient.jar
Normal file
Binary file not shown.
555
Software/run_n_imp8_kommunikationsprotokoll/ChatClient.java
Normal file
555
Software/run_n_imp8_kommunikationsprotokoll/ChatClient.java
Normal file
|
|
@ -0,0 +1,555 @@
|
|||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import java.util.*;
|
||||
import java.io.File;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.math.BigInteger;
|
||||
import javax.swing.border.*;
|
||||
import javax.swing.text.*;
|
||||
import javax.swing.JFileChooser;
|
||||
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Chat-Programm unter Verwendung eines Protokolls
|
||||
*
|
||||
*
|
||||
* @version 1.2 vom 08.11.2019
|
||||
* 1.2: Eingabefelder verschwinden nicht mehr wegen Zeilenumbruch, UTF8 korrekt
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class ChatClient extends JFrame implements MySocketListener {
|
||||
//
|
||||
protected int HOEHE = 60; // Höhe einer Nachricht
|
||||
// Anfang Attribute
|
||||
protected JPanel jPanel1 = new JPanel(null, true);
|
||||
protected JPanel jPanel2 = new JPanel(null, true);
|
||||
protected JLabel jLabel2 = new JLabel();
|
||||
protected JTextField jTFName = new JTextField();
|
||||
protected JTextField jTFAdress = new JTextField();
|
||||
protected JLabel jLabel3 = new JLabel();
|
||||
protected JButton jBVerbinden = new JButton();
|
||||
protected JLabel jLabel1 = new JLabel();
|
||||
protected JTextField jTFNachricht = new JTextField();
|
||||
|
||||
protected MySocket client = null;
|
||||
protected JLabel jLabel5 = new JLabel();
|
||||
protected JScrollPane jScrollPane1 = new JScrollPane();
|
||||
protected JPanel jp;
|
||||
protected ArrayList<Nachricht> nachrichten;
|
||||
protected ArrayList<String> kontakte;
|
||||
protected JLabel jLabel4 = new JLabel();
|
||||
protected GridBagLayout gbl;
|
||||
protected int keyColor = 0;
|
||||
private JLabel jLabel6 = new JLabel();
|
||||
protected JScrollPane jScrollPane2 = new JScrollPane();
|
||||
private MessageChoosePanel messageChoosePanel1 = new MessageChoosePanel();
|
||||
private JComboBox<String> jCBEmpfaenger = new JComboBox<String>();
|
||||
private DefaultComboBoxModel<String> jCBEmpfaengerModel = new DefaultComboBoxModel<String>();
|
||||
private JPanel jPNachricht = new JPanel(null, true);
|
||||
private JLabel jLabel7 = new JLabel();
|
||||
private JButton jBSend = new JButton();
|
||||
private JButton jBProtokollLaden = new JButton();
|
||||
private JComboBox<String> jCBLevel = new JComboBox<String>();
|
||||
private DefaultComboBoxModel<String> jCBLevelModel = new DefaultComboBoxModel<String>();
|
||||
private JFileChooser chooser = new JFileChooser();
|
||||
|
||||
// Ende Attribute
|
||||
|
||||
public ChatClient(String title) {
|
||||
// Frame-Initialisierung
|
||||
super(title);
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
addWindowListener(new WindowListener() {
|
||||
public void windowActivated(WindowEvent e) {}
|
||||
public void windowClosed(WindowEvent e) {}
|
||||
public void windowClosing(WindowEvent e) {
|
||||
if (client != null) {
|
||||
client.sendeNachricht("exit");
|
||||
client.trenneVerbindung();
|
||||
} // end of if
|
||||
}
|
||||
public void windowDeactivated(WindowEvent e) {}
|
||||
public void windowDeiconified(WindowEvent e) {}
|
||||
public void windowIconified(WindowEvent e){}
|
||||
public void windowOpened(WindowEvent e){}
|
||||
});
|
||||
|
||||
|
||||
int frameWidth = 1081;
|
||||
int frameHeight = 683;
|
||||
setSize(frameWidth, frameHeight);
|
||||
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
int x = (d.width - getSize().width) / 2;
|
||||
int y = (d.height - getSize().height) / 2;
|
||||
setLocation(x, y);
|
||||
setResizable(false);
|
||||
Container cp = getContentPane();
|
||||
cp.setLayout(null);
|
||||
// Anfang Komponenten
|
||||
// ----------------------- Verbindung zu Server -----------------------------------
|
||||
jPanel1.setBounds(8, 8, 600, 41);
|
||||
jPanel1.setOpaque(false);
|
||||
jPanel1.setBorder(BorderFactory.createBevelBorder(1, Color.WHITE, Color.DARK_GRAY));
|
||||
cp.add(jPanel1);
|
||||
jLabel2.setBounds(244, 11, 62, 20);
|
||||
jLabel2.setText("Server");
|
||||
jPanel1.add(jLabel2);
|
||||
jTFName.setBounds(60, 11, 150, 20);
|
||||
jTFName.setText("anonymous");
|
||||
jPanel1.add(jTFName);
|
||||
jTFAdress.setBounds(292, 11, 150, 20);
|
||||
jTFAdress.setText("localhost");
|
||||
jPanel1.add(jTFAdress);
|
||||
|
||||
jLabel1.setBounds(8, 12, 62, 18);
|
||||
jLabel1.setText("Name");
|
||||
jPanel1.add(jLabel1);
|
||||
jBVerbinden.setBounds(486, 8, 99, 25);
|
||||
jBVerbinden.setText("Verbinden");
|
||||
jBVerbinden.setMargin(new Insets(2, 2, 2, 2));
|
||||
jBVerbinden.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
jBVerbinden_ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
jPanel1.add(jBVerbinden);
|
||||
// -------------------------- Protokoll ------------------------------------------------
|
||||
jPanel2.setBounds(618, 8, 430, 41);
|
||||
jPanel2.setOpaque(false);
|
||||
jPanel2.setBorder(BorderFactory.createBevelBorder(1, Color.WHITE, Color.DARK_GRAY));
|
||||
cp.add(jPanel2);
|
||||
jCBLevelModel = new DefaultComboBoxModel();
|
||||
jCBLevelModel.addElement("Standardmodus (Normal)");
|
||||
jCBLevelModel.addElement("Nachrichten können verloren gehen (Mittel)");
|
||||
jCBLevelModel.addElement("Nachrichten können Bitfehler haben (Schwer)");
|
||||
|
||||
jCBLevel.setModel(jCBLevelModel);
|
||||
jCBLevel.setBounds(10, 8, 280, 30);
|
||||
jPanel2.add(jCBLevel);
|
||||
jBProtokollLaden.setBounds(300, 8, 120, 25);
|
||||
jBProtokollLaden.setText("Protokoll laden");
|
||||
jBProtokollLaden.setMargin(new Insets(2, 2, 2, 2));
|
||||
jBProtokollLaden.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
jBProtokollLaden_ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
jPanel2.add(jBProtokollLaden);
|
||||
|
||||
|
||||
jLabel5.setBounds(8, 64, 121, 80);
|
||||
jLabel5.setText("<html>Nachrichten<br>laut Protokoll</html>");
|
||||
jLabel5.setVerticalAlignment(JLabel.TOP);
|
||||
cp.add(jLabel5);
|
||||
|
||||
jLabel4.setBounds(8, 296, 86, 20);
|
||||
jLabel4.setText("Verlauf");
|
||||
cp.add(jLabel4);
|
||||
|
||||
jLabel6.setBounds(816, 624, 229, 20);
|
||||
jLabel6.setText("(cc) 2019, Thomas Schaller, Version 1.2");
|
||||
jLabel6.setForeground(Color.GRAY);
|
||||
cp.add(jLabel6);
|
||||
messageChoosePanel1.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent evt) {
|
||||
messageChoosePanel1_MouseClicked(evt);
|
||||
}
|
||||
});
|
||||
jScrollPane2 = new JScrollPane(messageChoosePanel1);
|
||||
jScrollPane2.setBounds(144, 64, 905, 161);
|
||||
jScrollPane2.setBorder(new javax.swing.border.LineBorder(Color.DARK_GRAY, 1));
|
||||
cp.add(jScrollPane2);
|
||||
|
||||
// ------------------- Nachricht -----------------------------
|
||||
jLabel7.setBounds(8, 248, 110, 20);
|
||||
jLabel7.setText("Nachricht");
|
||||
cp.add(jLabel7);
|
||||
|
||||
JPanel rahmen = new JPanel();
|
||||
rahmen.setBounds(144,240,905,45);
|
||||
rahmen.setBorder(new javax.swing.border.LineBorder(Color.DARK_GRAY, 1));
|
||||
rahmen.setLayout(null);
|
||||
cp.add(rahmen);
|
||||
|
||||
kontakte = new ArrayList<String>();
|
||||
kontakte.add("alle");
|
||||
|
||||
jCBEmpfaengerModel = new DefaultComboBoxModel(kontakte.toArray());
|
||||
jCBEmpfaenger.setModel(jCBEmpfaengerModel);
|
||||
jCBEmpfaenger.setBounds(624, 8, 161, 30);
|
||||
rahmen.add(jCBEmpfaenger);
|
||||
jPNachricht.setBounds(10, 8, 609, 30);
|
||||
jPNachricht.setOpaque(false);
|
||||
jPNachricht.setBorder(new LineBorder(Color.BLACK, 0));
|
||||
rahmen.add(jPNachricht);
|
||||
|
||||
jBSend.setBounds(800, 8, 99, 30);
|
||||
jBSend.setText("Abschicken");
|
||||
jBSend.setMargin(new Insets(2, 2, 2, 2));
|
||||
jBSend.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
jBSend_ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
rahmen.add(jBSend);
|
||||
|
||||
jTFNachricht.setBounds(10, 20, 358, 20);
|
||||
nachrichten = new ArrayList<Nachricht>();
|
||||
|
||||
jp = new JPanel();
|
||||
jScrollPane1 = new JScrollPane(jp);
|
||||
jScrollPane1.setBounds(144, 296, 905, 321);
|
||||
jScrollPane1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
|
||||
jScrollPane1.setBorder(new javax.swing.border.LineBorder(Color.DARK_GRAY, 1));
|
||||
cp.add(jScrollPane1);
|
||||
gbl = new GridBagLayout();
|
||||
jp.setLayout(gbl);
|
||||
|
||||
this.updateNachrichtenListe();
|
||||
// Ende Komponenten
|
||||
|
||||
// File-Choose Dialog
|
||||
chooser.setCurrentDirectory(new File("."));
|
||||
FileFilter filter = new FileNameExtensionFilter("XML-Dateien", "xml");
|
||||
// Filter wird unserem JFileChooser hinzugefügt
|
||||
chooser.addChoosableFileFilter(filter);
|
||||
chooser.setAcceptAllFileFilterUsed(false);
|
||||
|
||||
|
||||
setVisible(true);
|
||||
} // end of public ChatClient
|
||||
|
||||
// Anfang Methoden
|
||||
|
||||
//-------------------------------------------------------------- XML - Protokoll -------------------------------------------------------------------------
|
||||
/** Laden eines vorher definierten Protokolls aus XML-Datei
|
||||
*/
|
||||
public void jBProtokollLaden_ActionPerformed(ActionEvent evt) {
|
||||
// Dialog zum Oeffnen von Dateien anzeigen
|
||||
int rueckgabeWert =chooser.showDialog(null, "Protokoll laden");
|
||||
/* Abfrage, ob auf "Öffnen" geklickt wurde */
|
||||
if(rueckgabeWert == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
readXMLFile( chooser.getSelectedFile().getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
/** XML-File verarbeiten => Nachrichten hinzufügen
|
||||
*/
|
||||
public void readXMLFile(String dateiname) {
|
||||
XMLDokument f = new XMLDokument(dateiname);
|
||||
if (!f.getName().equals("protokoll")) return; // ist es wirklich eine Protokolldefinition
|
||||
jLabel5.setText("<html>Nachrichten<br>laut Protokoll:<br>"+f.getAttributwert("name")+"</html>");
|
||||
boolean ok = f.stepInto();
|
||||
messageChoosePanel1.deleteAllMessages();
|
||||
while (ok) {
|
||||
if (f.getName().equals("nachricht")) { // in oberste Ebene müssen "nachrichten" Elemente stehen
|
||||
Message m = new Message();
|
||||
boolean ok2 = f.stepInto(); // eintauchen in nachrichten-Element (kann text, buchstabe und ziffer enthalten)
|
||||
while (ok2) { // gibt es weitere Unterelemente?
|
||||
if(f.getName().equals("text")) {
|
||||
TextElement t = new TextElement();
|
||||
t.setText(f.getInhalt());
|
||||
m.add(t);
|
||||
}
|
||||
if(f.getName().equals("buchstabe")) {
|
||||
m.add(new BuchstabeElement());
|
||||
}
|
||||
if(f.getName().equals("ziffer")) {
|
||||
m.add(new ZifferElement());
|
||||
}
|
||||
ok2 = f.step(); // nächstes Unterelement
|
||||
|
||||
} // end of while
|
||||
f.stepOut(); // wieder auf Nachrichtenebene zurück
|
||||
messageChoosePanel1.add(m);
|
||||
}
|
||||
ok = f.step();
|
||||
} // end of while
|
||||
|
||||
messageChoosePanel1.invalidate();
|
||||
messageChoosePanel1.repaint();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------- Client-Server Verbindung ---------------------------------------------------
|
||||
/** Methode zum Verbinden mit einem Server
|
||||
*/
|
||||
public void jBVerbinden_ActionPerformed(ActionEvent evt) {
|
||||
String a = jTFAdress.getText();
|
||||
int p = 44444;
|
||||
if (client != null && client.isAktiv()) {
|
||||
jTFName.setEnabled(true);
|
||||
jTFAdress.setEnabled(true);
|
||||
|
||||
jBVerbinden.setText("Verbinden");
|
||||
client.sendeNachricht("exit");
|
||||
client.trenneVerbindung();
|
||||
} else {
|
||||
client = new MySocket(a, p, this);
|
||||
if (client.isAktiv()) {
|
||||
jTFName.setEnabled(false);
|
||||
jTFAdress.setEnabled(false);
|
||||
jBVerbinden.setText("Trennen");
|
||||
client.sendeNachricht(("user:"+jTFName.getText()+":alle"));
|
||||
}
|
||||
} // end of if-else
|
||||
} // end of jBVerbinden_ActionPerformed
|
||||
/** Neuer Client macht nichts
|
||||
*/
|
||||
public void neuerClient(MySocket client) {
|
||||
}
|
||||
|
||||
public void nachrichtEmpfangen(MySocket client) {
|
||||
String s = client.holeNachricht();
|
||||
String[] ss = s.split(":");
|
||||
|
||||
if (ss[0].equals("user")) {
|
||||
kontakte.add(ss[1]);
|
||||
Nachricht n = new Nachricht("Server","alle","Neuer User: "+ss[1]);
|
||||
n.setSended(true);
|
||||
nachrichten.add(0,n);
|
||||
this.updateNachrichtenListe();
|
||||
DefaultComboBoxModel m = new DefaultComboBoxModel(kontakte.toArray());
|
||||
jCBEmpfaenger.setModel(m);
|
||||
}
|
||||
if(ss[0].equals("mess")) {
|
||||
Nachricht n = new Nachricht(ss[1],ss[2],Base64.decode(ss[3]));
|
||||
nachrichten.add(0,n);
|
||||
this.updateNachrichtenListe();
|
||||
|
||||
} // end of if
|
||||
}
|
||||
|
||||
public void verbindungBeendet(MySocket client) {
|
||||
jTFName.setEnabled(true);
|
||||
jTFAdress.setEnabled(true);
|
||||
jBVerbinden.setText("Verbinden");
|
||||
client = null;
|
||||
}
|
||||
|
||||
/** Aktualisiert die empfangenen Nachrichten
|
||||
*/
|
||||
public void updateNachrichtenListe() {
|
||||
|
||||
jp.setBounds(jScrollPane1.getViewport().getBounds());
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
while (jp.getComponentCount()>1) {
|
||||
jp.remove(1);
|
||||
} // end of while
|
||||
jp.removeAll();
|
||||
|
||||
|
||||
c.weightx=0;
|
||||
c.gridwidth=1;
|
||||
int xx = 0;
|
||||
JLabel name = null;
|
||||
for (Nachricht n : nachrichten) {
|
||||
|
||||
name = new JLabel();
|
||||
name.setText("<html>Von "+n.getAbsender()+"</html>");
|
||||
name.setBorder(BorderFactory.createBevelBorder(0));
|
||||
name.setBackground(new Color(250,255,200));
|
||||
name.setOpaque(true);
|
||||
c.gridx=0; c.gridy = xx;
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
jp.add(name,c);
|
||||
|
||||
JPanel nnn = new JPanel();
|
||||
nnn.setLayout(new GridBagLayout());
|
||||
nnn.setBorder(BorderFactory.createBevelBorder(0));
|
||||
nnn.setBackground(new Color(250,255,200));
|
||||
nnn.setOpaque(true);
|
||||
|
||||
|
||||
JLabel nachricht = new JLabel();
|
||||
if (n.getInhaltString().trim().length()>65) {
|
||||
nachricht.setText("<html>"+n.getInhaltString().trim().substring(0,62)+"...</html>");
|
||||
} else {
|
||||
nachricht.setText("<html>"+n.getInhaltString().trim()+"</html>");
|
||||
} // end of if-else
|
||||
|
||||
c.gridx=0; c.gridy = 0;
|
||||
c.weightx=1.0; c.weighty= 0;
|
||||
|
||||
nnn.add(nachricht,c);
|
||||
|
||||
c.gridx=1; c.gridy = xx;
|
||||
c.weightx = 1.0;
|
||||
jp.add(nnn,c);
|
||||
|
||||
JPanel abspanel = new JPanel();
|
||||
abspanel.setPreferredSize(new Dimension(150,HOEHE));
|
||||
abspanel.setBorder(BorderFactory.createBevelBorder(0));
|
||||
abspanel.setBackground(new Color(250,255,200));
|
||||
abspanel.setOpaque(true);
|
||||
abspanel.setLayout(new FlowLayout());
|
||||
abspanel.add(new JLabel("an "+n.getEmpfaenger()));
|
||||
|
||||
c.gridx=2; c.gridy = xx;
|
||||
c.weightx = 0.0;
|
||||
jp.add(abspanel,c);
|
||||
xx++;
|
||||
}
|
||||
JPanel dummy = new JPanel();
|
||||
dummy.setBorder(BorderFactory.createBevelBorder(0));
|
||||
dummy.setLayout(null);
|
||||
dummy.setBackground(new Color(250,255,200));
|
||||
dummy.setOpaque(true);
|
||||
dummy.setPreferredSize(new Dimension(150,HOEHE));
|
||||
|
||||
c.gridx=0; c.gridy = xx;
|
||||
c.gridwidth=4;
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.weightx = 1.0;
|
||||
c.weighty = 1.0;
|
||||
jp.add(dummy,c);
|
||||
|
||||
jp.revalidate();
|
||||
jp.repaint();
|
||||
}
|
||||
|
||||
/** Nachricht in Nachrichtenvorrat ausgewählt, im Sendenfenster wird eine Nachricht vorbereitet (incl. Eingabefelder)
|
||||
*/
|
||||
public void messageChoosePanel1_MouseClicked(MouseEvent evt) {
|
||||
Message m = messageChoosePanel1.getElement(evt);
|
||||
if (m==null) {
|
||||
// System.out.println("nicht getroffen");
|
||||
} else {
|
||||
jPNachricht.setLayout(new BoxLayout(jPNachricht, BoxLayout.LINE_AXIS));
|
||||
JLabel l = new JLabel();
|
||||
l.setText("");
|
||||
l.setBounds(10,2,2,20);
|
||||
l.setOpaque(true);
|
||||
jPNachricht.add(l);
|
||||
|
||||
JPanel ml = new JPanel();
|
||||
|
||||
Font fo = new Font("SansSerif", Font.BOLD, 12);
|
||||
ml.setBackground(new Color(50,200,50));
|
||||
ml.setBorder(new TextBubbleBorder(ml.getBackground(),2,6,0));
|
||||
ml.setOpaque(true);
|
||||
|
||||
FlowLayout flow = new FlowLayout();
|
||||
flow.setHgap(3);
|
||||
flow.setVgap(2);
|
||||
flow.setAlignment(FlowLayout.LEFT );
|
||||
ml.setLayout(flow);
|
||||
int breite = 10;
|
||||
for (int i=0;i<m.size() ; i++ ) {
|
||||
Element e = m.get(i);
|
||||
JComponent c = new JLabel();
|
||||
if (e instanceof TextElement) {
|
||||
c = new JLabel();
|
||||
((JLabel) c).setText(((TextElement) e).getText());
|
||||
c.setOpaque(true);
|
||||
c.setBackground(e.getColor());
|
||||
c.setForeground(Color.white);
|
||||
c.setBorder(new TextBubbleBorder(e.getColor(), 3, 3, 0));
|
||||
} // end of if
|
||||
if (e instanceof BuchstabeElement) {
|
||||
c = new JTextField();
|
||||
((JTextField) c).setHorizontalAlignment(SwingConstants.CENTER);
|
||||
((JTextField) c).setDocument(new MyTextFieldDocument(2));
|
||||
((JTextField) c).setText("");
|
||||
c.setPreferredSize(new Dimension(22,22));
|
||||
c.setBorder(new TextBubbleBorder(e.getColor(), 3, 3, 0));
|
||||
} // end of if
|
||||
if (e instanceof ZifferElement) {
|
||||
c = new JNumberField();
|
||||
((JNumberField) c).setDocument(new MyTextFieldDocument(2));
|
||||
((JNumberField) c).setText("0");
|
||||
((JNumberField) c).setHorizontalAlignment(SwingConstants.CENTER);
|
||||
c.setPreferredSize(new Dimension(22,22));
|
||||
c.setBorder(new TextBubbleBorder(e.getColor(), 3, 3, 0));
|
||||
} // end of if
|
||||
|
||||
c.setFont(fo);
|
||||
ml.add(c);
|
||||
breite += c.getPreferredSize().getWidth()+7;
|
||||
|
||||
}
|
||||
|
||||
JLabel filler = new JLabel();
|
||||
filler.setPreferredSize(new Dimension(5,10));
|
||||
ml.add(filler);
|
||||
ml.setPreferredSize(new Dimension(breite,10));
|
||||
|
||||
// end of for
|
||||
jPNachricht.removeAll();
|
||||
jPNachricht.add(ml);
|
||||
Dimension minSize = new Dimension(0, 5);
|
||||
Dimension prefSize = new Dimension(500, 5);
|
||||
Dimension maxSize = new Dimension(500, 5);
|
||||
jPNachricht.add(new Box.Filler(minSize, prefSize, maxSize));
|
||||
jPNachricht.revalidate();
|
||||
jPNachricht.repaint();
|
||||
|
||||
}
|
||||
} // end of messageChoosePanel1_MouseClicked
|
||||
|
||||
public void jBSend_ActionPerformed(ActionEvent evt) {
|
||||
if (client != null && client.isAktiv()) {
|
||||
int level = jCBLevel.getSelectedIndex();
|
||||
Random r = new Random();
|
||||
JPanel nn = (JPanel) jPNachricht.getComponent(0);
|
||||
String text = "";
|
||||
String text_uebertragen = "";
|
||||
|
||||
for (Component c : nn.getComponents() ) {
|
||||
if (c instanceof JLabel) {
|
||||
text+= ((JLabel) c).getText();
|
||||
} // end of if
|
||||
if (c instanceof JTextField) {
|
||||
text+= ((JTextField) c).getText();
|
||||
} // end of if
|
||||
text += " ";
|
||||
} // end of for
|
||||
if (level ==2 && r.nextDouble()>0.6) { // Übertragungsfehler einbauen
|
||||
int pos = r.nextInt(text.length());
|
||||
char c = text.charAt(pos);
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
c = (char) (r.nextInt(26)+65);
|
||||
}
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
c = (char) (r.nextInt(26)+97);
|
||||
}
|
||||
if (c >= '0' && c <= '9') {
|
||||
c = (char) (r.nextInt(10)+48);
|
||||
}
|
||||
// end of if-else
|
||||
text_uebertragen = text.substring(0,pos)+ c+text.substring(pos+1);
|
||||
} else {
|
||||
text_uebertragen = text;
|
||||
} // end of if-else
|
||||
|
||||
Nachricht n = new Nachricht(jTFName.getText(), (String) jCBEmpfaenger.getSelectedItem(), text);
|
||||
Nachricht n2 = new Nachricht(jTFName.getText(), (String) jCBEmpfaenger.getSelectedItem(), text_uebertragen);
|
||||
String b = "mess:"+n2.getAbsender()+":"+n2.getEmpfaenger()+":"+Base64.encode(n2.getInhalt());
|
||||
|
||||
if (level < 1 || r.nextDouble() < 0.75) { // Nachricht kann verloren gehen bei Level 2
|
||||
client.sendeNachricht(b);
|
||||
}
|
||||
nachrichten.add(0,n);
|
||||
|
||||
this.updateNachrichtenListe();
|
||||
} else {
|
||||
jTFName.setEnabled(true);
|
||||
jTFAdress.setEnabled(true);
|
||||
jBVerbinden.setEnabled(true);
|
||||
} // end of if
|
||||
} // end of jBSend_ActionPerformed
|
||||
|
||||
// Ende Methoden
|
||||
|
||||
public static void main(String[] args) {
|
||||
new ChatClient("ChatClient");
|
||||
} // end of main
|
||||
|
||||
} // end of class ChatClient
|
||||
BIN
Software/run_n_imp8_kommunikationsprotokoll/ChatServerGUI.jar
Normal file
BIN
Software/run_n_imp8_kommunikationsprotokoll/ChatServerGUI.jar
Normal file
Binary file not shown.
252
Software/run_n_imp8_kommunikationsprotokoll/ChatServerGUI.java
Normal file
252
Software/run_n_imp8_kommunikationsprotokoll/ChatServerGUI.java
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import java.util.ArrayList;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
*
|
||||
* Chat-Server-Programm: Die Nachrichten werden einfach an alle Teilnehmer weitergegeben
|
||||
*
|
||||
*
|
||||
* @version 1.2 vom 08.11.2019
|
||||
* 1.2: IP-Adresse wird angezeigt
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class ChatServerGUI extends JFrame implements MyServerSocketListener {
|
||||
// Anfang Attribute
|
||||
private ArrayList<MySocket> clients;
|
||||
private ArrayList<String> names;
|
||||
private static boolean ende;
|
||||
private MyServer server;
|
||||
private JLabel jLabel1 = new JLabel();
|
||||
private JButton jBStarten = new JButton();
|
||||
private JTextField jTFIP = new JTextField();
|
||||
private JList jList1 = new JList();
|
||||
private DefaultListModel jList1Model = new DefaultListModel();
|
||||
private JScrollPane jList1ScrollPane = new JScrollPane(jList1);
|
||||
private JLabel jLabel2 = new JLabel();
|
||||
private int changeClientListAktiv = 0;
|
||||
private JLabel jLabel3 = new JLabel();
|
||||
// Ende Attribute
|
||||
|
||||
public ChatServerGUI() {
|
||||
// Frame-Initialisierung
|
||||
super();
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
int frameWidth = 300;
|
||||
int frameHeight = 311;
|
||||
setSize(frameWidth, frameHeight);
|
||||
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
int x = (d.width - getSize().width) / 2;
|
||||
int y = (d.height - getSize().height) / 2;
|
||||
setLocation(x, y);
|
||||
setTitle("Chat-Server");
|
||||
setResizable(false);
|
||||
Container cp = getContentPane();
|
||||
cp.setLayout(null);
|
||||
// Anfang Komponenten
|
||||
|
||||
jLabel1.setBounds(8, 16, 110, 20);
|
||||
jLabel1.setText("Server-Adresse");
|
||||
cp.add(jLabel1);
|
||||
jTFIP.setBounds(110, 16, 165, 20);
|
||||
try {
|
||||
jTFIP.setText(""+InetAddress.getLocalHost());
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
}
|
||||
jTFIP.setEditable(false);
|
||||
cp.add(jTFIP);
|
||||
jBStarten.setBounds(96, 208, 75, 25);
|
||||
jBStarten.setText("Starten");
|
||||
jBStarten.setMargin(new Insets(2, 2, 2, 2));
|
||||
jBStarten.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
jBStarten_ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
cp.add(jBStarten);
|
||||
|
||||
jList1.setModel(jList1Model);
|
||||
jList1ScrollPane.setBounds(8, 62, 270, 137);
|
||||
cp.add(jList1ScrollPane);
|
||||
jLabel2.setBounds(8, 38, 110, 20);
|
||||
jLabel2.setText("Chatteilnehmer");
|
||||
cp.add(jLabel2);
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent evt) {
|
||||
ChatServerGUI_WindowClosing(evt);
|
||||
}
|
||||
});
|
||||
jLabel3.setBounds(24, 248, 229, 20);
|
||||
jLabel3.setText("(cc) 2019, Thomas Schaller, Version 1.2");
|
||||
jLabel3.setForeground(Color.GRAY);
|
||||
cp.add(jLabel3);
|
||||
// Ende Komponenten
|
||||
|
||||
setVisible(true);
|
||||
|
||||
clients = new ArrayList<MySocket>();
|
||||
names = new ArrayList<String>();
|
||||
server = null;
|
||||
|
||||
} // end of public ChatServerGUI
|
||||
|
||||
|
||||
|
||||
// Anfang Methoden
|
||||
|
||||
public void neuerClient(MySocket client) {
|
||||
for (String n : names) {
|
||||
if (!n.equals("ManInTheMiddle")) {
|
||||
client.sendeNachricht("user:"+n);
|
||||
} // end of if
|
||||
} // end of for
|
||||
this.clients.add(client);
|
||||
// System.out.println("Habe Kontakt mit "+client.getSocket().getInetAddress()+" Port "+client.getSocket().getPort());
|
||||
this.names.add("?");
|
||||
// changeClientList();
|
||||
}
|
||||
|
||||
public void changeClientList() {
|
||||
changeClientListAktiv++;
|
||||
if (changeClientListAktiv == 1) {
|
||||
do{
|
||||
changeClientListAktiv--;
|
||||
DefaultListModel newListModel = new DefaultListModel();
|
||||
System.out.println("lm: "+jList1Model.size());
|
||||
System.out.println("Clients: "+clients.size());
|
||||
for (int i = 0; i < clients.size() ; i++ ) {
|
||||
MySocket s = clients.get(i);
|
||||
String n = names.get(i);
|
||||
newListModel.addElement(n+"("+s.getSocket().getInetAddress()+":"+s.getSocket().getPort()+")");
|
||||
System.out.println(n+"("+s.getSocket().getInetAddress()+":"+s.getSocket().getPort()+")");
|
||||
System.out.println("lm: "+jList1Model.size());
|
||||
} // end of for
|
||||
jList1.setModel(newListModel);
|
||||
jList1.validate();
|
||||
}
|
||||
while (changeClientListAktiv > 0 );
|
||||
} // end of if
|
||||
}
|
||||
|
||||
public void nachrichtEmpfangen(MySocket client) {
|
||||
String s = client.holeNachricht();
|
||||
System.out.println("Habe Nachricht empfangen:"+s);
|
||||
String[] ss = s.split(":");
|
||||
int i = clients.indexOf(client);
|
||||
|
||||
if (ss[0].equals("exit")) {
|
||||
s = s+names.get(i);
|
||||
clients.remove(i);
|
||||
names.remove(i);
|
||||
client.trenneVerbindung();
|
||||
for (int j=0; j<clients.size(); j++) {
|
||||
MySocket c = clients.get(j);
|
||||
if (c!=client) {
|
||||
c.sendeNachricht(s);
|
||||
} // end of if
|
||||
}
|
||||
changeClientList();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ss[0].equals("user")) {
|
||||
names.set(i,ss[1]);
|
||||
for (int j=0; j<clients.size(); j++) {
|
||||
MySocket c = clients.get(j);
|
||||
if (c!=client) {
|
||||
c.sendeNachricht(s);
|
||||
} // end of if
|
||||
}
|
||||
changeClientList();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (ss[0].equals("mitm")) {
|
||||
names.set(i,"ManInTheMiddle");
|
||||
changeClientList();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ss[0].equals("mess")) {
|
||||
int nextMitM=-1;
|
||||
int start=0;
|
||||
if (names.get(i).equals("ManInTheMiddle")) {
|
||||
start = i+1;
|
||||
}
|
||||
|
||||
for (int j=start;j<clients.size() ;j++ ) {
|
||||
if (names.get(j).equals("ManInTheMiddle")) {
|
||||
nextMitM = j;
|
||||
break;
|
||||
|
||||
} // end of if
|
||||
} // end of for
|
||||
if (nextMitM!=-1) {
|
||||
MySocket c = clients.get(nextMitM);
|
||||
c.sendeNachricht(s);
|
||||
} else {
|
||||
for (int j=0; j<clients.size(); j++) {
|
||||
MySocket c = clients.get(j);
|
||||
if (!ss[1].equals(names.get(j)) && (ss[2].equals("alle") || ss[2].equals(names.get(j))) && !names.get(j).equals("ManInTheMiddle")) {
|
||||
c.sendeNachricht(s);
|
||||
} // end of if
|
||||
}
|
||||
} // end of if-else
|
||||
|
||||
} // end of if
|
||||
} // end of if
|
||||
|
||||
|
||||
|
||||
|
||||
public void verbindungBeendet(MySocket client) {
|
||||
if (clients.contains(client)) {
|
||||
|
||||
int i = clients.indexOf(client);
|
||||
|
||||
clients.remove(i);
|
||||
System.out.println("Verbindung mit "+client.getSocket().getInetAddress()+" Port: "+client.getSocket().getPort()+" verloren.");
|
||||
for (MySocket c: clients) {
|
||||
if (c!=client) {
|
||||
c.sendeNachricht(("exit:"+names.get(i)+":alle"));
|
||||
} // end of if
|
||||
}
|
||||
names.remove(i);
|
||||
changeClientList();
|
||||
} // end of if
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
new ChatServerGUI();
|
||||
} // end of main
|
||||
|
||||
public void jBStarten_ActionPerformed(ActionEvent evt) {
|
||||
if (jBStarten.getText().equals("Starten")) {
|
||||
server = new MyServer(this, 44444);
|
||||
server.starten();
|
||||
jBStarten.setText("Stoppen");
|
||||
|
||||
} else {
|
||||
server.stoppen();
|
||||
server = null;
|
||||
jBStarten.setText("Starten");
|
||||
} // end of if-else
|
||||
} // end of jBStarten_ActionPerformed
|
||||
|
||||
public void ChatServerGUI_WindowClosing(WindowEvent evt) {
|
||||
if (server != null) server.stoppen();
|
||||
} // end of ChatServerGUI_WindowClosing
|
||||
|
||||
// Ende Methoden
|
||||
} // end of class ChatServerGUI
|
||||
54
Software/run_n_imp8_kommunikationsprotokoll/Element.java
Normal file
54
Software/run_n_imp8_kommunikationsprotokoll/Element.java
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import java.awt.Color;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Oberklasse für alle Elemente einer Nachricht
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public abstract class Element {
|
||||
private String text="";
|
||||
|
||||
public void setText(String t) {
|
||||
text = t.toUpperCase();
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public abstract Color getColor();
|
||||
|
||||
public void paint(Graphics g, int x, int y, Font fo) {
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
int w = g.getFontMetrics(fo).stringWidth(getText());
|
||||
g2.setColor(getColor().darker());
|
||||
g2.fillRoundRect(x+1,y+2,w+12,20,8,10);
|
||||
g2.setColor(getColor());
|
||||
g2.fillRoundRect(x,y,w+12,20,8,10);
|
||||
g2.setColor(Color.white);
|
||||
g2.setFont(fo);
|
||||
g2.drawString(getText(),x+6,y+15);
|
||||
}
|
||||
|
||||
public int getWidth(Graphics g, Font fo) {
|
||||
return g.getFontMetrics(fo).stringWidth(getText());
|
||||
}
|
||||
|
||||
public int getHeight(Graphics g, Font fo) {
|
||||
return g.getFontMetrics(fo).getHeight();
|
||||
}
|
||||
|
||||
public abstract Element getCopy();
|
||||
|
||||
public abstract String getXMLIdentifier();
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Hilfsklasse die Anzeige eines Nachrichten-Elements für den Vorrat aus dem man auswählen kann.
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class ElementPanel extends JPanel {
|
||||
private Element e;
|
||||
private Font fo;
|
||||
|
||||
public ElementPanel(Element e) {
|
||||
this.fo = new Font("SansSerif", Font.BOLD, 12);
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
|
||||
public void paint(Graphics g) {
|
||||
e.paint(g, 0, 0, fo);
|
||||
}
|
||||
|
||||
public Element getElement() {
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
BIN
Software/run_n_imp8_kommunikationsprotokoll/JEClasses.jar
Normal file
BIN
Software/run_n_imp8_kommunikationsprotokoll/JEClasses.jar
Normal file
Binary file not shown.
69
Software/run_n_imp8_kommunikationsprotokoll/Message.java
Normal file
69
Software/run_n_imp8_kommunikationsprotokoll/Message.java
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import java.util.ArrayList;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Eine Nachricht aus mehereren Elementen
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class Message {
|
||||
private ArrayList<Element> elemente = new ArrayList<Element>();
|
||||
public void add(Element e) {
|
||||
elemente.add(e);
|
||||
}
|
||||
|
||||
public void delete(int i) {
|
||||
elemente.remove(i);
|
||||
}
|
||||
|
||||
public void delete(Element e) {
|
||||
elemente.remove(e);
|
||||
}
|
||||
|
||||
public Element get(int i) {
|
||||
return elemente.get(i);
|
||||
|
||||
}
|
||||
|
||||
public void addBefore(Element e, Element e2) {
|
||||
elemente.add(elemente.indexOf(e2),e);
|
||||
}
|
||||
|
||||
|
||||
public int size() {
|
||||
return elemente.size();
|
||||
}
|
||||
|
||||
public void paint(Graphics g, int x, int y, Font fo) {
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
int p = x;
|
||||
for (Element e: elemente) {
|
||||
e.paint(g, p, y, fo);
|
||||
p+=e.getWidth(g, fo)+15;
|
||||
} // end of for
|
||||
|
||||
}
|
||||
|
||||
public int getWidth(Graphics g, Font fo) {
|
||||
int b = -8;
|
||||
for (Element e: elemente) {
|
||||
b += e.getWidth(g, fo)+15;
|
||||
} // end of for
|
||||
return b;
|
||||
|
||||
}
|
||||
|
||||
public int getHeight(Graphics g, Font fo) {
|
||||
return g.getFontMetrics(fo).getHeight()+12;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* Panel zur Anzeige mehrerer Nachrichten.
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class MessageChoosePanel extends JPanel {
|
||||
private Color f;
|
||||
private Font fo;
|
||||
private ArrayList<Message> ml;
|
||||
|
||||
public MessageChoosePanel() {
|
||||
this.f = new Color(50,200,50);
|
||||
this.fo = new Font("SansSerif", Font.BOLD, 12);
|
||||
this.ml = new ArrayList<Message>();
|
||||
|
||||
}
|
||||
|
||||
public void add(Message nm) {
|
||||
ml.add(nm);
|
||||
setPreferredSize(new Dimension(500, ml.size()*40));
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void deleteAllMessages() {
|
||||
ml.clear();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
int y = 5;
|
||||
for (Message m: ml) {
|
||||
|
||||
int b = m.getWidth(g, fo);
|
||||
g2.setColor(f.darker());
|
||||
g2.fillRoundRect(12,y+2,b+12,30,8,10);
|
||||
g2.setColor(f);
|
||||
g2.fillRoundRect(10,y,b+12,30,8,10);
|
||||
m.paint(g, 14, y+4, fo);
|
||||
y += m.getHeight(g, fo)+7;
|
||||
} // end of for
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Nachricht bestimmen, die an bestimmter Position angezeigt wird.
|
||||
public Message getElement(MouseEvent evt) {
|
||||
if (evt.getY() / 35 >= ml.size()) {
|
||||
return null;
|
||||
} // end of if
|
||||
return ml.get(evt.getY() / 35);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Panel zur Anzeige einer einzigen Nachricht
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class MessagePanel extends JPanel {
|
||||
private Color f;
|
||||
private Font fo;
|
||||
private Message m;
|
||||
|
||||
|
||||
public MessagePanel( Message m) {
|
||||
this.f = new Color(50,200,50);
|
||||
this.fo = new Font("SansSerif", Font.BOLD, 12);
|
||||
this.m = m;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
int b = m.getWidth(g, fo);
|
||||
if (b < 50) b = 50;
|
||||
g2.setColor(f.darker());
|
||||
g2.fillRoundRect(2,2,b+12,30,8,10);
|
||||
g2.setColor(f);
|
||||
g2.fillRoundRect(0,0,b+12,30,8,10);
|
||||
m.paint(g, 4, 4, fo);
|
||||
}
|
||||
|
||||
// Bestimmt das Element einer Nachricht an einer bestimmten Position
|
||||
public Element getElement(Point evt) {
|
||||
if (evt.getY()>4 && evt.getY()<26) {
|
||||
int p=1;
|
||||
for (int i=0; i<m.size() ;i++ ) {
|
||||
int w = getFontMetrics(fo).stringWidth(m.get(i).getText())+12;
|
||||
|
||||
if (evt.getX()>=p && evt.getX() < p+w+3) {
|
||||
return m.get(i);
|
||||
} // end of if
|
||||
p += w+3;
|
||||
} // end of for
|
||||
} // end of if
|
||||
return null;
|
||||
}
|
||||
|
||||
public Message getMessage() {
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Kontextmenü, wenn auf einzelnes Element geklickt wurde
|
||||
*
|
||||
*
|
||||
* @version 1.1 vom 14.06.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class MessagePopup extends JPopupMenu implements ActionListener {
|
||||
|
||||
|
||||
private Element e;
|
||||
private Message m;
|
||||
private JMenuItem dmi1, dmi2, dmi3;
|
||||
private JPanel p;
|
||||
private ProtokollErstellen parent;
|
||||
|
||||
public MessagePopup( MouseEvent event, Message m, Element e, JPanel p, ProtokollErstellen parent){
|
||||
this.e = e;
|
||||
this.m = m;
|
||||
this.p = p;
|
||||
this.parent = parent;
|
||||
dmi2 = new JMenuItem("Text bearbeiten");
|
||||
dmi2.addActionListener(this);
|
||||
add(dmi2);
|
||||
dmi1 = new JMenuItem("Element löschen");
|
||||
dmi1.addActionListener(this);
|
||||
add(dmi1);
|
||||
dmi3 = new JMenuItem("Nachricht löschen");
|
||||
dmi3.addActionListener(this);
|
||||
add(dmi3);
|
||||
show(event.getComponent(), event.getX(), event.getY());
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
|
||||
|
||||
if (ae.getSource() == dmi1) {
|
||||
m.delete(e);
|
||||
p.repaint();
|
||||
}
|
||||
if (ae.getSource() == dmi2 && !(e instanceof ZifferElement)) {
|
||||
String eingabe = (String)JOptionPane.showInputDialog(null, "Bitte gib den Text ein",
|
||||
"Textbaustein", JOptionPane.QUESTION_MESSAGE,null,null,e.getText());
|
||||
|
||||
if (eingabe != null) e.setText(eingabe);
|
||||
p.repaint();
|
||||
}
|
||||
if (ae.getSource() == dmi3) {
|
||||
parent.delete(p);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
98
Software/run_n_imp8_kommunikationsprotokoll/MyServer.java
Normal file
98
Software/run_n_imp8_kommunikationsprotokoll/MyServer.java
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Scanner;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Die Klasse MyServer verwaltet einen ServerSocket. Sie erstellt einen ServerSocket an einem
|
||||
* bestimmten Port und wartet dort auf Clients. Es können mehrere Clients gleichzeitig angemeldet sein.
|
||||
* Eine Klasse, die diesen Server benutzt, muss MyServerSocketListener implementieren. Sie wird dann
|
||||
* über die Methode neuerClient informiert, wenn sich ein neuer Client am Server angemeldet hat.
|
||||
* Beschreibung
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 15.11.2012
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class MyServer extends Thread {
|
||||
|
||||
// Anfang Attribute
|
||||
private ServerSocket ss;
|
||||
private int port;
|
||||
private boolean aktiv = true;
|
||||
private MyServerSocketListener listener;
|
||||
// Ende Attribute
|
||||
|
||||
/** Dieser Konstruktor erzeugt einen neuen ServerSocket, startet ihn aber nicht sofort.
|
||||
* @param listener Klasse, die MyServerSocketListener implementiert und dann über neue Clients und eingehende Nachrichten informiert wird.
|
||||
* @param port Port, den der ServerSocket abhört.
|
||||
*/
|
||||
|
||||
public MyServer(MyServerSocketListener listener, int port) {
|
||||
this.port = port;
|
||||
this.listener = listener;
|
||||
try {
|
||||
ss = new ServerSocket(port);
|
||||
} catch(Exception e) {
|
||||
System.out.println(e);
|
||||
} // end of try
|
||||
}
|
||||
|
||||
// Anfang Methoden
|
||||
/** Liefert den Port, den der Server abhört.
|
||||
* @return Port
|
||||
*/
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
/** Startet das Abhören des Ports und das Annehmen der Clients
|
||||
*/
|
||||
public void starten() {
|
||||
start();
|
||||
}
|
||||
|
||||
/** Verwaltet das Annehmen der Clients (Diese Methode bitte nicht direkt aufrufen, sondern mit starten() aktivieren).
|
||||
*/
|
||||
public void run() {
|
||||
aktiv = true;
|
||||
try {
|
||||
while(aktiv) {
|
||||
System.out.println("Warte auf Client");
|
||||
Socket s = ss.accept();
|
||||
System.out.println("Client empfangen");
|
||||
MySocket ms = new MySocket(s, listener);
|
||||
listener.neuerClient(ms);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
System.out.println(e);
|
||||
} // end of try
|
||||
|
||||
|
||||
}
|
||||
|
||||
/** Bricht das Abhören des Ports ab. Es kann nicht wieder durch starten aktiviert werden. Dazu muss ein neuer Server erstellt werden.
|
||||
*/
|
||||
public void stoppen() {
|
||||
aktiv = false;
|
||||
try{
|
||||
ss.close();
|
||||
interrupt();
|
||||
} catch( Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Meldet, ob der Server aktiv ist.
|
||||
* @return true, falls der Server den Port abhört, sonst false.
|
||||
*/
|
||||
public boolean getAktiv() {
|
||||
return aktiv;
|
||||
}
|
||||
|
||||
// Ende Methoden
|
||||
} // end of Server
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* Listenerdefinitionen für MyServer und MySocket.
|
||||
* Klassen, die mit diesen beiden Klassen arbeiten müssen diese Listener implementieren.
|
||||
*
|
||||
* @version 1.0 vom 15.11.2012
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
|
||||
interface MyServerSocketListener extends MySocketListener {
|
||||
void neuerClient(MySocket s); // ein neuer Client hat sich mit dem Server verbunden.
|
||||
}
|
||||
196
Software/run_n_imp8_kommunikationsprotokoll/MySocket.java
Normal file
196
Software/run_n_imp8_kommunikationsprotokoll/MySocket.java
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Scanner;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Die Klasse MySocket verwaltet eine Client-Server-Verbindung. Sie wartet auf eingehende Nachrichten und
|
||||
* informiert ihren Listener, wenn eine Nachricht eingangen ist. Die Nachricht kann dann beim Socket abgeholt werden.
|
||||
* Außerdem können Nachrichten in Form von Strings versendet werden.
|
||||
* Der Listener wird außerdem informiert, wenn die Verbindung zusammengebrochen / beendet ist.
|
||||
* Der Listener muss das Interface MySocketListener implementieren.
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 15.11.2012
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class MySocket extends Thread{
|
||||
|
||||
// Anfang Attribute2
|
||||
private boolean aktiv;
|
||||
private Socket socket;
|
||||
private BufferedReader eingang=null;
|
||||
PrintWriter ausgang=null;
|
||||
MySocketListener listener=null;
|
||||
|
||||
// Ende Attribute2
|
||||
|
||||
/** Dieser Konstruktor erstellt einen MySocket aus einem schon vorhandenen Socket und ist für die Verwendung durch MyServer gedacht.
|
||||
* @param s Socket, der durch MySocket verwaltet werden soll.
|
||||
* @param listener Listener, der über eingehende Nachrichten und das Beenden der Verbindung informiert wird. Der Listener muss MySocketListener implementieren.
|
||||
*/
|
||||
public MySocket(Socket s, MySocketListener listener){
|
||||
this.socket = s;
|
||||
this.listener = listener;
|
||||
try {
|
||||
eingang = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
ausgang = new PrintWriter(socket.getOutputStream());
|
||||
aktiv = true;
|
||||
this.start();
|
||||
} catch(Exception e) {;
|
||||
System.out.println(e);
|
||||
e.printStackTrace();
|
||||
aktiv = false;
|
||||
} // end of try
|
||||
}
|
||||
|
||||
/** Dieser Konstruktor erstellt einen neuen Socket. Er verbindet sich mit einem Server an der angegebenen Adresse unter dem angegebenen Port. Der Listener wird
|
||||
* über eingehende Nachrichten und das Beenden der Verbindung informiert.
|
||||
* @param address IP-Adresse oder Domain-Name des Servers
|
||||
* @param port Portnummer, die der Server abhört
|
||||
* @param listener Listener, der über eingehende Nachrichten und das Beenden der Verbindung informiert wird. Der Listener muss MySocketListener implementieren.
|
||||
*/
|
||||
public MySocket(String address, int port, MySocketListener listener) {
|
||||
this.listener = listener;
|
||||
try {
|
||||
this.socket = new Socket(address, port);
|
||||
eingang = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
ausgang = new PrintWriter(socket.getOutputStream());
|
||||
aktiv = true;
|
||||
this.start();
|
||||
} catch(Exception e) {
|
||||
System.out.println(e);
|
||||
e.printStackTrace();
|
||||
aktiv = false;
|
||||
} // end of try
|
||||
}
|
||||
|
||||
// Anfang Methoden2
|
||||
/** Verwaltet das Annehmen der Nachrichten (Diese Methode bitte nicht direkt aufrufen, sie wird automatisch gestartet).
|
||||
*/
|
||||
public void run(){
|
||||
try {
|
||||
while (aktiv){
|
||||
if (listener != null && eingang.ready()) listener.nachrichtEmpfangen(this);
|
||||
Thread.sleep(5);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
if(socket!=null)try{socket.close();}catch(Exception ex){;}
|
||||
System.err.println(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
aktiv = false;
|
||||
if (listener != null) listener.verbindungBeendet(this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Liefert die eingangene Nachricht. Diese Methode bitte nur aufrufen, wenn der Listener über den Eingang einer Nachricht informiert wurde, da die Methode sonst bis
|
||||
* zur nächsten eingehenden Nachricht wartet.
|
||||
* @return Nachricht
|
||||
*/
|
||||
public String holeNachricht() {
|
||||
try{
|
||||
|
||||
|
||||
if (aktiv && eingang.ready()) {
|
||||
|
||||
String s = eingang.readLine();
|
||||
System.out.println(s);
|
||||
byte[] b = Base64.decode(s);
|
||||
/* for (int i = 0; i < b.length ; i++) {
|
||||
System.out.print(b[i]);
|
||||
System.out.print(" ");
|
||||
} // end of for
|
||||
System.out.println("");*/
|
||||
|
||||
return s;
|
||||
} // end of if
|
||||
}
|
||||
catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Versendet eine Nachricht an den Server.
|
||||
* @param nachricht Zu sendender Text.
|
||||
*/
|
||||
public void sendeNachricht(String nachricht) {
|
||||
try {
|
||||
//byte[] b = nachricht;
|
||||
/* for (int i = 0; i < b.length ; i++) {
|
||||
System.out.print(b[i]);
|
||||
System.out.print(" ");
|
||||
} // end of for
|
||||
System.out.println("");*/
|
||||
//ausgang.println(Base64.encode(nachricht));
|
||||
ausgang.println(nachricht);
|
||||
// System.out.println(Base64.encode(nachricht));
|
||||
ausgang.flush();
|
||||
} catch(Exception e) {
|
||||
System.out.println(e);
|
||||
e.printStackTrace();
|
||||
if (listener != null) listener.verbindungBeendet(this);
|
||||
aktiv = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Bricht eine bestehende Client-Server-Verbindung ab.
|
||||
*/
|
||||
|
||||
public void trenneVerbindung() {
|
||||
aktiv = false;
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch(Exception e) {
|
||||
System.out.println(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} // end of if
|
||||
socket = null; // end of try
|
||||
}
|
||||
|
||||
/** Liefert den Socket der Verbindung. Kann benutzt werden, um dann aus dem Socket weitere Informationen wie IP-Adressen oder Portnummern zu ermitteln.
|
||||
* @return Socket, der Verbindung.
|
||||
*/
|
||||
public Socket getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
/** Liefert den Status der Verbindung.
|
||||
* @return true, falls die Verbindung noch aktiv ist, sonst false.
|
||||
*/
|
||||
public boolean isAktiv() {
|
||||
return aktiv;
|
||||
}
|
||||
|
||||
/** Räumt alles auf, damit der Thread nicht weiterläuft (bitte nicht aufrufen).
|
||||
*/
|
||||
public void finalize() {
|
||||
// Schließen der Streams und des Sockets, wenn
|
||||
// die Verbindung gelöscht wird wird
|
||||
try {
|
||||
trenneVerbindung();
|
||||
}
|
||||
catch(Exception e) {
|
||||
System.out.println(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// Ende Methoden2
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* Listenerdefinitionen für MyServer und MySocket.
|
||||
* Klassen, die mit diesen beiden Klassen arbeiten müssen diese Listener implementieren.
|
||||
*
|
||||
* @version 1.0 vom 15.11.2012
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
interface MySocketListener { // Der Listener wird über folgendes informiert...
|
||||
void nachrichtEmpfangen(MySocket s); // am Socket ist eine Nachricht eingegangen. Diese kann dann mit s.holeNachricht() abgeholt werden.
|
||||
void verbindungBeendet(MySocket s); // die Verbindung wurde beendet oder ist zusammengebrochen.
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import javax.swing.text.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Hilfsklasse zur Eingabe eines Textes mit begrenzter Länge
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Sam Hotte (https://www.java-forum.org/thema/jtextfield-eingabelaenge-beschraenken.27393/)
|
||||
*/
|
||||
|
||||
public class MyTextFieldDocument extends PlainDocument {
|
||||
|
||||
private int maxLength_ = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Erzeugt ein javax.swing.text.Document fuer das JTextField.
|
||||
*
|
||||
* @param maxLength
|
||||
* maximale Zeichenanzahl
|
||||
*/
|
||||
public MyTextFieldDocument(final int maxLength) {
|
||||
this.maxLength_ = maxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fügt den String nur dann ein, wenn die maximale Anzahl noch nicht überschritten ist.
|
||||
*
|
||||
* @param offs
|
||||
* Offset (Position, an der der String eingefuegt werden soll)
|
||||
* @param str
|
||||
* einzufuegender String
|
||||
* @param a
|
||||
* Attribut-Set (werden hier nicht weiter beachtet)
|
||||
* @throws BadLocationException
|
||||
* wird "von oben" durchgereicht
|
||||
* @see javax.swing.text.AttributeSet
|
||||
*/
|
||||
public void insertString(final int offs, final String str,
|
||||
final AttributeSet a) throws BadLocationException {
|
||||
if (str == null) {
|
||||
return;
|
||||
}
|
||||
int actualLength = this.getLength();
|
||||
if (actualLength + str.length() < this.maxLength_) {
|
||||
super.insertString(offs, str, a);
|
||||
} else {
|
||||
java.awt.Toolkit.getDefaultToolkit().beep();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
119
Software/run_n_imp8_kommunikationsprotokoll/Nachricht.java
Normal file
119
Software/run_n_imp8_kommunikationsprotokoll/Nachricht.java
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/**
|
||||
*
|
||||
* Gesendete oder empfangene Nachricth im Chat (konnte auch Verschlüsselung, wird hier nicht gebraucht
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Nachricht {
|
||||
|
||||
// Anfang Attribute
|
||||
private byte[] inhalt;
|
||||
private String absender;
|
||||
private String empfaenger;
|
||||
private long time;
|
||||
private boolean stopped;
|
||||
private boolean sended;
|
||||
// Ende Attribute
|
||||
|
||||
public Nachricht(String absender, String empfaenger, String inhalt) {
|
||||
setInhalt(inhalt);
|
||||
this.absender = absender;
|
||||
this.empfaenger = empfaenger;
|
||||
this.time = System.currentTimeMillis();
|
||||
this.stopped = false;
|
||||
this.sended = false;
|
||||
}
|
||||
|
||||
public Nachricht(String absender, String empfaenger, byte[] inhalt, byte[] hashCode) {
|
||||
this.inhalt = inhalt;
|
||||
this.absender = absender;
|
||||
this.empfaenger = empfaenger;
|
||||
this.time = System.currentTimeMillis();
|
||||
this.stopped = false;
|
||||
this.sended = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Nachricht(String absender, String empfaenger, byte[] inhalt) {
|
||||
this.inhalt = inhalt;
|
||||
this.absender = absender;
|
||||
this.empfaenger = empfaenger;
|
||||
this.time = System.currentTimeMillis();
|
||||
this.stopped = false;
|
||||
this.sended = false;
|
||||
}
|
||||
|
||||
// Anfang Methoden
|
||||
public String getInhaltString() {
|
||||
return new String(inhalt);
|
||||
}
|
||||
|
||||
public byte[] getInhalt() {
|
||||
return inhalt;
|
||||
}
|
||||
|
||||
|
||||
public void setInhalt(String inhalt) {
|
||||
this.inhalt = inhalt.getBytes();
|
||||
}
|
||||
|
||||
public void setInhalt(byte[] inhalt) {
|
||||
this.inhalt = inhalt;
|
||||
}
|
||||
|
||||
public String getAbsender() {
|
||||
return absender;
|
||||
}
|
||||
|
||||
public void setAbsender(String absender) {
|
||||
this.absender = absender;
|
||||
}
|
||||
|
||||
public String getEmpfaenger() {
|
||||
return empfaenger;
|
||||
}
|
||||
|
||||
public void setEmpfaenger(String empfaenger) {
|
||||
this.empfaenger = empfaenger;
|
||||
}
|
||||
|
||||
public Nachricht copy() {
|
||||
Nachricht n = new Nachricht(absender, "", inhalt);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
public int getRestzeit() {
|
||||
if (sended || stopped) {
|
||||
return 0;
|
||||
} // end of if
|
||||
return 10 - (int) ((System.currentTimeMillis()-this.time)/1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean getSended() {
|
||||
return sended;
|
||||
}
|
||||
|
||||
public void setSended(boolean s) {
|
||||
sended = s;
|
||||
}
|
||||
|
||||
|
||||
public boolean getStopped() {
|
||||
return stopped;
|
||||
}
|
||||
|
||||
public void setStopped(boolean s) {
|
||||
stopped = s;
|
||||
}
|
||||
// Ende Methoden
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,434 @@
|
|||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.JFileChooser;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
/**
|
||||
*
|
||||
* Programm zur Erstellung einer Protokolldefinition
|
||||
*
|
||||
* @version 1.2 vom 08.11.2019
|
||||
* 1.2: Protokolle mit Umlauten werden korrekt in UTF-8 gespeichert.
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class ProtokollErstellen extends JFrame {
|
||||
// Anfang Attribute
|
||||
private JLabel jLabel3 = new JLabel();
|
||||
// Elemente die einer Nachricht hinzugefügt werden können
|
||||
private JPanel jPElementVorrat = new JPanel(null, true);
|
||||
private ElementPanel element1 = new ElementPanel(new TextElement());
|
||||
private ElementPanel element2 = new ElementPanel(new BuchstabeElement());
|
||||
private ElementPanel element3 = new ElementPanel(new ZifferElement());
|
||||
// Scrollpane für die kreierten Nachrichten
|
||||
private JScrollPane jScrollPane1 = new JScrollPane();
|
||||
private JPanel jPNachrichten = new JPanel(null, true);
|
||||
// Laden- und Speichernbutton
|
||||
private JButton jBLoad = new JButton();
|
||||
private JButton jBSave = new JButton();
|
||||
// Gerade ausgewähltes Element, das in eine Nachricht gezogen wird
|
||||
private Element dragElement = null;
|
||||
// Wo ging das Drag los?
|
||||
private Point dragPoint = null;
|
||||
private JFileChooser chooser ;
|
||||
// Ende Attribute
|
||||
|
||||
public ProtokollErstellen (String title) {
|
||||
super (title);
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
int frameWidth = 577;
|
||||
int frameHeight = 356;
|
||||
setSize(frameWidth, frameHeight);
|
||||
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
int x = (d.width - getSize().width) / 2;
|
||||
int y = (d.height - getSize().height) / 2;
|
||||
setLocation(x, y);
|
||||
Container cp = getContentPane();
|
||||
cp.setLayout(null);
|
||||
// Anfang Komponenten
|
||||
// Element für die Nachrichten (alle können mit der Mouse auf eine Nachricht gezogen werden
|
||||
{
|
||||
|
||||
element1.setBounds(10, 6, 50, 33);
|
||||
element1.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
elementGewaehlt(evt);
|
||||
}
|
||||
});
|
||||
element1.addMouseListener(new MouseAdapter() {
|
||||
public void mouseReleased(MouseEvent evt) {
|
||||
elementLosgelassen(evt);
|
||||
}
|
||||
});
|
||||
jPElementVorrat.add(element1);
|
||||
|
||||
element2.setBounds(60, 6, 25, 33);
|
||||
element2.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
elementGewaehlt(evt);
|
||||
}
|
||||
});
|
||||
element2.addMouseListener(new MouseAdapter() {
|
||||
public void mouseReleased(MouseEvent evt) {
|
||||
elementLosgelassen(evt);
|
||||
}
|
||||
});
|
||||
jPElementVorrat.add(element2);
|
||||
|
||||
element3.setBounds(88, 6, 25, 33);
|
||||
element3.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
elementGewaehlt(evt);
|
||||
}
|
||||
});
|
||||
element3.addMouseListener(new MouseAdapter() {
|
||||
public void mouseReleased(MouseEvent evt) {
|
||||
elementLosgelassen(evt);
|
||||
}
|
||||
});
|
||||
jPElementVorrat.add(element3);
|
||||
jPElementVorrat.setBounds(8, 8, 545, 33);
|
||||
jPElementVorrat.setOpaque(false);
|
||||
jPElementVorrat.setBorder(BorderFactory.createBevelBorder(1, new Color(0xC0C0C0), Color.GRAY));
|
||||
cp.add(jPElementVorrat);
|
||||
|
||||
}
|
||||
|
||||
// Scrollfenster für die kreierten Nachrichten
|
||||
jScrollPane1.setBounds(8, 48, 545, 217);
|
||||
jScrollPane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
|
||||
jScrollPane1.setBorder(BorderFactory.createBevelBorder(0, Color.GRAY, new Color(0xC0C0C0)));
|
||||
cp.add(jScrollPane1);
|
||||
jScrollPane1.setViewportView(jPNachrichten);
|
||||
jPNachrichten.setOpaque(false);
|
||||
jPNachrichten.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent evt) {
|
||||
jPNachrichten_MouseClicked(evt);
|
||||
}
|
||||
});
|
||||
|
||||
// Buttons zum Speichern und Laden
|
||||
jBLoad.setBounds(88, 275, 145, 25);
|
||||
jBLoad.setText("Protokoll laden");
|
||||
jBLoad.setMargin(new Insets(2, 2, 2, 2));
|
||||
jBLoad.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
jBLoad_ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
cp.add(jBLoad);
|
||||
jBSave.setBounds(320, 275, 153, 25);
|
||||
jBSave.setText("Protokoll speichern");
|
||||
jBSave.setMargin(new Insets(2, 2, 2, 2));
|
||||
jBSave.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
jBSave_ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
cp.add(jBSave);
|
||||
jLabel3.setBounds(160, 305, 229, 20);
|
||||
jLabel3.setText("(cc) 2019, Thomas Schaller, Version 1.2");
|
||||
jLabel3.setForeground(Color.GRAY);
|
||||
cp.add(jLabel3);
|
||||
setTitle("Protokoll:");
|
||||
// Ende Komponenten
|
||||
|
||||
// FileChoose Dialog
|
||||
chooser = new JFileChooser();
|
||||
FileFilter filter = new FileNameExtensionFilter("XML-Dateien", "xml");
|
||||
// Filter wird unserem JFileChooser hinzugefügt
|
||||
chooser.addChoosableFileFilter(filter);
|
||||
chooser.setAcceptAllFileFilterUsed(false);
|
||||
chooser.setCurrentDirectory(new File("."));
|
||||
|
||||
setResizable(false);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
// Anfang Methoden
|
||||
|
||||
|
||||
/** Laden einer XML-Protokolldefinition
|
||||
*/
|
||||
public void jBLoad_ActionPerformed(ActionEvent evt) {
|
||||
// Dialog zum Oeffnen von Dateien anzeigen
|
||||
int rueckgabeWert =chooser.showDialog(null, "Protokoll laden");
|
||||
|
||||
|
||||
/* Abfrage, ob auf "Öffnen" geklickt wurde */
|
||||
if(rueckgabeWert == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
readXMLFile( chooser.getSelectedFile().getAbsolutePath());
|
||||
}
|
||||
|
||||
} // end of jBLoad_ActionPerformed
|
||||
|
||||
|
||||
public void readXMLFile(String dateiname) {
|
||||
XMLDokument f = new XMLDokument(dateiname);
|
||||
if (!f.getName().equals("protokoll")) return; // ist es wirklich eine Protokolldefinition
|
||||
setTitle("Protokoll: "+f.getAttributwert("name"));
|
||||
|
||||
boolean ok = f.stepInto();
|
||||
jPNachrichten.removeAll();
|
||||
|
||||
while (ok) { // Solange weitere Einträge vorhanden sind
|
||||
if (f.getName().equals("nachricht")) { // in oberste Ebene müssen "nachrichten" Elemente stehen
|
||||
Message m = newMessage();
|
||||
|
||||
boolean ok2 = f.stepInto(); // eintauchen in nachrichten-Element (kann text, buchstabe und ziffer enthalten)
|
||||
while (ok2) { // gibt es weitere Unterelemente?
|
||||
if(f.getName().equals("text")) {
|
||||
TextElement t = new TextElement();
|
||||
t.setText(f.getInhalt());
|
||||
m.add(t);
|
||||
}
|
||||
if(f.getName().equals("buchstabe")) {
|
||||
m.add(new BuchstabeElement());
|
||||
}
|
||||
if(f.getName().equals("ziffer")) {
|
||||
m.add(new ZifferElement());
|
||||
}
|
||||
ok2 = f.step(); // nächstes Unterelement
|
||||
|
||||
} // end of while
|
||||
f.stepOut();
|
||||
|
||||
|
||||
}
|
||||
ok = f.step(); // wieder auf Nachrichtenebene zurück
|
||||
|
||||
|
||||
} // end of while
|
||||
|
||||
jPNachrichten.setPreferredSize(new Dimension(600,5+jPNachrichten.getComponentCount()*40));
|
||||
jPNachrichten.invalidate();
|
||||
jPNachrichten.repaint();
|
||||
}
|
||||
|
||||
/** Speichern einer XML-Protokolldefinition
|
||||
*/
|
||||
public void jBSave_ActionPerformed(ActionEvent evt) {
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
FileFilter filter = new FileNameExtensionFilter("XML-Dateien",
|
||||
"xml");
|
||||
// Filter wird unserem JFileChooser hinzugefügt
|
||||
chooser.addChoosableFileFilter(filter);
|
||||
chooser.setAcceptAllFileFilterUsed(false);
|
||||
// Dialog zum Oeffnen von Dateien anzeigen
|
||||
int rueckgabeWert =chooser.showDialog(null, "Protokoll speichern");
|
||||
|
||||
|
||||
/* Abfrage, ob auf "Speichern" geklickt wurde */
|
||||
if(rueckgabeWert == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
writeXMLFile( chooser.getSelectedFile().getAbsolutePath(), chooser.getSelectedFile().getName());
|
||||
}
|
||||
|
||||
} // end of jBSave_ActionPerformed
|
||||
|
||||
|
||||
|
||||
|
||||
public void writeXMLFile(String dateiname, String protokollname) {
|
||||
if (protokollname.contains(".")) protokollname.substring(0,protokollname.indexOf("."));
|
||||
setTitle("Protokoll: "+protokollname);
|
||||
|
||||
XMLDokument d = new XMLDokument();
|
||||
d.fuegeElementHinzu("protokoll"); // root-Element hinzufügen
|
||||
d.setAttributwert("name",protokollname);
|
||||
d.stepInto(); // auf Nachrichten-Ebene eintauchen
|
||||
|
||||
for (Component c: jPNachrichten.getComponents()) { // alle Nachrichten aus dem Nachrichtenfenster
|
||||
d.fuegeElementHinzu("nachricht");
|
||||
d.stepInto(); // auf Unterelemente-Ebene eintauchen
|
||||
Message m = ((MessagePanel) c).getMessage();
|
||||
|
||||
for (int i = 0; i< m.size(); i++) {
|
||||
String a = m.get(i).getXMLIdentifier();
|
||||
d.fuegeElementHinzu(a);
|
||||
if(a.equals("text")) d.setInhalt(m.get(i).getText()); // Bei Texten auch den Inhalt speichern
|
||||
} // end of for
|
||||
d.stepOut(); // auf Nachrichtenebene zurückkehren
|
||||
} // end of for
|
||||
d.stepOut();
|
||||
if(!dateiname.endsWith(".xml")) dateiname += ".xml";
|
||||
d.speichereDokument(dateiname);
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------- Mausaktionen -------------------------------------------------------------
|
||||
|
||||
/** Kontextmenü für rechte Maustaste im Nachrichtenfenster => neue Nachricht, alle Nachrichten löschen
|
||||
*/
|
||||
public void jPNachrichten_MouseClicked(MouseEvent evt) {
|
||||
if(SwingUtilities.isRightMouseButton(evt)){
|
||||
ProtokollPopup menu = new ProtokollPopup(evt, this, null);
|
||||
}
|
||||
} // end of jPNachrichten_MouseClicked
|
||||
|
||||
/** Kontextmenü für rechte Maustaste auf eine Nachricht => neue Nachricht, Nachricht löschen, Text bearbeiten
|
||||
*/
|
||||
public void messagePanel1_MouseClicked(MouseEvent evt) {
|
||||
if(SwingUtilities.isRightMouseButton(evt)){
|
||||
MessagePanel messagePanel1 = (MessagePanel) evt.getComponent();
|
||||
Element e = messagePanel1.getElement(evt.getPoint());
|
||||
if (e==null) { // KLick auf Nachricht, aber kein Element => neue Nachricht, Alle löschen
|
||||
ProtokollPopup menu = new ProtokollPopup(evt, this, messagePanel1);
|
||||
} else { // Klick auf Element der Nachricht => Element löschen, Text bearbeiten
|
||||
MessagePopup menu = new MessagePopup(evt, messagePanel1.getMessage(), e, messagePanel1, this);
|
||||
|
||||
}
|
||||
}
|
||||
// end of if
|
||||
} // end of messagePanel1_MouseClicked
|
||||
|
||||
/** Neue Nachricht erzeugen, MouseListener für Kontextmenü und Element-Schieben hinzufügen */
|
||||
|
||||
public Message newMessage() {
|
||||
Message m = new Message();
|
||||
MessagePanel messagePanel1 = new MessagePanel(m);
|
||||
messagePanel1.setBounds(8, 5+jPNachrichten.getComponentCount()*40, 529, 40);
|
||||
jPNachrichten.add(messagePanel1);
|
||||
messagePanel1.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent evt) {
|
||||
messagePanel1_MouseClicked(evt);
|
||||
}
|
||||
});
|
||||
messagePanel1.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
elementVerschieben(evt);
|
||||
}
|
||||
});
|
||||
messagePanel1.addMouseListener(new MouseAdapter() {
|
||||
public void mouseReleased(MouseEvent evt) {
|
||||
elementLosgelassen(evt);
|
||||
}
|
||||
});
|
||||
messagePanel1.addMouseMotionListener(new MouseMotionAdapter() {
|
||||
public void mouseDragged(MouseEvent evt) {
|
||||
elementWurdeGeschoben(evt);
|
||||
}
|
||||
});
|
||||
jPNachrichten.setPreferredSize(new Dimension(400,5+jPNachrichten.getComponentCount()*40));
|
||||
jPNachrichten.invalidate();
|
||||
jPNachrichten.repaint();
|
||||
jScrollPane1.setViewportView(jPNachrichten);
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Einzelen Nachricht löschen */
|
||||
public void delete(JPanel p) {
|
||||
jPNachrichten.remove(p);
|
||||
for (Component c : jPNachrichten.getComponents()) {
|
||||
if(c.getY() > p.getY()) {
|
||||
c.setBounds(8, c.getY()-40, 529, 40);
|
||||
}
|
||||
|
||||
} // end of for
|
||||
jPNachrichten.setPreferredSize(new Dimension(400,5+jPNachrichten.getComponentCount()*40));
|
||||
jPNachrichten.invalidate();
|
||||
jPNachrichten.repaint();
|
||||
jScrollPane1.setViewportView(jPNachrichten);
|
||||
}
|
||||
|
||||
/** Alle Nachrichten löschen */
|
||||
public void deleteAllMessages() {
|
||||
jPNachrichten.removeAll();
|
||||
jPNachrichten.setPreferredSize(new Dimension(400,5+jPNachrichten.getComponentCount()*40));
|
||||
jPNachrichten.invalidate();
|
||||
jPNachrichten.repaint();
|
||||
jScrollPane1.setViewportView(jPNachrichten);
|
||||
}
|
||||
|
||||
/** Element aus Vorrat auswählen und in Nachricht ziehen, wenn mit linker Maustaste angeklickt. */
|
||||
public void elementGewaehlt(MouseEvent evt) {
|
||||
if(SwingUtilities.isLeftMouseButton(evt)){
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
dragElement = ((ElementPanel) evt.getComponent()).getElement().getCopy();
|
||||
// Bild des Elements als Cursour verwenden
|
||||
BufferedImage mouseImage = new BufferedImage(40,35, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g2 = mouseImage.createGraphics();
|
||||
dragElement.paint(g2,0,0,new Font("SansSerif", Font.BOLD, 12));
|
||||
Cursor c = toolkit.createCustomCursor(mouseImage , new Point(5, 5), "img");
|
||||
setCursor (c);
|
||||
|
||||
}
|
||||
} // end of element2_MousePressed
|
||||
|
||||
/** Verschieben eines Elements, erst aus Nachricht entfernen, wenn die Verschiebung weit genug */
|
||||
public void elementVerschieben(MouseEvent evt) {
|
||||
if(SwingUtilities.isLeftMouseButton(evt)){
|
||||
Element e = ((MessagePanel) (evt.getComponent())).getElement(evt.getPoint());
|
||||
if(e != null) {
|
||||
dragElement = e;
|
||||
dragPoint = evt.getPoint(); // dragPoint != null => Element ist noch in Nachricht
|
||||
// Bild des Elements als Cursour verwenden
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
BufferedImage mouseImage = new BufferedImage(40,35, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g2 = mouseImage.createGraphics();
|
||||
dragElement.paint(g2,0,0,new Font("SansSerif", Font.BOLD, 12));
|
||||
Cursor c = toolkit.createCustomCursor(mouseImage , new Point(5, 5), "img");
|
||||
setCursor (c);
|
||||
|
||||
} // end of if-else
|
||||
}
|
||||
} // end of element2_MousePressed
|
||||
|
||||
/** Drag des Elements, wenn die Verschiebung weit genug (>3 Pixel), dann wird es aus der Nachricht entfernt */
|
||||
public void elementWurdeGeschoben(MouseEvent evt) {
|
||||
if(SwingUtilities.isLeftMouseButton(evt) && dragElement != null && dragPoint != null && (Math.abs(dragPoint.getX()-evt.getX())+Math.abs(dragPoint.getY()-evt.getY())>3)){
|
||||
((MessagePanel) (evt.getComponent())).getMessage().delete(dragElement);
|
||||
jPNachrichten.invalidate();
|
||||
jPNachrichten.repaint();
|
||||
dragPoint = null; // Element wurde aus Nachricht entfernt
|
||||
}
|
||||
} // end of element2_MousePressed
|
||||
|
||||
/** Neu Positionierung des Drag-Elements (sowohl für neue Elemente aus Vorrat als auch für Verschobene), sofern es aus der Nachricht schon entfernt wurde. */
|
||||
public void elementLosgelassen(MouseEvent evt) {
|
||||
|
||||
if(SwingUtilities.isLeftMouseButton(evt) && dragElement != null && dragPoint == null){
|
||||
|
||||
Point p = evt.getPoint();
|
||||
Point pp = SwingUtilities.convertPoint(evt.getComponent(), p, jPNachrichten); // Koordinaten bezogen auf neue Nachricht bestimmen
|
||||
|
||||
Component mp = jPNachrichten.getComponentAt(pp);
|
||||
if(mp != null && mp instanceof MessagePanel) {
|
||||
Point p3 = SwingUtilities.convertPoint(evt.getComponent(), p, mp); // Koordinaten bezogen auf neue Nachricht bestimmen
|
||||
Element e = ((MessagePanel) mp).getElement(p3);
|
||||
if(e == null) {
|
||||
((MessagePanel) mp).getMessage().add(dragElement);
|
||||
|
||||
} else {
|
||||
((MessagePanel) mp).getMessage().addBefore(dragElement,e);
|
||||
|
||||
} // end of if-else
|
||||
|
||||
|
||||
} else {
|
||||
Message m = newMessage();
|
||||
m.add(dragElement);
|
||||
} // end of if-else
|
||||
jPNachrichten.invalidate();
|
||||
jPNachrichten.repaint();
|
||||
}
|
||||
dragElement = null;
|
||||
dragPoint = null;
|
||||
Cursor dc = new Cursor(Cursor.DEFAULT_CURSOR);
|
||||
|
||||
setCursor (dc);
|
||||
|
||||
} // end of element2_MouseReleased
|
||||
|
||||
// Ende Methoden
|
||||
|
||||
public static void main(String[] args) {
|
||||
new ProtokollErstellen("ProtokollErstellen");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Kontextmenü für Rechtsklick im Nachrichten-Erzeugungsfenster
|
||||
*
|
||||
*
|
||||
* @version 1.1 vom 14.06.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class ProtokollPopup extends JPopupMenu implements ActionListener {
|
||||
|
||||
|
||||
|
||||
private JMenuItem dmi1, dmi2, dmi3;
|
||||
private ProtokollErstellen parent;
|
||||
private JPanel messagePanel;
|
||||
|
||||
public ProtokollPopup( MouseEvent event, ProtokollErstellen parent, JPanel messagePanel){
|
||||
|
||||
this.parent = parent;
|
||||
this.messagePanel = messagePanel;
|
||||
dmi1 = new JMenuItem("Neue Nachricht");
|
||||
dmi1.addActionListener(this);
|
||||
add(dmi1);
|
||||
if(messagePanel != null) {
|
||||
dmi3 = new JMenuItem("Nachricht löschen");
|
||||
dmi3.addActionListener(this);
|
||||
add(dmi3);
|
||||
|
||||
}
|
||||
|
||||
dmi2 = new JMenuItem("Alle Nachrichten löschen");
|
||||
dmi2.addActionListener(this);
|
||||
add(dmi2);
|
||||
show(event.getComponent(), event.getX(), event.getY());
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
|
||||
|
||||
if (ae.getSource() == dmi1) {
|
||||
parent.newMessage();
|
||||
}
|
||||
if (ae.getSource() == dmi2) {
|
||||
parent.deleteAllMessages();
|
||||
}
|
||||
if (ae.getSource() == dmi3) {
|
||||
parent.delete(messagePanel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.awt.geom.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Runder, farbiger Rahmen um Textfelder und Eingabefelder
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Andrew Thompson (https://stackoverflow.com/questions/8462414/internal-padding-for-jtextarea-with-background-image)
|
||||
*/
|
||||
|
||||
public class TextBubbleBorder extends AbstractBorder {
|
||||
|
||||
private Color color;
|
||||
private int thickness = 4;
|
||||
private int radii = 8;
|
||||
private int pointerSize = 7;
|
||||
private Insets insets = null;
|
||||
private BasicStroke stroke = null;
|
||||
private int strokePad;
|
||||
private int pointerPad = 4;
|
||||
private boolean left = true;
|
||||
RenderingHints hints;
|
||||
|
||||
TextBubbleBorder(
|
||||
Color color) {
|
||||
this(color, 4, 8, 7);
|
||||
}
|
||||
|
||||
TextBubbleBorder(
|
||||
Color color, int thickness, int radii, int pointerSize) {
|
||||
this.thickness = thickness;
|
||||
this.radii = radii;
|
||||
this.pointerSize = pointerSize;
|
||||
this.color = color;
|
||||
|
||||
stroke = new BasicStroke(thickness);
|
||||
strokePad = thickness / 2;
|
||||
|
||||
// hints = new RenderingHints(
|
||||
// RenderingHints.KEY_ANTIALIASING,
|
||||
// RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
//
|
||||
int pad = radii + strokePad;
|
||||
pad = 3;
|
||||
int bottomPad = pad + pointerSize + strokePad;
|
||||
insets = new Insets(3, 5, 3, 7);
|
||||
}
|
||||
|
||||
TextBubbleBorder(
|
||||
Color color, int thickness, int radii, int pointerSize, boolean left) {
|
||||
this(color, thickness, radii, pointerSize);
|
||||
this.left = left;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets(Component c) {
|
||||
return insets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets(Component c, Insets insets) {
|
||||
return getBorderInsets(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder(
|
||||
Component c,
|
||||
Graphics g,
|
||||
int x, int y,
|
||||
int width, int height) {
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
|
||||
int bottomLineY = height - thickness - pointerSize;
|
||||
|
||||
RoundRectangle2D.Double bubble = new RoundRectangle2D.Double(
|
||||
0 + strokePad,
|
||||
0 + strokePad,
|
||||
width - thickness-2,
|
||||
bottomLineY-1,
|
||||
radii,
|
||||
radii);
|
||||
|
||||
RoundRectangle2D.Double bubble2 = new RoundRectangle2D.Double(
|
||||
0 + strokePad+1,
|
||||
0 + strokePad+2,
|
||||
width - thickness-2,
|
||||
bottomLineY-1,
|
||||
radii,
|
||||
radii);
|
||||
|
||||
Area area = new Area(bubble);
|
||||
Area area2 = new Area(bubble2);
|
||||
|
||||
|
||||
// Paint the BG color of the parent, everywhere outside the clip
|
||||
// of the text bubble.
|
||||
Component parent = c.getParent();
|
||||
if (parent!=null) {
|
||||
Color bg = parent.getBackground();
|
||||
Rectangle rect = new Rectangle(0,0,width, height);
|
||||
Area borderRegion = new Area(rect);
|
||||
borderRegion.subtract(area);
|
||||
borderRegion.subtract(area2);
|
||||
g2.setClip(borderRegion);
|
||||
g2.setColor(bg);
|
||||
g2.fillRect(0, 0, width, height);
|
||||
g2.setClip(null);
|
||||
}
|
||||
|
||||
g2.setStroke(stroke);
|
||||
Rectangle rect = new Rectangle(0,0,width, height);
|
||||
Area borderRegion = new Area(rect);
|
||||
borderRegion.subtract(area);
|
||||
g2.setClip(borderRegion);
|
||||
g2.setColor(color.darker());
|
||||
g2.draw(area2);
|
||||
g2.setClip(null);
|
||||
g2.setColor(color);
|
||||
g2.draw(area);
|
||||
}
|
||||
}
|
||||
31
Software/run_n_imp8_kommunikationsprotokoll/TextElement.java
Normal file
31
Software/run_n_imp8_kommunikationsprotokoll/TextElement.java
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import java.awt.Color;
|
||||
/**
|
||||
*
|
||||
* Hilfsklasse für ein Text-Element (fester String)
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class TextElement extends Element {
|
||||
public TextElement() {
|
||||
super();
|
||||
super.setText("TEXT");
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return new Color(200,50,50);
|
||||
}
|
||||
|
||||
public Element getCopy() {
|
||||
TextElement e = new TextElement();
|
||||
e.setText(e.getText());
|
||||
return e;
|
||||
}
|
||||
|
||||
public String getXMLIdentifier() {
|
||||
return "text";
|
||||
}
|
||||
|
||||
}
|
||||
213
Software/run_n_imp8_kommunikationsprotokoll/XMLDokument.java
Normal file
213
Software/run_n_imp8_kommunikationsprotokoll/XMLDokument.java
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/**
|
||||
*
|
||||
* Hilfsklasse zum Umgang mit XML-Dokumenten
|
||||
* Man hat einen Zeiger, den man durch den XML-Baum bewegen kann.
|
||||
*
|
||||
* @version 1.1 vom 14.06.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.io.*;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.jdom.Document;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jdom.input.SAXBuilder;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.jdom.output.XMLOutputter;
|
||||
import org.jdom.output.Format;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class XMLDokument {
|
||||
|
||||
// Anfang Attribute
|
||||
private Document doc;
|
||||
private ArrayList<Element> pointer;
|
||||
// Ende Attribute
|
||||
|
||||
/** Leeres XMLDokument erzeugen */
|
||||
public XMLDokument() {
|
||||
this.doc = new Document();
|
||||
this.pointer = new ArrayList<Element>();
|
||||
this.pointer.add(null);
|
||||
}
|
||||
|
||||
/** XML-Dokument aus Datei erzeugen */
|
||||
public XMLDokument(String dateiname) {
|
||||
oeffneDokument(dateiname);
|
||||
}
|
||||
|
||||
// Anfang Methoden
|
||||
/** Öffnet das durch den Dateinamen gegebene Dokument
|
||||
* @param dateiname Dateiname des XML-Files
|
||||
*/
|
||||
public void oeffneDokument(String dateiname) {
|
||||
doc = null;
|
||||
File f = new File(dateiname);
|
||||
|
||||
try {
|
||||
// Das Dokument erstellen
|
||||
SAXBuilder builder = new SAXBuilder();
|
||||
InputSource is = new InputSource(new FileInputStream(f));
|
||||
is.setEncoding("UTF-8");
|
||||
doc = builder.build(is);
|
||||
|
||||
} catch (JDOMException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
pointer = new ArrayList<Element>(); // Zeiger im Baum auf Root-Element
|
||||
pointer.add(doc.getRootElement());
|
||||
}
|
||||
|
||||
/** Speichert den XML-Baum im angegebenen Dateinamen
|
||||
* @param dateiname Dateiname des XML-Files
|
||||
*/
|
||||
public void speichereDokument(String dateiname) {
|
||||
try {
|
||||
// new XMLOutputter().output(doc, System.out);
|
||||
XMLOutputter xmlOutput = new XMLOutputter();
|
||||
|
||||
// display nice nice
|
||||
xmlOutput.setFormat(Format.getPrettyFormat());
|
||||
File f = new File(dateiname);
|
||||
//FileOutputStream outputFile = new FileOutputStream(f);
|
||||
PrintWriter outputFile = new PrintWriter(f, "UTF-8");
|
||||
System.out.println("Speicher in : "+f.getAbsolutePath() );
|
||||
xmlOutput.output(doc, outputFile);
|
||||
outputFile.close();
|
||||
System.out.println("File Saved!");
|
||||
} catch (IOException io) {
|
||||
System.out.println(io.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------- Zeigerbewegungen --------------------------------------------------
|
||||
/** Bewegt den Zeiger in der gleiche Ebene zum nächsten Eintrag (falls es dieses gibt)
|
||||
* @return gibt es noch ein weiteres Element?
|
||||
*/
|
||||
public boolean step() {
|
||||
if(pointer.size() > 1 && pointer.get(0) != null) { // ist das XML-Dokument nicht komplett leer
|
||||
Element e = pointer.get(1);
|
||||
Element e2 = pointer.get(0);
|
||||
List<Element> l = e.getChildren(); // alle Kinder des übergeordneten Elements
|
||||
if (l !=null) {
|
||||
int i = l.indexOf(e2);
|
||||
if (i+1 < l.size()) { // gibt es noch ein nächstes Kind?
|
||||
pointer.remove(0);
|
||||
pointer.add(0,l.get(i+1));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Wechselt eine Ebene tiefer im XML-Baum, d.h. zu den Kindern des aktuellen Elements (falls es diese gibt, sonst wird null-Pointer als aktuelles Element gesetzt)
|
||||
* @return false, wenn es gar keine Kinder gibt, sonst true.
|
||||
*/
|
||||
public boolean stepInto() {
|
||||
if(pointer.size() > 0 && pointer.get(0)!=null) { // ist XML-Baum nicht komplett leer
|
||||
Element e = pointer.get(0);
|
||||
List<Element> l = e.getChildren(); // bestimme Kinder des aktuellen Elements
|
||||
|
||||
if (l != null && l.size() > 0) { // tauche ein, wenn es welche gibt
|
||||
pointer.add(0,l.get(0));
|
||||
return true;
|
||||
|
||||
} else {
|
||||
pointer.add(0,null);
|
||||
} // end of if-else
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Kehre eine Ebene zurück
|
||||
* @return true, wenn dies möglich ist, false, wenn schon auf höchster Ebenen
|
||||
*/
|
||||
public boolean stepOut() {
|
||||
if(pointer.size() > 1) {
|
||||
pointer.remove(0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------- Methoden für das aktuelle Element -------------------------------------------------
|
||||
/** Frage den Namen des aktuellen Elements ab*/
|
||||
public String getName() {
|
||||
if (pointer.size() == 0 || pointer.get(0)==null) return "";
|
||||
return pointer.get(0).getName();
|
||||
}
|
||||
|
||||
/** Setze den Namen des aktuellen Elements */
|
||||
public void setName(String name) {
|
||||
if (pointer.size() == 0 || pointer.get(0)==null) return;
|
||||
pointer.get(0).setName(name);
|
||||
}
|
||||
|
||||
/** Frage einen Attributwert des aktuellen Elements ab*/
|
||||
public String getAttributwert(String attribut) {
|
||||
if (pointer.size() == 0 || pointer.get(0)==null) return "";
|
||||
return pointer.get(0).getAttributeValue(attribut);
|
||||
}
|
||||
|
||||
/** Setze einen Attributwert des aktuellen Elements */
|
||||
public void setAttributwert(String attribut, String wert) {
|
||||
if (pointer.size() == 0 || pointer.get(0)==null) return;
|
||||
pointer.get(0).setAttribute(attribut, wert);
|
||||
}
|
||||
|
||||
/** Frage den Inhalt/Text des aktuellen Elements ab*/
|
||||
public String getInhalt() {
|
||||
if (pointer.size() == 0 || pointer.get(0)==null) return "";
|
||||
return pointer.get(0).getValue();
|
||||
}
|
||||
|
||||
/** Setze den Inhalt/Text des aktuellen Elements */
|
||||
public void setInhalt(String inhalt) {
|
||||
if (pointer.size() == 0 || pointer.get(0)==null) return;
|
||||
pointer.get(0).setText(inhalt);
|
||||
}
|
||||
|
||||
// ----------------------------------------------- XML-Struktur aufbauen ------------------------------------------------
|
||||
/** Erzeuge neues Element nach der aktuellen Position und setze dieses als aktuelles Element
|
||||
* @param name Name des neuen Elements
|
||||
*/
|
||||
public void fuegeElementHinzu(String name) {
|
||||
if(pointer.size()==1){ // man ist auf Root-Ebene
|
||||
if(pointer.get(0)==null) { // XML-Baum ist bisher leer => neues Root-Element , sonst wird Element ignoriert, es gibt nur ein Root-Element
|
||||
Element e = new Element(name);
|
||||
doc.setRootElement(e);
|
||||
pointer.remove(0);
|
||||
pointer.add(0,e);
|
||||
}
|
||||
} else {
|
||||
Element parent = pointer.get(1); // Neues Element wird nach aktuellem eingefügt
|
||||
Element aktuell = pointer.get(0);
|
||||
Element e = new Element(name);
|
||||
if(aktuell == null) {
|
||||
parent.addContent(e);
|
||||
pointer.remove(0);
|
||||
pointer.add(0,e);
|
||||
} else {
|
||||
parent.addContent(parent.indexOf(aktuell)+1, e);
|
||||
pointer.remove(0);
|
||||
pointer.add(0,e);
|
||||
} // end of if-else
|
||||
|
||||
} // end of if-else
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import java.awt.Color;
|
||||
|
||||
/**
|
||||
*
|
||||
* Hilfsklasse für ein Ziffer-Element (varibaler Ziffer)
|
||||
*
|
||||
*
|
||||
* @version 1.0 vom 13.04.2018
|
||||
* @author Thomas Schaller
|
||||
*/
|
||||
|
||||
public class ZifferElement extends Element {
|
||||
public ZifferElement() {
|
||||
super();
|
||||
super.setText("#");
|
||||
}
|
||||
|
||||
|
||||
public void setText(String t) {
|
||||
super.setText("#");
|
||||
}
|
||||
|
||||
|
||||
public Color getColor() {
|
||||
return Color.blue;
|
||||
}
|
||||
|
||||
public Element getCopy() {
|
||||
ZifferElement e = new ZifferElement();
|
||||
return e;
|
||||
}
|
||||
|
||||
public String getXMLIdentifier() {
|
||||
return "ziffer";
|
||||
}
|
||||
}
|
||||
11
Software/run_n_imp8_kommunikationsprotokoll/readme.adoc
Normal file
11
Software/run_n_imp8_kommunikationsprotokoll/readme.adoc
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
= Material der ZPG IMP 8:
|
||||
|
||||
|===
|
||||
|Zuordnung| Rechner und Netze
|
||||
|Klassenstufe| IMP 8
|
||||
|Bildungsplanbezug |
|
||||
|Werkzeug|
|
||||
|Autoren|
|
||||
|===
|
||||
|
||||
== Inhalt
|
||||
Loading…
Add table
Add a link
Reference in a new issue