/*
* Datei: Vis.java
* Autor(en): Lukas K�nig
* Java-Version: 6.0
* Erstellt (vor): 14.11.2008
*
* (c) Lukas K�nig, die Datei unterliegt der LGPL
* -> http://www.gnu.de/lgpl-ger.html
*/
package fmg.fmg8.graphVis;
import fmg.fmg8.earleyErkenner.EarleyErkenner;
import fmg.fmg8.endlAutomat.AutomatenNummer;
import fmg.fmg8.endlAutomat.conditions.Condition;
import fmg.fmg8.endlAutomat.conditions.ConditionNummer;
import fmg.fmg8.endlAutomat.mutation.CondMutVerfahren;
import fmg.fmg8.endlAutomat.script.ScriptInterpreter;
import fmg.fmg8.endlAutomat.translator.Translator;
import fmg.fmg8.graphVis.darstellungsModi.DarstModEA;
import fmg.fmg8.graphVis.darstellungsModi.Konstanten;
import fmg.fmg8.graphVis.fensterDialoge.AllgemeinerDialog;
import fmg.fmg8.graphVis.fensterDialoge.WindHideAdapt;
import fmg.fmg8.graphVis.graph.Knoten;
import fmg.fmg8.graphVis.zeichenModi.PfeilMaster;
import fmg.fmg8.sonstiges.SonstMeth;
import fmg.fmg8.sonstiges.Zwischenablage;
import fmg.fmg8.statistik.Parametersatz;
import fmg.fmg8.umgebung2D.Roboter;
import fmg.fmg8.umgebung2D.Umgebung;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
/**
* Applet zur Visualisierung eines Graphen.
*
* @author Lukas K�nig.
*/
public class Vis extends Frame implements Observer {
/**
* Am 14.09.06 generiert.
*/
private static final long serialVersionUID = -4078048087117840970L;
/**
* Speichert die aktiven VisTrans-Fenster.
*/
private LinkedList<VisTrans> aktVisTrans;
/**
* Der aktuelle Graph, der ausgegeben werden soll.
*/
private Roboter rob;
/**
* Der aktuell gew�hlte Knoten.
*/
private Knoten gewKnot;
/**
* Die aktuelle Reihe des Layouts (dummy).
*/
int row = 0;
/**
* Der selektierte Knoten (dieser Knoten kann gerade bearbeitet werden).
*/
private Knoten[] selKnot;
/**
* Objekt, das die Polygone (u. �.) zur Darstellung eines Graphen erzeugt.
*/
private PfeilMaster zeichenArt;
/**
* Objekt, das aktuell die Graphdarstellung erzeugt.
*/
private DarstModEA[] darstArten;
/**
* Der aktuell anzuzeigende Graph.
*/
private DargestellterGraph aktGraph;
/**
* Das Steuerfenster.
*/
private SteuerFenster steuer;
/**
* Der Automat als Sequenz.
*/
private JTextField[] sequenzen;
/**
* Die Gr��e der Sequenz.
*/
private JLabel[] groessen;
/**
* Die Bedingungen, die zu den Automaten geh�ren.
*/
private JTextField[] conditions;
/**
* Der Name des von <code>this</code> dargestellten Graphen.
*/
private String robName;
/**
* Gibt an, ob gerade eine Simulation l�uft.
*/
private boolean simLaueft;
/**
* Z�hlt die Anzahl der Aufrufe der NeuZeichnen-Methode ohne Update.
*/
private int zaehler;
/**
* Die Parameter.
*/
private Parametersatz pars;
/**
* Implementierung einiger Methoden zum benutzen der Windows-Zwischenablage.
*/
private Zwischenablage zwischenablage;
/**
* Der zurzeit ausgew�hlte Automat des aktuellen Roboters.
*/
private int aktAut;
/**
* Der Automat, den der Roboter zurzeit tats�chlich benutzt.
*/
private int benutztAut;
/**
* Implementierung eines �berschriebenen Konstruktors. Die Graphen werden
* von der Festplatte geladen.
*
* @param fenstertitel Der als Titel anzuzeigende String.
* @param grNam Der Name des aktuellen Graphen.
* @param eltFenst Das Eltern-Steuerfenster.
* @param umg Die Umgebung, in der sich der Roboter befindet.
* @param earl Der Earley-Erkenner f�r die Sequenz-Grammatik.
* @param mutVerh Die Mutation f�r das Verhalten des Roboter, der zu
* dieser Visualisierung geh�rt.
* @param mutTrans Die Mutation f�r den �bersetzer des Roboters, der
* zu dieser Visualisierung geh�rt.
* @param rnd Der Zufallsgenerator.
* @param id Die Identifikationsnummer des Roboters.
* @param params Der Parametersatz.
* @param autAnz Die Anzahl an Automaten, falls die Graphen nicht
* von der Festplatte geladen werden k�nnen.
* @param trans Die Translatoren.
*/
public Vis(
final String fenstertitel,
final String grNam,
final SteuerFenster eltFenst,
final Umgebung umg,
final EarleyErkenner earl,
final CondMutVerfahren mutVerh,
final CondMutVerfahren mutTrans,
final Random rnd,
final int id,
final Parametersatz params,
final int autAnz,
final Translator[] trans) {
super(fenstertitel);
this.aktAut = 0;
this.benutztAut = 0;
this.pars = params;
this.steuer = eltFenst;
this.simLaueft = false;
this.zaehler = 0;
this.init(
grNam,
umg,
earl,
mutVerh,
mutTrans,
rnd,
id,
null,
autAnz,
null,
trans);
this.start(false);
}
/**
* Erzeugt ein Vis-Objekt aus Automatensequenzen.
*
* @param fenstertitel Der Fenstertitel.
* @param seq Die Sequenz.
* @param ident Die Identifikationsnummer des Roboters.
* @param params Die Parameter.
* @param conds Die Bedingungen.
* @param trans Die Translatoren.
*/
public Vis(final String fenstertitel,
final String[] seq,
final Condition[] conds,
final int ident,
final Parametersatz params,
final Translator[] trans) {
super(fenstertitel);
this.pars = params;
this.aktAut = 0;
this.benutztAut = 0;
this.init(fenstertitel, null, null, null, null, null,
ident, seq, seq.length, conds, trans);
this.start(true);
}
/**
* Initialisierungsmethode (Roboter und Darstellung).
*
* @param grName Der Name des aktuellen Graphen.
* @param umg Die Umgebung, in der sich der Roboter befindet.
* @param earl Der Earley-Erkenner f�r die Sequenz-Grammatik.
* @param mutVerh Die Mutation f�r das Verhalten des Roboter, der zu
* dieser Visualisierung geh�rt.
* @param mutTrans Die Mutation f�r den �bersetzer des Roboters, der
* zu dieser Visualisierung geh�rt.
* @param randm Der Zufallsgenerator.
* @param ident Die Identifikationsnummer des Roboters.
* @param laden Ob der Roboter von Festplatte geladen werden soll
* (null) oder aus einer Sequenz gelesen (Text).
* @param autAnz Die Anzahl der Automaten, mit denen der Roboter
* ausgestattet sein soll.
* @param conds Die Bedingungen.
* @param trans Die Translatoren.
*/
private void init(
final String grName,
final Umgebung umg,
final EarleyErkenner earl,
final CondMutVerfahren mutVerh,
final CondMutVerfahren mutTrans,
final Random randm,
final int ident,
final String[] laden,
final int autAnz,
final Condition[] conds,
final Translator[] trans) {
this.aktVisTrans = new LinkedList<VisTrans>();
if (this.rob == null) {
this.rob = new Roboter(
0,
0,
0,
fmg.fmg8.umgebung2D.Konstanten.ROB_AUSDEHNUNG_X,
fmg.fmg8.umgebung2D.Konstanten.ROB_AUSDEHNUNG_Y,
umg,
earl,
mutVerh,
mutTrans,
ident,
this.pars,
randm,
this.isVisible(),
null,
new ScriptInterpreter(
this.pars,
ScriptInterpreter.MODUS_VERHALTEN),
autAnz,
trans);
this.robName = grName;
}
this.init2(autAnz);
if (conds != null) {
for (int i = 0; i < conds.length; i++) {
if (conds[i] != null) {
this.setzeCond(i, conds[i].toString());
}
}
}
if (laden == null) {
this.ladeRob();
this.setzeConds(this.getRob().getConds());
} else {
this.setzeSeqs(laden);
this.rob.erzeugeAusSequenzen(laden, conds, null, false);
}
this.aktGraph = this.darstArten[this.aktAut].erzeuge(
this.rob.vAuts()[this.aktAut], this.selKnot[this.aktAut]);
this.setzeSeqs(this.rob.erzeugeStrSeqs());
}
/**
* Die zweite Initialisierungsmethode (�brige Variablen).
*
* @param autAnz Die Anzahl der Automaten pro Roboter.
*/
private void init2(final int autAnz) {
this.removeAll();
this.setSize(800, 730);
this.addWindowListener(new WindHideAdapt());
this.darstArten = new DarstModEA[autAnz];
for (int i = 0; i < autAnz; i++) {
this.darstArten[i] = new DarstModEA(
50,
Konstanten.OBEN,
this.getWidth() - 50,
this.getHeight() - 50);
}
this.zwischenablage = new Zwischenablage();
this.zeichenArt = new PfeilMaster(this.pars);
this.selKnot = new Knoten[autAnz];
this.gewKnot = null;
this.setLayout(new BorderLayout());
JPanel editPanel = new JPanel();
editPanel.setLayout(new GridBagLayout());
Panel masterPanel = new Panel();
masterPanel.setLayout(new BorderLayout());
editPanel.setPreferredSize(new Dimension(600, 20 * autAnz));
JScrollPane scroll = new JScrollPane(editPanel);
scroll.setPreferredSize(new Dimension(400, 100));
this.sequenzen = new JTextField[autAnz];
this.groessen = new JLabel[autAnz];
this.conditions = new JTextField[autAnz];
for (int i = 0; i < autAnz; i++) {
this.sequenzen[i] = new JTextField("", 40);
this.groessen[i] = new JLabel("(9999 Bytes)", Label.LEFT);
this.conditions[i] = new JTextField("423", 20);
editPanel.add(this.groessen[i], this.getGridBagConstraint());
editPanel.add(this.sequenzen[i], this.getGridBagConstraint3());
editPanel.add(this.conditions[i], this.getGridBagConstraint4());
this.sequenzen[i].addMouseListener(new MouseAdapter() {
public void mousePressed(final MouseEvent event) {
int i = Vis.this.seqNum((JTextField) event.getComponent());
Vis.this.selectAktAut(false, i);
if (event.getButton() == 3) {
Vis.this.showTrans(i);
}
}
}
);
this.conditions[i].addMouseListener(new MouseAdapter() {
public void mousePressed(final MouseEvent event) {
int i = Vis.this.condNum((JTextField) event.getComponent());
Vis.this.selectAktAut(false, i);
}
}
);
}
this.setzeConds(this.getRob().getConds());
this.selectAktAut(true, this.aktAut);
masterPanel.add(scroll);
this.add(masterPanel, BorderLayout.NORTH);
editPanel.add(new JLabel(), getGridBagConstraintEnd());
this.setResizable(true);
}
/**
* Dummy.
*
* @return Dummy.
*/
private GridBagConstraints getGridBagConstraint() {
GridBagConstraints c = new GridBagConstraints();
c.weightx = 0.5;
c.weighty = 0;
c.gridx = 1;
c.gridy = this.row;
c.anchor = GridBagConstraints.LINE_START;
return c;
}
/**
* Dummy.
*
* @return Dummy.
*/
private GridBagConstraints getGridBagConstraint3() {
GridBagConstraints c = new GridBagConstraints();
c.weightx = 0;
c.weighty = 0;
c.gridx = 3;
c.gridy = this.row;
c.anchor = GridBagConstraints.LINE_START;
return c;
}
/**
* Dummy.
*
* @return Dummy.
*/
private GridBagConstraints getGridBagConstraint4() {
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(0, 10, 0, 0);
c.weightx = 1;
c.weighty = 0;
c.gridx = 4;
c.gridy = this.row++;
c.anchor = GridBagConstraints.LINE_START;
return c;
}
/**
* Dummy.
*
* @return Dummy.
*/
private GridBagConstraints getGridBagConstraintEnd() {
GridBagConstraints x = new GridBagConstraints();
row++;
x.gridx = 5;
x.gridy = 100;
x.weightx = 1;
x.weighty = 1;
x.anchor = GridBagConstraints.LINE_START;
return x;
}
/**
* Selektiert einen Automaten als den aktiven Automaten.
*
* @param init Ob initial alle Farben gesetzt werden sollen.
* @param autNum Die Nummer des zu selektierenden Automaten.
*/
private void selectAktAut(
final boolean init,
final int autNum) {
if (init || this.aktAut != autNum) {
for (int i = 0; i < this.sequenzen.length; i++) {
this.sequenzen[i].setBackground(Color.white);
this.sequenzen[i].setForeground(Color.black);
this.groessen[i].setBackground(Color.white);
this.groessen[i].setForeground(Color.black);
}
this.sequenzen[autNum].setBackground(new Color(50, 0, 100));
this.sequenzen[autNum].setForeground(Color.yellow);
this.groessen[this.benutztAut].setForeground(Color.blue);
this.aktAut = autNum;
this.neuZeichnen();
}
}
/**
* Zeigt das Translatorfenster eines der aktuellen Automaten an.
*
* @param autNum Die Nummer des anzuzeigenden Translators.
*/
private void showTrans(final int autNum) {
for (VisTrans v : this.aktVisTrans) {
v.dispose();
}
this.aktVisTrans.clear();
VisTrans v = new VisTrans(
"Translator ["
+ this.robName
+ " - "
+ autNum
+ "]",
this.getRob().getTranslatoren()[autNum],
this.pars);
this.aktVisTrans.add(v);
v.neuZeichnen();
v.setVisible(true);
}
/**
* Gibt die zu einem der Textfelder, die eine Sequenz beinhalten geh�rige
* Automatennummer zur�ck.
*
* @param txt Die Sequenz, deren Nummer gesucht werden soll.
*
* @return Die Nummer des Automaten, der zu der Sequenz geh�rt. Falls
* es keinen solchen Automaten gibt, wird -1 zur�ckgegeben.
*/
private int seqNum(final JTextField txt) {
for (int i = 0; i < this.sequenzen.length; i++) {
if (this.sequenzen[i] == txt) {
return i;
}
}
return -1;
}
/**
* Gibt die zu einer der Bedingungen geh�rende
* Automatennummer zur�ck.
*
* @param cond Die Sequenz, deren Nummer gesucht werden soll.
*
* @return Die Nummer des Automaten, der zu der Sequenz geh�rt. Falls
* es keinen solchen Automaten gibt, wird -1 zur�ckgegeben.
*/
private int condNum(final JTextField cond) {
for (int i = 0; i < this.sequenzen.length; i++) {
if (this.conditions[i] == cond) {
return i;
}
}
return -1;
}
/**
* Die Startmethode des (urspr�nglichen) Applets.
*
* @param eingesch
* Ob die initialisierung eingeschr�nkt erfolgen soll, in diesem
* Fall werden nur die Listener initialisiert, die keine
* Ver�nderung an Graphen vornehmen.
*/
private void start(final boolean eingesch) {
this.addComponentListener(new ComponentListener() {
@Override
public void componentHidden(final ComponentEvent e) {
}
@Override
public void componentMoved(final ComponentEvent e) {
}
@Override
public void componentResized(final ComponentEvent e) {
for (int i = 0; i < Vis.this.getRob().getVAut().length; i++) {
Vis.this.darstArten[i].setAusd(50,
Konstanten.OBEN,
Vis.this.getWidth() - 50,
Vis.this.getHeight() - 50);
}
}
@Override
public void componentShown(final ComponentEvent e) {
}
}
);
if (eingesch) {
this.addMouseListener(new MouseAdapter() {
public void mousePressed(final MouseEvent event) {
if (!Vis.this.simLaueft) {
final int x = event.getX();
final int y = event.getY();
final int radius = (int) (
fmg.fmg8.graphVis.zeichenModi.Konstanten.KN_DURCHM)
/ 2;
ArrayList<Knoten> naKn;
naKn = Vis.this.aktGraph.holeUmObj(x, y, radius);
if (naKn.size() > 0) {
Vis.this.gewKnot = (Knoten) naKn.get(0);
Vis.this.selKnot[Vis.this.aktAut] = (Knoten) naKn
.get(0);
} else {
Vis.this.selKnot[Vis.this.aktAut] = null;
}
Vis.this.neuZeichnen();
}
}
public void mouseReleased(final MouseEvent event) {
Vis.this.gewKnot = null;
}
});
this.addKeyListener(new KeyListener() {
/**
* Die Key-Typed-Methode.
*/
public void keyTyped(final KeyEvent e) {
// throw new RuntimeException("Taste wurde gedr�ckt.");
}
/**
* Die Key-Released-Methode.
*/
public void keyReleased(final KeyEvent e) {
// throw new RuntimeException("Taste wurde losgelassen.");
}
/**
* Die Key-Pressed-Methode.
*/
public void keyPressed(final KeyEvent e) {
if (e.getKeyCode() == java.awt.event.KeyEvent.VK_C) {
if (e.isControlDown()) {
String copy = Vis.this.holeAktGrSeq();
SonstMeth.log(SonstMeth.LOG_DEBUG,
"In Zwischenablage (" + copy + ")",
Vis.this.pars);
Vis.this.zwischenablage.copyToClipboard(copy);
}
}
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(final MouseEvent event) {
int x = event.getX();
int y = event.getY();
int un = Vis.this.getSize().height - 50;
int re = Vis.this.getSize().width - 50;
int li = 50;
if (Vis.this.gewKnot != null) {
if (x < li) {
x = li;
}
if (x > re) {
x = re;
}
if (y < Konstanten.OBEN) {
y = Konstanten.OBEN;
}
if (y > un) {
y = un;
}
Vis.this.darstArten[Vis.this.aktAut].neueKoord(
Vis.this.gewKnot, x, y);
Vis.this.aktGraph = Vis.this.darstArten[Vis.this.aktAut]
.erzeuge(Vis.this.rob.vAuts()[Vis.this.aktAut],
Vis.this.selKnot[Vis.this.aktAut]);
Vis.super.update(Vis.this.getGraphics());
Vis.this.repaint();
}
}
});
return;
}
this.addKeyListener(new KeyListener() {
/**
* Die Key-Typed-Methode.
*/
public void keyTyped(final KeyEvent e) {
}
/**
* Die Key-Released-Methode.
*/
public void keyReleased(final KeyEvent e) {
}
/**
* Die Key-Pressed-Methode.
*/
public void keyPressed(final KeyEvent e) {
if (e.getKeyCode() == java.awt.event.KeyEvent.VK_C) {
if (e.isControlDown()) {
String copy = Vis.this.holeAktGrSeq();
SonstMeth.log(SonstMeth.LOG_DEBUG,
"In Zwischenablage (" + copy + ")",
Vis.this.pars);
Vis.this.zwischenablage.copyToClipboard(copy);
}
}
if (e.getKeyCode() == java.awt.event.KeyEvent.VK_V) {
if (e.isControlDown()) {
String copy = Vis.this.zwischenablage.getClipbB();
SonstMeth.log(
SonstMeth.LOG_DEBUG,
"Aus Zwischenablage mit Standardtranslator ("
+ copy
+ ")",
Vis.this.pars);
Vis.this.erzeugeAktAusSequenz(copy, null, false);
Vis.this.steuer.loescheSelKnot();
Vis.this.repaint();
}
}
}
});
this.addMouseListener(new MouseAdapter() {
public void mousePressed(final MouseEvent event) {
if (!Vis.this.simLaueft) {
final int x = event.getX();
final int y = event.getY();
final int radius = (int) (
fmg.fmg8.graphVis.zeichenModi.Konstanten.KN_DURCHM) / 2;
ArrayList<Knoten> naKn;
naKn = Vis.this.aktGraph.holeUmObj(x, y, radius);
if (naKn.size() > 0) {
Vis.this.gewKnot = (Knoten) naKn.get(0);
Vis.this.selKnot[Vis.this.aktAut] = (Knoten) naKn
.get(0);
} else {
Vis.this.selKnot[Vis.this.aktAut] = null;
}
Vis.this.neuZeichnen();
}
}
public void mouseClicked(final MouseEvent event) {
if (!Vis.this.simLaueft) {
if (event.getButton() == 1 && event.getClickCount() == 2) {
final int x = event.getX();
final int y = event.getY();
final int radius = (int) (
fmg.fmg8.graphVis.zeichenModi.Konstanten.KN_DURCHM)
/ 2;
ArrayList<Knoten> naKn;
naKn = Vis.this.aktGraph.holeUmObj(x, y, radius);
if (naKn.size() > 0) {
Vis.this.rob.vAuts()[Vis.this.aktAut]
.setStart((Knoten) naKn.get(0));
} else {
Vis.this.rob.vAuts()[Vis.this.aktAut]
.entferneStartZ();
}
Vis.this.neuZeichnen();
Vis.this.steuer
.selKn(Vis.this.selKnot[Vis.this.aktAut]);
} else if (event.getButton() == 3
&& event.getClickCount() == 2) {
final int x = event.getX();
final int y = event.getY();
final int radius = (int) (
fmg.fmg8.graphVis.zeichenModi.Konstanten.KN_DURCHM)
/ 2;
ArrayList<Knoten> naKn;
naKn = Vis.this.aktGraph.holeUmObj(x, y, radius);
if (naKn.size() > 0) {
Vis.this.rob.vAuts()[Vis.this.aktAut]
.einfStern(((Knoten) naKn.get(0))
.holeName(),
new ArrayList<Integer>(Vis.this.rob
.vAuts()[Vis.this.aktAut]
.holAdj().keySet()));
Vis.this.neuZeichnen();
Vis.this.steuer
.selKn(Vis.this.selKnot[Vis.this.aktAut]);
}
} else if (event.getButton() == 3
&& event.getClickCount() == 3) {
final int x = event.getX();
final int y = event.getY();
final int radius = (int) (
fmg.fmg8.graphVis.zeichenModi.Konstanten.KN_DURCHM)
/ 2;
ArrayList<Knoten> naKn;
naKn = Vis.this.aktGraph.holeUmObj(x, y, radius);
if (naKn.size() == 0) {
Vis.this.rob.vAuts()[Vis.this.aktAut]
.einfClique(new ArrayList<Integer>(
Vis.this.rob.vAuts()[Vis.this.aktAut]
.holAdj().keySet()));
Vis.this.neuZeichnen();
Vis.this.steuer
.selKn(Vis.this.selKnot[Vis.this.aktAut]);
}
}
}
}
public void mouseReleased(final MouseEvent event) {
if (!Vis.this.simLaueft) {
Vis.this.gewKnot = null;
Vis.this.steuer.selKn(Vis.this.selKnot[Vis.this.aktAut]);
}
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(final MouseEvent event) {
int x = event.getX();
int y = event.getY();
int un = Vis.this.getSize().height - 50;
int re = Vis.this.getSize().width - 50;
int li = 50;
if (Vis.this.gewKnot != null) {
if (x < li) {
x = li;
}
if (x > re) {
x = re;
}
if (y < Konstanten.OBEN) {
y = Konstanten.OBEN;
}
if (y > un) {
y = un;
}
Vis.this.darstArten[Vis.this.aktAut].neueKoord(
Vis.this.gewKnot, x, y);
Vis.this.aktGraph = Vis.this.darstArten[Vis.this.aktAut]
.erzeuge(Vis.this.rob.vAuts()[Vis.this.aktAut],
Vis.this.selKnot[Vis.this.aktAut]);
Vis.super.update(Vis.this.getGraphics());
Vis.this.repaint();
}
}
});
}
/**
* W�hlt einen Knoten in einem Graph aus wie beim Klick-Ereignis.
* Im Unterschied zum Klickereignis, werden jedoch alle Knoten der nicht
* aktiven Graphen auf null gesetzt.
*
* @param k Der auszuw�hlende Knoten.
* @param autNum Der Automat, dessen Knoten gew�hlt werden soll.
*/
public void selKnoten(final Knoten k, final int autNum) {
for (int i = 0; i < this.rob.vAuts().length; i++) {
this.selKnot[i] = null;
}
if (k != null) {
Integer aktKnot;
Iterator<Integer> it = this.getRob().vAuts()[autNum]
.getKnList().iterator();
while (it.hasNext()) {
aktKnot = (Integer) it.next();
if (aktKnot.equals(k.holeName())) {
this.selKnot[autNum]
= this.getRob().vAuts()[autNum].holeKnoten(aktKnot);
this.steuer.selKn(this.selKnot[autNum]);
this.neuZeichnenOhneUpdate();
break;
}
}
}
}
/**
* Setzt die Knotenpositionen des aktuellen Graphen zur�ck.
*/
public void zuruecksetzen() {
this.zuruecksetzen(this.aktAut);
}
/**
* Setzt die Knotenpositionen des angegebenen Automaten zur�ck.
*
* @param num Die Nummer des Automaten.
*/
public void zuruecksetzen(final int num) {
this.darstArten[num].loescheKnotenKoord();
this.aktGraph = this.darstArten[num].erzeuge(
this.rob.vAuts()[num], this.selKnot[num]);
if (num == this.aktAut) {
this.repaint();
}
}
/**
* Zeichnet den Graphen neu mit L�schen des Bildschirms.
*/
public void neuZeichnen() {
this.setzeSeqs(this.rob.erzeugeStrSeqs());
this.aktGraph = this.darstArten[this.aktAut].erzeuge(
this.rob.vAuts()[this.aktAut], this.selKnot[this.aktAut]);
super.update(this.getGraphics());
this.repaint();
}
/**
* Zeichnet den Graphen neu ohne L�schen der Bildschirms.
*/
public void neuZeichnenOhneUpdate() {
this.setzeSeqs(this.rob.erzeugeStrSeqs());
this.aktGraph = this.darstArten[this.aktAut].erzeuge(
this.rob.vAuts()[this.aktAut], this.selKnot[this.aktAut]);
this.zaehler++;
if (zaehler % 30 == 0) {
super.update(this.getGraphics());
}
this.repaint();
}
/**
* Setzt einen String, aber ber�cksichtigt das Kontrollzeichen '\n'.
*
* @param g Das Grafikobjekt.
* @param s Der String.
* @param x X-Koordinate.
* @param y Y-Koordinate.
*/
public void setzeString(final Graphics g, final String s, final int x,
final int y) {
int returnPos;
String schreibe;
String rest;
Font font;
if (s.length() > 0) {
font = g.getFont();
g.setFont(new Font("Monospaced", Font.BOLD, font.getSize()));
returnPos = s.indexOf("\n");
if (returnPos < 0) {
returnPos = s.length() - 1;
} else if (returnPos >= s.length()) {
returnPos = s.length() - 1;
}
schreibe = s.substring(0, returnPos);
rest = s.substring(returnPos + 1, s.length());
g.drawString(schreibe, x, y);
this.setzeString(g, rest, x, y + 14);
g.setFont(font);
}
}
/**
* Methode zum Vorbereiten vor dem Neuzeichnen.
*
* @param g
* Das Graphics-Objekt.
*/
public void update(final Graphics g) {
this.paint(g);
}
/**
* Zeichenmethode.
*
* @param g
* Das Grafikobjekt.
*/
public void paint(final Graphics g) {
for (int i = 0; i < this.sequenzen.length; i++) {
if (this.sequenzen != null && this.sequenzen[i] != null) {
this.groessen[i].setText("("
+ (this.sequenzen[i].getText().length() + 2) / 5
+ " Bytes)");
}
this.conditions[i].setText(rob.getConds()[i].toString());
}
fmg.fmg8.graphVis.zeichenModi.Geometrie2D.maleObjListe(
g,
this.zeichenArt.graph(this.aktGraph),
this.pars);
this.requestFocus();
}
/**
* L�scht den Graph von der Festplatte, der den gleichen Namen tr�gt wie
* <code>this</code> und die zugeh�rigen Koordinaten.
*
* @return <code>true</code>, gdw. der Graph UND die Koordinaten
* erfolgreich gel�scht wurde.
*/
public boolean loescheGraphDateien() {
File loeschen1 = new File(this.pars.getStdPfad() + File.separator
+ this.robName + ".gra");
File loeschen2 = new File(this.pars.getStdPfad() + File.separator
+ this.robName + ".koo");
File loeschen3 = new File(this.pars.getStdPfad() + File.separator
+ this.robName + ".con");
File loeschen4 = new File(this.pars.getStdPfad() + File.separator
+ this.robName + ".tmp");
// L�scht
return loeschen1.delete()
&& loeschen2.delete()
&& loeschen3.delete()
&& loeschen4.delete();
}
/**
* Setzt die Sequenzen der Automaten im Fenster.
*
* @param seqs
* Die zu setzenden Sequenzen.
*/
private void setzeSeqs(final String[] seqs) {
for (int i = 0; i < this.sequenzen.length; i++) {
this.sequenzen[i].setText(seqs[i]);
}
}
/**
* L�dt den Roboter mit den Koordinaten der Knoten.
*/
public void ladeRob() {
String pfad = this.pars.getStdPfad() + File.separator;
DarstModEA[] alt = new DarstModEA[this.darstArten.length];
String[] leereSeqs = new String[this.sequenzen.length];
for (int i = 0; i < this.darstArten.length; i++) {
alt[i] = this.darstArten[i];
}
for (int i = 0; i < leereSeqs.length; i++) {
leereSeqs[i] = "";
}
if (this.simLaueft) {
throw new RuntimeException("Darf nicht aufgerufen werden, solange"
+ "eine Simulation l�uft.");
}
// Roboter laden.
try {
this.rob.ladeAuts(this.robName);
this.init2(rob.vAuts().length);
if (this.isVisible()) {
this.setVisible(true);
}
} catch (Exception e) {
SonstMeth.log(SonstMeth.LOG_WARNING, "Sequenzen nicht gelesen: "
+ this.robName, this.pars);
this.setzeSeqs(leereSeqs);
}
// Koordinaten laden.
try {
DarstModEA[] darArt;
FileInputStream fs = new FileInputStream(pfad + this.robName + "."
+ fmg.fmg8.graphVis.Konstanten.KOORD_ENDUNG);
ObjectInputStream is = new ObjectInputStream(fs);
darArt = (DarstModEA[]) is.readObject();
for (int i = 0; i < this.darstArten.length; i++) {
if (i < darArt.length) {
this.darstArten[i] = darArt[i];
}
}
is.close();
} catch (Exception e) {
SonstMeth.log(SonstMeth.LOG_WARNING, "Kordinaten nicht gelesen: "
+ this.robName, this.pars);
}
}
/**
* Speichert den Graphen mit den Koordinaten der Knoten.
*
* @param anweisung
* Zus�tzliche opt. Anweisung, die angibt durch "Alle" oder
* "Keinen" angibt, dass ohne Sicherheitsabfrage die
* entsprechende Aktion durchgef�hrt wird.
*
* @return Text des vom Benutzer angeklickten Buttons.
*/
public String speichereGraph(final String anweisung) {
String pfad = this.pars.getStdPfad() + File.separator;
ArrayList<String> buttons = new ArrayList<String>();
String ja = Messages.getString("Vis.Yes");
String nein = Messages.getString("Vis.No");
String alle = Messages.getString("Vis.All");
String keiner = Messages.getString("Vis.None");
String abbrechen = Messages.getString("Vis.Cancel");
buttons.add(ja);
buttons.add(nein);
buttons.add(alle);
buttons.add(keiner);
buttons.add(abbrechen);
AllgemeinerDialog nachfrage;
nachfrage = new AllgemeinerDialog(this, Messages
.getString("Vis.SollDerEndlicheAutomat")
+ this.robName + Messages.getString("Vis.GespeichertWerden"),
Messages.getString("Vis.saveGraph"), buttons, null);
if (!anweisung.equals(alle) && !anweisung.equals(keiner)) {
nachfrage.setVisible(true);
}
if (anweisung.equals(alle) || nachfrage.getResult().equals(ja)
|| nachfrage.getResult().equals(alle)) {
this.rob.speichereAuts(this.robName);
if (this.pars.getpngAutSp()) {
this.savePNG(this.robName);
}
try {
FileOutputStream fs = new FileOutputStream(pfad + this.robName
+ "." + fmg.fmg8.graphVis.Konstanten.KOORD_ENDUNG);
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(this.darstArten);
os.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
if (anweisung.equals(alle) || anweisung.equals(keiner)) {
return anweisung;
} else {
return nachfrage.getResult();
}
}
/**
* Erzeugt die Translatoren neu aus Standardsequenzen.
*
* @param seqs Die Standardsequenzen.
*/
public void erzeugeTransAusStdSeqs(final String[] seqs) {
this.rob.erzTransAusSeqs(seqs, null, false);
}
/**
* Erzeugt einen Automaten des Roboters aus der �bergebenen Sequenz und
* richtet die entsprechenden Bildschirmausgaben ein.
*
* @param autNum Die Nummer des zu erzeugenden Automaten.
* @param seq Die Automatensequenz.
* @param cond Die Bedingung.
* @param pruefen Ob die Sequenz auf grammatische Fehler gepr�ft werden
* soll.
*/
public void erzeugeAusSequenz(final int autNum,
final String seq,
final Condition cond,
final boolean pruefen) {
this.rob.erzeugeAusSequenz(autNum, seq, cond, null, pruefen);
this.setzeCond(autNum, this.rob.getConds()[autNum].toString());
// Vis.super.update(Vis.this.getGraphics());
this.neuZeichnen();
}
/**
* Erzeugt den aktiven Automaten des Roboters aus der �bergebenen Sequenz
* und richtet die entsprechenden Bildschirmausgaben ein.
*
* @param seq Die Automatensequenz.
* @param cond Die Bedingung.
* @param pruefen Ob die Sequenz auf grammatische Fehler gepr�ft werden
* soll.
*/
public void erzeugeAktAusSequenz(final String seq,
final Condition cond,
final boolean pruefen) {
this.erzeugeAusSequenz(this.aktAut, seq, cond, pruefen);
}
/**
* Erzeugt alle Automaten des Roboters aus den �bergebenen Sequenzen
* und richtet die entsprechenden Bildschirmausgaben ein.
*
* @param seqs Die Automatensequenz.
* @param conds Die Bedingungen.
* @param pruefen Ob die Sequenzen auf grammatische Fehler gepr�ft werden
* soll.
*/
public void erzeugeAlleAusSeq(final String[] seqs,
final Condition[] conds,
final boolean pruefen) {
for (int i = 0; i < this.rob.vAuts().length; i++) {
this.rob.erzeugeAusSequenz(i, seqs[i], conds[i], null, pruefen);
}
this.neuZeichnen();
}
/**
* Setzt alle Sequenzen NUR in die Darstellung.
*
* @param seqs Die zu setzenden Sequenzen.
*/
public void setzeAlleSeq(final String[] seqs) {
for (int i = 0; i < this.sequenzen.length; i++) {
this.setzeSeq(i, seqs[i]);
}
}
/**
* Setzt die Sequenz des aktiven Automaten NUR in die Darstellung.
*
* @param s
* Die Sequenz.
*/
public void setzeAktSeq(final String s) {
this.setzeSeq(this.aktAut, s);
}
/**
* Setzt eine Sequenz NUR in die Darstellung.
*
* @param autNum Die Automatennummer.
* @param s Die zu setzende Sequenz.
*/
public void setzeSeq(final int autNum, final String s) {
this.sequenzen[autNum].setText(s);
}
/**
* Gibt die Sequenz des gerade aktiven Graphen von <code>this</code>
* zur�ck.
*
* @return Die Sequenz des Graphen.
*/
public String holeAktGrSeq() {
return this.getRob().erzeugeStringSequenz(aktAut);
}
/**
* Gibt den Sequenztext von <code>this</code> zur�ck.
*
* @return Der Text der Sequenz.
*/
public String holeAktTxtSeq() {
return this.sequenzen[this.aktAut].getText();
}
/**
* @return Returns the robot.
*/
public Roboter getRob() {
return this.rob;
}
/**
* Erzeugt eine Textausgabe von <code>this</code>.
*
* @return Textausgabe von <code>this</code>.
*/
public String toString() {
return this.robName;
}
/**
* @return Returns the selKnot of the active automaton.
*/
public Knoten getAktSelKnot() {
return this.selKnot[this.aktAut];
}
/**
* @return Returns the graphName.
*/
public String getGraphName() {
return this.robName;
}
/**
* Entfernt alle Knoten und Kanten des aktuell aktiven Graphen.
*/
public void leereAktGraph() {
this.leereGraph(this.aktAut);
}
/**
* Entfernt alle Knoten und Kanten eines Graphen.
*
* @param autNum Die Automatennummer.
*/
public void leereGraph(final int autNum) {
if (this.simLaueft) {
throw new RuntimeException("Darf nicht aufgerufen werden, solange"
+ "eine Simulation l�uft.");
}
this.rob.vAuts()[autNum].leereGraph();
}
/**
* Entfernt alle Knoten und Kanten aller Graphen.
*/
public void leereAlleGraphen() {
for (int i = 0; i < this.rob.vAuts().length; i++) {
this.leereGraph(i);
}
}
/**
* @param roboter The ea to set.
*/
public void setRob(final Roboter roboter) {
if (this.simLaueft) {
throw new RuntimeException("Darf nicht aufgerufen werden, solange"
+ "eine Simulation l�uft.");
}
this.rob = roboter;
}
/**
* @param simLf
* The simLaueft to set.
*/
public void setSimLaueft(final boolean simLf) {
this.simLaueft = simLf;
}
/**
* @return Returns the darstellArt.
*/
public DarstModEA[] getDarstellArt() {
return this.darstArten;
}
/**
* @param darstellArt The darstellArt to set.
*/
public void setDarstellArt(final DarstModEA[] darstellArt) {
this.darstArten = darstellArt;
}
/**
* Mutiert den zur Darstellung geh�renden Roboter (nicht den sich in der
* Simulation befindenden Roboter!).
*/
public void mutiere() {
if (this.simLaueft) {
throw new RuntimeException("Darf nicht aufgerufen werden, solange"
+ "eine Simulation l�uft.");
}
this.rob.mutiere();
this.rob.mutiereBeds();
this.setzeConds(this.rob.getConds());
this.repaint();
}
/**
* @param grName The graphName to set.
*/
public void setGraphName(final String grName) {
this.loescheGraphDateien();
this.robName = grName;
this.setTitle(Messages.getString("SteuerFenster.EA") + grName + "]");
this.speichereGraph(Messages.getString("Vis.All"));
}
/**
* Die Update-Methode des Observers.
*
* @param o
* Das observierte Objekt.
* @param arg
* Der Zusatzparameter.
*/
public void update(final Observable o, final Object arg) {
Knoten k;
AutomatenNummer aN;
ConditionNummer cN;
int autNum;
if (arg == null) {
return;
}
if (arg.getClass().equals(Integer.class)) {
// Neuer Automat wurde ausgew�hlt.
autNum = ((Integer) arg).intValue();
this.benutztAut = autNum;
this.selectAktAut(false, autNum);
} else if (arg.getClass().equals(Knoten.class)) {
// Neuer Knoten wurde ausgew�hlt.
k = (Knoten) arg;
this.selKnoten(k, this.benutztAut);
} else if (arg.getClass().equals(AutomatenNummer.class)) {
// Sequenz wurde ver�ndert.
aN = (AutomatenNummer) arg;
this.erzeugeAusSequenz(aN.getAutNum(),
aN.getSequenz(),
null,
false);
} else if (arg.getClass().equals(ConditionNummer.class)) {
// Bedingungen wurden ver�ndert.
cN = (ConditionNummer) arg;
this.setzeCond(cN.getAutNum(), cN.getSequenz());
for (VisTrans v : this.aktVisTrans) {
v.neuZeichnen();
}
}
}
/**
* @return Die Nummer des aktuell aktiven Automaten.
*/
public int getAktAut() {
return this.aktAut;
}
/**
* Setzt die Bedingungen NUR in der Darstellung.
*
* @param conds Die zu setzenden Bedingungen.
*/
public void setzeConds(final Condition[] conds) {
for (int i = 0; i < conds.length; i++) {
this.conditions[i].setText(conds[i].toString());
}
}
/**
* Setzt eine Bedingung in die Darstellung und den internen Roboter.
*
* @param i Die Nummer der Bedingung.
* @param cond Die Bedingung.
*/
private void setzeCond(final int i,
final String cond) {
this.rob.setCond(i, SonstMeth.ausBed(cond));
this.conditions[i].setText(cond);
}
/**
* @return Die conditions in der DARSTELLUNG!
*/
public String[] getConditions() {
String[] ss = new String[this.conditions.length];
for (int i = 0; i < this.conditions.length; i++) {
ss[i] = this.conditions[i].getText();
}
return ss;
}
/**
* Gibt die Sequenzen als Strings zur�ck.
*
* @return Die Sequenzen als Strings.
*/
public String[] getSeqs() {
String[] seqs = new String[this.sequenzen.length];
for (int i = 0; i < seqs.length; i++) {
seqs[i] = this.sequenzen[i].getText();
}
return seqs;
}
/**
* Speichert die Darstellung des aktuellen Automaten in eine PNG-Datei.
*
* @param datNam Der Name der Datei (ohne Erweiterung).
*/
public void savePNG(final String datNam) {
fmg.fmg8.graphVis.zeichenModi.Geometrie2D.saveObjectsToFile(
this.zeichenArt.graph(this.aktGraph),
datNam,
"png",
this.pars);
}
}