/************************************************************/ /* Netz.java Version 2003/03/28 */ /* */ /* Tom Fellmann, Christoph Weißenborn */ /* */ /************************************************************/ import java.awt.*; import java.io.*; import java.util.*; import javax.swing.*; /********************************************************************/ /* Klasse Netz */ /********************************************************************/ public class Netz extends JPanel /*implements Scrollable*/ { /***************************************************/ /* Petrinetz-Daten-Teil */ /***************************************************/ public static final Color HINTERGRUNDFARBE_KEINNETZ = new Color(112,112,112); public static final Color HINTERGRUNDFARBE_NETZ = new Color(144,144,144); public static final int TYP_NICHTDEF = 0; public static final int TYP_PLATZ = 1; public static final int TYP_TRANS = 2; public static final int TYP_KANTE = 3; public static final int MIN_FARBANZAHL=1; public static final int MAX_FARBANZAHL=15; public static final int MAX_FARBENDARSTELLANZ=8; //wenn ändern, dann die Arraygröße in Platz.java smartiesPunkte.radiuskoeff anpassen! public static final int MAX_MARKENDARSTELLANZ=8; //wenn ändern, dann die Arraygröße in Platz.java smartiesPunkte.radiuskoeff anpassen! public static final int MODUS_NICHTS=0; public static final int MODUS_EINGABE=1; public static final int MODUS_SIMULATION=2; public static final int KANTE_MARKEN_GROESSE = 12; // DURCHMESSER !! public static final int PLATZ_RADIUS=50; //30 public static final int TRANSITIONS_BREITE=30; //20 public static final int TRANSITIONS_HOEHE=30; //20 public static final int KOMPONENTEN_ABSTAND=65; // public static final int RAND_ABSTAND=10; // private static int Farbanzahl = 0; //ist nur in Interval [1..6] gültig, bei MODUS_NICHTS ist sie 0 private NetzModus Modus; private PlatzListe Plaetze; private TransitionListe Transitionen; private KantenListe Kanten; private boolean Veraendert; //wurden an der Datei Änderungen vorgenommen, die noch nicht gespeichert sind? private String DateiName; //Dateiname für Speichern/Laden, mit kompletter Pfadangabe private int wegenKanteMatrix = 0; //gibt an, wieviele Kanten wegen zuvielen Marken/Kapazitäten eine Matrix brauchen private int wegenPlatzMatrix = 0; //gibt an, wieviele Plätze wegen zuvielen Marken/Kapazitäten eine Matrix brauchen private boolean seitletztemMalenGeaendert; //ob sich die Plätze in der Matrix geändert haben /*********************************************************/ /* Konstruktor */ /*********************************************************/ public Netz(int farbAnzahl) { this.Farbanzahl = farbAnzahl; Modus = new NetzModus(); this.Plaetze = new PlatzListe(); this.Transitionen = new TransitionListe(); this.Kanten = new KantenListe(); this.Veraendert = false; this.DateiName = new String(""); this.setSize( Petri.screenSize); this.setPreferredSize( new Dimension( 0, 0)); this.setVisible(true); this.setEnabled(true); this.setBackground( HINTERGRUNDFARBE_KEINNETZ); seitletztemMalenGeaendert = false; }//Netz-Konstruktor /*********************************************************/ /* struktureller Teil */ /*********************************************************/ public void NeuesNetz(int Modus) { //löscht alle Komponenten des Netzes; bestimmt Modus für Netz Enumeration e; setSize( Petri.screenSize); Platz hPlatz; Transition hTrans; Kante hKante; e = Plaetze.Aufzaehlung(); while(e.hasMoreElements()) { hPlatz = (Platz)e.nextElement(); hPlatz.Leeren(false,null,null); remove(hPlatz); } e = Transitionen.Aufzaehlung(); while(e.hasMoreElements()) { hTrans = (Transition)e.nextElement(); hTrans.Leeren(false,null,null); remove(hTrans); } e = Kanten.Aufzaehlung(); while(e.hasMoreElements()) { hKante = (Kante)e.nextElement(); hKante.Leeren(); remove( hKante); } Plaetze.Leeren(); Platz.maxID = 0; //es gibt keine zugreifbaren Objekte. Daher wieder mit ID=0 beginnen! Transitionen.Leeren(); Transition.maxID = 0; Kanten.Leeren(); Kante.maxID = 0; this.Modus.set(Modus); DateiName = new String(""); setVeraendert( false, true); revalidate(); }//NeuesNetz(int) public boolean NeuesNetz(int Modus, int Farbanzahl) { //zusätzlich wird Farbanzahl geändert! NeuesNetz(Modus); if (istGueltigeFarbanzahl(Farbanzahl)) { this.Farbanzahl = Farbanzahl; return true; } else return false; }//NeuesNetz(int, int) public boolean getVeraendert() { return Veraendert; }//getVeraendert public boolean setVeraendert(boolean Veraendert, boolean DateinameNeu) { if( (this.Veraendert != Veraendert) || (DateinameNeu) ){ this.Veraendert = Veraendert; String neuTitel; if (istModusNichts()) { neuTitel = ""; } else { if (hatDateiName()) neuTitel = DateiName; else neuTitel = "Unbenannt"; if (Veraendert) neuTitel = "! " + neuTitel; } Petri.frame.aktualisiereTitel( neuTitel); return true; } else return false; }//setVeraendert public boolean Speichern(File Datei) throws IOException { //unter der angegebenen Datei speichern //setzt voraus, das eine gültige Datei bereits erstellt wurde boolean rueckwert = false; Enumeration enum; FileWriter Schreiber = new FileWriter(Datei); try { Schreiber.write("N" + Integer.toString(Farbanzahl)+ "_"); Dimension Groesse = getSize(); Schreiber.write( Integer.toString(Groesse.width)+ "_"); Schreiber.write( Integer.toString(Groesse.height)+ "_"); Schreiber.write("Pl"); //Plaetze enum = Plaetze.Aufzaehlung(); while(enum.hasMoreElements()) ((Platz)enum.nextElement()).Speichern(Schreiber); Schreiber.write("EP"); //Ende-Plaetze Schreiber.write("Tr"); //Transitionen enum = Transitionen.Aufzaehlung(); while(enum.hasMoreElements()) ((Transition)enum.nextElement()).Speichern(Schreiber); Schreiber.write("ET"); //Ende-Transitionen Schreiber.write("Kn"); //Kanten enum = Kanten.Aufzaehlung(); while(enum.hasMoreElements()) ((Kante)enum.nextElement()).Speichern(Schreiber); Schreiber.write("EK"); //Ende-Kanten //alles erfolgreich beendet this.DateiName = Datei.getPath(); setVeraendert( false, true); rueckwert = true; } catch(Exception e) { } finally { //das DateiZugriffsObject muß noch gelöscht werden! if (Schreiber != null) try { Schreiber.close(); } catch(Exception e) {}; return rueckwert; } }//Speichern class LeseDaten { int start = 0, wert[] = {0,0,0}; String str = null, text = null; BufferedReader Leser = null; } public boolean Laden(File Datei) { //setzt voraus, das eine gültige Datei bereits erstellt wurde boolean rueckwert = false; LeseDaten LD = new LeseDaten(); try { LD.Leser = new BufferedReader( new FileReader(Datei)); NetzLesen: { LD.start = 0; if( !EinlesenOK(LD)) break NetzLesen; if( !TestStrLesenOK( "N", LD)) break NetzLesen; if( !IntLesenBisCharOK( 1, '_', LD)) break NetzLesen; NeuesNetz( MODUS_EINGABE, LD.wert[1]); if( !IntLesenBisCharOK( 1, '_', LD)) break NetzLesen; if( !IntLesenBisCharOK( 2, '_', LD)) break NetzLesen; setSize( LD.wert[1], LD.wert[2]); setPreferredSize( getSize()); if( !TestStrLesenOK( "Pl", LD)) break NetzLesen; PlaetzeLesen: { Platz ePlatz; while( LD.str.charAt(LD.start)=='P' ) { ePlatz = Platz.Laden(LD); if( ePlatz == null) break NetzLesen; if( Plaetze.IDvorhanden(ePlatz.getID())) break NetzLesen; Plaetze.Einfuegen(ePlatz); add(ePlatz); } } if( !TestStrLesenOK( "EPTr", LD)) break NetzLesen; TransitionenLesen: { Transition eTrans; while( LD.str.charAt(LD.start)=='T' ) { eTrans = Transition.Laden(LD); if( eTrans == null) break NetzLesen; if( Transitionen.IDvorhanden(eTrans.getID())) break NetzLesen; Transitionen.Einfuegen(eTrans); add(eTrans); } } if( !TestStrLesenOK( "ETKn", LD)) break NetzLesen; KantenLesen: { Kante eKante; while( LD.str.charAt(LD.start)=='K' ) { eKante = Kante.Laden(LD, Plaetze, Transitionen); if( eKante == null) break NetzLesen; if( Kanten.IDvorhanden(eKante.getID())) break NetzLesen; Kanten.Einfuegen(eKante); add(eKante); } } if( !TestStrLesenOK( "EK", LD)) break NetzLesen; this.DateiName = Datei.getPath(); setVeraendert( false, true); rueckwert = true; } if( !rueckwert) NeuesNetz( MODUS_NICHTS); } catch(Exception e) { NeuesNetz( MODUS_NICHTS); } finally { if( LD.Leser != null ) try { LD.Leser.close(); } catch(Exception e) {} return rueckwert; } }//Laden protected static boolean EinlesenOK(LeseDaten LD) throws IOException { try{ if( !LD.Leser.ready() ) return false; LD.str = LD.Leser.readLine(); LD.start = 0; return LD.str != null; } catch(Exception e) { return false; } }//weiterlesen protected static boolean IntLesenBisCharOK(int wertNum, char ch, LeseDaten LD) { try{ int ende = LD.str.indexOf( ch, LD.start); LD.wert[wertNum] = 0; LD.wert[wertNum] = Integer.parseInt( LD.str.substring( LD.start, ende)); LD.start = ende+1; return true; } catch(Exception e) { return false; } }//IntLesenOK protected static boolean TestStrLesenOK(String muster, LeseDaten LD) { try{ if( LD.str.startsWith( muster, LD.start)) { LD.start += muster.length(); return true; } else return false; } catch(Exception e) { return false; } }//TestStrLesenOK protected static boolean TextLesenOK(int laenge, LeseDaten LD) { try{ LD.text = LD.str.substring( LD.start, LD.start+laenge); LD.start += laenge; return LD.text != null; } catch(Exception e) { return false; } }//TextLesenOK public boolean setModus(int Modus) { return this.Modus.set(Modus); }//setModus public void Vergroessern(int links, int oben, int rechts, int unten){ Enumeration enum = Plaetze.Aufzaehlung(); while( enum.hasMoreElements() ) ((Platz)enum.nextElement()).Verschieben( links, oben, false); enum = Transitionen.Aufzaehlung(); while( enum.hasMoreElements() ) ((Transition)enum.nextElement()).Verschieben( links, oben, false); enum = Kanten.Aufzaehlung(); while( enum.hasMoreElements() ) ((Kante)enum.nextElement()).berechneEndpunkte(); setSize( getSize().width+ links+ rechts, getSize().height+ oben+ unten); setPreferredSize( getSize()); Petri.frame.zeichenflaeche.getViewport().setViewPosition( newPointUebersetztNachZeichenflaeche( new Point( links, oben))); Petri.frame.zeichenflaeche.revalidate(); setVeraendert( true, false); repaint(); }//Vergroessern private Point newPointUebersetztNachZeichenflaeche(Point p){ Point vpos = Petri.frame.zeichenflaeche.getViewport().getViewPosition(); return new Point( p.x+ vpos.x, p.y+ vpos.y); }//uebersetztNachZeichenflaeche /********************************************************************************************/ /* Platz - Teil */ /********************************************************************************************/ /* Platz Anlegen */ /***********************************************************/ public Platz PlatzAnlegen(Point anlegeP) { //evtl. kann Test auf Eingabe-Modus entfallen, da Buttons ggf. deaktiviert sind if( Modus.get()==MODUS_EINGABE ) { //Eingabe Point p = newPointUebersetztNachZeichenflaeche( anlegeP); if( !istInnerhalbVonNetz( RechteckUmMittelpunkt( p, PLATZ_RADIUS, RAND_ABSTAND)) ){ Petri.frame.jStatusBar.setText("Position liegt zu nah am Rand des Netzes!"); return null; } Rectangle testRechteck = RechteckUmMittelpunkt( p, PLATZ_RADIUS, KOMPONENTEN_ABSTAND); boolean zunahPlatz = (Plaetze.InRechteck( testRechteck) > 0); boolean zunahTrans = (Transitionen.InRechteck( testRechteck) > 0); if( zunahPlatz || zunahTrans ) { String meldung = ""; if( zunahPlatz) meldung = "Abbruch, da Punkt zu nah an einem Platz!"; if( zunahTrans) meldung = "Abbruch, da Punkt zu nah an einer Transition!"; if( zunahPlatz && zunahTrans) meldung = "Abbruch, da Punkt zu nah an einem Platz und einer Transition!"; Petri.frame.jStatusBar.setText(meldung); return null; } Platz einPlatz = new Platz( p, PLATZ_RADIUS, "p" + Integer.toString(Platz.maxID)); Plaetze.Einfuegen(einPlatz); add(einPlatz); setVeraendert( true, false); NichtsMarkieren(); einPlatz.MarkierungAendern( true); Dimension neueGroesse = Vergroessern( getSize(), p, einPlatz.getRadius()); if( neueGroesse!=null ) { setPreferredSize( neueGroesse); Petri.frame.zeichenflaeche.revalidate(); //Rollbalken aktuallisieren } repaint(); Petri.frame.jStatusBar.setText("Platz <"+ einPlatz.getText()+"> wurde angelegt!"); return einPlatz; } else { //Simulationsmodus oder kein Netz, keine Plätze einfügbar Petri.frame.jStatusBar.setText("Anlegen von Plätzen ist nur im Eingabemodus möglich!"); return null; } }//PlatzAnlegen /* Platz Entfernen */ /***********************************************************/ public boolean PlatzEntfernen(Point entfernP) { //evtl. kann Test auf Eingabe-Modus entfallen, da Buttons ggf. deaktiviert sind if( Modus.get()==MODUS_EINGABE ) { //Eingabe Point p = newPointUebersetztNachZeichenflaeche( entfernP); Rectangle testRechteck = RechteckUmMittelpunkt( p, PLATZ_RADIUS, 0); /* sicherstellen, daß Zuordnung (x,y)->Platz eindeutig! */ if( Plaetze.InRechteck( testRechteck) != 1 ) { Petri.frame.jStatusBar.setText("Der zu löschende Platz konnte nicht eindeutig bestimmt werden!"); return false; } Platz hPlatz = Plaetze.AusRechteck( testRechteck); if( PetriFrame.Mitteilung( "Soll der Platz <"+ hPlatz.getText()+ "> wirklich gelöscht werden?", "Loeschen Bestaetigen", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) != JOptionPane.YES_OPTION ) return true; Petri.frame.jStatusBar.setText("Platz "+ hPlatz.getText()+ " wurde entfernt!"); hPlatz.Leeren( true, this, Kanten); //mitKanten Plaetze.Entfernen( hPlatz); remove( hPlatz); repaint(); setVeraendert( true, false); return true; } else { //Simulationsmodus oder kein Netz, keine Plätze einfügbar Petri.frame.jStatusBar.setText("Löschen von Plätzen ist nur im Eingabemodus möglich!"); return false; } }//PlatzEntfernen /* Platz Verschieben */ /***********************************************************/ public Platz PlatzVerschieben(Point vonP, Point nachP) { //evtl. kann Test auf Eingabe-Modus entfallen, da Buttons ggf. deaktiviert sind if( Modus.get()==MODUS_EINGABE ) { //Eingabe Point von = newPointUebersetztNachZeichenflaeche( vonP); Point nach = newPointUebersetztNachZeichenflaeche( nachP); if( !istInnerhalbVonNetz( RechteckUmMittelpunkt( nach, PLATZ_RADIUS, RAND_ABSTAND)) ) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah am Rand des Netzes!"); return null; } Rectangle nachRechteck = RechteckUmMittelpunkt( nach, PLATZ_RADIUS, KOMPONENTEN_ABSTAND); int zunahPlatz = Plaetze.InRechteck( nachRechteck); int zunahTrans = Transitionen.InRechteck( nachRechteck); if(( zunahTrans > 0 ) || ( zunahPlatz > 1 )) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah an anderen Komponenten des Netzes!"); return null; } Rectangle vonRechteck = RechteckUmMittelpunkt( von, PLATZ_RADIUS, 0); if( Plaetze.InRechteck( vonRechteck) != 1) { Petri.frame.jStatusBar.setText("Zu verschiebender Platz konnte nicht eindeutig bestimmt werden!"); return null; } if(( zunahPlatz == 1 ) && ( Plaetze.AusRechteck( nachRechteck).getID() != Plaetze.AusRechteck( vonRechteck).getID() )) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah an anderen Komponenten des Netzes!"); return null; } Platz einPlatz = Plaetze.AusRechteck( vonRechteck); einPlatz.Verschieben( nach.x-von.x, nach.y-von.y, true); repaint(); setVeraendert( true, false); return einPlatz; } else { //Simulationsmodus oder kein Netz Petri.frame.jStatusBar.setText("Verschieben von Plätzen ist nur im Eingabemodus möglich!"); return null; } }//PlatzVerschieben /* Platz Verschieben */ /***********************************************************/ public Platz PlatzVerschieben(Platz einPlatz, Point nachP) { //evtl. kann Test auf Eingabe-Modus entfallen, da Buttons ggf. deaktiviert sind if( Modus.get()==MODUS_EINGABE ) { //Eingabe Point nach = newPointUebersetztNachZeichenflaeche( nachP); if( !istInnerhalbVonNetz( RechteckUmMittelpunkt( nach, PLATZ_RADIUS, RAND_ABSTAND)) ) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah am Rand des Netzes!"); return null; } Rectangle nachRechteck = RechteckUmMittelpunkt( nach, PLATZ_RADIUS, KOMPONENTEN_ABSTAND); int zunahPlatz = Plaetze.InRechteck( nachRechteck); int zunahTrans = Transitionen.InRechteck( nachRechteck); if(( zunahTrans > 0 ) || ( zunahPlatz > 1 )) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah an anderen Komponenten des Netzes!"); return null; } if(( zunahPlatz == 1 ) && ( Plaetze.AusRechteck( nachRechteck).getID() != einPlatz.getID() )) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah an anderen Komponenten des Netzes!"); return null; } Point p = einPlatz.getMittelPkt(); einPlatz.Verschieben( nach.x-p.x, nach.y-p.y, true); repaint(); setVeraendert( true, false); return einPlatz; } else { //Simulationsmodus oder kein Netz Petri.frame.jStatusBar.setText("Verschieben von Plätzen ist nur im Eingabemodus m%ouml;glich!"); return null; } }//PlatzVerschieben /* Platz Markieren */ /***********************************************************/ public void PlatzMarkieren(Point p) { Transitionen.MarkierungenAufheben(); Plaetze.MarkierungenAufheben(); if( p != null ) Plaetze.MarkiereInRechteck( RechteckUmMittelpunkt( newPointUebersetztNachZeichenflaeche( p), PLATZ_RADIUS, 0)); repaint(); }//PlatzMarkieren public void PlatzMarkieren(Platz ePlatz) { Transitionen.MarkierungenAufheben(); Plaetze.MarkierungenAufheben(); if( ePlatz != null ) ePlatz.MarkierungAendern( true); repaint(); }//PlatzMarkieren /********************************************************************************************/ /* Transition - Teil */ /********************************************************************************************/ /* Transition Anlegen */ /***********************************************************/ public Transition TransitionAnlegen(Point anlegeP) { if( Modus.get()==MODUS_EINGABE ) { //Eingabe Point p = newPointUebersetztNachZeichenflaeche( anlegeP); if( !istInnerhalbVonNetz( RechteckUmMittelpunkt( p, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, RAND_ABSTAND)) ) { Petri.frame.jStatusBar.setText("Position liegt zu nah am Rand des Netzes!"); return null; } Rectangle testRechteck = RechteckUmMittelpunkt( p, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, KOMPONENTEN_ABSTAND); boolean zunahPlatz = (Plaetze.InRechteck( testRechteck) > 0); boolean zunahTrans = (Transitionen.InRechteck( testRechteck) > 0); if( zunahPlatz || zunahTrans ) { String meldung = ""; if( zunahPlatz && zunahTrans) meldung = "Abbruch, da Punkt zu nah an einem Platz und einer Transition!"; else if( zunahPlatz) meldung = "Abbruch, da Punkt zu nah an einem Platz!"; else if( zunahTrans) meldung = "Abbruch, da Punkt zu nah an einer Transition!"; Petri.frame.jStatusBar.setText(meldung); return null; } Transition eineTrans = new Transition( p, new Dimension( TRANSITIONS_BREITE, TRANSITIONS_HOEHE), "t" + Integer.toString(Transition.maxID)); Transitionen.Einfuegen(eineTrans); add(eineTrans); setVeraendert( true, false); NichtsMarkieren(); eineTrans.MarkierungAendern( true); Dimension neueGroesse = Vergroessern( getSize(), p, eineTrans.getGroesse()); if( neueGroesse != null ){ setPreferredSize(neueGroesse); Petri.frame.zeichenflaeche.revalidate(); //Rollbalken aktuallisieren } repaint(); Petri.frame.jStatusBar.setText("Eine Transiton wurde angelegt."); return eineTrans; } else { //Simulationsmodus oder kein Netz, keine Transitionen einfügbar Petri.frame.jStatusBar.setText("Anlegen von Transitionen ist nur im Eingabemodus möglich!"); return null; } }//TransitionAnlegen /* Transition Entfernen */ /***********************************************************/ public boolean TransitionEntfernen(Point entfernP) { //evtl. kann Test auf Eingabe-Modus entfallen, da Buttons ggf. deaktiviert sind if( Modus.get()==MODUS_EINGABE ) { //Eingabe Point p = newPointUebersetztNachZeichenflaeche( entfernP); Rectangle testRechteck = RechteckUmMittelpunkt( p, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, 0); if( Transitionen.InRechteck( testRechteck) != 1 ) { Petri.frame.jStatusBar.setText("Die zu löschende Transition konnte nicht eindeutig bestimmt werden!"); return false; } Transition hTrans = Transitionen.AusRechteck( testRechteck); if( PetriFrame.Mitteilung( "Soll die Transition <"+ hTrans.getText()+ "> wirklich gelöscht werden?", "Loeschen Bestaetigen", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) != JOptionPane.YES_OPTION ) return true; Petri.frame.jStatusBar.setText("Transition " + hTrans.getText() + " wurde entfernt!"); hTrans.Leeren( true, this, Kanten); Transitionen.Entfernen( hTrans); remove( hTrans); setVeraendert( true, false); repaint(); return true; } else { //Simulationsmodus oder kein Netz, keine transitionen entfernbar Petri.frame.jStatusBar.setText("Entfernen von Transitionen ist nur im Eingabemodus möglich!"); return false; } }//TransitionEntfernen /* Transition Verschieben */ /***********************************************************/ public Transition TransitionVerschieben(Point vonP, Point nachP) { //evtl. kann Test auf Eingabe-Modus entfallen, da Buttons ggf. deaktiviert sind if( Modus.get()==MODUS_EINGABE ) { //Eingabe Point von = newPointUebersetztNachZeichenflaeche( vonP); Point nach = newPointUebersetztNachZeichenflaeche( nachP); if( !istInnerhalbVonNetz( RechteckUmMittelpunkt( nach, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, RAND_ABSTAND)) ) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah am Rand des Netzes!"); return null; } Rectangle nachRechteck = RechteckUmMittelpunkt( nach, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, KOMPONENTEN_ABSTAND); int zunahPlatz = Plaetze.InRechteck( nachRechteck); int zunahTrans = Transitionen.InRechteck( nachRechteck); if(( zunahPlatz > 0 ) || ( zunahTrans > 1 )) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah an anderen Komponenten des Netzes!"); return null; } Rectangle vonRechteck = RechteckUmMittelpunkt( von, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, 0); if( Transitionen.InRechteck( vonRechteck) != 1 ) { Petri.frame.jStatusBar.setText("Zu verschiebende Transition konnte nicht eindeutig bestimmt werden!"); return null; } if(( zunahTrans == 1 ) && ( Transitionen.AusRechteck( nachRechteck).getID() != Transitionen.AusRechteck( vonRechteck).getID() )) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah an anderen Komponenten des Netzes!"); return null; } Transition eineTrans = Transitionen.AusRechteck( vonRechteck); eineTrans.Verschieben( nach.x-von.x, nach.y-von.y, true); repaint(); setVeraendert( true, false); return eineTrans; } else { //Simulationsmodus oder kein Netz Petri.frame.jStatusBar.setText("Verschieben von Transitonen nur im Eingabemodus möglich!"); return null; } }//TransitionVerschieben /* Transition Verschieben */ /***********************************************************/ public Transition TransitionVerschieben(Transition eineTrans, Point nachP) { //evtl. kann Test auf Eingabe-Modus entfallen, da Buttons ggf. deaktiviert sind if( Modus.get()==MODUS_EINGABE ) { //Eingabe Point nach = newPointUebersetztNachZeichenflaeche( nachP); if( !istInnerhalbVonNetz( RechteckUmMittelpunkt( nach, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, RAND_ABSTAND)) ) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah am Rand des Netzes!"); return null; } Rectangle nachRechteck = RechteckUmMittelpunkt( nach, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, KOMPONENTEN_ABSTAND); int zunahPlatz = Plaetze.InRechteck( nachRechteck); int zunahTrans = Transitionen.InRechteck( nachRechteck); if(( zunahPlatz > 0 ) || ( zunahTrans > 1 )) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah an anderen Komponenten des Netzes!"); return null; } if(( zunahTrans == 1 ) && ( Transitionen.AusRechteck( nachRechteck).getID() != eineTrans.getID() )) { Petri.frame.jStatusBar.setText("Zielposition liegt zu nah an anderen Komponenten des Netzes!"); return null; } Point p = eineTrans.getMittelPkt(); eineTrans.Verschieben( nach.x-p.x, nach.y-p.y, true); repaint(); setVeraendert( true, false); return eineTrans; } else { //Simulationsmodus oder kein Netz Petri.frame.jStatusBar.setText("Verschieben von Transitonen nur im Eingabemodus möglich!"); return null; } }//TransitionVerschieben /* Transition Markieren */ /***********************************************************/ public void TransitionMarkieren(Point markP) { Plaetze.MarkierungenAufheben(); Transitionen.MarkierungenAufheben(); if( markP != null ) Transitionen.MarkiereInRechteck( RechteckUmMittelpunkt( newPointUebersetztNachZeichenflaeche( markP), TRANSITIONS_BREITE, TRANSITIONS_HOEHE, 0)); repaint(); }//TransitionMarkieren public void TransitionMarkieren(Transition eTrans) { Plaetze.MarkierungenAufheben(); Transitionen.MarkierungenAufheben(); if( eTrans != null ) eTrans.MarkierungAendern( true); repaint(); }//TransitionMarkieren /* Transitionen TestSchalten */ /***********************************************************/ public void TransitionenTestSchalten() { Enumeration enum = Transitionen.Aufzaehlung(); while(enum.hasMoreElements()) ((Transition)enum.nextElement()).TestSchalten(); this.revalidate(); }//TransitionenTestSchalten /* Transition Schalten am Punkt */ /***********************************************************/ public boolean TransitionSchalten(Point schaltP) { Point p = newPointUebersetztNachZeichenflaeche( schaltP); Rectangle r = RechteckUmMittelpunkt( p, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, 1); if( Transitionen.InRechteck(r) != 1 ){ Petri.frame.jStatusBar.setText("Zu Schaltende Transition konnte nicht eindeutig bestimmt werden!"); return false; } Transition eTrans = Transitionen.AusRechteck( r); int markenanzahl; if( (markenanzahl=eTrans.Schalten()) > -1 ){ if( markenanzahl > 0 ) setVeraendert( true, false); //nicht schaltfaehige aber markierte Transitionen "unmarkieren" , neuen markieren Enumeration enum = Transitionen.Aufzaehlung(); while(enum.hasMoreElements()) ((Transition)enum.nextElement()).TestSchalten(); Petri.frame.jStatusBar.setText("Es wurde Transition <"+eTrans.getText()+"> geschaltet!"); } paint( getGraphics()); return true; }//TransitionSchalten /* Transition BeendeSchalten */ /***********************************************************/ public void TransitionenEndeSchalten() { Enumeration enum = Transitionen.Aufzaehlung(); while(enum.hasMoreElements()) ((Transition)enum.nextElement()).Abschalten(); this.revalidate(); }//TransitionenTestSchalten /********************************************************************************************/ /* Kante - Teil */ /********************************************************************************************/ /* Kante Anlegen */ /***********************************************************/ public Kante KanteAnlegen( Point vonP, Point nachP) { if( Modus.get()==MODUS_EINGABE ) { //Eingabe Point von = newPointUebersetztNachZeichenflaeche( vonP); Point nach = newPointUebersetztNachZeichenflaeche( nachP); Rectangle quellplatzrechteck = RechteckUmMittelpunkt( von, PLATZ_RADIUS, 5); Rectangle quelltransrechteck = RechteckUmMittelpunkt( von, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, 5); int quellplatz = Plaetze.InRechteck( quellplatzrechteck); int quelltrans = Transitionen.InRechteck( quelltransrechteck); if(( quellplatz+quelltrans != 1 ) || ( quellplatz > 1 ) || ( quelltrans > 1 )) { Petri.frame.jStatusBar.setText("Abbruch, da Quellknoten nicht eindeutig bestimmt werden konnte!"); return null; } Kante eineKante; if( quellplatz == 1 ) { Rectangle zielrechteck = RechteckUmMittelpunkt( nach, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, 5); if( Transitionen.InRechteck( zielrechteck) != 1 ) { Petri.frame.jStatusBar.setText("Abbruch, da Zieltransition nicht eindeutig bestimmt werden konnte!"); return null; } Platz vonPlatz = Plaetze.AusRechteck(quellplatzrechteck); Transition nachTrans = Transitionen.AusRechteck( zielrechteck); eineKante = new Kante( "k" + Integer.toString(Kante.maxID), vonPlatz, nachTrans, new Tupel(0)); vonPlatz.WegKanteEinfuegen(eineKante); nachTrans.VorKanteEinfuegen(eineKante); } else if( quelltrans == 1 ) { Rectangle zielrechteck = RechteckUmMittelpunkt( nach, PLATZ_RADIUS, 5); if( Plaetze.InRechteck( zielrechteck) != 1 ) { Petri.frame.jStatusBar.setText("Abbruch, da Zielplatz nicht eindeutig bestimmt werden konnte!"); return null; } Transition vonTrans = Transitionen.AusRechteck( quelltransrechteck); Platz nachPlatz = Plaetze.AusRechteck( zielrechteck); eineKante = new Kante( "k" + Integer.toString(Kante.maxID), vonTrans, nachPlatz, new Tupel(0)); vonTrans.NachKanteEinfuegen(eineKante); nachPlatz.HinKanteEinfuegen(eineKante); } else return null; Kanten.Einfuegen(eineKante); add(eineKante); setVeraendert( true, false); NichtsMarkieren(); repaint(); Petri.frame.jStatusBar.setText("Kante <"+ eineKante.getText()+"> wurde angelegt."); return eineKante; } else { //Simulationsmodus oder kein Netz, keine Kanten einfügbar Petri.frame.jStatusBar.setText("Anlegen von Kanten ist nur im Eingabemodus möglich!"); return null; } }//KanteAnlegen /* Kante Entfernen */ /***********************************************************/ public boolean KanteEntfernen(Point entfernP) { if( Modus.get()==MODUS_EINGABE ) { //Eingabe Point p = newPointUebersetztNachZeichenflaeche( entfernP); Rectangle testRechteck = RechteckUmMittelpunkt( p, KOMPONENTEN_ABSTAND>>1, 0); if( Kanten.InRechteck(testRechteck) != 1 ){ Petri.frame.jStatusBar.setText("Die zu löschende Kante konnte nicht eindeutig bestimmt werden!"); return false; } Kante hKante = Kanten.AusRechteck( testRechteck); if( PetriFrame.Mitteilung( "Soll die Kante <"+ hKante.getText()+ "> wirklich gelöscht werden?", "Loeschen Bestaetigen", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) != JOptionPane.YES_OPTION ) return true; hKante.getPlatz().KanteLoeschen( hKante); hKante.getTransition().KanteLoeschen( hKante); hKante.MarkenZuweisen( new Tupel( 0)); Petri.frame.jStatusBar.setText("Kante "+ hKante.getText()+ " wurde entfernt!"); Kanten.Entfernen( hKante); hKante.Leeren(); remove( hKante); setVeraendert( true, false); repaint(); return true; } else { //Simulationsmodus oder kein Netz, keine Kante entfernbar Petri.frame.jStatusBar.setText("Entfernen von Kanten ist nur im Eingabemodus möglich!"); return false; } }//KanteEntfernen /***********************************************************/ /* Objekt & -typ am Punkt */ /***********************************************************/ public int getObjektTyp(Point objP) { Point p = newPointUebersetztNachZeichenflaeche( objP); if( Modus.get()==MODUS_EINGABE ) { //Eingabe if( Plaetze.InRechteck( RechteckUmMittelpunkt( p, PLATZ_RADIUS, 1)) >= 1) return TYP_PLATZ; if( Transitionen.InRechteck( RechteckUmMittelpunkt( p, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, 1)) >= 1) return TYP_TRANS; if( Kanten.InRechteck( RechteckUmMittelpunkt( p, KOMPONENTEN_ABSTAND>>1, 1)) >= 1) return TYP_KANTE; } else if( Modus.get()==MODUS_SIMULATION ){ //Simulation if( Transitionen.InRechteck( RechteckUmMittelpunkt( p, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, 1)) >= 1) return TYP_TRANS; } return TYP_NICHTDEF; }//getObjektTyp public PN_Knoten getObjekt(Point objP) { Point p = newPointUebersetztNachZeichenflaeche( objP); if( Modus.get()==MODUS_EINGABE ) { //Eingabe Rectangle r; r = RechteckUmMittelpunkt( p, PLATZ_RADIUS, 1); if( Plaetze.InRechteck( r) >= 1) return Plaetze.AusRechteck(r); r = RechteckUmMittelpunkt( p, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, 1); if( Transitionen.InRechteck( r) >= 1) return Transitionen.AusRechteck(r); r = RechteckUmMittelpunkt( p, KOMPONENTEN_ABSTAND>>1, 1); if( Kanten.InRechteck( r) >= 1) return Kanten.AusRechteck(r); } else if( Modus.get()==MODUS_SIMULATION ) { //Simulation Rectangle r; r = RechteckUmMittelpunkt( p, TRANSITIONS_BREITE, TRANSITIONS_HOEHE, 1); if( Transitionen.InRechteck( r) >= 1) return Transitionen.AusRechteck(r); } return null; }//getObjekt /***********************************************************/ /* Markierungen aufheben */ /***********************************************************/ public void NichtsMarkieren() { Plaetze.MarkierungenAufheben(); Transitionen.MarkierungenAufheben(); repaint(); }//NichtsMarkieren /*********************************************************/ /* Zugriff auf gekapselte Daten */ /*********************************************************/ public String getDateiName() { return new String(DateiName); }//getDateiName public boolean hatDateiName() { return DateiName.compareTo("")!=0; }//hatDateiName public boolean istModusNichts() { return Modus.get()==MODUS_NICHTS; }//istModusNichts public boolean istModusEingabe() { return Modus.get()==MODUS_EINGABE; }//istModusEingabe public boolean istModusSimulation() { return Modus.get()==MODUS_SIMULATION; }//istModusSimulation private boolean istInnerhalbVonNetz(Rectangle drin) { Rectangle huelle = new Rectangle( getSize()); return huelle.contains( drin); }//istInnerhalbVonNetz public static int getFarbanzahl(){ return Farbanzahl; }//getFarbanzahl public static boolean istGueltigeFarbanzahl(int testAnzahl) { return ((MIN_FARBANZAHL<=testAnzahl) && (testAnzahl<=MAX_FARBANZAHL)); }//istGueltigeFarbanzahl private static Rectangle RechteckUmMittelpunkt( Point p, int radius, int rand) { return new Rectangle( p.x-radius-rand, p.y-radius-rand, radius+rand<<1, radius+rand<<1); } private static Rectangle RechteckUmMittelpunkt( Point p, int breite, int hoehe, int rand) { return new Rectangle( p.x-rand-(breite>>1), p.y-rand-(hoehe>>1), breite+(rand<<1), hoehe+(rand<<1)); } private static Dimension Vergroessern( Dimension alt, Point p, int radius) { boolean vergroessert = false; if( p.x + radius > alt.width ) { alt.width = p.x + (radius<<1); vergroessert = true; } if( p.y + radius > alt.height ) { alt.height = p.y + (radius<<1); vergroessert = true; } if(vergroessert) return alt; return null; } private static Dimension Vergroessern( Dimension alt, Point p, Dimension element) { boolean vergroessert = false; if( p.x + (element.width>>1) > alt.width ) { alt.width = p.x + element.width; vergroessert = true; } if( p.y + (element.height>>1) > alt.height ) { alt.height = p.y + element.height; vergroessert = true; } if(vergroessert) return alt; return null; } /*********************************************************/ /* Scrollable-Implementierungsteil */ /*********************************************************/ public Dimension getPreferredScrollableViewportSize() { System.out.println("getPreferredScrollableViewportSize"); return getSize(); }//getPrefferedScrollableViewportSize public int getScrollableUnitIncrement( Rectangle visibleRect, int orientation, int direction) { return 20; }//getScrollableUnitIncrement public int getScrollableBlockIncrement( Rectangle visibleRect, int orientation, int direction) { if( orientation == SwingConstants.HORIZONTAL) { return visibleRect.width/2; } else { return visibleRect.height/2; } }//getScrollableBlockIncrement public boolean getScrollableTracksViewportHeight() { return false; }//getScrollableTracksViewportHeight public boolean getScrollableTracksViewportWidth() { return false; }//getScrollableTracksViewportWidth /*********************************************************/ /* Darstellungsteil */ /*********************************************************/ public void paintComponent(Graphics g) { super.paintComponent(g); for( int i = getComponentCount() - 1; i >= 0; i--) this.getComponent(i).paint(g); if( seitletztemMalenGeaendert ){ Petri.frame.PlatzMatrixRE.aktualisieren(); Petri.frame.PlatzMatrixUN.aktualisieren(); Petri.frame.KanteMatrixRE.aktualisieren(); Petri.frame.KanteMatrixUN.aktualisieren(); seitletztemMalenGeaendert = false; } if( Petri.frame.MatrizenSindRechts){ Petri.frame.PlatzMatrixRE.revalidate(); Petri.frame.KanteMatrixRE.revalidate(); //Petri.frame.PlatzMatrixRE.repaint(); //Petri.frame.KanteMatrixRE.repaint(); } else { Petri.frame.PlatzMatrixUN.revalidate(); Petri.frame.KanteMatrixUN.revalidate(); //Petri.frame.PlatzMatrixUN.repaint(); //Petri.frame.KanteMatrixUN.repaint(); } }//Zeichnen protected void setMatrixPlatzGeaendert() { seitletztemMalenGeaendert = true; }//setMatrixPlatzGeaendert protected void setMatrixKanteGeaendert() { seitletztemMalenGeaendert = true; }//setMatrixKanteGeaendert public boolean isMatrixKanteBenoetigt() { return wegenKanteMatrix > 0; }//MatrixKanteBenoetigt public boolean isMatrixPlatzBenoetigt() { return wegenPlatzMatrix > 0; }//MatrixPlatzBenoetigt public void InMatrixEinfuegen(Kante ausloeser, boolean enable) { if( enable ){ wegenKanteMatrix++; Petri.frame.KanteMatrixRE.einfuegeKante( ausloeser); Petri.frame.KanteMatrixUN.einfuegeKante( ausloeser); if( Petri.frame.MatrizenSindRechts ){ Petri.frame.jMenuItemAMatrU.setVisible( true); Petri.frame.KanteMatrixRE.setVisible( true); Petri.frame.MatrizenRE.setVisible( true); } else { Petri.frame.jMenuItemAMatrR.setVisible( true); Petri.frame.KanteMatrixUN.setVisible( true); Petri.frame.MatrizenUN.setVisible( true); } } else { wegenKanteMatrix--; Petri.frame.KanteMatrixRE.entferneKante( ausloeser); Petri.frame.KanteMatrixUN.entferneKante( ausloeser); if( wegenKanteMatrix == 0 ){ if( Petri.frame.MatrizenSindRechts ){ Petri.frame.KanteMatrixRE.setVisible( false); if( wegenPlatzMatrix==0 ){ Petri.frame.MatrizenRE.setVisible( false); Petri.frame.jMenuItemAMatrU.setVisible( false); } } else { Petri.frame.KanteMatrixUN.setVisible( false); if( wegenPlatzMatrix==0 ){ Petri.frame.MatrizenUN.setVisible( false); Petri.frame.jMenuItemAMatrR.setVisible( false); } } } } }//InMatrixEinfuegen public void InMatrixEinfuegen(Platz ausloeser, boolean enable) { if( enable){ wegenPlatzMatrix++; Petri.frame.PlatzMatrixRE.einfuegePlatz( ausloeser); Petri.frame.PlatzMatrixUN.einfuegePlatz( ausloeser); //seitletztemMalenGeaendert = false; if( Petri.frame.MatrizenSindRechts ){ Petri.frame.jMenuItemAMatrU.setVisible( true); Petri.frame.PlatzMatrixRE.setVisible( true); Petri.frame.MatrizenRE.setVisible( true); } else { Petri.frame.jMenuItemAMatrR.setVisible( true); Petri.frame.PlatzMatrixUN.setVisible( true); Petri.frame.MatrizenUN.setVisible( true); } } else { wegenPlatzMatrix--; Petri.frame.PlatzMatrixRE.entfernePlatz( ausloeser); Petri.frame.PlatzMatrixUN.entfernePlatz( ausloeser); //seitletztemMalenGeaendert = false; if( wegenPlatzMatrix == 0 ){ if( Petri.frame.MatrizenSindRechts ){ Petri.frame.PlatzMatrixRE.setVisible( false); if( wegenKanteMatrix==0 ){ Petri.frame.MatrizenRE.setVisible( false); Petri.frame.jMenuItemAMatrU.setVisible( false); } } else { Petri.frame.PlatzMatrixUN.setVisible( false); if( wegenKanteMatrix==0 ){ Petri.frame.MatrizenUN.setVisible( false); Petri.frame.jMenuItemAMatrR.setVisible( false); } } } } }//InMatrixEinfuegen protected static String Zweistellig(int zahl) { String s = Integer.toString( zahl); if( s.length()==0 ) return " "; if( s.length()==1 ) return " "+ s; return s; }//Zweistellig //... und ? /********************************************************************/ /* Klasse NetzModus */ /********************************************************************/ class NetzModus { //paßt die Einstellungen der Menueinträge entsprechend dem Modus an private int wert; public NetzModus() { wert = Netz.MODUS_NICHTS; }//NetzModus-Konstruktor public int get() { return wert; }//get public boolean set(int Modus) { if( wert==Modus ) return true; switch(Modus) { case Netz.MODUS_NICHTS: Petri.frame.maus.setEreignisBehandlung( false); setBackground( HINTERGRUNDFARBE_KEINNETZ); setPreferredSize( new Dimension( 0, 0)); Petri.frame.jMenuItemBAnleg.setEnabled(false); Petri.frame.jMenuItemBEntf.setEnabled(false); Petri.frame.jMenuItemBEigen.setEnabled(false); Petri.frame.jMenuItemDSchli.setEnabled(false); Petri.frame.jMenuItemDSpeic.setEnabled(false); Petri.frame.jMenuItemDSpeicU.setEnabled(false); Petri.frame.jMenuItemAMatrR.setEnabled(false); Petri.frame.jMenuItemAMatrU.setEnabled(false); Petri.frame.jMenuItemAVergr.setEnabled(false); Petri.frame.jMenuItemSimBeg.setEnabled(false); Petri.frame.jMenuItemSimBeg.setVisible(true); Petri.frame.jMenuItemSimEnde.setEnabled(false); Petri.frame.jMenuItemSimEnde.setVisible(true); break; case Netz.MODUS_EINGABE: Petri.frame.maus.setEreignisBehandlung( true); Petri.frame.maus.setStatus( PetriFrame.Maus.STATUS.EIGENSCHAFTEN); setBackground( HINTERGRUNDFARBE_NETZ); setPreferredSize( getSize()); Petri.frame.jMenuItemBAnleg.setEnabled(true); Petri.frame.jMenuItemBEntf.setEnabled(true); Petri.frame.jMenuItemBEigen.setEnabled(true); Petri.frame.jMenuItemDSchli.setEnabled(true); Petri.frame.jMenuItemDSpeic.setEnabled(true); Petri.frame.jMenuItemDSpeicU.setEnabled(true); Petri.frame.jMenuItemAMatrR.setEnabled(true); Petri.frame.jMenuItemAMatrU.setEnabled(true); Petri.frame.jMenuItemAVergr.setEnabled(true); Petri.frame.jMenuItemSimBeg.setEnabled(true); Petri.frame.jMenuItemSimBeg.setVisible(true); Petri.frame.jMenuItemSimEnde.setVisible(false); break; case Netz.MODUS_SIMULATION: Petri.frame.maus.setEreignisBehandlung( true); setBackground( HINTERGRUNDFARBE_NETZ); setPreferredSize( getSize()); Petri.frame.jMenuItemBAnleg.setEnabled(false); Petri.frame.jMenuItemBEntf.setEnabled(false); Petri.frame.jMenuItemBEigen.setEnabled(false); Petri.frame.jMenuItemDSchli.setEnabled(true); Petri.frame.jMenuItemDSpeic.setEnabled(true); Petri.frame.jMenuItemDSpeicU.setEnabled(true); Petri.frame.jMenuItemAMatrR.setEnabled(true); Petri.frame.jMenuItemAMatrU.setEnabled(true); Petri.frame.jMenuItemAVergr.setEnabled(false); Petri.frame.jMenuItemSimBeg.setVisible(false); Petri.frame.jMenuItemSimEnde.setEnabled(true); Petri.frame.jMenuItemSimEnde.setVisible(true); break; default: return false; } wert = Modus; return true; }//set }//NetzModus }//Netz-Klasse