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