package lsystem;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.net.*;
/**
* Lindenmayer-System
* Belegarbeit AlgoDat WS99/SS2000, Aufgabe 8
*
* Kontroll-Panel.
*
* @author Christian Semrau
* Christian.Semrau@student.uni-magdeburg.de
*/
public class LSystemControls extends Panel
implements ItemListener, ActionListener {
/** das Applet */
private LSystemApplet applet;
/** internes LSystem */
// private LSystem LS;
private String[] Regeln;
/** aktuell angezeigte Regel */
private int aktuelleRegel;
/** der "Startknopf" */
private Button Berechnen;
/** der "Stopknopf" */
private Button Stop;
/** Beispiel-LSysteme */
Choice GruppenChoice;
LSystemChoiceGroup Gruppen;
/** die Eingabe-Felder */
private Choice Axiom, Regel;
private TextField RegelFeld, WinkelFeld, TiefeFeld, StartWinkelFeld;
/** Rekursionstiefe hoch/runter */
private Button TiefeHoch, TiefeRunter;
private TextField InfoZeile;
/** konnte die txt-Datei gelesen werden */
boolean couldReadFile;
Panel DataManage;
String aktCard;
private Button Manage;
Button Add;
Button Replace;
Button Remove;
TextArea LSystemArea;
/**
* Legt ein Kontroll-Panel an.
* Ist app==null, werden keine Komponenten angelegt (ausser GruppenChoice und
* Gruppen), sondern nur die Datei ausgewertet!
*
* @param L belegLsystem.LSystemApplet
*/
public LSystemControls(LSystemApplet app) {
applet = app;
GruppenChoice = new Choice();
Gruppen = new LSystemChoiceGroup(this, GruppenChoice);
ladeBeispiele();
if (app!=null){
Axiom = new Choice();
Regel = new Choice();
RegelFeld = new TextField(20);
WinkelFeld = new TextField(5);
TiefeFeld = new TextField(2);
StartWinkelFeld = new TextField(5);
TiefeHoch = new Button("+");
TiefeRunter = new Button("-");
InfoZeile = new TextField(20);
InfoZeile.setEditable(false);
// Axiom und Regel fuellen
for (int i=0; i<26; i++){
String s = Utils.letterString(i);
Axiom.addItem(s);
Regel.addItem(s);
}
Berechnen = new Button("Berechnen");
Stop = new Button("Stop");
Manage = new Button("Manage");
Add = new Button("Hinzufuegen");
Add.setActionCommand("Add");
Replace = new Button("Ersetzen");
Replace.setActionCommand("Replace");
Remove = new Button("Loeschen");
Remove.setActionCommand("Remove");
LSystemArea = new TextArea("",3,20,TextArea.SCROLLBARS_BOTH);
TiefeHoch.setActionCommand("TiefeHoch");
TiefeRunter.setActionCommand("TiefeRunter");
// wir wollen nicht "+" und "-" als ActionCommand
initGUI();
addListeners();
}
}
/**
* Reagiert auf die Buttons und einige TextFields.
* @param event java.awt.event.ActionEvent
*/
public void actionPerformed(ActionEvent event) {
Object obj = event.getSource();
if (obj instanceof Button){
String action = event.getActionCommand();
if (action.equals("TiefeHoch")){
// Tiefe aus dem Eingabefeld auslesen
int T = readTiefe();
// T<=0 bedeutet Fehler
// neue (erhoehte) Tiefe ins Eingabefeld schreiben
if (T>0) TiefeFeld.setText(""+(++T));
setInfo(copyTextFieldsToLSystem());
}else
if (action.equals("TiefeRunter")){
int T = readTiefe();
// T<=0 bedeutet Fehler, T darf nicht ==0 werden
if (T>1) TiefeFeld.setText(""+(--T));
setInfo(copyTextFieldsToLSystem());
}
if (action.equals("Berechnen")){
// alle Werte aus den Eingabefeldern holen
LSystem LS = copyTextFieldsToLSystem();
// LS ist null, wenn die Eingaben fehlerhaft sind
if (LS!=null){
setInfo(LS);
applet.startThread(LS);
}
}
if (action.equals("Stop")){
applet.stopThread();
}
if (action.equals("Manage")){
if ("Data".equals(aktCard)){
LSystemChoice LSC = Gruppen.aktChoice;
Remove.setEnabled(LSC.Name.equals("default"));
LSystem L = copyTextFieldsToLSystem();
LSystemArea.setText(L.toString()+'\n');
aktCard = "Manage";
}else{
aktCard = "Data";
}
selectCard(aktCard);
}
if ("Add".equals(action)){
String S = LSystemArea.getText();
// System.out.println(Utils.specString(S));
parseAdd("default", Utils.splitIntoLines(S));
selectCard("Data");
}else
if ("Replace".equals(action)){
String S = LSystemArea.getText();
// System.out.println(Utils.specString(S));
parseReplace(Utils.splitIntoLines(S));
selectCard("Data");
}else
if ("Remove".equals(action)){
String S = LSystemArea.getText();
// System.out.println(Utils.specString(S));
parseRemove(Utils.splitIntoLines(S));
selectCard("Data");
}
}//if (obj instanceof Button)
else
if (obj==TiefeFeld){
// System.out.println(event);
setInfo(copyTextFieldsToLSystem());
}else
if (obj==RegelFeld){
andereRegel();
// setInfo(copyTextFieldsToLSystem());
}
}//actionPerformed
/**
* Listener fuer die Komponenten registrieren.
*/
public void addListeners() {
// GruppenChoice und Gruppen haben ihren eigenen Listener
Axiom.addItemListener(this);
Regel.addItemListener(this);
Berechnen.addActionListener(this);
Stop.addActionListener(this);
TiefeHoch.addActionListener(this);
TiefeRunter.addActionListener(this);
TiefeFeld.addActionListener(this);
RegelFeld.addActionListener(this);
}
/**
* Sichert die vorige Regel und schreibt die aktuelle Regel.
*/
private void andereRegel() {
// Sichert die vorige Regel (auch wenn sie fehlerhaft ist)
String R = RegelFeld.getText();
if (LSystem.regelOK(R)){
Regeln[aktuelleRegel] = R;
// Schreibt die neue Regel ins Eingabefeld
setRegelText();
setInfo(copyTextFieldsToLSystem());
}else{
Regel.select(aktuelleRegel);
InfoZeile.setText("Fehler in Regel");
}
}
/**
* Kopiert das LSystem in die Textfelder.
*/
public void copyLSystemToTextFields(LSystem L) {
L = new LSystem(L); // Kopie anlegen, Fehler werden dabei bereinigt
int i = L.getAxiom()-'A';
Axiom.select(i); // waehlt Index aus
Regel.select(i); // waehlt Index aus
Regeln = L.getRegeln();
setRegelText();
WinkelFeld.setText(""+L.getWinkel());
TiefeFeld.setText(""+L.getTiefe());
StartWinkelFeld.setText(""+L.getStartWinkel());
setInfo(L);
}
/**
* Liefert das eingegebene LSystem, oder null, wenn es fehlerhaft ist.
*/
public LSystem copyTextFieldsToLSystem() {
String r = RegelFeld.getText();
if (!LSystem.regelOK(r)){
InfoZeile.setText("Fehler in Regel");
return null;
}else{
Regeln[aktuelleRegel] = r;
}
String name = Gruppen.aktChoice.getSelectedItem();
char axiom = Utils.letter(Axiom.getSelectedIndex());
float winkel=readWinkel();
int tiefe=readTiefe();
float startWinkel=readStartWinkel();
if (winkel>1e6) return null;
if (tiefe<0) return null;
if (startWinkel>1e6) return null;
return new LSystem(name, axiom, Regeln, winkel, tiefe, startWinkel);
}
/**
*
*/
public void initGUI() {
GridBagLayout gbl = new GridBagLayout();
GridBagConstraints gbc;
setLayout(gbl);
Panel p;
FlowLayout l = new FlowLayout(FlowLayout.LEFT,5,5);
// setBackground(Color.blue);
p = new Panel(l);
p.add(Berechnen);
p.add(Stop);
p.add(Manage);
Manage.addActionListener(this);
gbc = Utils.makegbc(0,0,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
add(p);
Panel p1 = initGUIData();
Panel p2 = initGUIManage();
DataManage = new Panel(new CardLayout(0,0));
DataManage.add("Data", p1);
DataManage.add("Manage", p2);
gbc = Utils.makegbc(0,1,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(DataManage, gbc);
add(DataManage);
aktCard = "Data";
}
/**
*
*/
public Panel initGUIData() {
GridBagLayout gbl = new GridBagLayout();
GridBagConstraints gbc;
Panel p;
FlowLayout l = new FlowLayout(FlowLayout.LEFT,5,5);
Panel D = new Panel();
D.setLayout(gbl);
// D.setBackground(Color.lightGray);
int line = 0;
p = new Panel(l);
p.add(GruppenChoice);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
D.add(p);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(Gruppen, gbc);
D.add(Gruppen);
p = new Panel(l);
p.add(new Label("Axiom:",Label.LEFT));
p.add(Axiom);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
D.add(p);
p = new Panel(l);
p.add(new Label("Regel:",Label.LEFT));
p.add(Regel);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
D.add(p);
p = new Panel(l);
p.add(RegelFeld);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
D.add(p);
p = new Panel(l);
p.add(new Label("Winkel:",Label.LEFT));
p.add(WinkelFeld);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
D.add(p);
p = new Panel(l);
p.add(new Label("Tiefe:",Label.LEFT));
p.add(TiefeFeld);
p.add(TiefeHoch);
p.add(TiefeRunter);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
D.add(p);
p = new Panel(l);
p.add(new Label("StartWinkel:",Label.LEFT));
p.add(StartWinkelFeld);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
D.add(p);
p = new Panel(l);
p.add(InfoZeile);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
D.add(p);
return D;
}
/**
*
*/
public Panel initGUIManage() {
GridBagLayout gbl = new GridBagLayout();
GridBagConstraints gbc;
Panel p;
FlowLayout l = new FlowLayout(FlowLayout.LEFT,5,5);
int line = 0;
Panel D = new Panel();
D.setLayout(gbl);
// D.setBackground(Color.green);
p = new Panel(l);
p.add(Add);
p.add(Replace);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
D.add(p);
p = new Panel(l);
p.add(Remove);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.NONE);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(p, gbc);
D.add(p);
gbc = Utils.makegbc(0,line++,1,1,GridBagConstraints.HORIZONTAL);
gbc.anchor = GridBagConstraints.WEST;
// gbc.weightx = 100;
gbl.setConstraints(LSystemArea, gbc);
D.add(LSystemArea);
Add.addActionListener(this);
Replace.addActionListener(this);
Remove.addActionListener(this);
return D;
}
/**
* Reagiert auf ItemEvents der Choice-Objekte.
* @param event java.awt.event.ItemEvent
*/
public void itemStateChanged(ItemEvent event) {
// System.out.println(event);
ItemSelectable source = event.getItemSelectable();
if (source==Axiom){
// wenn das Axiom geaendert wird, wird auch eine andere Regel angezeigt.
Regel.select(Axiom.getSelectedIndex());
andereRegel();
}else
if (source==Regel){
andereRegel();
}
}
/**
* Laedt die Beispiel-LSysteme.
* Es wird dafuer gesorgt, dass kein Name doppelt in der Liste ist.
* @return belegLsystem.LSystem[]
*/
private void ladeBeispiele() {
String fn = "lsystem/lsystems.txt";
if (applet!=null){
String s = applet.getParameter2("IniFile");
if (s!=null) fn = s;
}
String[] S = null;
if (applet==null)
S = Utils.readStringArray(fn);
else{
URL base = applet.getDocumentBase2();
if (base!=null)
S = Utils.readFile(base, fn);
else
S = Utils.readStringArray(fn);
}
// Beispiele einlesen
couldReadFile = (S!=null);
parseAdd("IniDefault", S);
// Beispiele parsen und LSysteme erzeugen
if (!couldReadFile){
// nur wenn die Datei nicht gelesen werden konnte
LSystemChoice LSC = Gruppen.getChoice("IniDefault");
LSC.addLSystem(new LSystem("Koch-Kurve", 'F', "F:F-F++F-F;", 60, 5, 0));
LSC.addLSystem(new LSystem("Busch", 'F', "F:FF-[-F+F+F]+[+F-F-F];", 22.5f, 4, -70));
LSC.addLSystem(new LSystem("Baumkurve", 'F', "F:[-G][+G];G:H<50[+G][-G];", 45, 7, -90));
LSC.addLSystem(new LSystem("Drachenkurve", 'F', "F:F+G;G:F-G;", 90, 12, 0));
LSC.addLSystem(new LSystem("Hilbertkurve", 'X', "X:-YF+XFX+FY-; Y:+XF-YFY-FX+;", 90, 4, 0));
LSC.addLSystem(new LSystem("quadratische Kochkurve", 'F', "F:F-F+F+F-F;", 90, 3, 0));
LSC.addLSystem(new LSystem("Baumgruppe", 'L', "L:LF[/90X]F; X:F-[X][+X]+F[+FX]-X; F:FF;", 22, 6, 0));
LSC.addLSystem(new LSystem("Sierpinski", 'F', "F:G+F+G;G:F-G-F;", 60, 6, 0));
/*
new LSystem("ChS Initialen :-)", 'F',
"F:[_EHEEHE](E)[/90EG[JEJGE]GGGE](EEGG)[EGIEIEJEJGE]; "+
"E:EE; H:+>41G+G+; I:-<29G-G-; J:+<29G+G+;",
30, 2, 0).addToVector(v);
*/
}
}
/**
* Test-Routine.
*/
public static void main(String args[]) {
System.out.println("-");
LSystemControls LSC = new LSystemControls(null);
}
/**
* Verarbeitet das String-array und fuegt erzeugte LSysteme ein.
*/
private void parseAdd(String defGroup, String[] Sa) {
if (Sa==null||Sa.length<=0) return;
Vector sv2 = parseToVector(Sa);
String aktGroup = defGroup;
for(Enumeration e = sv2.elements(); e.hasMoreElements(); ){
String akt = (String)e.nextElement();
if (akt.startsWith("#[")){
if (akt.endsWith("]")){
aktGroup = akt.substring(2,akt.length()-1).trim();
}
}else{
if (akt.startsWith("(")){
LSystem L = new LSystem(akt);
// System.out.println(L);
Gruppen.addLSystem(aktGroup, L);
}
}
}
}
/**
* Verarbeitet das String-array und ersetzt erzeugte LSysteme.
*/
private void parseRemove(String[] Sa) {
if (Sa==null||Sa.length<=0) return;
Vector sv2 = parseToVector(Sa);
String aktGroup = "default";
for(Enumeration e = sv2.elements(); e.hasMoreElements(); ){
String akt = (String)e.nextElement();
// System.out.println("\""+akt+"\"");
if (akt.startsWith("#[")){
aktGroup = akt.substring(2,akt.length()-1);
// System.out.println(aktGroup);
}else{
if (akt.startsWith("(")){
String[] A = LSystem.splitLine(akt);
// System.out.println("t1");
// System.out.println(akt);
// LSystem L = new LSystem(akt);
// System.out.println("t2");
// System.out.println(L);
Gruppen.removeLSystem(aktGroup, A[0]); //L.getName());
}else
Gruppen.removeLSystem(aktGroup, akt);
}
}
}
/**
* Verarbeitet das String-array und ersetzt erzeugte LSysteme.
*/
private void parseReplace(String[] Sa) {
if (Sa==null||Sa.length<=0) return;
Vector sv2 = parseToVector(Sa);
String aktGroup = "default";
for(Enumeration e = sv2.elements(); e.hasMoreElements(); ){
String akt = (String)e.nextElement();
// System.out.println("\""+akt+"\"");
if (akt.startsWith("#[")){
aktGroup = akt.substring(2,akt.length()-1);
// System.out.println(aktGroup);
}else{
if (akt.startsWith("(")){
LSystem L = new LSystem(akt);
// System.out.println(L);
Gruppen.replaceLSystem(aktGroup, L);
}
}
}
}
/**
* Filtert aus dem array alle ueberfluessigen Zeilen und erstellt einen Vector.
* @return java.util.Vector
* @param S java.lang.String[]
*/
public static Vector parseToVector(String[] Sa) {
Vector sv = new Vector(Sa.length);
// Leerzeilen und Kommentare rausfiltern
int commentDepth = 0;
for (int i = 0; i